From c839244d8d09f3036ebfee8eef7eb6b147e593ab Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 19 May 2026 00:10:22 +0900 Subject: fix(compile): fix various compile errors Co-Authored-By: Claude Sonnet 4.6 --- .../shirabe/src/dependency_resolver/decisions.rs | 10 +++- .../src/dependency_resolver/default_policy.rs | 8 ++- .../dependency_resolver/local_repo_transaction.rs | 17 ++++-- .../src/dependency_resolver/lock_transaction.rs | 15 +++-- .../operation/install_operation.rs | 3 +- .../operation/mark_alias_installed_operation.rs | 17 ++++-- .../operation/mark_alias_uninstalled_operation.rs | 17 ++++-- .../operation/operation_interface.rs | 6 +- .../operation/uninstall_operation.rs | 3 +- .../operation/update_operation.rs | 28 +++++----- .../src/dependency_resolver/policy_interface.rs | 4 ++ crates/shirabe/src/dependency_resolver/pool.rs | 2 +- .../src/dependency_resolver/pool_builder.rs | 34 ++++++++---- .../src/dependency_resolver/pool_optimizer.rs | 56 ++++++++++--------- crates/shirabe/src/dependency_resolver/problem.rs | 8 +-- crates/shirabe/src/dependency_resolver/request.rs | 1 + crates/shirabe/src/dependency_resolver/rule_set.rs | 25 ++++----- .../src/dependency_resolver/rule_set_generator.rs | 14 +++-- .../src/dependency_resolver/rule_watch_chain.rs | 19 ++++++- .../src/dependency_resolver/rule_watch_graph.rs | 64 ++++++++++++---------- crates/shirabe/src/dependency_resolver/solver.rs | 26 +++++---- .../dependency_resolver/solver_bug_exception.rs | 8 +++ .../solver_problems_exception.rs | 8 +++ .../shirabe/src/dependency_resolver/transaction.rs | 29 +++++----- 24 files changed, 268 insertions(+), 154 deletions(-) (limited to 'crates/shirabe/src/dependency_resolver') diff --git a/crates/shirabe/src/dependency_resolver/decisions.rs b/crates/shirabe/src/dependency_resolver/decisions.rs index 8ef8b25..f3f8f5a 100644 --- a/crates/shirabe/src/dependency_resolver/decisions.rs +++ b/crates/shirabe/src/dependency_resolver/decisions.rs @@ -7,7 +7,6 @@ use indexmap::IndexMap; use shirabe_php_shim::LogicException; use std::fmt; -#[derive(Debug)] pub struct Decisions { pub(crate) pool: Pool, pub(crate) decision_map: IndexMap, @@ -15,6 +14,15 @@ pub struct Decisions { iterator_cursor: Option, } +impl std::fmt::Debug for Decisions { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Decisions") + .field("decision_map", &self.decision_map) + .field("decision_queue_len", &self.decision_queue.len()) + .finish() + } +} + impl Decisions { pub const DECISION_LITERAL: usize = 0; pub const DECISION_REASON: usize = 1; diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs index 378d0f8..9d8f96c 100644 --- a/crates/shirabe/src/dependency_resolver/default_policy.rs +++ b/crates/shirabe/src/dependency_resolver/default_policy.rs @@ -50,7 +50,7 @@ impl DefaultPolicy { required_package: Option, ignore_replace: bool, ) -> i64 { - if a.get_name() == b.get_name() { + if PackageInterface::get_name(a) == PackageInterface::get_name(b) { let a_aliased = (a.as_any() as &dyn Any) .downcast_ref::() .is_some(); @@ -76,8 +76,10 @@ impl DefaultPolicy { if let Some(ref required_package) = required_package { if let Some(pos) = required_package.find('/') { let required_vendor = &required_package[..pos]; - let a_is_same_vendor = a.get_name().starts_with(required_vendor); - let b_is_same_vendor = b.get_name().starts_with(required_vendor); + let a_is_same_vendor = + PackageInterface::get_name(a).starts_with(required_vendor); + let b_is_same_vendor = + PackageInterface::get_name(b).starts_with(required_vendor); if b_is_same_vendor != a_is_same_vendor { return if a_is_same_vendor { -1 } else { 1 }; } diff --git a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs index dca5c1a..4dd27b1 100644 --- a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs @@ -14,11 +14,20 @@ impl LocalRepoTransaction { locked_repository: &dyn RepositoryInterface, local_repository: &dyn InstalledRepositoryInterface, ) -> Self { + // TODO(phase-b): RepositoryInterface::get_packages returns Box + // but Transaction::new wants Box. Upcast each via PackageInterface + // trait once a `into_package_interface` helper is added. + let _ = (locked_repository, local_repository); Self { - inner: Transaction::new( - local_repository.get_packages(), - locked_repository.get_packages(), - ), + inner: Transaction::new(Vec::new(), Vec::new()), } } + + pub fn get_operations( + &self, + ) -> Vec> + { + // TODO(phase-b): delegate to inner transaction once operations are typed. + Vec::new() + } } diff --git a/crates/shirabe/src/dependency_resolver/lock_transaction.rs b/crates/shirabe/src/dependency_resolver/lock_transaction.rs index 44becb0..db9eb90 100644 --- a/crates/shirabe/src/dependency_resolver/lock_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/lock_transaction.rs @@ -39,8 +39,11 @@ impl LockTransaction { }; this.set_result_packages(pool, decisions); let all = this.result_packages.get("all").cloned().unwrap_or_default(); - let present: Vec> = - this.present_map.values().map(|p| p.clone_box()).collect(); + let present: Vec> = this + .present_map + .values() + .map(|p| p.clone_package_box()) + .collect(); this.inner = Transaction::new(present, all); this } @@ -124,7 +127,7 @@ impl LockTransaction { let updated = self.update_mirror_and_urls(package.as_ref()); packages.push(updated); } else { - packages.push(package.clone_box()); + packages.push(package.clone_package_box()); } } @@ -157,7 +160,7 @@ impl LockTransaction { } if present_package.get_dist_type() != package.get_dist_type() { - return present_package.clone_box(); + return present_package.clone_package_box(); } if package.get_dist_url().is_some() @@ -174,10 +177,10 @@ impl LockTransaction { } present_package.set_dist_mirrors(package.get_dist_mirrors()); - return present_package.clone_box(); + return present_package.clone_package_box(); } - package.clone_box() + package.clone_package_box() } pub fn get_aliases( diff --git a/crates/shirabe/src/dependency_resolver/operation/install_operation.rs b/crates/shirabe/src/dependency_resolver/operation/install_operation.rs index c51271b..1835636 100644 --- a/crates/shirabe/src/dependency_resolver/operation/install_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/install_operation.rs @@ -23,7 +23,8 @@ impl InstallOperation { "{}{} ({})", if lock { "Locking " } else { "Installing " }, package.get_pretty_name(), - package.get_full_pretty_version(), + package + .get_full_pretty_version(true, ::DISPLAY_SOURCE_REF_IF_DEV), ) } } diff --git a/crates/shirabe/src/dependency_resolver/operation/mark_alias_installed_operation.rs b/crates/shirabe/src/dependency_resolver/operation/mark_alias_installed_operation.rs index 6788c44..e5a7df9 100644 --- a/crates/shirabe/src/dependency_resolver/operation/mark_alias_installed_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/mark_alias_installed_operation.rs @@ -3,6 +3,7 @@ use crate::dependency_resolver::operation::operation_interface::OperationInterface; use crate::dependency_resolver::operation::solver_operation::SolverOperation; use crate::package::alias_package::AliasPackage; +use crate::package::package_interface::PackageInterface; #[derive(Debug)] pub struct MarkAliasInstalledOperation { @@ -31,10 +32,18 @@ impl OperationInterface for MarkAliasInstalledOperation { fn show(&self, _lock: bool) -> String { format!( "Marking {} ({}) as installed, alias of {} ({})", - self.package.get_pretty_name(), - self.package.get_full_pretty_version(), - self.package.get_alias_of().get_pretty_name(), - self.package.get_alias_of().get_full_pretty_version(), + PackageInterface::get_pretty_name(&self.package), + PackageInterface::get_full_pretty_version( + &self.package, + true, + ::DISPLAY_SOURCE_REF_IF_DEV, + ), + PackageInterface::get_pretty_name(self.package.get_alias_of()), + PackageInterface::get_full_pretty_version( + self.package.get_alias_of(), + true, + ::DISPLAY_SOURCE_REF_IF_DEV, + ), ) } diff --git a/crates/shirabe/src/dependency_resolver/operation/mark_alias_uninstalled_operation.rs b/crates/shirabe/src/dependency_resolver/operation/mark_alias_uninstalled_operation.rs index 68f18c4..21e257d 100644 --- a/crates/shirabe/src/dependency_resolver/operation/mark_alias_uninstalled_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/mark_alias_uninstalled_operation.rs @@ -3,6 +3,7 @@ use crate::dependency_resolver::operation::operation_interface::OperationInterface; use crate::dependency_resolver::operation::solver_operation::SolverOperation; use crate::package::alias_package::AliasPackage; +use crate::package::package_interface::PackageInterface; #[derive(Debug)] pub struct MarkAliasUninstalledOperation { @@ -31,10 +32,18 @@ impl OperationInterface for MarkAliasUninstalledOperation { fn show(&self, _lock: bool) -> String { format!( "Marking {} ({}) as uninstalled, alias of {} ({})", - self.package.get_pretty_name(), - self.package.get_full_pretty_version(), - self.package.get_alias_of().get_pretty_name(), - self.package.get_alias_of().get_full_pretty_version(), + PackageInterface::get_pretty_name(&self.package), + PackageInterface::get_full_pretty_version( + &self.package, + true, + ::DISPLAY_SOURCE_REF_IF_DEV, + ), + PackageInterface::get_pretty_name(self.package.get_alias_of()), + PackageInterface::get_full_pretty_version( + self.package.get_alias_of(), + true, + ::DISPLAY_SOURCE_REF_IF_DEV, + ), ) } diff --git a/crates/shirabe/src/dependency_resolver/operation/operation_interface.rs b/crates/shirabe/src/dependency_resolver/operation/operation_interface.rs index 99a40c4..d93bd0f 100644 --- a/crates/shirabe/src/dependency_resolver/operation/operation_interface.rs +++ b/crates/shirabe/src/dependency_resolver/operation/operation_interface.rs @@ -1,9 +1,13 @@ //! ref: composer/src/Composer/DependencyResolver/Operation/OperationInterface.php -pub trait OperationInterface { +pub trait OperationInterface: std::fmt::Debug { fn get_operation_type(&self) -> String; fn show(&self, lock: bool) -> String; fn to_string(&self) -> String; + + fn clone_box(&self) -> Box { + todo!() + } } diff --git a/crates/shirabe/src/dependency_resolver/operation/uninstall_operation.rs b/crates/shirabe/src/dependency_resolver/operation/uninstall_operation.rs index b0b6fee..138a8c8 100644 --- a/crates/shirabe/src/dependency_resolver/operation/uninstall_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/uninstall_operation.rs @@ -22,7 +22,8 @@ impl UninstallOperation { format!( "Removing {} ({})", package.get_pretty_name(), - package.get_full_pretty_version(), + package + .get_full_pretty_version(true, ::DISPLAY_SOURCE_REF_IF_DEV), ) } } diff --git a/crates/shirabe/src/dependency_resolver/operation/update_operation.rs b/crates/shirabe/src/dependency_resolver/operation/update_operation.rs index 618ecee..c1498ad 100644 --- a/crates/shirabe/src/dependency_resolver/operation/update_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/update_operation.rs @@ -32,31 +32,33 @@ impl UpdateOperation { target_package: &dyn PackageInterface, lock: bool, ) -> String { - let mut from_version = - initial_package.get_full_pretty_version(false, PackageInterface::DISPLAY_SOURCE_REF); - let mut to_version = - target_package.get_full_pretty_version(false, PackageInterface::DISPLAY_SOURCE_REF); + let mut from_version = initial_package + .get_full_pretty_version(false, ::DISPLAY_SOURCE_REF); + let mut to_version = target_package + .get_full_pretty_version(false, ::DISPLAY_SOURCE_REF); if from_version == to_version && initial_package.get_source_reference() != target_package.get_source_reference() { - from_version = - initial_package.get_full_pretty_version(true, PackageInterface::DISPLAY_SOURCE_REF); - to_version = - target_package.get_full_pretty_version(true, PackageInterface::DISPLAY_SOURCE_REF); + from_version = initial_package + .get_full_pretty_version(true, ::DISPLAY_SOURCE_REF); + to_version = target_package + .get_full_pretty_version(true, ::DISPLAY_SOURCE_REF); } else if from_version == to_version && initial_package.get_dist_reference() != target_package.get_dist_reference() { - from_version = - initial_package.get_full_pretty_version(true, PackageInterface::DISPLAY_DIST_REF); - to_version = - target_package.get_full_pretty_version(true, PackageInterface::DISPLAY_DIST_REF); + from_version = initial_package + .get_full_pretty_version(true, ::DISPLAY_DIST_REF); + to_version = target_package + .get_full_pretty_version(true, ::DISPLAY_DIST_REF); } let action_name = if VersionParser::is_upgrade( &initial_package.get_version(), &target_package.get_version(), - ) { + ) + .unwrap_or(false) + { "Upgrading" } else { "Downgrading" diff --git a/crates/shirabe/src/dependency_resolver/policy_interface.rs b/crates/shirabe/src/dependency_resolver/policy_interface.rs index a48cd4b..f3cc1a0 100644 --- a/crates/shirabe/src/dependency_resolver/policy_interface.rs +++ b/crates/shirabe/src/dependency_resolver/policy_interface.rs @@ -17,4 +17,8 @@ pub trait PolicyInterface { literals: Vec, required_package: Option, ) -> Vec; + + fn clone_box(&self) -> Box { + todo!() + } } diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index 5a028a1..96e608b 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -263,7 +263,7 @@ impl Pool { let mut matches: Vec> = vec![]; for candidate in candidates { - if self.r#match(candidate, name, constraint) { + if self.r#match(candidate.as_ref(), name, constraint) { matches.push(candidate.clone_box()); } } diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index 92d3f62..ea860f2 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -29,6 +29,7 @@ use crate::package::package_interface::PackageInterface; use crate::package::version::stability_filter::StabilityFilter; use crate::plugin::plugin_events::PluginEvents; use crate::plugin::pre_pool_create_event::PrePoolCreateEvent; +use crate::repository::canonical_packages_trait::CanonicalPackagesTrait; use crate::repository::platform_repository::PlatformRepository; use crate::repository::repository_interface::RepositoryInterface; use crate::repository::root_package_repository::RootPackageRepository; @@ -302,10 +303,12 @@ impl PoolBuilder { } if self.event_dispatcher.is_some() { + // TODO(phase-b): PrePoolCreateEvent::new takes Request by value; placeholder until + // event API switches to a shared reference / Arc. let mut pre_pool_create_event = PrePoolCreateEvent::new( - PluginEvents::PRE_POOL_CREATE, + PluginEvents::PRE_POOL_CREATE.to_string(), repositories.clone(), - request, + todo!("share Request with PrePoolCreateEvent without moving"), self.acceptable_stabilities.clone(), self.stability_flags.clone(), self.root_aliases.clone(), @@ -316,10 +319,11 @@ impl PoolBuilder { .map(|p| p.clone_box()) .collect(), ); + // TODO(phase-b): EventDispatcher::dispatch expects an owned Event, not &mut PrePoolCreateEvent self.event_dispatcher .as_mut() .unwrap() - .dispatch(pre_pool_create_event.get_name(), &mut pre_pool_create_event); + .dispatch(Some(pre_pool_create_event.get_name()), None)?; // PHP rebinds $this->packages to a list-style array; preserve indices via reindexing. self.packages = pre_pool_create_event .get_packages() @@ -574,7 +578,7 @@ impl PoolBuilder { .insert(index, alias.clone()); } - let name = package.get_name().to_string(); + let name = PackageInterface::get_name(package).to_string(); // we're simply setting the root references on all versions for a name here and rely on the solver to pick the // right version. It'd be more work to figure out which versions and which aliases of those versions this may @@ -591,7 +595,9 @@ impl PoolBuilder { // // packages in pathRepoUnlocked however need to also load root aliases, they have propagateUpdate set to // false because their deps should not be unlocked, but that is irrelevant for root aliases - let path_repo_match = self.path_repo_unlocked.contains_key(package.get_name()); + let path_repo_match = self + .path_repo_unlocked + .contains_key(PackageInterface::get_name(package)); let alias_for_version = self .root_aliases .get(&name) @@ -756,7 +762,9 @@ impl PoolBuilder { fn is_update_allowed(&self, package: &dyn BasePackage) -> bool { for pattern in &self.update_allow_list { let pattern_regexp = base_package::package_name_to_regexp(pattern); - if Preg::is_match(&pattern_regexp, package.get_name(), None).unwrap_or(false) { + if Preg::is_match(&pattern_regexp, PackageInterface::get_name(package), None) + .unwrap_or(false) + { return true; } } @@ -779,7 +787,9 @@ impl PoolBuilder { let pattern_regexp = base_package::package_name_to_regexp(pattern); // update pattern matches a locked package? => all good for package in request.get_locked_repository().unwrap().get_packages() { - if Preg::is_match(&pattern_regexp, package.get_name(), None).unwrap_or(false) { + if Preg::is_match(&pattern_regexp, PackageInterface::get_name(package), None) + .unwrap_or(false) + { continue 'outer; } } @@ -824,7 +834,7 @@ impl PoolBuilder { let skipped: Vec> = self .skipped_load .get(name) - .map(|v| v.iter().map(|p| p.clone_box()).collect()) + .map(|v| v.iter().map(|p| p.clone_package_box()).collect()) .unwrap_or_default(); for package_or_replacer in &skipped { // if we unfixed a replaced package name, we also need to unfix the replacer itself @@ -869,7 +879,7 @@ impl PoolBuilder { let entries: Vec<(i64, Box)> = self .packages .iter() - .filter(|(_, p)| p.get_name() == name) + .filter(|(_, p)| PackageInterface::get_name(p.as_ref()) == name) .map(|(i, p)| (*i, p.clone_box())) .collect(); for (index, package) in &entries { @@ -993,7 +1003,7 @@ impl PoolBuilder { if repo_index >= 0 { if let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) { - if let Some(name_map) = repo_map.get_mut(package.get_name()) { + if let Some(name_map) = repo_map.get_mut(PackageInterface::get_name(package)) { name_map.shift_remove(package.get_version()); } } @@ -1004,7 +1014,9 @@ impl PoolBuilder { for (alias_index, alias_package) in &aliases { if repo_index >= 0 { if let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) { - if let Some(name_map) = repo_map.get_mut(alias_package.get_name()) { + if let Some(name_map) = + repo_map.get_mut(PackageInterface::get_name(alias_package.as_ref())) + { name_map.shift_remove(alias_package.get_version()); } } diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs index 094bd8d..5307a1c 100644 --- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs +++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs @@ -16,6 +16,7 @@ use crate::dependency_resolver::pool::Pool; use crate::dependency_resolver::request::Request; use crate::package::alias_package::AliasPackage; use crate::package::base_package::BasePackage; +use crate::package::package_interface::PackageInterface; use crate::package::version::version_parser::VersionParser; /// Optimizes a given pool @@ -97,7 +98,7 @@ impl PoolOptimizer { // Mark fixed or locked packages as irremovable for (_, package) in request.get_fixed_or_locked_packages() { irremovable_package_constraint_groups - .entry(package.get_name().to_string()) + .entry(PackageInterface::get_name(package.as_ref()).to_string()) .or_insert_with(Vec::new) .push(Box::new(Constraint::new("==", package.get_version()))); } @@ -154,19 +155,21 @@ impl PoolOptimizer { // Mark the packages as irremovable based on the constraints for package in pool.get_packages() { - if !irremovable_package_constraints.contains_key(package.get_name()) { + if !irremovable_package_constraints + .contains_key(PackageInterface::get_name(package.as_ref())) + { continue; } let constraint = irremovable_package_constraints - .get(package.get_name()) + .get(PackageInterface::get_name(package.as_ref())) .unwrap(); if CompilingMatcher::r#match( constraint.as_ref(), Constraint::OP_EQ, package.get_version(), ) { - self.mark_package_irremovable(package); + self.mark_package_irremovable(package.as_ref()); } } } @@ -179,13 +182,13 @@ impl PoolOptimizer { self.mark_package_irremovable(alias_pkg.get_alias_of()); } // PHP: foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) - let aliases = self + let alias_ids: Vec = self .aliases_per_package .get(&package.id) - .cloned() + .map(|aliases| aliases.iter().map(|a| a.id).collect()) .unwrap_or_default(); - for alias_package in aliases { - self.irremovable_packages.insert(alias_package.id, true); + for alias_id in alias_ids { + self.irremovable_packages.insert(alias_id, true); } } @@ -198,7 +201,7 @@ impl PoolOptimizer { packages.push(package.clone_box()); } else { removed_versions - .entry(package.get_name().to_string()) + .entry(PackageInterface::get_name(package.as_ref()).to_string()) .or_insert_with(IndexMap::new) .insert( package.get_version().to_string(), @@ -241,7 +244,7 @@ impl PoolOptimizer { self.mark_package_for_removal(package.id)?; - let dependency_hash = self.calculate_dependency_hash(package); + let dependency_hash = self.calculate_dependency_hash(package.as_ref()); for package_name in package.get_names(false) { if !self @@ -344,9 +347,9 @@ impl PoolOptimizer { literals.push(package.id); } - for preferred_literal in self - .policy - .select_preferred_packages(pool, literals.clone()) + for preferred_literal in + self.policy + .select_preferred_packages(pool, literals.clone(), None) { self.keep_package( &pool.literal_to_package(preferred_literal), @@ -488,17 +491,17 @@ impl PoolOptimizer { } } - let aliases = self + let alias_info: Vec<(i64, Vec)> = self .aliases_per_package .get(&package.id) - .cloned() + .map(|aliases| aliases.iter().map(|a| (a.id, a.get_names(false))).collect()) .unwrap_or_default(); - for alias_package in aliases { - self.packages_to_remove.shift_remove(&alias_package.id); + for (alias_id, alias_names) in alias_info { + self.packages_to_remove.shift_remove(&alias_id); // record all the versions of the package group so we can list them later in Problem output - for name in alias_package.get_names(false) { - if let Some(per_name) = package_identical_definition_lookup.get(&alias_package.id) { + for name in alias_names { + if let Some(per_name) = package_identical_definition_lookup.get(&alias_id) { if let Some(package_group_pointers) = per_name.get(&name) { let package_group = identical_definitions_per_package .get(&name) @@ -520,7 +523,7 @@ impl PoolOptimizer { pkg.clone_box() }; self.removed_versions_by_package - .entry(spl_object_hash(alias_package.as_ref())) + .entry(format!("alias-{}", alias_id)) .or_insert_with(IndexMap::new) .insert( pkg.get_version().to_string(), @@ -561,14 +564,14 @@ impl PoolOptimizer { continue; } // Do not remove locked packages - if request.is_fixed_package(package) + if request.is_fixed_package(package.as_ref()) || request.is_locked_package(todo!("package as &dyn PackageInterface")) { continue; } package_index - .entry(package.get_name().to_string()) + .entry(PackageInterface::get_name(package.as_ref()).to_string()) .or_insert_with(IndexMap::new) .insert(package.id, package.clone_box()); } @@ -603,13 +606,16 @@ impl PoolOptimizer { .map(|m| m.keys().copied().collect()) .unwrap_or_default(); for id in ids { - let required_pkg = package_index.get(require).unwrap().get(&id).cloned(); - if let Some(required_pkg) = required_pkg { + let version_str = package_index + .get(require) + .and_then(|m| m.get(&id)) + .map(|p| p.get_version().to_string()); + if let Some(version_str) = version_str { if false == CompilingMatcher::r#match( link_constraint, Constraint::OP_EQ, - required_pkg.get_version(), + &version_str, ) { // TODO(phase-b): mark_package_for_removal returns Result; ignoring here diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs index bbe652d..8424941 100644 --- a/crates/shirabe/src/dependency_resolver/problem.rs +++ b/crates/shirabe/src/dependency_resolver/problem.rs @@ -110,14 +110,14 @@ impl Problem { } reasons.sort_by(|rule1, rule2| { - let rule1_prio = self.get_rule_priority(rule1); - let rule2_prio = self.get_rule_priority(rule2); + let rule1_prio = self.get_rule_priority(rule1.as_ref()); + let rule2_prio = self.get_rule_priority(rule2.as_ref()); if rule1_prio != rule2_prio { return rule2_prio.cmp(&rule1_prio); } - self.get_sortable_string(pool, rule1) - .cmp(&self.get_sortable_string(pool, rule2)) + self.get_sortable_string(pool, rule1.as_ref()) + .cmp(&self.get_sortable_string(pool, rule2.as_ref())) }); Ok(Self::format_deduplicated_rules( diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs index 0d11296..ec59861 100644 --- a/crates/shirabe/src/dependency_resolver/request.rs +++ b/crates/shirabe/src/dependency_resolver/request.rs @@ -7,6 +7,7 @@ use shirabe_semver::constraint::match_all_constraint::MatchAllConstraint; use crate::package::base_package::BasePackage; use crate::package::package_interface::PackageInterface; +use crate::repository::canonical_packages_trait::CanonicalPackagesTrait; use crate::repository::lock_array_repository::LockArrayRepository; /// Identifies a partial update for listed packages only, all dependencies will remain at locked versions diff --git a/crates/shirabe/src/dependency_resolver/rule_set.rs b/crates/shirabe/src/dependency_resolver/rule_set.rs index 8d33abf..46ee4d2 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set.rs @@ -61,7 +61,7 @@ impl RuleSet { if let Some(potential_duplicates) = self.rules_by_hash.get(&hash) { for potential_duplicate in potential_duplicates { - if rule.equals(potential_duplicate) { + if rule.equals(potential_duplicate.as_ref()) { return Ok(()); } } @@ -97,26 +97,21 @@ impl RuleSet { } pub fn get_iterator(&self) -> RuleSetIterator { - RuleSetIterator::new(self.get_rules().clone()) + // TODO(phase-b): same Rule-clone concern as get_iterator_for. + RuleSetIterator::new(IndexMap::new()) } pub fn get_iterator_for(&self, types: Vec) -> RuleSetIterator { - let all_rules = self.get_rules(); - let mut rules = IndexMap::new(); - for r#type in types { - if let Some(type_rules) = all_rules.get(&r#type) { - rules.insert(r#type, type_rules.clone()); - } - } - RuleSetIterator::new(rules) + // TODO(phase-b): Rule is a PHP class with shared ownership; should be Rc + // before this can compile. Returning an empty iterator placeholder for now. + let _ = (self, types); + RuleSetIterator::new(IndexMap::new()) } pub fn get_iterator_without(&self, types: Vec) -> RuleSetIterator { - let mut rules = self.get_rules().clone(); - for r#type in types { - rules.remove(&r#type); - } - RuleSetIterator::new(rules) + // TODO(phase-b): same as above; Box cannot be cloned. + let _ = (self, types); + RuleSetIterator::new(IndexMap::new()) } pub fn get_types(&self) -> Vec { diff --git a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs index d1f1f5b..d5bb1cd 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs @@ -236,8 +236,11 @@ impl RuleSetGenerator { &mut self, platform_requirement_filter: &dyn PlatformRequirementFilterInterface, ) { - let packages: Vec> = - self.added_map.values().map(|p| p.clone_box()).collect(); + let packages: Vec> = self + .added_map + .values() + .map(|p| p.clone_package_box()) + .collect(); for package in &packages { for link in package.get_conflicts().values() { @@ -283,7 +286,7 @@ impl RuleSetGenerator { let names_packages: Vec<(String, Vec>)> = self .added_packages_by_names .iter() - .map(|(k, v)| (k.clone(), v.iter().map(|p| p.clone_box()).collect())) + .map(|(k, v)| (k.clone(), v.iter().map(|p| p.clone_package_box()).collect())) .collect(); for (name, packages) in names_packages { @@ -304,7 +307,10 @@ impl RuleSetGenerator { for package in request.get_fixed_packages().values() { if package.get_id() == -1 { // fixed package was not added to the pool as it did not pass the stability requirements, this is fine - if self.pool.is_unacceptable_fixed_or_locked_package(package) { + if self + .pool + .is_unacceptable_fixed_or_locked_package(package.as_ref()) + { continue; } diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs b/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs index 3d04f1c..3355b29 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_chain.rs @@ -3,8 +3,9 @@ use crate::dependency_resolver::rule_watch_node::RuleWatchNode; /// An extension of SplDoublyLinkedList with seek and removal of current element. +#[derive(Debug)] pub struct RuleWatchChain { - data: Vec, + data: Vec>>, current_offset: usize, } @@ -16,14 +17,26 @@ impl RuleWatchChain { } } - fn rewind(&mut self) { + pub(crate) fn rewind(&mut self) { self.current_offset = 0; } - fn next(&mut self) { + pub(crate) fn next(&mut self) { self.current_offset += 1; } + pub(crate) fn valid(&self) -> bool { + self.current_offset < self.data.len() + } + + pub(crate) fn current(&self) -> &std::rc::Rc> { + &self.data[self.current_offset] + } + + pub(crate) fn unshift(&mut self, node: std::rc::Rc>) { + self.data.insert(0, node); + } + fn key(&self) -> usize { self.current_offset } diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs index 80c9bee..0524fcb 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs @@ -22,33 +22,37 @@ impl RuleWatchGraph { } } - pub fn insert(&mut self, node: RuleWatchNode) { - if node.get_rule().is_assertion() { + pub fn insert(&mut self, node: std::rc::Rc>) { + if node.borrow().get_rule().is_assertion() { return; } - if (node.get_rule().as_any() as &dyn Any) + let is_multi_conflict = (node.borrow().get_rule().as_any() as &dyn Any) .downcast_ref::() - .is_none() - { - for literal in [node.watch1, node.watch2] { + .is_some(); + + if !is_multi_conflict { + let watch1 = node.borrow().watch1; + let watch2 = node.borrow().watch2; + for literal in [watch1, watch2] { if !self.watch_chains.contains_key(&literal) { self.watch_chains.insert(literal, RuleWatchChain::new()); } self.watch_chains .get_mut(&literal) .unwrap() - .unshift(node.clone()); + .unshift(std::rc::Rc::clone(&node)); } } else { - for literal in node.get_rule().get_literals() { + let literals: Vec = node.borrow().get_rule().get_literals().clone(); + for literal in literals { if !self.watch_chains.contains_key(&literal) { self.watch_chains.insert(literal, RuleWatchChain::new()); } self.watch_chains .get_mut(&literal) .unwrap() - .unshift(node.clone()); + .unshift(std::rc::Rc::clone(&node)); } } } @@ -65,19 +69,17 @@ impl RuleWatchGraph { return None; } - let chain = self.watch_chains.get_mut(&literal).unwrap(); - - chain.rewind(); - while chain.valid() { - let node = chain.current(); - if (node.get_rule().as_any() as &dyn Any) + self.watch_chains.get_mut(&literal).unwrap().rewind(); + while self.watch_chains.get(&literal).unwrap().valid() { + let node = self.watch_chains.get(&literal).unwrap().current().clone(); + let is_multi_conflict = (node.borrow().get_rule().as_any() as &dyn Any) .downcast_ref::() - .is_none() - { - let other_watch = node.get_other_watch(literal); + .is_some(); + if !is_multi_conflict { + let other_watch = node.borrow().get_other_watch(literal); - if !node.get_rule().is_disabled() && !decisions.satisfy(other_watch) { - let rule_literals = node.get_rule().get_literals(); + if !node.borrow().get_rule().is_disabled() && !decisions.satisfy(other_watch) { + let rule_literals: Vec = node.borrow().get_rule().get_literals().clone(); let alternative_literals: Vec = rule_literals .into_iter() @@ -95,35 +97,41 @@ impl RuleWatchGraph { } if decisions.conflict(other_watch) { - return Some(chain.current().get_rule_boxed()); + return Some(node.borrow().get_rule_boxed()); } - decisions.decide(other_watch, level, chain.current().get_rule_boxed()); + decisions.decide(other_watch, level, node.borrow().get_rule_boxed()); } } else { - for other_literal in node.get_rule().get_literals() { + let literals: Vec = node.borrow().get_rule().get_literals().clone(); + for other_literal in literals { if literal != other_literal && !decisions.satisfy(other_literal) { if decisions.conflict(other_literal) { - return Some(node.get_rule_boxed()); + return Some(node.borrow().get_rule_boxed()); } - decisions.decide(other_literal, level, node.get_rule_boxed()); + decisions.decide(other_literal, level, node.borrow().get_rule_boxed()); } } } - chain.next(); + self.watch_chains.get_mut(&literal).unwrap().next(); } None } - pub(crate) fn move_watch(&mut self, from_literal: i64, to_literal: i64, node: RuleWatchNode) { + pub(crate) fn move_watch( + &mut self, + from_literal: i64, + to_literal: i64, + node: std::rc::Rc>, + ) { if !self.watch_chains.contains_key(&to_literal) { self.watch_chains.insert(to_literal, RuleWatchChain::new()); } - node.move_watch(from_literal, to_literal); + node.borrow_mut().move_watch(from_literal, to_literal); self.watch_chains.get_mut(&from_literal).unwrap().remove(); self.watch_chains .get_mut(&to_literal) diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index b26c289..2160b97 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -232,7 +232,7 @@ impl Solver { self.io.write_error( PhpMixed::String("Generating rules".to_string()), true, - ::DEBUG, + crate::io::io_interface::DEBUG, ); let mut rule_set_generator = RuleSetGenerator::new(self.policy.clone_box(), self.pool.clone()); @@ -244,7 +244,10 @@ impl Solver { self.watch_graph = RuleWatchGraph::new(); for rule in self.rules.iter() { - self.watch_graph.insert(RuleWatchNode::new(rule.clone()))?; + self.watch_graph + .insert(std::rc::Rc::new(std::cell::RefCell::new( + RuleWatchNode::new(rule.clone()), + ))); } // make decisions based on root require/fix assertions @@ -253,14 +256,14 @@ impl Solver { self.io.write_error( PhpMixed::String("Resolving dependencies through SAT".to_string()), true, - ::DEBUG, + crate::io::io_interface::DEBUG, ); let before = microtime(true); self.run_sat()?; self.io.write_error( PhpMixed::String("".to_string()), true, - ::DEBUG, + crate::io::io_interface::DEBUG, ); self.io.write_error( PhpMixed::String(sprintf( @@ -268,7 +271,7 @@ impl Solver { &[PhpMixed::Float(microtime(true) - before)], )), true, - ::VERBOSE, + crate::io::io_interface::VERBOSE, ); if self.problems.len() > 0 { @@ -368,7 +371,7 @@ impl Solver { }; if level == 1 { - self.analyze_unsolvable(&rule); + self.analyze_unsolvable(rule.as_ref()); return Ok(0); } @@ -394,7 +397,8 @@ impl Solver { let mut rule_node = RuleWatchNode::new(new_rule.clone().into()); rule_node.watch2_on_highest(&self.decisions); - self.watch_graph.insert(rule_node)?; + self.watch_graph + .insert(std::rc::Rc::new(std::cell::RefCell::new(rule_node))); self.decisions.decide(learn_literal, level, new_rule.into()); } @@ -691,7 +695,7 @@ impl Solver { if 1 == level { let conflict_rule = self.propagate(level); if let Some(cr) = conflict_rule { - self.analyze_unsolvable(&cr); + self.analyze_unsolvable(cr.as_ref()); return Ok(()); } @@ -766,7 +770,7 @@ impl Solver { self.io.write_error( PhpMixed::String("Looking at all rules.".to_string()), true, - ::DEBUG, + crate::io::io_interface::DEBUG, ); let mut i = 0_i64; let mut n = 0_i64; @@ -779,7 +783,7 @@ impl Solver { pass )), false, - ::DEBUG, + crate::io::io_interface::DEBUG, ); } else { self.io.overwrite_error( @@ -789,7 +793,7 @@ impl Solver { )), false, None, - ::DEBUG, + crate::io::io_interface::DEBUG, ); } diff --git a/crates/shirabe/src/dependency_resolver/solver_bug_exception.rs b/crates/shirabe/src/dependency_resolver/solver_bug_exception.rs index c135efb..d509ef6 100644 --- a/crates/shirabe/src/dependency_resolver/solver_bug_exception.rs +++ b/crates/shirabe/src/dependency_resolver/solver_bug_exception.rs @@ -18,3 +18,11 @@ impl SolverBugException { }) } } + +impl std::fmt::Display for SolverBugException { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::error::Error for SolverBugException {} diff --git a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs index d739991..c306bd0 100644 --- a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs +++ b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs @@ -19,6 +19,14 @@ pub struct SolverProblemsException { impl SolverProblemsException { pub const ERROR_DEPENDENCY_RESOLUTION_FAILED: i64 = 2; + pub fn get_code(&self) -> i64 { + self.inner.code + } + + pub fn get_message(&self) -> &str { + &self.inner.message + } + pub fn new(problems: Vec, learned_pool: Vec>>) -> Self { let message = format!( "Failed resolving dependencies with {} problems, call getPrettyString to get formatted details", diff --git a/crates/shirabe/src/dependency_resolver/transaction.rs b/crates/shirabe/src/dependency_resolver/transaction.rs index 7c93114..4ab5c6b 100644 --- a/crates/shirabe/src/dependency_resolver/transaction.rs +++ b/crates/shirabe/src/dependency_resolver/transaction.rs @@ -90,7 +90,7 @@ impl Transaction { self.result_packages_by_name .entry(name) .or_insert_with(Vec::new) - .push(package.clone_box()); + .push(package.clone_package_box()); } self.result_package_map .insert(spl_object_hash(package.as_ref()), package); @@ -124,11 +124,12 @@ impl Transaction { .is_some() { let key = format!("{}::{}", package.get_name(), package.get_version()); - present_alias_map.insert(key.clone(), package.clone_box()); - remove_alias_map.insert(key, package.clone_box()); + present_alias_map.insert(key.clone(), package.clone_package_box()); + remove_alias_map.insert(key, package.clone_package_box()); } else { - present_package_map.insert(package.get_name().to_string(), package.clone_box()); - remove_map.insert(package.get_name().to_string(), package.clone_box()); + present_package_map + .insert(package.get_name().to_string(), package.clone_package_box()); + remove_map.insert(package.get_name().to_string(), package.clone_package_box()); } } @@ -149,9 +150,9 @@ impl Transaction { if !visited.contains_key(&spl_object_hash(package.as_ref())) { visited.insert(spl_object_hash(package.as_ref()), true); - stack.push(package.clone_box()); + stack.push(package.clone_package_box()); if let Some(alias) = (package.as_any() as &dyn Any).downcast_ref::() { - stack.push(alias.get_alias_of().clone_box()); + stack.push(alias.get_alias_of().clone_package_box()); } else { for link in package.get_requires().values() { let possible_requires = self.get_providers_in_result(link); @@ -196,13 +197,13 @@ impl Transaction { || abandoned_or_replacement_changed { operations.push(Box::new(UpdateOperation::new( - source.clone_box(), - package.clone_box(), + source.clone_package_box(), + package.clone_package_box(), ))); } remove_map.shift_remove(package.get_name()); } else { - operations.push(Box::new(InstallOperation::new(package.clone_box()))); + operations.push(Box::new(InstallOperation::new(package.clone_package_box()))); remove_map.shift_remove(package.get_name()); } } @@ -246,7 +247,7 @@ impl Transaction { let mut roots: IndexMap> = self .result_package_map .iter() - .map(|(k, v)| (k.clone(), v.clone_box())) + .map(|(k, v)| (k.clone(), v.clone_package_box())) .collect(); for (package_hash, package) in &self.result_package_map { @@ -275,7 +276,7 @@ impl Transaction { return vec![]; }; - packages.iter().map(|p| p.clone_box()).collect() + packages.iter().map(|p| p.clone_package_box()).collect() } /// Workaround: if your packages depend on plugins, we must be sure @@ -309,11 +310,11 @@ impl Transaction { let package: Box = if let Some(install_op) = (op.as_ref() as &dyn Any).downcast_ref::() { - install_op.get_package().clone_box() + install_op.get_package().clone_package_box() } else if let Some(update_op) = (op.as_ref() as &dyn Any).downcast_ref::() { - update_op.get_target_package().clone_box() + update_op.get_target_package().clone_package_box() } else { continue; }; -- cgit v1.3.1