diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-07-19 17:15:50 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-07-19 17:53:42 +0900 |
| commit | 7e84d9ea31584e0dc04f04d14f6905ab9d978c72 (patch) | |
| tree | c357e1cd4e94916d2ecf69def9dfe0462e52d07a /crates/shirabe/src | |
| parent | dca13a64c2d1007585025f6069963b76cf6c0f75 (diff) | |
| download | php-shirabe-7e84d9ea31584e0dc04f04d14f6905ab9d978c72.tar.gz php-shirabe-7e84d9ea31584e0dc04f04d14f6905ab9d978c72.tar.zst php-shirabe-7e84d9ea31584e0dc04f04d14f6905ab9d978c72.zip | |
fix(alias-package): stop delegating own-state accessors to aliasOf
AliasPackage wrongly delegated several methods (id, names, unique
name, pretty string, full pretty version, repository, __toString)
to aliasOf, but PHP's AliasPackage inherits these from BasePackage
unmodified, so they must use the alias's own state instead. This
collapsed alias and aliasOf into the same SAT literal id, breaking
the solver's alias-resolution rules; un-ignore the two solver tests
that exposed it.
Diffstat (limited to 'crates/shirabe/src')
| -rw-r--r-- | crates/shirabe/src/package/alias_package.rs | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/crates/shirabe/src/package/alias_package.rs b/crates/shirabe/src/package/alias_package.rs index 79204df7..fcefcc63 100644 --- a/crates/shirabe/src/package/alias_package.rs +++ b/crates/shirabe/src/package/alias_package.rs @@ -7,9 +7,11 @@ use crate::package::PackageHandle; use crate::package::PackageInterface; use crate::package::version::VersionParser; use crate::repository::RepositoryInterfaceHandle; +use crate::repository::RepositoryInterfaceWeakHandle; use chrono::{DateTime, Utc}; use indexmap::IndexMap; -use shirabe_php_shim::{PhpMixed, in_array}; +use indexmap::IndexSet; +use shirabe_php_shim::{LogicException, PhpMixed, in_array}; use shirabe_semver::constraint::SimpleConstraint; #[derive(Debug, Clone)] @@ -17,6 +19,8 @@ pub struct AliasPackage { id: i64, name: String, pretty_name: String, + /// Back-reference to the owning repository. `Weak` breaks the repository -> packages cycle. + repository: Option<RepositoryInterfaceWeakHandle>, /// @var string pub(crate) version: String, @@ -62,6 +66,7 @@ impl AliasPackage { id: -1, name: alias_name.to_lowercase(), pretty_name: alias_name, + repository: None, version, pretty_version, dev, @@ -195,8 +200,9 @@ impl std::fmt::Display for AliasPackage { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "{} ({}alias of {})", - self.alias_of, + "{}-{} ({}alias of {})", + self.name, + self.version, if self.root_package_alias { "root " } else { "" }, self.alias_of.get_version(), ) @@ -215,15 +221,28 @@ impl PackageInterface for AliasPackage { } fn get_names(&self, provides: bool) -> Vec<String> { - self.alias_of.get_names(provides) + let mut names: IndexSet<String> = IndexSet::new(); + names.insert(self.get_name().to_string()); + + if provides { + for link in self.provides.values() { + names.insert(link.get_target().to_string()); + } + } + + for link in self.replaces.values() { + names.insert(link.get_target().to_string()); + } + + names.into_iter().collect() } fn set_id(&mut self, id: i64) { - self.alias_of.set_id(id); + self.id = id; } fn get_id(&self) -> i64 { - self.alias_of.get_id() + self.id } fn is_dev(&self) -> bool { @@ -413,24 +432,36 @@ impl PackageInterface for AliasPackage { truncate: bool, display_mode: crate::package::DisplayMode, ) -> String { - self.alias_of - .get_full_pretty_version(truncate, display_mode) + BasePackage::get_full_pretty_version(self, truncate, display_mode) } fn get_unique_name(&self) -> String { - self.alias_of.get_unique_name() + format!("{}-{}", self.get_name(), self.get_version()) } fn get_pretty_string(&self) -> String { - self.alias_of.get_pretty_string() + format!("{} {}", self.get_pretty_name(), self.get_pretty_version()) } fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> { - self.alias_of.set_repository(repository) + if let Some(existing) = self.repository.as_ref().and_then(|w| w.upgrade()) + && !std::rc::Rc::ptr_eq(&existing, repository.as_rc()) + { + return Err(LogicException { + message: "A package can only be added to one repository".to_string(), + code: 0, + } + .into()); + } + self.repository = Some(repository.downgrade()); + Ok(()) } fn get_repository(&self) -> Option<RepositoryInterfaceHandle> { - self.alias_of.get_repository() + self.repository + .as_ref() + .and_then(|w| w.upgrade()) + .map(RepositoryInterfaceHandle::from_rc) } } @@ -460,16 +491,20 @@ impl BasePackage for AliasPackage { } fn repository_opt(&self) -> Option<RepositoryInterfaceHandle> { - // PHP `AliasPackage::getRepository()` delegates to `$this->aliasOf->getRepository()`. - self.alias_of.get_repository() + self.repository + .as_ref() + .and_then(|w| w.upgrade()) + .map(RepositoryInterfaceHandle::from_rc) } fn set_repository_box(&mut self, repository: RepositoryInterfaceHandle) { - let _ = self.alias_of.set_repository(repository); + self.repository = Some(repository.downgrade()); } fn take_repository(&mut self) -> Option<RepositoryInterfaceHandle> { - // AliasPackage holds no repository of its own; never mutate the aliased package here. - None + self.repository + .take() + .and_then(|w| w.upgrade()) + .map(RepositoryInterfaceHandle::from_rc) } } |
