From 7db937af313d857d0f66bebaf8ac72d518559bac Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 2 Aug 2026 19:46:36 +0900 Subject: fix(repository): restore late-bound initialize in ComposerRepository fallthroughs findPackage()/findPackages()/search() delegate their non-lazy, non-provider fallthrough to the inner ArrayRepository, whose self-initialization froze the packages array before ComposerRepository::initialize could read the root file, so a plain v1-style repo (inline "packages" in packages.json) always answered empty. Guard the delegations with the same is_initialized() check used by count()/hasPackage(). getProviders() had the inverse defect: PHP reads the raw $this->packages property, but the port went through count(), whose initialize poisoned the initialization flag so the root file would never load afterwards. Check the raw field for non-empty instead, matching PHP's truthiness test. Same defect class as 97b5211a and the 3e367f78 downloader fix. Co-Authored-By: Claude Fable 5 --- .../shirabe/src/repository/composer_repository.rs | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'crates/shirabe') diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index c15c6e12..18de557b 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -860,6 +860,12 @@ impl ComposerRepository { return Ok(results); } + // PHP's ArrayRepository::search() calls $this->getPackages(), which + // virtual-dispatches to ComposerRepository::initialize(); the guard restores that + // (same guard as in count()). + if !self.inner.is_initialized() { + self.initialize()?; + } let inner_results = self.inner.search(query, mode, None)?; let converted: Vec> = inner_results .into_iter() @@ -1220,7 +1226,16 @@ impl ComposerRepository { } } - if self.inner.count()? > 0 { + // PHP checks the raw $this->packages property (`if ($this->packages)`); going through + // count() would run ArrayRepository::initialize() and freeze the initialization flag, + // so the root file would never be loaded afterwards. + if self + .inner + .packages + .borrow() + .as_ref() + .is_some_and(|p| !p.is_empty()) + { for (k, v) in self.inner.get_providers(package_name.to_string())? { let mut entry: IndexMap = IndexMap::new(); entry.insert("name".to_string(), PhpMixed::String(v.name)); @@ -3484,6 +3499,12 @@ impl RepositoryInterface for ComposerRepository { return Ok(None); } + // PHP's ArrayRepository::findPackage() calls $this->getPackages(), which + // virtual-dispatches to ComposerRepository::initialize(); the guard restores that + // (same guard as in count()). + if !self.inner.is_initialized() { + self.initialize()?; + } self.inner.find_package( &name, crate::repository::FindPackageConstraint::Constraint(constraint), @@ -3554,6 +3575,12 @@ impl RepositoryInterface for ComposerRepository { return Ok(vec![]); } + // PHP's ArrayRepository::findPackages() calls $this->getPackages(), which + // virtual-dispatches to ComposerRepository::initialize(); the guard restores that + // (same guard as in count()). + if !self.inner.is_initialized() { + self.initialize()?; + } self.inner.find_packages( &name, constraint.map(crate::repository::FindPackageConstraint::Constraint), -- cgit v1.3.1