diff options
Diffstat (limited to 'crates/shirabe/src/dependency_resolver')
10 files changed, 229 insertions, 179 deletions
diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs index c24e382..cc33b81 100644 --- a/crates/shirabe/src/dependency_resolver/default_policy.rs +++ b/crates/shirabe/src/dependency_resolver/default_policy.rs @@ -5,7 +5,8 @@ use std::cell::RefCell; use indexmap::IndexMap; use shirabe_semver::compiling_matcher::CompilingMatcher; -use shirabe_semver::constraint::Constraint; +use shirabe_semver::constraint::AnyConstraint; +use shirabe_semver::constraint::SimpleConstraint; use crate::dependency_resolver::PolicyInterface; use crate::dependency_resolver::Pool; @@ -209,14 +210,16 @@ impl PolicyInterface for DefaultPolicy { if (a.is_dev() && a.get_version().starts_with("dev-")) || (b.is_dev() && b.get_version().starts_with("dev-")) { - let constraint = Constraint::new(operator, b.get_version()); - let version = Constraint::new("==", a.get_version()); + let constraint = + SimpleConstraint::new(operator.to_string(), b.get_version().to_string(), None); + let version = + SimpleConstraint::new("==".to_string(), a.get_version().to_string(), None); return constraint.match_specific(&version, true); } CompilingMatcher::r#match( - &Constraint::new(operator, b.get_version()), - Constraint::OP_EQ, + &SimpleConstraint::new(operator.to_string(), b.get_version().to_string(), None).into(), + SimpleConstraint::OP_EQ, a.get_version().to_string(), ) } diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index e43eb53..771f363 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -5,8 +5,8 @@ use std::fmt; use indexmap::IndexMap; use shirabe_php_shim::{Countable, STR_PAD_LEFT, abs, spl_object_hash, str_pad}; use shirabe_semver::compiling_matcher::CompilingMatcher; -use shirabe_semver::constraint::Constraint; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; +use shirabe_semver::constraint::SimpleConstraint; use crate::advisory::PartialSecurityAdvisory; use crate::package::BasePackage; @@ -70,7 +70,7 @@ impl Pool { pub fn get_removed_versions( &self, name: &str, - constraint: &dyn ConstraintInterface, + constraint: &AnyConstraint, ) -> IndexMap<String, String> { let Some(versions) = self.removed_versions.get(name) else { return IndexMap::new(); @@ -78,7 +78,9 @@ impl Pool { let mut result: IndexMap<String, String> = IndexMap::new(); for (version, pretty_version) in versions { - if constraint.matches(&Constraint::new("==", version)) { + if constraint + .matches(&SimpleConstraint::new("==".to_string(), version.to_string(), None).into()) + { result.insert(version.clone(), pretty_version.clone()); } } @@ -110,7 +112,7 @@ impl Pool { pub fn is_security_removed_package_version( &self, package_name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> bool { let empty = IndexMap::new(); let versions = self @@ -119,7 +121,9 @@ impl Pool { .unwrap_or(&empty); for (version, _package_with_security_advisories) in versions { if let Some(c) = constraint { - if c.matches(&Constraint::new("==", version)) { + if c.matches( + &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), + ) { return true; } } @@ -132,7 +136,7 @@ impl Pool { pub fn get_security_advisory_identifiers_for_package_version( &self, package_name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> Vec<String> { let empty = IndexMap::new(); let versions = self @@ -141,7 +145,9 @@ impl Pool { .unwrap_or(&empty); for (version, package_with_security_advisories) in versions { if let Some(c) = constraint { - if c.matches(&Constraint::new("==", version)) { + if c.matches( + &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), + ) { return package_with_security_advisories .iter() .map(|advisory| advisory.advisory_id.clone()) @@ -156,7 +162,7 @@ impl Pool { pub fn is_abandoned_removed_package_version( &self, package_name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> bool { let empty = IndexMap::new(); let versions = self @@ -165,7 +171,9 @@ impl Pool { .unwrap_or(&empty); for (version, _pretty_version) in versions { if let Some(c) = constraint { - if c.matches(&Constraint::new("==", version)) { + if c.matches( + &SimpleConstraint::new("==".to_string(), version.to_string(), None).into(), + ) { return true; } } @@ -226,11 +234,11 @@ impl Pool { pub fn what_provides( &mut self, name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> Vec<Box<dyn BasePackage>> { // PHP: $key = (string) $constraint; let key = match constraint { - Some(c) => c.__to_string(), + Some(c) => c.to_string(), None => String::new(), }; if let Some(by_key) = self.provider_cache.get(name) { @@ -254,7 +262,7 @@ impl Pool { pub(crate) fn compute_what_provides( &self, name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> Vec<Box<dyn BasePackage>> { let Some(candidates) = self.package_by_name.get(name) else { return vec![]; @@ -306,7 +314,7 @@ impl Pool { &self, candidate: &dyn BasePackage, name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> bool { let candidate_name = candidate.get_name(); let candidate_version = candidate.get_version(); @@ -315,7 +323,7 @@ impl Pool { return constraint.is_none() || CompilingMatcher::r#match( constraint.unwrap(), - Constraint::OP_EQ, + SimpleConstraint::OP_EQ, candidate_version.to_string(), ); } diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index fcc0339..f80ef38 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -11,10 +11,10 @@ use shirabe_php_shim::{ array_search, array_search_mixed, count, in_array, microtime, number_format, round, spl_object_hash, sprintf, strpos, }; -use shirabe_semver::constraint::Constraint; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MatchAllConstraint; use shirabe_semver::constraint::MultiConstraint; +use shirabe_semver::constraint::SimpleConstraint; use crate::dependency_resolver::Pool; use crate::dependency_resolver::PoolOptimizer; @@ -41,13 +41,13 @@ pub struct PoolBuilder { stability_flags: IndexMap<String, i64>, root_aliases: IndexMap<String, IndexMap<String, IndexMap<String, String>>>, root_references: IndexMap<String, String>, - temporary_constraints: IndexMap<String, Box<dyn ConstraintInterface>>, + temporary_constraints: IndexMap<String, AnyConstraint>, event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>, pool_optimizer: Option<PoolOptimizer>, io: Box<dyn IOInterface>, alias_map: IndexMap<String, IndexMap<i64, AliasPackage>>, - packages_to_load: IndexMap<String, Box<dyn ConstraintInterface>>, - loaded_packages: IndexMap<String, Box<dyn ConstraintInterface>>, + packages_to_load: IndexMap<String, AnyConstraint>, + loaded_packages: IndexMap<String, AnyConstraint>, loaded_per_repo: IndexMap<i64, IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>>, packages: IndexMap<i64, Box<dyn BasePackage>>, unacceptable_fixed_or_locked_packages: Vec<Box<dyn BasePackage>>, @@ -88,7 +88,7 @@ impl PoolBuilder { io: Box<dyn IOInterface>, event_dispatcher: Option<std::rc::Rc<std::cell::RefCell<EventDispatcher>>>, pool_optimizer: Option<PoolOptimizer>, - temporary_constraints: IndexMap<String, Box<dyn ConstraintInterface>>, + temporary_constraints: IndexMap<String, AnyConstraint>, security_advisory_pool_filter: Option<SecurityAdvisoryPoolFilter>, ) -> Self { Self { @@ -195,14 +195,14 @@ impl PoolBuilder { // loading any packages self.loaded_packages.insert( package.get_name().to_string(), - Box::new(MatchAllConstraint::new()), + MatchAllConstraint::new(None).into(), ); // replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways for (_k, link) in &package.get_replaces() { self.loaded_packages.insert( link.get_target().to_string(), - Box::new(MatchAllConstraint::new()), + MatchAllConstraint::new(None).into(), ); } @@ -238,7 +238,7 @@ impl PoolBuilder { } self.packages_to_load - .insert(package_name.clone(), constraint.clone_box()); + .insert(package_name.clone(), constraint.clone()); self.max_extended_reqs.insert(package_name.clone(), true); } @@ -271,7 +271,7 @@ impl PoolBuilder { for package_name in package.get_names(true) { let constraint = match self.temporary_constraints.get(&package_name) { - Some(c) => c.clone_box(), + Some(c) => c.clone(), None => continue, }; @@ -288,7 +288,8 @@ impl PoolBuilder { let mut found = false; for (_idx, version) in &package_and_aliases { - if CompilingMatcher::matches(&*constraint, Constraint::OP_EQ, version) { + if CompilingMatcher::matches(&constraint, SimpleConstraint::OP_EQ, version) + { found = true; } } @@ -377,9 +378,9 @@ impl PoolBuilder { &mut self, request: &Request, name: &str, - constraint: &dyn ConstraintInterface, + constraint: &AnyConstraint, ) { - let constraint = constraint.clone_box(); + let constraint = constraint.clone(); // Skip platform requires at this stage if PlatformRepository::is_platform_package(name) { return; @@ -398,8 +399,8 @@ impl PoolBuilder { let root_requires = request.get_requires(); let mut constraint = constraint; if let Some(root_constraint) = root_requires.get(name) { - if !Intervals::is_subset_of(&*constraint, &**root_constraint).unwrap_or(false) { - constraint = root_constraint.clone_box(); + if !Intervals::is_subset_of(&constraint, root_constraint).unwrap_or(false) { + constraint = root_constraint.clone(); } } @@ -410,17 +411,18 @@ impl PoolBuilder { // MultiConstraint::create() will optimize anyway) if let Some(existing) = self.packages_to_load.get(name) { // Already marked for loading and this does not expand the constraint to be loaded, nothing to do - if Intervals::is_subset_of(&*constraint, &**existing).unwrap_or(false) { + if Intervals::is_subset_of(&constraint, existing).unwrap_or(false) { return; } // extend the constraint to be loaded constraint = Intervals::compact_constraint( MultiConstraint::create( - vec![existing.clone_box(), constraint.clone_box()], + vec![existing.clone(), constraint.clone()], false, + None, ) - .unwrap_or_else(|_| Box::new(MatchAllConstraint::new())), + .unwrap_or_else(|_| MatchAllConstraint::new(None).into()), ); } @@ -431,7 +433,7 @@ impl PoolBuilder { // No need to load this package with this constraint because it is // a subset of the constraint with which we have already loaded packages - if Intervals::is_subset_of(&*constraint, &**self.loaded_packages.get(name).unwrap()) + if Intervals::is_subset_of(&constraint, self.loaded_packages.get(name).unwrap()) .unwrap_or(false) { return; @@ -444,13 +446,11 @@ impl PoolBuilder { name.to_string(), Intervals::compact_constraint( MultiConstraint::create( - vec![ - self.loaded_packages.get(name).unwrap().clone_box(), - constraint, - ], + vec![self.loaded_packages.get(name).unwrap().clone(), constraint], false, + None, ) - .unwrap_or_else(|_| Box::new(MatchAllConstraint::new())), + .unwrap_or_else(|_| MatchAllConstraint::new(None).into()), ), ); self.loaded_packages.shift_remove(name); @@ -475,23 +475,23 @@ impl PoolBuilder { for name in to_remove { self.packages_to_load.shift_remove(&name); } - let snapshot: Vec<(String, Box<dyn ConstraintInterface>)> = self + let snapshot: Vec<(String, AnyConstraint)> = self .packages_to_load .iter() - .map(|(k, v)| (k.clone(), v.clone_box())) + .map(|(k, v)| (k.clone(), v.clone())) .collect(); for (name, constraint) in &snapshot { self.loaded_packages - .insert(name.clone(), constraint.clone_box()); + .insert(name.clone(), constraint.clone()); } // Load packages in chunks of 50 to prevent memory usage build-up due to caches of all sorts // TODO(phase-b): array_chunk shim signature expects &[T]; build IndexMap chunks manually. - let mut package_batches: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = { - let mut chunks: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = Vec::new(); - let mut current: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new(); + let mut package_batches: Vec<IndexMap<String, AnyConstraint>> = { + let mut chunks: Vec<IndexMap<String, AnyConstraint>> = Vec::new(); + let mut current: IndexMap<String, AnyConstraint> = IndexMap::new(); for (k, v) in self.packages_to_load.iter() { - current.insert(k.clone(), v.clone_box()); + current.insert(k.clone(), v.clone()); if current.len() as i64 >= Self::LOAD_BATCH_SIZE { chunks.push(std::mem::take(&mut current)); } @@ -525,11 +525,11 @@ impl PoolBuilder { // Iterate by index because we mutate package_batches inside the loop. for batch_index in 0..package_batches.len() { - let package_batch: IndexMap<String, Option<Box<dyn ConstraintInterface>>> = - package_batches[batch_index] - .iter() - .map(|(k, v)| (k.clone(), Some(v.clone_box()))) - .collect(); + let package_batch: IndexMap<String, Option<AnyConstraint>> = package_batches + [batch_index] + .iter() + .map(|(k, v)| (k.clone(), Some(v.clone()))) + .collect(); let result = repository.load_packages( package_batch, self.acceptable_stabilities.clone(), @@ -598,18 +598,18 @@ impl PoolBuilder { } // PHP: array_chunk(array_merge(...$packageBatches), self::LOAD_BATCH_SIZE, true) - let mut merged: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new(); + let mut merged: IndexMap<String, AnyConstraint> = IndexMap::new(); for batch in &package_batches { for (k, v) in batch { - merged.insert(k.clone(), v.clone_box()); + merged.insert(k.clone(), v.clone()); } } // Rebuild chunks from merged. package_batches = { - let mut chunks: Vec<IndexMap<String, Box<dyn ConstraintInterface>>> = Vec::new(); - let mut current: IndexMap<String, Box<dyn ConstraintInterface>> = IndexMap::new(); + let mut chunks: Vec<IndexMap<String, AnyConstraint>> = Vec::new(); + let mut current: IndexMap<String, AnyConstraint> = IndexMap::new(); for (k, v) in merged.iter() { - current.insert(k.clone(), v.clone_box()); + current.insert(k.clone(), v.clone()); if current.len() as i64 >= Self::LOAD_BATCH_SIZE { chunks.push(std::mem::take(&mut current)); } @@ -929,7 +929,7 @@ impl PoolBuilder { self.mark_package_name_for_loading( request, &replacer_name, - &MatchAllConstraint::new(), + &MatchAllConstraint::new(None).into(), ); } else { let pkgs: Vec<Box<dyn BasePackage>> = @@ -1050,8 +1050,8 @@ impl PoolBuilder { fn mark_package_name_for_loading_if_required(&mut self, request: &Request, name: &str) { if self.is_root_require(request, name) { - let cons = request.get_requires()[name].clone_box(); - self.mark_package_name_for_loading(request, name, &*cons); + let cons = request.get_requires()[name].clone(); + self.mark_package_name_for_loading(request, name, &cons); } let pkgs: Vec<Box<dyn BasePackage>> = diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs index 326587a..27b3ffb 100644 --- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs +++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs @@ -6,9 +6,9 @@ use anyhow::Result; use indexmap::IndexMap; use shirabe_php_shim::{LogicException, PhpMixed, implode, ksort, spl_object_hash}; use shirabe_semver::compiling_matcher::CompilingMatcher; -use shirabe_semver::constraint::Constraint; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MultiConstraint; +use shirabe_semver::constraint::SimpleConstraint; use shirabe_semver::intervals::Intervals; use crate::dependency_resolver::PolicyInterface; @@ -29,12 +29,10 @@ pub struct PoolOptimizer { irremovable_packages: IndexMap<i64, bool>, /// @var array<string, array<string, ConstraintInterface>> - require_constraints_per_package: - IndexMap<String, IndexMap<String, Box<dyn ConstraintInterface>>>, + require_constraints_per_package: IndexMap<String, IndexMap<String, AnyConstraint>>, /// @var array<string, array<string, ConstraintInterface>> - conflict_constraints_per_package: - IndexMap<String, IndexMap<String, Box<dyn ConstraintInterface>>>, + conflict_constraints_per_package: IndexMap<String, IndexMap<String, AnyConstraint>>, /// @var array<int, true> packages_to_remove: IndexMap<i64, bool>, @@ -90,23 +88,27 @@ impl PoolOptimizer { } fn prepare(&mut self, request: &Request, pool: &Pool) { - let mut irremovable_package_constraint_groups: IndexMap< - String, - Vec<Box<dyn ConstraintInterface>>, - > = IndexMap::new(); + let mut irremovable_package_constraint_groups: IndexMap<String, Vec<AnyConstraint>> = + IndexMap::new(); // Mark fixed or locked packages as irremovable for (_, package) in request.get_fixed_or_locked_packages() { irremovable_package_constraint_groups .entry(PackageInterface::get_name(package.as_ref()).to_string()) .or_insert_with(Vec::new) - .push(Box::new(Constraint::new("==", package.get_version()))); + .push( + SimpleConstraint::new( + "==".to_string(), + package.get_version().to_string(), + None, + ) + .into(), + ); } // Extract requested package requirements for (require, constraint) in request.get_requires() { - // TODO(phase-b): clone Box<dyn ConstraintInterface> - self.extract_require_constraints_per_package(require, todo!("constraint.clone_box()")); + self.extract_require_constraints_per_package(require, constraint.clone()); } // First pass over all packages to extract information and mark package constraints irremovable @@ -115,16 +117,14 @@ impl PoolOptimizer { for link in package.get_requires().values() { self.extract_require_constraints_per_package( link.get_target(), - // TODO(phase-b): clone constraint - todo!("link.get_constraint().clone_box()"), + link.get_constraint().clone(), ); } // Extract package conflicts for link in package.get_conflicts().values() { self.extract_conflict_constraints_per_package( link.get_target(), - // TODO(phase-b): clone constraint - todo!("link.get_constraint().clone_box()"), + link.get_constraint().clone(), ); } @@ -138,16 +138,14 @@ impl PoolOptimizer { } } - let mut irremovable_package_constraints: IndexMap<String, Box<dyn ConstraintInterface>> = - IndexMap::new(); + let mut irremovable_package_constraints: IndexMap<String, AnyConstraint> = IndexMap::new(); for (package_name, constraints) in irremovable_package_constraint_groups { - // TODO(phase-b): MultiConstraint::new signature; move ownership of constraints vec irremovable_package_constraints.insert( package_name, if 1 == constraints.len() { - todo!("constraints[0] moved out") + constraints.into_iter().next().unwrap() } else { - Box::new(MultiConstraint::new(constraints, false)) + MultiConstraint::new(constraints, false, None).into() }, ); } @@ -165,8 +163,8 @@ impl PoolOptimizer { .get(PackageInterface::get_name(package.as_ref())) .unwrap(); if CompilingMatcher::r#match( - constraint.as_ref(), - Constraint::OP_EQ, + constraint, + SimpleConstraint::OP_EQ, package.get_version().to_string(), ) { self.mark_package_irremovable(package.as_ref()); @@ -262,8 +260,8 @@ impl PoolOptimizer { let mut group_hash_parts: Vec<String> = vec![]; if CompilingMatcher::r#match( - require_constraint.as_ref(), - Constraint::OP_EQ, + require_constraint, + SimpleConstraint::OP_EQ, package.get_version().to_string(), ) { group_hash_parts.push(format!( @@ -276,7 +274,7 @@ impl PoolOptimizer { for (_, link) in package.get_replaces() { if CompilingMatcher::r#match( link.get_constraint(), - Constraint::OP_EQ, + SimpleConstraint::OP_EQ, package.get_version().to_string(), ) { // Use the same hash part as the regular require hash because that's what the replacement does @@ -293,8 +291,8 @@ impl PoolOptimizer { { for (_, conflict_constraint) in conflict_constraints { if CompilingMatcher::r#match( - conflict_constraint.as_ref(), - Constraint::OP_EQ, + conflict_constraint, + SimpleConstraint::OP_EQ, package.get_version().to_string(), ) { group_hash_parts.push(format!( @@ -415,7 +413,7 @@ impl PoolOptimizer { // performance more than the additional few packages that could be filtered out would benefit the process. subhash.insert( link.get_target().to_string(), - link.get_constraint().__to_string(), + link.get_constraint().to_string(), ); } @@ -638,7 +636,7 @@ impl PoolOptimizer { if false == CompilingMatcher::r#match( link_constraint, - Constraint::OP_EQ, + SimpleConstraint::OP_EQ, version_str, ) { @@ -662,13 +660,13 @@ impl PoolOptimizer { fn extract_require_constraints_per_package( &mut self, package: &str, - constraint: Box<dyn ConstraintInterface>, + constraint: AnyConstraint, ) { for expanded in self.expand_disjunctive_multi_constraints(constraint) { self.require_constraints_per_package .entry(package.to_string()) .or_insert_with(IndexMap::new) - .insert(expanded.__to_string(), expanded); + .insert(expanded.to_string(), expanded); } } @@ -680,32 +678,28 @@ impl PoolOptimizer { fn extract_conflict_constraints_per_package( &mut self, package: &str, - constraint: Box<dyn ConstraintInterface>, + constraint: AnyConstraint, ) { for expanded in self.expand_disjunctive_multi_constraints(constraint) { self.conflict_constraints_per_package .entry(package.to_string()) .or_insert_with(IndexMap::new) - .insert(expanded.__to_string(), expanded); + .insert(expanded.to_string(), expanded); } } /// @return ConstraintInterface[] fn expand_disjunctive_multi_constraints( &self, - constraint: Box<dyn ConstraintInterface>, - ) -> Vec<Box<dyn ConstraintInterface>> { - let constraint = Intervals::compact_constraint(&*constraint).unwrap_or(constraint); + constraint: AnyConstraint, + ) -> Vec<AnyConstraint> { + let constraint = Intervals::compact_constraint(&constraint).unwrap_or(constraint); - if let Some(multi) = constraint.as_any().downcast_ref::<MultiConstraint>() { - if multi.is_disjunctive() { + if let Some(multi) = constraint.as_multi_constraint() { + if multi.is_disjunctive_mc() { // No need to call ourselves recursively here because Intervals::compactConstraint() ensures that there // are no nested disjunctive MultiConstraint instances possible - return multi - .get_constraints() - .iter() - .map(|c| c.clone_box()) - .collect(); + return multi.get_constraints().iter().map(|c| c.clone()).collect(); } } diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs index a69a4a2..4436ec8 100644 --- a/crates/shirabe/src/dependency_resolver/problem.rs +++ b/crates/shirabe/src/dependency_resolver/problem.rs @@ -9,9 +9,9 @@ use shirabe_php_shim::{ phpversion, spl_object_hash, sprintf, str_replace, str_starts_with, stripos, strpos, strtolower, substr, substr_count, version_compare, }; -use shirabe_semver::constraint::Constraint; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MultiConstraint; +use shirabe_semver::constraint::SimpleConstraint; use crate::advisory::SecurityAdvisory; use crate::dependency_resolver::Pool; @@ -92,14 +92,13 @@ impl Problem { let reason_data = rule_ref.get_reason_data(); // TODO(phase-b): reason_data for RULE_ROOT_REQUIRE; extract via ReasonData::RootRequire variant. - let (package_name, constraint): (String, Option<&dyn ConstraintInterface>) = - match reason_data { - rule::ReasonData::RootRequire { - package_name, - constraint, - } => (package_name.clone(), Some(constraint.as_ref())), - _ => (String::new(), None), - }; + let (package_name, constraint): (String, Option<&AnyConstraint>) = match reason_data { + rule::ReasonData::RootRequire { + package_name, + constraint, + } => (package_name.clone(), Some(constraint)), + _ => (String::new(), None), + }; let packages = pool.compute_what_provides(&package_name, constraint); if packages.len() == 0 { @@ -393,7 +392,7 @@ impl Problem { pool: &mut Pool, is_verbose: bool, package_name: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> (String, String) { if PlatformRepository::is_platform_package(package_name) { // handle php/php-*/hhvm @@ -572,7 +571,7 @@ impl Problem { if let Some(c) = constraint { if c.is_constraint() - && c.get_operator() == Constraint::STR_OP_EQ + && c.get_operator() == SimpleConstraint::STR_OP_EQ && Preg::is_match3(r"{^dev-.*#.*}", &c.get_pretty_string(), None).unwrap_or(false) { let new_constraint = @@ -580,17 +579,25 @@ impl Problem { .unwrap_or_else(|_| c.get_pretty_string()); let packages = repository_set.find_packages( package_name, - Some(Box::new(MultiConstraint::new( - vec![ - Box::new(Constraint::new(Constraint::STR_OP_EQ, &new_constraint)) - as Box<dyn ConstraintInterface>, - Box::new(Constraint::new( - Constraint::STR_OP_EQ, - &str_replace("#", "+", &new_constraint), - )) as Box<dyn ConstraintInterface>, - ], - false, - ))), + Some( + MultiConstraint::new( + vec![ + AnyConstraint::Simple(SimpleConstraint::new( + SimpleConstraint::STR_OP_EQ.to_string(), + new_constraint.clone(), + None, + )), + AnyConstraint::Simple(SimpleConstraint::new( + SimpleConstraint::STR_OP_EQ.to_string(), + str_replace("#", "+", &new_constraint), + None, + )), + ], + false, + None, + ) + .into(), + ), 0, ); if packages.len() > 0 { @@ -618,15 +625,21 @@ impl Problem { // first check if the actual requested package is found in normal conditions // if so it must mean it is rejected by another constraint than the one given here - let packages = - repository_set.find_packages(package_name, constraint.map(|c| c.clone_box()), 0); + let packages = repository_set.find_packages(package_name, constraint.map(|c| c.clone()), 0); if packages.len() > 0 { let root_reqs = repository_set.get_root_requires(); if root_reqs.contains_key(package_name) { let filtered: Vec<&Box<dyn BasePackage>> = packages .iter() .filter(|p| { - root_reqs[package_name].matches(&Constraint::new("==", p.get_version())) + root_reqs[package_name].matches( + &SimpleConstraint::new( + "==".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) }) .collect(); if filtered.len() == 0 { @@ -663,7 +676,14 @@ impl Problem { let filtered: Vec<&Box<dyn BasePackage>> = packages .iter() .filter(|p| { - temp_reqs[&name].matches(&Constraint::new("==", p.get_version())) + temp_reqs[&name].matches( + &SimpleConstraint::new( + "==".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) }) .collect(); if filtered.len() == 0 { @@ -696,10 +716,23 @@ impl Problem { } if let Some(ref lp) = locked_package { - let fixed_constraint = Constraint::new("==", lp.get_version()); + let fixed_constraint = AnyConstraint::from(SimpleConstraint::new( + "==".to_string(), + lp.get_version().to_string(), + None, + )); let filtered: Vec<&Box<dyn BasePackage>> = packages .iter() - .filter(|p| fixed_constraint.matches(&Constraint::new("==", p.get_version()))) + .filter(|p| { + fixed_constraint.matches( + &SimpleConstraint::new( + "==".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) + }) .collect(); if filtered.len() == 0 { return ( @@ -837,14 +870,14 @@ impl Problem { // check if the package is found when bypassing stability checks let packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone_box()), + constraint.map(|c| c.clone()), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, ); if packages.len() > 0 { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone_box()), + constraint.map(|c| c.clone()), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, ); if all_repos_packages.len() > 0 { @@ -887,7 +920,7 @@ impl Problem { // we must first verify if a valid package would be found in a lower priority repository let all_repos_packages = repository_set.find_packages( package_name, - constraint.map(|c| c.clone_box()), + constraint.map(|c| c.clone()), RepositorySet::ALLOW_SHADOWED_REPOSITORIES, ); if all_repos_packages.len() > 0 { @@ -993,7 +1026,7 @@ impl Problem { packages: &Vec<Box<dyn BasePackage>>, is_verbose: bool, pool: Option<&Pool>, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, use_removed_version_group: bool, ) -> String { struct PreparedEntry { @@ -1213,7 +1246,7 @@ impl Problem { higher_repo_packages: &Vec<Box<dyn BasePackage>>, all_repos_packages: &Vec<Box<dyn BasePackage>>, reason: &str, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, ) -> (String, String) { let mut next_repo_packages: Vec<Box<dyn BasePackage>> = Vec::new(); let mut next_repo: Option<Box<dyn crate::repository::RepositoryInterface>> = None; @@ -1346,10 +1379,10 @@ impl Problem { } /// Turns a constraint into text usable in a sentence describing a request - pub(crate) fn constraint_to_text(constraint: Option<&dyn ConstraintInterface>) -> String { + pub(crate) fn constraint_to_text(constraint: Option<&AnyConstraint>) -> String { if let Some(c) = constraint { if c.is_constraint() - && c.get_operator() == Constraint::STR_OP_EQ + && c.get_operator() == SimpleConstraint::STR_OP_EQ && !str_starts_with(&c.get_version(), "dev-") { if !Preg::is_match3(r"{^\d+(?:\.\d+)*$}", &c.get_pretty_string(), None) diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs index d181bd2..e2bfc3c 100644 --- a/crates/shirabe/src/dependency_resolver/request.rs +++ b/crates/shirabe/src/dependency_resolver/request.rs @@ -2,7 +2,7 @@ use indexmap::IndexMap; use shirabe_php_shim::{LogicException, spl_object_hash, strtolower}; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MatchAllConstraint; use crate::package::BasePackage; @@ -43,7 +43,7 @@ pub enum UpdateAllowTransitiveDeps { #[derive(Debug)] pub struct Request { pub(crate) locked_repository: Option<LockArrayRepository>, - pub(crate) requires: IndexMap<String, Box<dyn ConstraintInterface>>, + pub(crate) requires: IndexMap<String, AnyConstraint>, pub(crate) fixed_packages: IndexMap<String, Box<dyn BasePackage>>, pub(crate) locked_packages: IndexMap<String, Box<dyn BasePackage>>, pub(crate) fixed_locked_packages: IndexMap<String, Box<dyn BasePackage>>, @@ -69,10 +69,10 @@ impl Request { pub fn require_name( &mut self, package_name: &str, - constraint: Option<Box<dyn ConstraintInterface>>, + constraint: Option<AnyConstraint>, ) -> anyhow::Result<()> { let package_name = strtolower(package_name); - let constraint = constraint.unwrap_or_else(|| Box::new(MatchAllConstraint::new())); + let constraint = constraint.unwrap_or_else(|| MatchAllConstraint::new(None).into()); if self.requires.contains_key(&package_name) { return Err(LogicException { message: format!( @@ -155,7 +155,7 @@ impl Request { == UpdateAllowTransitiveDeps::UpdateListedWithTransitiveDeps } - pub fn get_requires(&self) -> &IndexMap<String, Box<dyn ConstraintInterface>> { + pub fn get_requires(&self) -> &IndexMap<String, AnyConstraint> { &self.requires } diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs index 90223e2..fbc8521 100644 --- a/crates/shirabe/src/dependency_resolver/rule.rs +++ b/crates/shirabe/src/dependency_resolver/rule.rs @@ -10,8 +10,8 @@ use shirabe_php_shim::{ LogicException, PhpMixed, RuntimeException, abs, array_filter, array_keys, array_shift, array_values, implode, is_object, }; -use shirabe_semver::constraint::Constraint; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; +use shirabe_semver::constraint::SimpleConstraint; use crate::dependency_resolver::GenericRule; use crate::dependency_resolver::MultiConflictRule; @@ -36,7 +36,7 @@ pub enum ReasonData { Int(i64), RootRequire { package_name: String, - constraint: Box<dyn ConstraintInterface>, + constraint: AnyConstraint, }, Fixed { package: Box<dyn BasePackage>, @@ -238,10 +238,14 @@ impl Rule { if pool.is_unacceptable_fixed_or_locked_package(p) { return true; } - if !link - .get_constraint() - .matches(&Constraint::new("=", p.get_version())) - { + if !link.get_constraint().matches( + &SimpleConstraint::new( + "=".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) { return true; } // required package was locked but has been unlocked and still matches @@ -275,7 +279,14 @@ impl Rule { if pool.is_unacceptable_fixed_or_locked_package(p) { return true; } - if !constraint.matches(&Constraint::new("=", p.get_version())) { + if !constraint.matches( + &SimpleConstraint::new( + "=".to_string(), + p.get_version().to_string(), + None, + ) + .into(), + ) { return true; } break; @@ -345,12 +356,11 @@ impl Rule { match self.get_reason() { r if r == RULE_ROOT_REQUIRE => { let reason_data = self.get_reason_data(); - let (package_name, constraint): (&str, &dyn ConstraintInterface) = match reason_data - { + let (package_name, constraint): (&str, &AnyConstraint) = match reason_data { ReasonData::RootRequire { package_name, constraint, - } => (package_name.as_str(), constraint.as_ref()), + } => (package_name.as_str(), constraint), _ => return String::new(), }; @@ -712,7 +722,7 @@ impl Rule { pool: &Pool, packages: Vec<Box<dyn BasePackage>>, is_verbose: bool, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, use_removed_version_group: bool, ) -> String { Problem::get_package_list( @@ -730,7 +740,7 @@ impl Rule { pool: &Pool, literals: &[i64], is_verbose: bool, - constraint: Option<&dyn ConstraintInterface>, + constraint: Option<&AnyConstraint>, use_removed_version_group: bool, ) -> String { let mut packages: Vec<Box<dyn BasePackage>> = vec![]; diff --git a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs index 45f1331..076ce42 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs @@ -205,14 +205,14 @@ impl RuleSetGenerator { } for link in package.get_requires().values() { - let mut constraint = link.get_constraint().clone_box(); + let mut constraint = link.get_constraint().clone(); if platform_requirement_filter.is_ignored(link.get_target()) { continue; } else if let Some(ignore_list_filter) = platform_requirement_filter .as_any() .downcast_ref::<IgnoreListPlatformRequirementFilter>( ) { - let fallback = constraint.clone_box(); + let fallback = constraint.clone(); constraint = ignore_list_filter .filter_constraint(link.get_target(), constraint, true) .unwrap_or(fallback); @@ -221,7 +221,7 @@ impl RuleSetGenerator { let possible_requires: Vec<Box<dyn PackageInterface>> = self .pool .borrow_mut() - .what_provides(link.get_target(), Some(&*constraint)) + .what_provides(link.get_target(), Some(&constraint)) .into_iter() .map(|p| p.clone_package_box()) .collect(); @@ -258,14 +258,14 @@ impl RuleSetGenerator { continue; } - let mut constraint = link.get_constraint().clone_box(); + let mut constraint = link.get_constraint().clone(); if platform_requirement_filter.is_ignored(link.get_target()) { continue; } else if let Some(ignore_list_filter) = platform_requirement_filter .as_any() .downcast_ref::<IgnoreListPlatformRequirementFilter>( ) { - let fallback = constraint.clone_box(); + let fallback = constraint.clone(); constraint = ignore_list_filter .filter_constraint(link.get_target(), constraint, false) .unwrap_or(fallback); @@ -274,7 +274,7 @@ impl RuleSetGenerator { let conflicts = self .pool .borrow_mut() - .what_provides(link.get_target(), Some(&*constraint)); + .what_provides(link.get_target(), Some(&constraint)); for conflict in &conflicts { // define the conflict rule for regular packages, for alias packages it's only needed if the name @@ -354,14 +354,14 @@ impl RuleSetGenerator { } for (package_name, constraint) in request.get_requires() { - let mut constraint = constraint.clone_box(); + let mut constraint = constraint.clone(); if platform_requirement_filter.is_ignored(package_name) { continue; } else if let Some(ignore_list_filter) = platform_requirement_filter .as_any() .downcast_ref::<IgnoreListPlatformRequirementFilter>( ) { - let fallback = constraint.clone_box(); + let fallback = constraint.clone(); constraint = ignore_list_filter .filter_constraint(package_name, constraint, true) .unwrap_or(fallback); @@ -370,7 +370,7 @@ impl RuleSetGenerator { let packages: Vec<Box<dyn PackageInterface>> = self .pool .borrow_mut() - .what_provides(package_name, Some(&*constraint)) + .what_provides(package_name, Some(&constraint)) .into_iter() .map(|p| p.clone_package_box()) .collect(); diff --git a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs index 742a709..4daf641 100644 --- a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs +++ b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs @@ -8,7 +8,8 @@ use crate::dependency_resolver::Request; use crate::package::PackageInterface; use crate::repository::RepositoryInterface; use indexmap::IndexMap; -use shirabe_semver::constraint::Constraint; +use shirabe_semver::constraint::AnyConstraint; +use shirabe_semver::constraint::SimpleConstraint; #[derive(Debug)] pub struct SecurityAdvisoryPoolFilter { @@ -64,7 +65,9 @@ impl SecurityAdvisoryPoolFilter { continue; } - let package_constraint = Constraint::new("==", package.get_version()); + let package_constraint = + SimpleConstraint::new("==".to_string(), package.get_version().to_string(), None) + .into(); for advisory in &advisory_map[&package_name] { // advisory is PartialSecurityAdvisory or SecurityAdvisory; both have affected_versions: Box<dyn ConstraintInterface> if advisory.affected_versions.matches(&package_constraint) { diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index e4539d2..820f792 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -8,7 +8,7 @@ use indexmap::IndexMap; use shirabe_php_shim::{ PhpMixed, array_pop, array_shift, array_unshift, microtime, spl_object_hash, sprintf, }; -use shirabe_semver::constraint::ConstraintInterface; +use shirabe_semver::constraint::AnyConstraint; use crate::dependency_resolver::Decisions; use crate::dependency_resolver::GenericRule; @@ -189,8 +189,8 @@ impl Solver { // TODO(phase-b): ConstraintInterface is a PHP class — Box<dyn ConstraintInterface> // cannot be cloned. We borrow the original constraint and only allocate a fresh // box when the ignore filter rewrites it. - let mut filtered: Option<Box<dyn ConstraintInterface>> = None; - let constraint_ref: &dyn ConstraintInterface = constraint.as_ref(); + let mut filtered: Option<AnyConstraint> = None; + let constraint_ref: &AnyConstraint = constraint; if platform_requirement_filter.is_ignored(package_name) { continue; } else if let Some(ignore_filter) = platform_requirement_filter @@ -204,8 +204,7 @@ impl Solver { let _ = &mut filtered; } - let active_constraint: &dyn ConstraintInterface = - filtered.as_deref().unwrap_or(constraint_ref); + let active_constraint: &AnyConstraint = filtered.as_ref().unwrap_or(constraint_ref); if self .pool |
