aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/dependency_resolver
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/src/dependency_resolver')
-rw-r--r--crates/shirabe/src/dependency_resolver/decisions.rs10
-rw-r--r--crates/shirabe/src/dependency_resolver/default_policy.rs8
-rw-r--r--crates/shirabe/src/dependency_resolver/local_repo_transaction.rs17
-rw-r--r--crates/shirabe/src/dependency_resolver/lock_transaction.rs15
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/install_operation.rs3
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/mark_alias_installed_operation.rs17
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/mark_alias_uninstalled_operation.rs17
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/operation_interface.rs6
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/uninstall_operation.rs3
-rw-r--r--crates/shirabe/src/dependency_resolver/operation/update_operation.rs28
-rw-r--r--crates/shirabe/src/dependency_resolver/policy_interface.rs4
-rw-r--r--crates/shirabe/src/dependency_resolver/pool.rs2
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_builder.rs34
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_optimizer.rs56
-rw-r--r--crates/shirabe/src/dependency_resolver/problem.rs8
-rw-r--r--crates/shirabe/src/dependency_resolver/request.rs1
-rw-r--r--crates/shirabe/src/dependency_resolver/rule_set.rs25
-rw-r--r--crates/shirabe/src/dependency_resolver/rule_set_generator.rs14
-rw-r--r--crates/shirabe/src/dependency_resolver/rule_watch_chain.rs19
-rw-r--r--crates/shirabe/src/dependency_resolver/rule_watch_graph.rs64
-rw-r--r--crates/shirabe/src/dependency_resolver/solver.rs26
-rw-r--r--crates/shirabe/src/dependency_resolver/solver_bug_exception.rs8
-rw-r--r--crates/shirabe/src/dependency_resolver/solver_problems_exception.rs8
-rw-r--r--crates/shirabe/src/dependency_resolver/transaction.rs29
24 files changed, 268 insertions, 154 deletions
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<i64, i64>,
@@ -15,6 +14,15 @@ pub struct Decisions {
iterator_cursor: Option<usize>,
}
+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<String>,
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::<AliasPackage>()
.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<dyn BasePackage>
+ // but Transaction::new wants Box<dyn PackageInterface>. 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<Box<dyn crate::dependency_resolver::operation::operation_interface::OperationInterface>>
+ {
+ // 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<Box<dyn PackageInterface>> =
- this.present_map.values().map(|p| p.clone_box()).collect();
+ let present: Vec<Box<dyn PackageInterface>> = 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 {
"{}<info>{}</info> (<comment>{}</comment>)",
if lock { "Locking " } else { "Installing " },
package.get_pretty_name(),
- package.get_full_pretty_version(),
+ package
+ .get_full_pretty_version(true, <dyn PackageInterface>::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 <info>{}</info> (<comment>{}</comment>) as installed, alias of <info>{}</info> (<comment>{}</comment>)",
- 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,
+ <dyn PackageInterface>::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,
+ <dyn PackageInterface>::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 <info>{}</info> (<comment>{}</comment>) as uninstalled, alias of <info>{}</info> (<comment>{}</comment>)",
- 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,
+ <dyn PackageInterface>::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,
+ <dyn PackageInterface>::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<dyn OperationInterface> {
+ 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 <info>{}</info> (<comment>{}</comment>)",
package.get_pretty_name(),
- package.get_full_pretty_version(),
+ package
+ .get_full_pretty_version(true, <dyn PackageInterface>::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, <dyn PackageInterface>::DISPLAY_SOURCE_REF);
+ let mut to_version = target_package
+ .get_full_pretty_version(false, <dyn PackageInterface>::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, <dyn PackageInterface>::DISPLAY_SOURCE_REF);
+ to_version = target_package
+ .get_full_pretty_version(true, <dyn PackageInterface>::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, <dyn PackageInterface>::DISPLAY_DIST_REF);
+ to_version = target_package
+ .get_full_pretty_version(true, <dyn PackageInterface>::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<i64>,
required_package: Option<String>,
) -> Vec<i64>;
+
+ fn clone_box(&self) -> Box<dyn PolicyInterface> {
+ 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<Box<dyn BasePackage>> = 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<Box<dyn PackageInterface>> = 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<dyn BasePackage>)> = 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<i64> = 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<String>)> = 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<i64>) -> 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<dyn Rule>
+ // 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<i64>) -> 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<dyn Rule> cannot be cloned.
+ let _ = (self, types);
+ RuleSetIterator::new(IndexMap::new())
}
pub fn get_types(&self) -> Vec<i64> {
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<Box<dyn PackageInterface>> =
- self.added_map.values().map(|p| p.clone_box()).collect();
+ let packages: Vec<Box<dyn PackageInterface>> = 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<Box<dyn PackageInterface>>)> = 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<RuleWatchNode>,
+ data: Vec<std::rc::Rc<std::cell::RefCell<RuleWatchNode>>>,
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<std::cell::RefCell<RuleWatchNode>> {
+ &self.data[self.current_offset]
+ }
+
+ pub(crate) fn unshift(&mut self, node: std::rc::Rc<std::cell::RefCell<RuleWatchNode>>) {
+ 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<std::cell::RefCell<RuleWatchNode>>) {
+ 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::<MultiConflictRule>()
- .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<i64> = 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::<MultiConflictRule>()
- .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<i64> = node.borrow().get_rule().get_literals().clone();
let alternative_literals: Vec<i64> = 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<i64> = 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<std::cell::RefCell<RuleWatchNode>>,
+ ) {
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,
- <dyn IOInterface>::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,
- <dyn IOInterface>::DEBUG,
+ crate::io::io_interface::DEBUG,
);
let before = microtime(true);
self.run_sat()?;
self.io.write_error(
PhpMixed::String("".to_string()),
true,
- <dyn IOInterface>::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,
- <dyn IOInterface>::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,
- <dyn IOInterface>::DEBUG,
+ crate::io::io_interface::DEBUG,
);
let mut i = 0_i64;
let mut n = 0_i64;
@@ -779,7 +783,7 @@ impl Solver {
pass
)),
false,
- <dyn IOInterface>::DEBUG,
+ crate::io::io_interface::DEBUG,
);
} else {
self.io.overwrite_error(
@@ -789,7 +793,7 @@ impl Solver {
)),
false,
None,
- <dyn IOInterface>::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<Problem>, learned_pool: Vec<Vec<Box<dyn Rule>>>) -> 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::<AliasPackage>() {
- 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<String, Box<dyn PackageInterface>> = 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<dyn PackageInterface> = if let Some(install_op) =
(op.as_ref() as &dyn Any).downcast_ref::<InstallOperation>()
{
- 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::<UpdateOperation>()
{
- update_op.get_target_package().clone_box()
+ update_op.get_target_package().clone_package_box()
} else {
continue;
};