diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-06 03:47:55 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-06 03:47:55 +0900 |
| commit | 8c5dba294fae26c8a46a308a46676e0afff217d6 (patch) | |
| tree | 4b5d51a82acc41ed4e49e42269dcf27b982b472a /crates | |
| parent | 0abd0141380aa491ad6e65c58979e2fa371e3df0 (diff) | |
| download | php-shirabe-8c5dba294fae26c8a46a308a46676e0afff217d6.tar.gz php-shirabe-8c5dba294fae26c8a46a308a46676e0afff217d6.tar.zst php-shirabe-8c5dba294fae26c8a46a308a46676e0afff217d6.zip | |
fix(dependency-resolver): preserve PHP array keying for alias links
Mirror PHP's array_merge semantics in AliasPackage so self.version
provide/replace/conflict links are appended under numeric keys ("0",
"1", ...) instead of collapsing onto the target-name key. This keeps
both the original and alias-version links and makes Pool::match's
contains_key("0") check (= PHP isset($x[0])) work as intended.
replace_self_version_dependencies now takes and returns
IndexMap<String, Link>, dropping the lossy re-key-by-target in the
AliasPackage/RootAliasPackage constructors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/shirabe/src/dependency_resolver/pool.rs | 3 | ||||
| -rw-r--r-- | crates/shirabe/src/package/alias_package.rs | 77 | ||||
| -rw-r--r-- | crates/shirabe/src/package/root_alias_package.rs | 13 |
3 files changed, 29 insertions, 64 deletions
diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index 708930c..91c3e31 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -336,9 +336,6 @@ impl Pool { let replaces = candidate.get_replaces(); // aliases create multiple replaces/provides for one target so they can not use the shortcut below - // TODO(phase-b): PHP uses isset($replaces[0])/isset($provides[0]) to detect numeric-indexed - // lists; the Rust IndexMap is string-keyed, so this branch checks the "0" key. Confirm - // semantics during Phase B review. if replaces.contains_key("0") || provides.contains_key("0") { for link in provides.values() { if link.get_target() == name diff --git a/crates/shirabe/src/package/alias_package.rs b/crates/shirabe/src/package/alias_package.rs index f4b9b55..7ab1967 100644 --- a/crates/shirabe/src/package/alias_package.rs +++ b/crates/shirabe/src/package/alias_package.rs @@ -79,51 +79,22 @@ impl AliasPackage { }; for r#type in Link::types() { - // PHP: $aliasOf->{'get' . ucfirst($type)}() - // TODO(phase-b): dynamic method dispatch — bridge each Link::TYPE_* to BasePackage getter - let links: Vec<Link> = match r#type { - Link::TYPE_REQUIRE => this.alias_of.get_requires().values().cloned().collect(), - Link::TYPE_DEV_REQUIRE => { - this.alias_of.get_dev_requires().values().cloned().collect() - } - Link::TYPE_PROVIDE => this.alias_of.get_provides().values().cloned().collect(), - Link::TYPE_CONFLICT => this.alias_of.get_conflicts().values().cloned().collect(), - Link::TYPE_REPLACE => this.alias_of.get_replaces().values().cloned().collect(), - _ => vec![], + let links: IndexMap<String, Link> = match r#type { + Link::TYPE_REQUIRE => this.alias_of.get_requires(), + Link::TYPE_DEV_REQUIRE => this.alias_of.get_dev_requires(), + Link::TYPE_PROVIDE => this.alias_of.get_provides(), + Link::TYPE_CONFLICT => this.alias_of.get_conflicts(), + Link::TYPE_REPLACE => this.alias_of.get_replaces(), + _ => unreachable!(), }; let replaced = this.replace_self_version_dependencies(links, r#type); match r#type { - Link::TYPE_REQUIRE => { - this.requires = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect(); - } - Link::TYPE_DEV_REQUIRE => { - this.dev_requires = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect(); - } - Link::TYPE_PROVIDE => { - this.provides = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect() - } - Link::TYPE_CONFLICT => { - this.conflicts = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect() - } - Link::TYPE_REPLACE => { - this.replaces = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect() - } - _ => {} + Link::TYPE_REQUIRE => this.requires = replaced, + Link::TYPE_DEV_REQUIRE => this.dev_requires = replaced, + Link::TYPE_PROVIDE => this.provides = replaced, + Link::TYPE_CONFLICT => this.conflicts = replaced, + Link::TYPE_REPLACE => this.replaces = replaced, + _ => unreachable!(), } } @@ -152,9 +123,9 @@ impl AliasPackage { /// @return Link[] pub(crate) fn replace_self_version_dependencies( &mut self, - mut links: Vec<Link>, + mut links: IndexMap<String, Link>, link_type: &str, - ) -> Vec<Link> { + ) -> IndexMap<String, Link> { // for self.version requirements, we use the original package's branch name instead, to avoid leaking the magic dev-master-alias to users let mut pretty_version = self.pretty_version.clone(); if pretty_version == VersionParser::DEFAULT_BRANCH_ALIAS { @@ -171,7 +142,7 @@ impl AliasPackage { true, ) { let mut new_links: Vec<Link> = vec![]; - for link in &links { + for link in links.values() { // link is self.version, but must be replacing also the replaced version if link.get_pretty_constraint().unwrap_or("") == "self.version" { let constraint = SimpleConstraint::new( @@ -189,11 +160,12 @@ impl AliasPackage { new_links.push(new_link); } } - links.extend(new_links); + for (index, new_link) in new_links.into_iter().enumerate() { + links.insert(index.to_string(), new_link); + } } else { - // PHP: foreach ($links as $index => $link) - for index in 0..links.len() { - if links[index].get_pretty_constraint().unwrap_or("") == "self.version" { + for link in links.values_mut() { + if link.get_pretty_constraint().unwrap_or("") == "self.version" { if link_type == Link::TYPE_REQUIRE { self.has_self_version_requires = true; } @@ -202,14 +174,13 @@ impl AliasPackage { self.version.to_string(), Some(pretty_version.clone()), ); - let new_link = Link::new( - links[index].get_source().to_string(), - links[index].get_target().to_string(), + *link = Link::new( + link.get_source().to_string(), + link.get_target().to_string(), constraint.into(), Some(link_type.to_string()), Some(pretty_version.clone()), ); - links[index] = new_link; } } } diff --git a/crates/shirabe/src/package/root_alias_package.rs b/crates/shirabe/src/package/root_alias_package.rs index d16cfc9..9f987eb 100644 --- a/crates/shirabe/src/package/root_alias_package.rs +++ b/crates/shirabe/src/package/root_alias_package.rs @@ -83,14 +83,11 @@ impl RootPackageInterface for RootAliasPackage { } fn set_requires(&mut self, requires: IndexMap<String, Link>) { - let replaced = self.inner.inner.replace_self_version_dependencies( - requires.values().cloned().collect(), - Link::TYPE_REQUIRE, - ); - self.inner.inner.requires = replaced - .into_iter() - .map(|l| (l.get_target().to_string(), l)) - .collect(); + self.inner.inner.requires = self + .inner + .inner + .replace_self_version_dependencies(requires.clone(), Link::TYPE_REQUIRE); + self.alias_of.set_requires(requires); } |
