diff options
Diffstat (limited to 'crates/shirabe/src/dependency_resolver')
26 files changed, 919 insertions, 374 deletions
diff --git a/crates/shirabe/src/dependency_resolver/decisions.rs b/crates/shirabe/src/dependency_resolver/decisions.rs index db1068d..22b6fa4 100644 --- a/crates/shirabe/src/dependency_resolver/decisions.rs +++ b/crates/shirabe/src/dependency_resolver/decisions.rs @@ -1,11 +1,11 @@ //! ref: composer/src/Composer/DependencyResolver/Decisions.php -use std::fmt; -use indexmap::IndexMap; -use shirabe_php_shim::LogicException; use crate::dependency_resolver::pool::Pool; use crate::dependency_resolver::rule::Rule; use crate::dependency_resolver::solver_bug_exception::SolverBugException; +use indexmap::IndexMap; +use shirabe_php_shim::LogicException; +use std::fmt; #[derive(Debug)] pub struct Decisions { @@ -43,16 +43,28 @@ impl Decisions { pub fn conflict(&self, literal: i64) -> bool { let package_id = literal.abs(); - (self.decision_map.contains_key(&package_id) && self.decision_map[&package_id] > 0 && literal < 0) - || (self.decision_map.contains_key(&package_id) && self.decision_map[&package_id] < 0 && literal > 0) + (self.decision_map.contains_key(&package_id) + && self.decision_map[&package_id] > 0 + && literal < 0) + || (self.decision_map.contains_key(&package_id) + && self.decision_map[&package_id] < 0 + && literal > 0) } pub fn decided(&self, literal_or_package_id: i64) -> bool { - self.decision_map.get(&literal_or_package_id.abs()).copied().unwrap_or(0) != 0 + self.decision_map + .get(&literal_or_package_id.abs()) + .copied() + .unwrap_or(0) + != 0 } pub fn undecided(&self, literal_or_package_id: i64) -> bool { - self.decision_map.get(&literal_or_package_id.abs()).copied().unwrap_or(0) == 0 + self.decision_map + .get(&literal_or_package_id.abs()) + .copied() + .unwrap_or(0) + == 0 } pub fn decided_install(&self, literal_or_package_id: i64) -> bool { @@ -79,10 +91,17 @@ impl Decisions { } } - panic!("{}", LogicException { - message: format!("Did not find a decision rule using {}", literal_or_package_id), - code: 0, - }.message); + panic!( + "{}", + LogicException { + message: format!( + "Did not find a decision rule using {}", + literal_or_package_id + ), + code: 0, + } + .message + ); } pub fn at_offset(&self, queue_offset: usize) -> &(i64, Rule) { @@ -133,7 +152,8 @@ impl Decisions { } pub fn current(&self) -> Option<&(i64, Rule)> { - self.iterator_cursor.and_then(|cursor| self.decision_queue.get(cursor)) + self.iterator_cursor + .and_then(|cursor| self.decision_queue.get(cursor)) } pub fn key(&self) -> Option<usize> { @@ -141,13 +161,9 @@ impl Decisions { } pub fn next(&mut self) { - self.iterator_cursor = self.iterator_cursor.and_then(|cursor| { - if cursor > 0 { - Some(cursor - 1) - } else { - None - } - }); + self.iterator_cursor = self + .iterator_cursor + .and_then(|cursor| if cursor > 0 { Some(cursor - 1) } else { None }); } pub fn valid(&self) -> bool { @@ -163,11 +179,19 @@ impl Decisions { let previous_decision = self.decision_map.get(&package_id).copied().unwrap_or(0); if previous_decision != 0 { - let literal_string = self.pool.literal_to_pretty_string(literal, &IndexMap::new()); + let literal_string = self + .pool + .literal_to_pretty_string(literal, &IndexMap::new()); let package = self.pool.literal_to_package(literal); - panic!("{}", SolverBugException::new( - format!("Trying to decide {} on level {}, even though {} was previously decided as {}.", literal_string, level, package, previous_decision) - ).0.message); + panic!( + "{}", + SolverBugException::new(format!( + "Trying to decide {} on level {}, even though {} was previously decided as {}.", + literal_string, level, package, previous_decision + )) + .0 + .message + ); } if literal > 0 { diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs index d84863b..f647327 100644 --- a/crates/shirabe/src/dependency_resolver/default_policy.rs +++ b/crates/shirabe/src/dependency_resolver/default_policy.rs @@ -51,8 +51,12 @@ impl DefaultPolicy { ignore_replace: bool, ) -> i64 { if a.get_name() == b.get_name() { - let a_aliased = (a.as_any() as &dyn Any).downcast_ref::<AliasPackage>().is_some(); - let b_aliased = (b.as_any() as &dyn Any).downcast_ref::<AliasPackage>().is_some(); + let a_aliased = (a.as_any() as &dyn Any) + .downcast_ref::<AliasPackage>() + .is_some(); + let b_aliased = (b.as_any() as &dyn Any) + .downcast_ref::<AliasPackage>() + .is_some(); if a_aliased && !b_aliased { return -1; } @@ -108,7 +112,9 @@ impl DefaultPolicy { let best_literals: Vec<i64> = literals .iter() .copied() - .filter(|&literal| pool.literal_to_package(literal).get_version() == preferred_version) + .filter(|&literal| { + pool.literal_to_package(literal).get_version() == preferred_version + }) .collect(); if !best_literals.is_empty() { return best_literals; @@ -174,15 +180,28 @@ impl DefaultPolicy { } impl PolicyInterface for DefaultPolicy { - fn version_compare(&self, a: &dyn PackageInterface, b: &dyn PackageInterface, operator: &str) -> bool { + fn version_compare( + &self, + a: &dyn PackageInterface, + b: &dyn PackageInterface, + operator: &str, + ) -> bool { if self.prefer_stable { let stab_a = a.get_stability().to_string(); let stab_b = b.get_stability().to_string(); if stab_a != stab_b { let (mut stab_a, mut stab_b) = (stab_a, stab_b); - if self.prefer_lowest && self.prefer_dev_over_prerelease && "stable" != stab_a && "stable" != stab_b { - if stab_a == "dev" { stab_a = "stable".to_string(); } - if stab_b == "dev" { stab_b = "stable".to_string(); } + if self.prefer_lowest + && self.prefer_dev_over_prerelease + && "stable" != stab_a + && "stable" != stab_b + { + if stab_a == "dev" { + stab_a = "stable".to_string(); + } + if stab_b == "dev" { + stab_b = "stable".to_string(); + } } return STABILITIES.get(stab_a.as_str()).copied().unwrap_or(0) < STABILITIES.get(stab_b.as_str()).copied().unwrap_or(0); @@ -213,7 +232,11 @@ impl PolicyInterface for DefaultPolicy { literals.sort(); let result_cache_key = format!( "{}{}", - literals.iter().map(|l| l.to_string()).collect::<Vec<_>>().join(","), + literals + .iter() + .map(|l| l.to_string()) + .collect::<Vec<_>>() + .join(","), required_package.as_deref().unwrap_or("") ); let pool_id = pool as *const Pool as i64; @@ -231,12 +254,8 @@ impl PolicyInterface for DefaultPolicy { for name_literals in packages.values_mut() { name_literals.sort_by(|&a, &b| { - let cache_key = format!( - "i{}.{}{}", - a, - b, - required_package.as_deref().unwrap_or("") - ); + let cache_key = + format!("i{}.{}{}", a, b, required_package.as_deref().unwrap_or("")); { let cache = self.sorting_cache_per_pool.borrow(); if let Some(pool_cache) = cache.get(&pool_id) { @@ -269,12 +288,7 @@ impl PolicyInterface for DefaultPolicy { let mut selected: Vec<i64> = packages.into_values().flatten().collect(); selected.sort_by(|&a, &b| { - let cache_key = format!( - "{}.{}{}", - a, - b, - required_package.as_deref().unwrap_or("") - ); + let cache_key = format!("{}.{}{}", a, b, required_package.as_deref().unwrap_or("")); { let cache = self.sorting_cache_per_pool.borrow(); if let Some(pool_cache) = cache.get(&pool_id) { diff --git a/crates/shirabe/src/dependency_resolver/generic_rule.rs b/crates/shirabe/src/dependency_resolver/generic_rule.rs index 520d483..f30d612 100644 --- a/crates/shirabe/src/dependency_resolver/generic_rule.rs +++ b/crates/shirabe/src/dependency_resolver/generic_rule.rs @@ -1,8 +1,8 @@ //! ref: composer/src/Composer/DependencyResolver/GenericRule.php -use anyhow::Result; -use shirabe_php_shim::{hash_raw, implode, unpack, RuntimeException, PHP_VERSION_ID}; use crate::dependency_resolver::rule::Rule; +use anyhow::Result; +use shirabe_php_shim::{PHP_VERSION_ID, RuntimeException, hash_raw, implode, unpack}; pub struct GenericRule { inner: Rule, @@ -10,7 +10,11 @@ pub struct GenericRule { } impl GenericRule { - pub fn new(mut literals: Vec<i64>, reason: shirabe_php_shim::PhpMixed, reason_data: shirabe_php_shim::PhpMixed) -> Self { + pub fn new( + mut literals: Vec<i64>, + reason: shirabe_php_shim::PhpMixed, + reason_data: shirabe_php_shim::PhpMixed, + ) -> Self { let inner = Rule::new(reason, reason_data); literals.sort(); Self { inner, literals } @@ -21,8 +25,17 @@ impl GenericRule { } pub fn get_hash(&self) -> Result<i64> { - let joined = self.literals.iter().map(|l| l.to_string()).collect::<Vec<_>>().join(","); - let algo = if PHP_VERSION_ID > 80100 { "xxh3" } else { "sha1" }; + let joined = self + .literals + .iter() + .map(|l| l.to_string()) + .collect::<Vec<_>>() + .join(","); + let algo = if PHP_VERSION_ID > 80100 { + "xxh3" + } else { + "sha1" + }; let binary = hash_raw(algo, &joined); let data = unpack("ihash", &binary); match data { @@ -33,13 +46,15 @@ impl GenericRule { Err(RuntimeException { message: format!("Failed unpacking: {}", joined), code: 0, - }.into()) + } + .into()) } } None => Err(RuntimeException { message: format!("Failed unpacking: {}", joined), code: 0, - }.into()), + } + .into()), } } @@ -52,7 +67,11 @@ impl GenericRule { } pub fn to_string(&self) -> String { - let prefix = if self.inner.is_disabled() { "disabled(" } else { "(" }; + let prefix = if self.inner.is_disabled() { + "disabled(" + } else { + "(" + }; let mut result = prefix.to_string(); for (i, literal) in self.literals.iter().enumerate() { if i != 0 { @@ -67,7 +86,9 @@ impl GenericRule { pub trait RuleLiterals { fn get_literals(&self) -> &Vec<i64>; - fn is_multi_conflict_rule(&self) -> bool { false } + fn is_multi_conflict_rule(&self) -> bool { + false + } } impl RuleLiterals for GenericRule { diff --git a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs index 5797a3b..dca5c1a 100644 --- a/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/local_repo_transaction.rs @@ -1,8 +1,8 @@ //! ref: composer/src/Composer/DependencyResolver/LocalRepoTransaction.php +use super::transaction::Transaction; use crate::repository::installed_repository_interface::InstalledRepositoryInterface; use crate::repository::repository_interface::RepositoryInterface; -use super::transaction::Transaction; #[derive(Debug)] pub struct LocalRepoTransaction { @@ -10,7 +10,10 @@ pub struct LocalRepoTransaction { } impl LocalRepoTransaction { - pub fn new(locked_repository: &dyn RepositoryInterface, local_repository: &dyn InstalledRepositoryInterface) -> Self { + pub fn new( + locked_repository: &dyn RepositoryInterface, + local_repository: &dyn InstalledRepositoryInterface, + ) -> Self { Self { inner: Transaction::new( local_repository.get_packages(), diff --git a/crates/shirabe/src/dependency_resolver/lock_transaction.rs b/crates/shirabe/src/dependency_resolver/lock_transaction.rs index 4b4cc32..44becb0 100644 --- a/crates/shirabe/src/dependency_resolver/lock_transaction.rs +++ b/crates/shirabe/src/dependency_resolver/lock_transaction.rs @@ -39,9 +39,8 @@ 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_box()).collect(); this.inner = Transaction::new(present, all); this } @@ -58,9 +57,15 @@ impl LockTransaction { if literal > 0 { let package = pool.literal_to_package(literal); - result_packages.get_mut("all").unwrap().push(package.clone_box()); + result_packages + .get_mut("all") + .unwrap() + .push(package.clone_box()); if !self.unlockable_map.contains_key(&package.get_id()) { - result_packages.get_mut("non-dev").unwrap().push(package.clone_box()); + result_packages + .get_mut("non-dev") + .unwrap() + .push(package.clone_box()); } } } @@ -81,22 +86,37 @@ impl LockTransaction { while i < remaining_dev.len() { if package.get_name() == remaining_dev[i].get_name() { let result_package = remaining_dev.remove(i); - self.result_packages.get_mut("non-dev").unwrap().push(result_package); + self.result_packages + .get_mut("non-dev") + .unwrap() + .push(result_package); } else { i += 1; } } } - self.result_packages.insert("dev".to_string(), remaining_dev); + self.result_packages + .insert("dev".to_string(), remaining_dev); } - pub fn get_new_lock_packages(&self, dev_mode: bool, update_mirrors: bool) -> Vec<Box<dyn PackageInterface>> { + pub fn get_new_lock_packages( + &self, + dev_mode: bool, + update_mirrors: bool, + ) -> Vec<Box<dyn PackageInterface>> { let key = if dev_mode { "dev" } else { "non-dev" }; let mut packages = vec![]; - let source = self.result_packages.get(key).map(|v| v.as_slice()).unwrap_or_default(); + let source = self + .result_packages + .get(key) + .map(|v| v.as_slice()) + .unwrap_or_default(); for package in source { - if (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>().is_some() { + if (package.as_any() as &dyn Any) + .downcast_ref::<AliasPackage>() + .is_some() + { continue; } @@ -129,7 +149,9 @@ impl LockTransaction { continue; } - if let Some(concrete_pkg) = (present_package.as_any() as &dyn Any).downcast_ref::<Package>() { + if let Some(concrete_pkg) = + (present_package.as_any() as &dyn Any).downcast_ref::<Package>() + { concrete_pkg.set_source_url(package.get_source_url()); concrete_pkg.set_source_mirrors(package.get_source_mirrors()); } @@ -167,10 +189,15 @@ impl LockTransaction { if let Some(all_packages) = self.result_packages.get("all") { for package in all_packages { - if (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>().is_some() { + if (package.as_any() as &dyn Any) + .downcast_ref::<AliasPackage>() + .is_some() + { let mut i = 0; while i < remaining_aliases.len() { - if remaining_aliases[i].get("package").map(|s| s.as_str()) == Some(package.get_name()) { + if remaining_aliases[i].get("package").map(|s| s.as_str()) + == Some(package.get_name()) + { used_aliases.push(remaining_aliases.remove(i)); } else { i += 1; @@ -189,7 +216,10 @@ impl LockTransaction { used_aliases } - pub fn get_operations(&self) -> &Vec<Box<dyn crate::dependency_resolver::operation::operation_interface::OperationInterface>> { + pub fn get_operations( + &self, + ) -> &Vec<Box<dyn crate::dependency_resolver::operation::operation_interface::OperationInterface>> + { self.inner.get_operations() } } diff --git a/crates/shirabe/src/dependency_resolver/mod.rs b/crates/shirabe/src/dependency_resolver/mod.rs new file mode 100644 index 0000000..9154084 --- /dev/null +++ b/crates/shirabe/src/dependency_resolver/mod.rs @@ -0,0 +1,26 @@ +pub mod decisions; +pub mod default_policy; +pub mod generic_rule; +pub mod local_repo_transaction; +pub mod lock_transaction; +pub mod multi_conflict_rule; +pub mod operation; +pub mod policy_interface; +pub mod pool; +pub mod pool_builder; +pub mod pool_optimizer; +pub mod problem; +pub mod request; +pub mod rule; +pub mod rule2_literals; +pub mod rule_set; +pub mod rule_set_generator; +pub mod rule_set_iterator; +pub mod rule_watch_chain; +pub mod rule_watch_graph; +pub mod rule_watch_node; +pub mod security_advisory_pool_filter; +pub mod solver; +pub mod solver_bug_exception; +pub mod solver_problems_exception; +pub mod transaction; diff --git a/crates/shirabe/src/dependency_resolver/multi_conflict_rule.rs b/crates/shirabe/src/dependency_resolver/multi_conflict_rule.rs index 172b6f4..b15434e 100644 --- a/crates/shirabe/src/dependency_resolver/multi_conflict_rule.rs +++ b/crates/shirabe/src/dependency_resolver/multi_conflict_rule.rs @@ -1,9 +1,9 @@ //! ref: composer/src/Composer/DependencyResolver/MultiConflictRule.php -use anyhow::Result; -use shirabe_php_shim::{hash_raw, PHP_VERSION_ID, RuntimeException}; use crate::dependency_resolver::generic_rule::RuleLiterals; use crate::dependency_resolver::rule::Rule; +use anyhow::Result; +use shirabe_php_shim::{PHP_VERSION_ID, RuntimeException, hash_raw}; #[derive(Debug)] pub struct MultiConflictRule { @@ -12,12 +12,17 @@ pub struct MultiConflictRule { } impl MultiConflictRule { - pub fn new(mut literals: Vec<i64>, reason: shirabe_php_shim::PhpMixed, reason_data: shirabe_php_shim::PhpMixed) -> Result<Self> { + pub fn new( + mut literals: Vec<i64>, + reason: shirabe_php_shim::PhpMixed, + reason_data: shirabe_php_shim::PhpMixed, + ) -> Result<Self> { if literals.len() < 3 { return Err(RuntimeException { message: "multi conflict rule requires at least 3 literals".to_string(), code: 0, - }.into()); + } + .into()); } // sort all packages ascending by id @@ -34,8 +39,17 @@ impl MultiConflictRule { } pub fn get_hash(&self) -> Result<i64> { - let joined = self.literals.iter().map(|l| l.to_string()).collect::<Vec<_>>().join(","); - let algo = if PHP_VERSION_ID > 80100 { "xxh3" } else { "sha1" }; + let joined = self + .literals + .iter() + .map(|l| l.to_string()) + .collect::<Vec<_>>() + .join(","); + let algo = if PHP_VERSION_ID > 80100 { + "xxh3" + } else { + "sha1" + }; let binary = hash_raw(algo, &format!("c:{}", joined)); let data = shirabe_php_shim::unpack("ihash", &binary); match data { @@ -46,13 +60,15 @@ impl MultiConflictRule { Err(RuntimeException { message: format!("Failed unpacking: {}", joined), code: 0, - }.into()) + } + .into()) } } None => Err(RuntimeException { message: format!("Failed unpacking: {}", joined), code: 0, - }.into()), + } + .into()), } } diff --git a/crates/shirabe/src/dependency_resolver/operation/mod.rs b/crates/shirabe/src/dependency_resolver/operation/mod.rs new file mode 100644 index 0000000..ffb0ac7 --- /dev/null +++ b/crates/shirabe/src/dependency_resolver/operation/mod.rs @@ -0,0 +1,7 @@ +pub mod install_operation; +pub mod mark_alias_installed_operation; +pub mod mark_alias_uninstalled_operation; +pub mod operation_interface; +pub mod solver_operation; +pub mod uninstall_operation; +pub mod update_operation; diff --git a/crates/shirabe/src/dependency_resolver/operation/update_operation.rs b/crates/shirabe/src/dependency_resolver/operation/update_operation.rs index eb6e9d6..618ecee 100644 --- a/crates/shirabe/src/dependency_resolver/operation/update_operation.rs +++ b/crates/shirabe/src/dependency_resolver/operation/update_operation.rs @@ -13,7 +13,10 @@ pub struct UpdateOperation { impl UpdateOperation { pub fn new(initial: Box<dyn PackageInterface>, target: Box<dyn PackageInterface>) -> Self { - Self { initial_package: initial, target_package: target } + Self { + initial_package: initial, + target_package: target, + } } pub fn get_initial_package(&self) -> &dyn PackageInterface { @@ -24,19 +27,36 @@ impl UpdateOperation { self.target_package.as_ref() } - pub fn format(initial_package: &dyn PackageInterface, 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); + pub fn format( + initial_package: &dyn PackageInterface, + 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); - 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); - } 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); + 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); + } 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); } - let action_name = if VersionParser::is_upgrade(&initial_package.get_version(), &target_package.get_version()) { + let action_name = if VersionParser::is_upgrade( + &initial_package.get_version(), + &target_package.get_version(), + ) { "Upgrading" } else { "Downgrading" @@ -62,7 +82,11 @@ impl OperationInterface for UpdateOperation { } fn show(&self, lock: bool) -> String { - Self::format(self.initial_package.as_ref(), self.target_package.as_ref(), lock) + Self::format( + self.initial_package.as_ref(), + self.target_package.as_ref(), + lock, + ) } fn to_string(&self) -> String { diff --git a/crates/shirabe/src/dependency_resolver/policy_interface.rs b/crates/shirabe/src/dependency_resolver/policy_interface.rs index 279cf38..a48cd4b 100644 --- a/crates/shirabe/src/dependency_resolver/policy_interface.rs +++ b/crates/shirabe/src/dependency_resolver/policy_interface.rs @@ -4,7 +4,17 @@ use crate::dependency_resolver::pool::Pool; use crate::package::package_interface::PackageInterface; pub trait PolicyInterface { - fn version_compare(&self, a: &dyn PackageInterface, b: &dyn PackageInterface, operator: &str) -> bool; + fn version_compare( + &self, + a: &dyn PackageInterface, + b: &dyn PackageInterface, + operator: &str, + ) -> bool; - fn select_preferred_packages(&self, pool: &Pool, literals: Vec<i64>, required_package: Option<String>) -> Vec<i64>; + fn select_preferred_packages( + &self, + pool: &Pool, + literals: Vec<i64>, + required_package: Option<String>, + ) -> Vec<i64>; } diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index c783f45..e86e4c2 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -3,7 +3,7 @@ use std::fmt; use indexmap::IndexMap; -use shirabe_php_shim::{abs, spl_object_hash, str_pad, Countable, STR_PAD_LEFT}; +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::Constraint; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; @@ -48,10 +48,7 @@ impl Pool { unacceptable_fixed_or_locked_packages: Vec<Box<BasePackage>>, removed_versions: IndexMap<String, IndexMap<String, String>>, removed_versions_by_package: IndexMap<String, IndexMap<String, String>>, - security_removed_versions: IndexMap< - String, - IndexMap<String, Vec<PartialSecurityAdvisory>>, - >, + security_removed_versions: IndexMap<String, IndexMap<String, Vec<PartialSecurityAdvisory>>>, abandoned_removed_versions: IndexMap<String, IndexMap<String, String>>, ) -> Self { let mut this = Self { @@ -116,7 +113,10 @@ impl Pool { constraint: Option<&dyn ConstraintInterface>, ) -> bool { let empty = IndexMap::new(); - let versions = self.security_removed_versions.get(package_name).unwrap_or(&empty); + let versions = self + .security_removed_versions + .get(package_name) + .unwrap_or(&empty); for (version, _package_with_security_advisories) in versions { if let Some(c) = constraint { if c.matches(&Constraint::new("==", version)) { @@ -135,7 +135,10 @@ impl Pool { constraint: Option<&dyn ConstraintInterface>, ) -> Vec<String> { let empty = IndexMap::new(); - let versions = self.security_removed_versions.get(package_name).unwrap_or(&empty); + let versions = self + .security_removed_versions + .get(package_name) + .unwrap_or(&empty); for (version, package_with_security_advisories) in versions { if let Some(c) = constraint { if c.matches(&Constraint::new("==", version)) { @@ -156,7 +159,10 @@ impl Pool { constraint: Option<&dyn ConstraintInterface>, ) -> bool { let empty = IndexMap::new(); - let versions = self.abandoned_removed_versions.get(package_name).unwrap_or(&empty); + let versions = self + .abandoned_removed_versions + .get(package_name) + .unwrap_or(&empty); for (version, _pretty_version) in versions { if let Some(c) = constraint { if c.matches(&Constraint::new("==", version)) { @@ -280,11 +286,7 @@ impl Pool { let package = self.literal_to_package(literal); let prefix = if installed_map.contains_key(&package.id) { - if literal > 0 { - "keep" - } else { - "remove" - } + if literal > 0 { "keep" } else { "remove" } } else { if literal > 0 { "install" @@ -328,8 +330,7 @@ impl Pool { if replaces.contains_key("0") || provides.contains_key("0") { for link in provides.values() { if link.get_target() == name - && (constraint.is_none() - || constraint.unwrap().matches(link.get_constraint())) + && (constraint.is_none() || constraint.unwrap().matches(link.get_constraint())) { return true; } @@ -337,8 +338,7 @@ impl Pool { for link in replaces.values() { if link.get_target() == name - && (constraint.is_none() - || constraint.unwrap().matches(link.get_constraint())) + && (constraint.is_none() || constraint.unwrap().matches(link.get_constraint())) { return true; } diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index 0d99587..f518545 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -6,8 +6,8 @@ use shirabe_external_packages::composer::pcre::preg::Preg; use shirabe_external_packages::composer::semver::compiling_matcher::CompilingMatcher; use shirabe_external_packages::composer::semver::intervals::Intervals; use shirabe_php_shim::{ - array_chunk, array_flip, array_map, array_merge, array_search, count, in_array, microtime, - number_format, round, spl_object_hash, sprintf, strpos, LogicException, PhpMixed, + LogicException, PhpMixed, array_chunk, array_flip, array_map, array_merge, array_search, count, + in_array, microtime, number_format, round, spl_object_hash, sprintf, strpos, }; use shirabe_semver::constraint::constraint::Constraint; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; @@ -126,7 +126,11 @@ impl PoolBuilder { self.allowed_types = types; } - pub fn build_pool(&mut self, repositories: Vec<Box<dyn RepositoryInterface>>, request: &mut Request) -> anyhow::Result<Pool> { + pub fn build_pool( + &mut self, + repositories: Vec<Box<dyn RepositoryInterface>>, + request: &mut Request, + ) -> anyhow::Result<Pool> { self.restricted_packages_list = if request.get_restricted_packages().is_some() { Some(array_flip(&request.get_restricted_packages().unwrap())) } else { @@ -139,7 +143,8 @@ impl PoolBuilder { if request.get_locked_repository().is_none() { return Err(LogicException { - message: "No lock repo present and yet a partial update was requested.".to_string(), + message: "No lock repo present and yet a partial update was requested." + .to_string(), code: 0, } .into()); @@ -165,9 +170,13 @@ impl PoolBuilder { // if they do get unlocked, but by default they are unlocked without update propagation. if locked_package.get_dist_type().as_deref() == Some("path") { let transport_options = locked_package.get_transport_options(); - let symlink_disabled = transport_options.get("symlink").map(|v| v.as_bool() == Some(false)).unwrap_or(false); + let symlink_disabled = transport_options + .get("symlink") + .map(|v| v.as_bool() == Some(false)) + .unwrap_or(false); if !transport_options.contains_key("symlink") || !symlink_disabled { - self.path_repo_unlocked.insert(locked_package.get_name().to_string(), true); + self.path_repo_unlocked + .insert(locked_package.get_name().to_string(), true); continue; } } @@ -180,11 +189,17 @@ impl PoolBuilder { for package in request.get_fixed_or_locked_packages() { // using MatchAllConstraint here because fixed packages do not need to retrigger // loading any packages - self.loaded_packages.insert(package.get_name().to_string(), Box::new(MatchAllConstraint::new())); + self.loaded_packages.insert( + package.get_name().to_string(), + Box::new(MatchAllConstraint::new()), + ); // 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())); + self.loaded_packages.insert( + link.get_target().to_string(), + Box::new(MatchAllConstraint::new()), + ); } // TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to @@ -193,7 +208,8 @@ impl PoolBuilder { let in_root_or_platform = package .get_repository() .map(|r| { - r.as_any().is::<RootPackageRepository>() || r.as_any().is::<PlatformRepository>() + r.as_any().is::<RootPackageRepository>() + || r.as_any().is::<PlatformRepository>() }) .unwrap_or(false); if in_root_or_platform @@ -206,7 +222,8 @@ impl PoolBuilder { { self.load_package(request, &repositories, &*package, false)?; } else { - self.unacceptable_fixed_or_locked_packages.push(package.clone_box()); + self.unacceptable_fixed_or_locked_packages + .push(package.clone_box()); } } @@ -216,7 +233,8 @@ impl PoolBuilder { continue; } - self.packages_to_load.insert(package_name.clone(), constraint.clone_box()); + self.packages_to_load + .insert(package_name.clone(), constraint.clone_box()); self.max_extended_reqs.insert(package_name.clone(), true); } @@ -253,7 +271,8 @@ impl PoolBuilder { None => continue, }; - let mut package_and_aliases: IndexMap<i64, Box<dyn BasePackage>> = IndexMap::new(); + let mut package_and_aliases: IndexMap<i64, Box<dyn BasePackage>> = + IndexMap::new(); package_and_aliases.insert(i, package.clone_box()); if let Some(aliases) = self.alias_map.get(&spl_object_hash(&*package)) { for (idx, alias) in aliases { @@ -263,7 +282,11 @@ impl PoolBuilder { let mut found = false; for (_idx, package_or_alias) in &package_and_aliases { - if CompilingMatcher::matches(&*constraint, Constraint::OP_EQ, package_or_alias.get_version()) { + if CompilingMatcher::matches( + &*constraint, + Constraint::OP_EQ, + package_or_alias.get_version(), + ) { found = true; } } @@ -287,7 +310,10 @@ impl PoolBuilder { self.root_aliases.clone(), self.root_references.clone(), self.packages.values().map(|p| p.clone_box()).collect(), - self.unacceptable_fixed_or_locked_packages.iter().map(|p| p.clone_box()).collect(), + self.unacceptable_fixed_or_locked_packages + .iter() + .map(|p| p.clone_box()) + .collect(), ); self.event_dispatcher .as_mut() @@ -300,12 +326,16 @@ impl PoolBuilder { .enumerate() .map(|(i, p)| (i as i64, p)) .collect(); - self.unacceptable_fixed_or_locked_packages = pre_pool_create_event.get_unacceptable_fixed_packages(); + self.unacceptable_fixed_or_locked_packages = + pre_pool_create_event.get_unacceptable_fixed_packages(); } let mut pool = Pool::new( self.packages.values().map(|p| p.clone_box()).collect(), - self.unacceptable_fixed_or_locked_packages.iter().map(|p| p.clone_box()).collect(), + self.unacceptable_fixed_or_locked_packages + .iter() + .map(|p| p.clone_box()) + .collect(), ); self.alias_map = IndexMap::new(); @@ -330,7 +360,12 @@ impl PoolBuilder { Ok(pool) } - fn mark_package_name_for_loading(&mut self, request: &Request, name: &str, constraint: Box<dyn ConstraintInterface>) { + fn mark_package_name_for_loading( + &mut self, + request: &Request, + name: &str, + constraint: Box<dyn ConstraintInterface>, + ) { // Skip platform requires at this stage if PlatformRepository::is_platform_package(name) { return; @@ -399,7 +434,11 @@ impl PoolBuilder { self.loaded_packages.shift_remove(name); } - fn load_packages_marked_for_loading(&mut self, request: &mut Request, repositories: &Vec<Box<dyn RepositoryInterface>>) -> anyhow::Result<()> { + fn load_packages_marked_for_loading( + &mut self, + request: &mut Request, + repositories: &Vec<Box<dyn RepositoryInterface>>, + ) -> anyhow::Result<()> { let to_remove: Vec<String> = self .packages_to_load .keys() @@ -420,7 +459,8 @@ impl PoolBuilder { .map(|(k, v)| (k.clone(), v.clone_box())) .collect(); for (name, constraint) in &snapshot { - self.loaded_packages.insert(name.clone(), constraint.clone_box()); + self.loaded_packages + .insert(name.clone(), constraint.clone_box()); } // Load packages in chunks of 50 to prevent memory usage build-up due to caches of all sorts @@ -432,7 +472,12 @@ impl PoolBuilder { // never need to load anything else from them let is_locked_repo = request .get_locked_repository() - .map(|lr| std::ptr::eq(lr as *const _ as *const u8, repository.as_ref() as *const _ as *const u8)) + .map(|lr| { + std::ptr::eq( + lr as *const _ as *const u8, + repository.as_ref() as *const _ as *const u8, + ) + }) .unwrap_or(false); if repository.as_any().is::<PlatformRepository>() || is_locked_repo { continue; @@ -447,17 +492,28 @@ impl PoolBuilder { package_batch, &self.acceptable_stabilities, &self.stability_flags, - self.loaded_per_repo.get(&(repo_index as i64)).cloned().unwrap_or_default(), + self.loaded_per_repo + .get(&(repo_index as i64)) + .cloned() + .unwrap_or_default(), ); - let names_found = result.get("namesFound").and_then(|v| v.as_list()).cloned().unwrap_or_default(); + let names_found = result + .get("namesFound") + .and_then(|v| v.as_list()) + .cloned() + .unwrap_or_default(); for name in &names_found { // avoid loading the same package again from other repositories once it has been found if let Some(b) = package_batches.get_mut(batch_index) { b.shift_remove(name.as_string().unwrap_or("")); } } - let packages_in_result = result.get("packages").and_then(|v| v.as_list()).cloned().unwrap_or_default(); + let packages_in_result = result + .get("packages") + .and_then(|v| v.as_list()) + .cloned() + .unwrap_or_default(); for package in &packages_in_result { let pkg = match package.as_package_interface() { Some(p) => p, @@ -472,7 +528,11 @@ impl PoolBuilder { if in_array(pkg.get_type(), &self.ignored_types, true) || (self.allowed_types.is_some() - && !in_array(pkg.get_type(), self.allowed_types.as_ref().unwrap(), true)) + && !in_array( + pkg.get_type(), + self.allowed_types.as_ref().unwrap(), + true, + )) { continue; } @@ -495,7 +555,13 @@ impl PoolBuilder { Ok(()) } - fn load_package(&mut self, request: &mut Request, repositories: &Vec<Box<dyn RepositoryInterface>>, package: &dyn BasePackage, propagate_update: bool) -> anyhow::Result<()> { + fn load_package( + &mut self, + request: &mut Request, + repositories: &Vec<Box<dyn RepositoryInterface>>, + package: &dyn BasePackage, + propagate_update: bool, + ) -> anyhow::Result<()> { let index = self.index_counter; self.index_counter += 1; self.packages.insert(index, package.clone_box()); @@ -537,19 +603,20 @@ impl PoolBuilder { } else { package.clone_box() }; - let alias_package: Box<dyn BasePackage> = if base_package.as_any().is::<CompletePackage>() { - Box::new(CompleteAliasPackage::new( - base_package.clone_box(), - alias.get("alias_normalized").cloned().unwrap_or_default(), - alias.get("alias").cloned().unwrap_or_default(), - )) - } else { - Box::new(AliasPackage::new( - base_package.clone_box(), - alias.get("alias_normalized").cloned().unwrap_or_default(), - alias.get("alias").cloned().unwrap_or_default(), - )) - }; + let alias_package: Box<dyn BasePackage> = + if base_package.as_any().is::<CompletePackage>() { + Box::new(CompleteAliasPackage::new( + base_package.clone_box(), + alias.get("alias_normalized").cloned().unwrap_or_default(), + alias.get("alias").cloned().unwrap_or_default(), + )) + } else { + Box::new(AliasPackage::new( + base_package.clone_box(), + alias.get("alias_normalized").cloned().unwrap_or_default(), + alias.get("alias").cloned().unwrap_or_default(), + )) + }; // PHP: $aliasPackage->setRootPackageAlias(true); // BasePackage doesn't expose this directly; the AliasPackage trait method handles it. @@ -577,7 +644,9 @@ impl PoolBuilder { if propagate_update && request.get_update_allow_transitive_dependencies() { let skipped_root_requires = self.get_skipped_root_requires(request, &require); - if request.get_update_allow_transitive_root_dependencies() || 0 == count(&skipped_root_requires) { + if request.get_update_allow_transitive_root_dependencies() + || 0 == count(&skipped_root_requires) + { self.unlock_package(request, repositories, &require)?; self.mark_package_name_for_loading(request, &require, link_constraint); } else { @@ -588,7 +657,9 @@ impl PoolBuilder { } } } - } else if self.path_repo_unlocked.contains_key(&require) && !self.loaded_packages.contains_key(&require) { + } else if self.path_repo_unlocked.contains_key(&require) + && !self.loaded_packages.contains_key(&require) + { // if doing a partial update and a package depends on a path-repo-unlocked package which is not referenced by the root, we need to ensure it gets loaded as it was not loaded by the request's root requirements // and would not be loaded above if update propagation is not allowed (which happens if the requirer is itself a path-repo-unlocked package) or if transitive deps are not allowed to be unlocked self.mark_package_name_for_loading(request, &require, link_constraint); @@ -603,10 +674,14 @@ impl PoolBuilder { if propagate_update && request.get_update_allow_transitive_dependencies() { for (_k, link) in &package.get_replaces() { let replace = link.get_target().to_string(); - if self.loaded_packages.contains_key(&replace) && self.skipped_load.contains_key(&replace) { + if self.loaded_packages.contains_key(&replace) + && self.skipped_load.contains_key(&replace) + { let skipped_root_requires = self.get_skipped_root_requires(request, &replace); - if request.get_update_allow_transitive_root_dependencies() || 0 == count(&skipped_root_requires) { + if request.get_update_allow_transitive_root_dependencies() + || 0 == count(&skipped_root_requires) + { self.unlock_package(request, repositories, &replace)?; // the replaced package only needs to be loaded if something else requires it self.mark_package_name_for_loading_if_required(request, &replace); @@ -660,7 +735,11 @@ impl PoolBuilder { for (_k, link) in &package_or_replacer.get_replaces() { if root_requires.contains_key(link.get_target()) { if name != package_or_replacer.get_name() { - matches.push(format!("{} (via replace of {})", package_or_replacer.get_name(), name)); + matches.push(format!( + "{} (via replace of {})", + package_or_replacer.get_name(), + name + )); } else { matches.push(package_or_replacer.get_name().to_string()); } @@ -735,7 +814,12 @@ impl PoolBuilder { /// Reverts the decision to use a locked package if a partial update with transitive dependencies /// found that this package actually needs to be updated - fn unlock_package(&mut self, request: &mut Request, repositories: &Vec<Box<dyn RepositoryInterface>>, name: &str) -> anyhow::Result<()> { + fn unlock_package( + &mut self, + request: &mut Request, + repositories: &Vec<Box<dyn RepositoryInterface>>, + name: &str, + ) -> anyhow::Result<()> { let skipped: Vec<Box<dyn PackageInterface>> = self .skipped_load .get(name) @@ -744,21 +828,35 @@ impl PoolBuilder { for package_or_replacer in &skipped { // if we unfixed a replaced package name, we also need to unfix the replacer itself // as long as it was not unfixed yet - if package_or_replacer.get_name() != name && self.skipped_load.contains_key(package_or_replacer.get_name()) { + if package_or_replacer.get_name() != name + && self + .skipped_load + .contains_key(package_or_replacer.get_name()) + { let replacer_name = package_or_replacer.get_name().to_string(); if request.get_update_allow_transitive_root_dependencies() - || (!self.is_root_require(request, name) && !self.is_root_require(request, &replacer_name)) + || (!self.is_root_require(request, name) + && !self.is_root_require(request, &replacer_name)) { self.unlock_package(request, repositories, &replacer_name)?; if self.is_root_require(request, &replacer_name) { - self.mark_package_name_for_loading(request, &replacer_name, Box::new(MatchAllConstraint::new())); + self.mark_package_name_for_loading( + request, + &replacer_name, + Box::new(MatchAllConstraint::new()), + ); } else { - let pkgs: Vec<Box<dyn BasePackage>> = self.packages.values().map(|p| p.clone_box()).collect(); + let pkgs: Vec<Box<dyn BasePackage>> = + self.packages.values().map(|p| p.clone_box()).collect(); for loaded_package in &pkgs { let requires = loaded_package.get_requires(); if let Some(req_link) = requires.get(&replacer_name) { - self.mark_package_name_for_loading(request, &replacer_name, req_link.get_constraint()); + self.mark_package_name_for_loading( + request, + &replacer_name, + req_link.get_constraint(), + ); } } } @@ -784,10 +882,15 @@ impl PoolBuilder { self.path_repo_unlocked.shift_remove(name); // remove locked package by this name which was already initialized - let locked_packages: Vec<Box<dyn BasePackage>> = request.get_locked_packages().iter().map(|p| p.clone_box()).collect(); + let locked_packages: Vec<Box<dyn BasePackage>> = request + .get_locked_packages() + .iter() + .map(|p| p.clone_box()) + .collect(); for locked_package in &locked_packages { if locked_package.as_alias_package().is_none() && locked_package.get_name() == name { - let pkgs: Vec<Box<dyn BasePackage>> = self.packages.values().map(|p| p.clone_box()).collect(); + let pkgs: Vec<Box<dyn BasePackage>> = + self.packages.values().map(|p| p.clone_box()).collect(); let index_opt = array_search(&**locked_package, &pkgs, true); if let Some(index) = index_opt { request.unlock_package(&**locked_package); @@ -798,23 +901,47 @@ impl PoolBuilder { // satisfied their requirements // and if this package is replacing another that is required by a locked or fixed package, ensure // that we load that replaced package in case an update to this package removes the replacement - let fixed_or_locked: Vec<Box<dyn BasePackage>> = request.get_fixed_or_locked_packages().iter().map(|p| p.clone_box()).collect(); + let fixed_or_locked: Vec<Box<dyn BasePackage>> = request + .get_fixed_or_locked_packages() + .iter() + .map(|p| p.clone_box()) + .collect(); for fixed_or_locked_package in &fixed_or_locked { - if std::ptr::eq(fixed_or_locked_package.as_ref() as *const _, locked_package.as_ref() as *const _) { + if std::ptr::eq( + fixed_or_locked_package.as_ref() as *const _, + locked_package.as_ref() as *const _, + ) { continue; } - if self.skipped_load.contains_key(fixed_or_locked_package.get_name()) { + if self + .skipped_load + .contains_key(fixed_or_locked_package.get_name()) + { let requires = fixed_or_locked_package.get_requires(); if let Some(req_link) = requires.get(locked_package.get_name()) { - self.mark_package_name_for_loading(request, locked_package.get_name(), req_link.get_constraint()); + self.mark_package_name_for_loading( + request, + locked_package.get_name(), + req_link.get_constraint(), + ); } for (_k, replace) in &locked_package.get_replaces() { - if requires.contains_key(replace.get_target()) && self.skipped_load.contains_key(replace.get_target()) { - self.unlock_package(request, repositories, replace.get_target())?; + if requires.contains_key(replace.get_target()) + && self.skipped_load.contains_key(replace.get_target()) + { + self.unlock_package( + request, + repositories, + replace.get_target(), + )?; // this package is in $requires so no need to call markPackageNameForLoadingIfRequired - self.mark_package_name_for_loading(request, replace.get_target(), replace.get_constraint()); + self.mark_package_name_for_loading( + request, + replace.get_target(), + replace.get_constraint(), + ); } } } @@ -827,21 +954,37 @@ impl PoolBuilder { fn mark_package_name_for_loading_if_required(&mut self, request: &Request, name: &str) { if self.is_root_require(request, name) { - self.mark_package_name_for_loading(request, name, request.get_requires()[name].clone_box()); + self.mark_package_name_for_loading( + request, + name, + request.get_requires()[name].clone_box(), + ); } - let pkgs: Vec<Box<dyn BasePackage>> = self.packages.values().map(|p| p.clone_box()).collect(); + let pkgs: Vec<Box<dyn BasePackage>> = + self.packages.values().map(|p| p.clone_box()).collect(); for package in &pkgs { for (_k, link) in &package.get_requires() { if name == link.get_target() { - self.mark_package_name_for_loading(request, link.get_target(), link.get_constraint()); + self.mark_package_name_for_loading( + request, + link.get_target(), + link.get_constraint(), + ); } } } } - fn remove_loaded_package(&mut self, _request: &Request, repositories: &Vec<Box<dyn RepositoryInterface>>, package: &dyn BasePackage, index: i64) { - let repos_box: Vec<Box<dyn RepositoryInterface>> = repositories.iter().map(|r| r.clone_box()).collect(); + fn remove_loaded_package( + &mut self, + _request: &Request, + repositories: &Vec<Box<dyn RepositoryInterface>>, + package: &dyn BasePackage, + index: i64, + ) { + let repos_box: Vec<Box<dyn RepositoryInterface>> = + repositories.iter().map(|r| r.clone_box()).collect(); let repo_index = match package.get_repository() { Some(repo) => array_search(&*repo, &repos_box, true).unwrap_or(-1), None => -1, @@ -881,7 +1024,11 @@ impl PoolBuilder { let before = microtime(true); let total = count(&pool.get_packages()) as f64; - let pool = self.pool_optimizer.as_mut().unwrap().optimize(request, pool); + let pool = self + .pool_optimizer + .as_mut() + .unwrap() + .optimize(request, pool); let filtered = total - (count(&pool.get_packages()) as f64); @@ -890,7 +1037,10 @@ impl PoolBuilder { } self.io.write_with_verbosity( - &sprintf("Pool optimizer completed in %.3f seconds", &[(microtime(true) - before).into()]), + &sprintf( + "Pool optimizer completed in %.3f seconds", + &[(microtime(true) - before).into()], + ), true, IOInterface::VERY_VERBOSE, ); @@ -910,7 +1060,12 @@ impl PoolBuilder { pool } - fn run_security_advisory_filter(&mut self, pool: Pool, repositories: &Vec<Box<dyn RepositoryInterface>>, request: &Request) -> Pool { + fn run_security_advisory_filter( + &mut self, + pool: Pool, + repositories: &Vec<Box<dyn RepositoryInterface>>, + request: &Request, + ) -> Pool { if self.security_advisory_pool_filter.is_none() { return pool; } @@ -920,7 +1075,11 @@ impl PoolBuilder { let before = microtime(true); let total = count(&pool.get_packages()) as f64; - let pool = self.security_advisory_pool_filter.as_mut().unwrap().filter(pool, repositories, request); + let pool = self.security_advisory_pool_filter.as_mut().unwrap().filter( + pool, + repositories, + request, + ); let filtered = total - (count(&pool.get_packages()) as f64); @@ -929,7 +1088,10 @@ impl PoolBuilder { } self.io.write_with_verbosity( - &sprintf("Security advisory pool filter completed in %.3f seconds", &[(microtime(true) - before).into()]), + &sprintf( + "Security advisory pool filter completed in %.3f seconds", + &[(microtime(true) - before).into()], + ), true, IOInterface::VERY_VERBOSE, ); diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs index 94b6771..b71af14 100644 --- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs +++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs @@ -4,7 +4,7 @@ use std::any::Any; use anyhow::Result; use indexmap::IndexMap; -use shirabe_php_shim::{implode, ksort, spl_object_hash, LogicException, PhpMixed}; +use shirabe_php_shim::{LogicException, PhpMixed, implode, ksort, spl_object_hash}; use shirabe_semver::compiling_matcher::CompilingMatcher; use shirabe_semver::constraint::constraint::Constraint; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; @@ -28,7 +28,8 @@ 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, Box<dyn ConstraintInterface>>>, /// @var array<string, array<string, ConstraintInterface>> conflict_constraints_per_package: @@ -104,10 +105,7 @@ impl PoolOptimizer { // 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, todo!("constraint.clone_box()")); } // First pass over all packages to extract information and mark package constraints irremovable @@ -131,9 +129,7 @@ impl PoolOptimizer { // Keep track of alias packages for every package so if either the alias or aliased is kept // we keep the others as they are a unit of packages really - if let Some(alias_pkg) = - (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() - { + if let Some(alias_pkg) = (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { self.aliases_per_package .entry(alias_pkg.get_alias_of().id) .or_insert_with(Vec::new) @@ -162,7 +158,9 @@ impl PoolOptimizer { continue; } - let constraint = irremovable_package_constraints.get(package.get_name()).unwrap(); + let constraint = irremovable_package_constraints + .get(package.get_name()) + .unwrap(); if CompilingMatcher::r#match( constraint.as_ref(), Constraint::OP_EQ, @@ -175,9 +173,7 @@ impl PoolOptimizer { fn mark_package_irremovable(&mut self, package: &BasePackage) { self.irremovable_packages.insert(package.id, true); - if let Some(alias_pkg) = - (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() - { + if let Some(alias_pkg) = (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { // recursing here so aliasesPerPackage for the aliasOf can be checked // and all its aliases marked as irremovable as well self.mark_package_irremovable(alias_pkg.get_alias_of()); @@ -279,8 +275,7 @@ impl PoolOptimizer { package.get_version(), ) { // Use the same hash part as the regular require hash because that's what the replacement does - group_hash_parts - .push(format!("require:{}", link.get_constraint())); + group_hash_parts.push(format!("require:{}", link.get_constraint())); } } } @@ -294,8 +289,7 @@ impl PoolOptimizer { Constraint::OP_EQ, package.get_version(), ) { - group_hash_parts - .push(format!("conflict:{}", conflict_constraint)); + group_hash_parts.push(format!("conflict:{}", conflict_constraint)); } } } @@ -350,7 +344,10 @@ 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()) + { self.keep_package( &pool.literal_to_package(preferred_literal), &identical_definitions_per_package, @@ -392,7 +389,10 @@ impl PoolOptimizer { // However, the majority of projects are going to specify their constraints already pretty // much in the best variant possible. In other words, we'd be wasting time here and it would actually hurt // 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()); + subhash.insert( + link.get_target().to_string(), + link.get_constraint().to_string(), + ); } // Sort for best result @@ -442,9 +442,7 @@ impl PoolOptimizer { self.packages_to_remove.shift_remove(&package.id); - if let Some(alias_pkg) = - (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() - { + if let Some(alias_pkg) = (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { // recursing here so aliasesPerPackage for the aliasOf can be checked // and all its aliases marked to be kept as well self.keep_package( @@ -467,7 +465,9 @@ impl PoolOptimizer { let pkg = if let Some(alias_pkg) = (pkg.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { - if alias_pkg.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS { + if alias_pkg.get_pretty_version() + == VersionParser::DEFAULT_BRANCH_ALIAS + { alias_pkg.get_alias_of().clone_box() } else { pkg.clone_box() @@ -498,9 +498,7 @@ impl PoolOptimizer { // 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) - { + if let Some(per_name) = package_identical_definition_lookup.get(&alias_package.id) { if let Some(package_group_pointers) = per_name.get(&name) { let package_group = identical_definitions_per_package .get(&name) diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs index 0108487..50b651d 100644 --- a/crates/shirabe/src/dependency_resolver/problem.rs +++ b/crates/shirabe/src/dependency_resolver/problem.rs @@ -5,9 +5,9 @@ use indexmap::IndexMap; use shirabe_external_packages::composer::pcre::preg::Preg; use shirabe_external_packages::symfony::console::formatter::output_formatter::OutputFormatter; use shirabe_php_shim::{ - defined, extension_loaded, implode, in_array, php_to_string, phpversion, sprintf, - spl_object_hash, str_replace, str_starts_with, stripos, strpos, strtolower, substr, - substr_count, version_compare, LogicException, PhpMixed, + LogicException, PhpMixed, defined, extension_loaded, implode, in_array, php_to_string, + phpversion, spl_object_hash, sprintf, str_replace, str_starts_with, stripos, strpos, + strtolower, substr, substr_count, version_compare, }; use shirabe_semver::constraint::constraint::Constraint; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; @@ -134,10 +134,7 @@ impl Problem { fn get_sortable_string(&self, pool: &Pool, rule: &Rule) -> String { match rule.get_reason() { - Rule::RULE_ROOT_REQUIRE => rule - .get_reason_data() - .as_array() - .unwrap()["packageName"] + Rule::RULE_ROOT_REQUIRE => rule.get_reason_data().as_array().unwrap()["packageName"] .as_string() .unwrap() .to_string(), @@ -302,12 +299,9 @@ impl Problem { }; if versions_list.len() > 1 { // remove the s from requires/conflicts to correct grammar - let message_var = Preg::replace( - r"{^(%s%s (?:require|conflict))s}", - "$1", - message, - ) - .unwrap_or(message.clone()); + let message_var = + Preg::replace(r"{^(%s%s (?:require|conflict))s}", "$1", message) + .unwrap_or(message.clone()); result.push(sprintf( &message_var, &[ @@ -331,7 +325,11 @@ impl Problem { } } - format!("\n{}- {}", indent, implode(&format!("\n{}- ", indent), &result)) + format!( + "\n{}- {}", + indent, + implode(&format!("\n{}- ", indent), &result) + ) } pub fn is_caused_by_lock( @@ -585,7 +583,13 @@ impl Problem { ), format!( "found {}. The # character in branch names is replaced by a + character. Make sure to require it as \"{}\".", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ), str_replace("#", "+", &c.get_pretty_string()) ), ); @@ -602,8 +606,7 @@ impl Problem { let filtered: Vec<&Box<dyn PackageInterface>> = packages .iter() .filter(|p| { - root_reqs[package_name] - .matches(&Constraint::new("==", &p.get_version())) + root_reqs[package_name].matches(&Constraint::new("==", &p.get_version())) }) .collect(); if filtered.len() == 0 { @@ -615,7 +618,13 @@ impl Problem { ), format!( "found {} but {} with your root composer.json require ({}).", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ), if Self::has_multiple_names(&packages) { "these conflict" } else { @@ -646,7 +655,13 @@ impl Problem { ), format!( "found {} but {} with your temporary update constraint ({}:{}).", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ), if Self::has_multiple_names(&packages) { "these conflict" } else { @@ -664,9 +679,7 @@ impl Problem { let fixed_constraint = Constraint::new("==", &lp.get_version()); let filtered: Vec<&Box<dyn PackageInterface>> = packages .iter() - .filter(|p| { - fixed_constraint.matches(&Constraint::new("==", &p.get_version())) - }) + .filter(|p| fixed_constraint.matches(&Constraint::new("==", &p.get_version()))) .collect(); if filtered.len() == 0 { return ( @@ -677,7 +690,13 @@ impl Problem { ), format!( "found {} but the package is fixed to {} (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ), lp.get_pretty_version() ), ); @@ -698,7 +717,13 @@ impl Problem { ), format!( "found {} in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false) + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ) ), ); } @@ -712,7 +737,13 @@ impl Problem { ), format!( "found {} but these were not loaded, because they are abandoned and you configured \"block-abandoned\" to true in your \"audit\" config.", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false) + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ) ), ); } @@ -781,7 +812,13 @@ impl Problem { ), format!( "found {} but these were not loaded, because they are affected by security advisories (\"{}\"). Go to https://packagist.org/security-advisories/ to find advisory details. To ignore the advisories, add them to the audit \"ignore\" config. To turn the feature off entirely, you can set \"block-insecure\" to false in your \"audit\" config.", - Self::get_package_list(&packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &packages, + is_verbose, + Some(pool), + constraint, + false + ), implode("\", \"", &advisories_list) ), ); @@ -900,9 +937,8 @@ impl Problem { let top_package = all_repos_packages.first(); if let Some(tp) = top_package { if tp.is_root_package_interface() { - suffix = - " See https://getcomposer.org/dep-on-root for details and assistance." - .to_string(); + suffix = " See https://getcomposer.org/dep-on-root for details and assistance." + .to_string(); } } @@ -1019,7 +1055,9 @@ impl Problem { let mut prepared_strings: Vec<String> = Vec::new(); for (name, mut package) in prepared { // remove the implicit default branch alias to avoid cruft in the display - if package.versions.contains_key(VersionParser::DEFAULT_BRANCH_ALIAS) + if package + .versions + .contains_key(VersionParser::DEFAULT_BRANCH_ALIAS) && has_default_branch.contains_key(&name) { package @@ -1222,7 +1260,13 @@ impl Problem { ), format!( "satisfiable by {} from {} but {} {} is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.", - Self::get_package_list(&next_repo_packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &next_repo_packages, + is_verbose, + Some(pool), + constraint, + false + ), next_repo.get_repo_name(), top_package.get_pretty_name(), top_package.get_pretty_version() @@ -1237,7 +1281,13 @@ impl Problem { let mut suggestion = format!( "Make sure you either fix the {} or avoid updating this package to keep the one present in the lock file ({}).", reason, - Self::get_package_list(&next_repo_packages, is_verbose, Some(pool), constraint, false) + Self::get_package_list( + &next_repo_packages, + is_verbose, + Some(pool), + constraint, + false + ) ); // symlinked path repos cannot be locked so do not suggest keeping it locked if next_repo_packages[0].get_dist_type() == "path" { @@ -1260,7 +1310,13 @@ impl Problem { ), format!( "found {} but {} not match your {} and {} therefore not installable. {}", - Self::get_package_list(higher_repo_packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + higher_repo_packages, + is_verbose, + Some(pool), + constraint, + false + ), if singular { "it does" } else { "these do" }, reason, if singular { "is" } else { "are" }, @@ -1277,10 +1333,26 @@ impl Problem { ), format!( "satisfiable by {} from {} but {} from {} has higher repository priority. The packages from the higher priority repository do not match your {} and are therefore not installable. That repository is canonical so the lower priority repo's packages are not installable. See https://getcomposer.org/repoprio for details and assistance.", - Self::get_package_list(&next_repo_packages, is_verbose, Some(pool), constraint, false), + Self::get_package_list( + &next_repo_packages, + is_verbose, + Some(pool), + constraint, + false + ), next_repo.get_repo_name(), - Self::get_package_list(higher_repo_packages, is_verbose, Some(pool), constraint, false), - higher_repo_packages.first().unwrap().get_repository().get_repo_name(), + Self::get_package_list( + higher_repo_packages, + is_verbose, + Some(pool), + constraint, + false + ), + higher_repo_packages + .first() + .unwrap() + .get_repository() + .get_repo_name(), reason ), ) @@ -1313,7 +1385,10 @@ impl Problem { "{} or {}", implode( ", ", - &versions[..versions.len() - 1].iter().cloned().collect::<Vec<_>>() + &versions[..versions.len() - 1] + .iter() + .cloned() + .collect::<Vec<_>>() ), last ) @@ -1343,7 +1418,11 @@ impl Problem { if providers.len() > 0 { let provider_count = providers.len() as i64; let slice = if provider_count > max_providers + 1 { - providers.iter().take(max_providers as usize).cloned().collect::<Vec<_>>() + providers + .iter() + .take(max_providers as usize) + .cloned() + .collect::<Vec<_>>() } else { providers.clone() }; diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs index 9aef975..e1f8c1e 100644 --- a/crates/shirabe/src/dependency_resolver/request.rs +++ b/crates/shirabe/src/dependency_resolver/request.rs @@ -1,7 +1,7 @@ //! ref: composer/src/Composer/DependencyResolver/Request.php use indexmap::IndexMap; -use shirabe_php_shim::{spl_object_hash, strtolower, LogicException}; +use shirabe_php_shim::{LogicException, spl_object_hash, strtolower}; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; use shirabe_semver::constraint::match_all_constraint::MatchAllConstraint; diff --git a/crates/shirabe/src/dependency_resolver/rule.rs b/crates/shirabe/src/dependency_resolver/rule.rs index 8c015b4..1ba1dd7 100644 --- a/crates/shirabe/src/dependency_resolver/rule.rs +++ b/crates/shirabe/src/dependency_resolver/rule.rs @@ -5,8 +5,8 @@ use std::any::Any; use anyhow::Result; use indexmap::IndexMap; use shirabe_php_shim::{ - abs, array_filter, array_keys, array_shift, array_values, implode, is_object, LogicException, - PhpMixed, + LogicException, PhpMixed, abs, array_filter, array_keys, array_shift, array_values, implode, + is_object, }; use shirabe_semver::constraint::constraint::Constraint; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; @@ -156,7 +156,9 @@ 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(&Constraint::new("=", p.get_version())) { return true; } @@ -173,7 +175,11 @@ impl Rule { } if self.get_reason() == Self::RULE_ROOT_REQUIRE { - if let ReasonData::RootRequire { package_name, constraint } = self.get_reason_data() { + if let ReasonData::RootRequire { + package_name, + constraint, + } = self.get_reason_data() + { if PlatformRepository::is_platform_package(package_name) { return false; } @@ -254,9 +260,10 @@ impl Rule { let reason_data = self.get_reason_data(); let (package_name, constraint): (&str, &dyn ConstraintInterface) = match reason_data { - ReasonData::RootRequire { package_name, constraint } => { - (package_name.as_str(), constraint.as_ref()) - } + ReasonData::RootRequire { + package_name, + constraint, + } => (package_name.as_str(), constraint.as_ref()), _ => return String::new(), }; @@ -273,7 +280,9 @@ impl Rule { let packages_non_alias: Vec<Box<BasePackage>> = packages .iter() .filter(|p| { - (p.as_any() as &dyn Any).downcast_ref::<AliasPackage>().is_none() + (p.as_any() as &dyn Any) + .downcast_ref::<AliasPackage>() + .is_none() }) .map(|p| p.clone_box()) .collect(); @@ -293,7 +302,13 @@ impl Rule { "Root composer.json requires {} {} -> satisfiable by {}.", package_name, constraint.get_pretty_string(), - self.format_packages_unique(pool, packages, is_verbose, Some(constraint), false), + self.format_packages_unique( + pool, + packages, + is_verbose, + Some(constraint), + false + ), ) } @@ -335,8 +350,11 @@ impl Rule { // swap literals if they are not in the right order with package2 being the conflicter if link.get_source() == package1.get_name() { std::mem::swap(&mut package1, &mut package2); - conflict_target = - format!("{} {}", package1.get_pretty_name(), link.get_pretty_constraint().unwrap_or("")); + conflict_target = format!( + "{} {}", + package1.get_pretty_name(), + link.get_pretty_constraint().unwrap_or("") + ); } // if the conflict is not directly against the package but something it provides/replaces, @@ -347,14 +365,16 @@ impl Rule { for provide in package1.get_provides().values() { if provide.get_target() == link.get_target() { provide_type = Some("provides"); - provided = Some(provide.get_pretty_constraint().unwrap_or("").to_string()); + provided = + Some(provide.get_pretty_constraint().unwrap_or("").to_string()); break; } } for replace in package1.get_replaces().values() { if replace.get_target() == link.get_target() { provide_type = Some("replaces"); - provided = Some(replace.get_pretty_constraint().unwrap_or("").to_string()); + provided = + Some(replace.get_pretty_constraint().unwrap_or("").to_string()); break; } } @@ -371,7 +391,11 @@ impl Rule { } } - format!("{} conflicts with {}.", package2.get_pretty_string(), conflict_target) + format!( + "{} conflicts with {}.", + package2.get_pretty_string(), + conflict_target + ) } r if r == Self::RULE_PACKAGE_REQUIRES => { @@ -488,14 +512,18 @@ impl Rule { return format!( "Only one of these can be installed: {}. {}", - self.format_packages_unique_from_literals(pool, &literals, is_verbose, None, true), + self.format_packages_unique_from_literals( + pool, &literals, is_verbose, None, true + ), reason, ); } format!( "You can only install one version of a package, so only one of these can be installed: {}.", - self.format_packages_unique_from_literals(pool, &literals, is_verbose, None, true), + self.format_packages_unique_from_literals( + pool, &literals, is_verbose, None, true + ), ) } r if r == Self::RULE_LEARNED => { @@ -512,7 +540,11 @@ impl Rule { let group = if installed_map.contains_key(&package.id) { if *literal > 0 { "keep" } else { "remove" } } else { - if *literal > 0 { "install" } else { "don't install" } + if *literal > 0 { + "install" + } else { + "don't install" + } }; groups @@ -604,7 +636,13 @@ impl Rule { packages.push(package); } - Problem::get_package_list(packages, is_verbose, pool, constraint, use_removed_version_group) + Problem::get_package_list( + packages, + is_verbose, + pool, + constraint, + use_removed_version_group, + ) } /// Helper for cases where literals come as int IDs (PHP supports both via union). @@ -620,13 +658,17 @@ impl Rule { for literal in literals { packages.push(pool.literal_to_package(*literal).clone_box()); } - Problem::get_package_list(packages, is_verbose, pool, constraint, use_removed_version_group) + Problem::get_package_list( + packages, + is_verbose, + pool, + constraint, + use_removed_version_group, + ) } fn deduplicate_default_branch_alias(&self, package: Box<BasePackage>) -> Box<BasePackage> { - if let Some(alias_pkg) = - (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() - { + if let Some(alias_pkg) = (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { if alias_pkg.get_pretty_version() == VersionParser::DEFAULT_BRANCH_ALIAS { return alias_pkg.get_alias_of().clone_box(); } diff --git a/crates/shirabe/src/dependency_resolver/rule2_literals.rs b/crates/shirabe/src/dependency_resolver/rule2_literals.rs index 9d3aefc..e86c93d 100644 --- a/crates/shirabe/src/dependency_resolver/rule2_literals.rs +++ b/crates/shirabe/src/dependency_resolver/rule2_literals.rs @@ -12,7 +12,12 @@ pub struct Rule2Literals { } impl Rule2Literals { - pub fn new(literal1: i64, literal2: i64, reason: shirabe_php_shim::PhpMixed, reason_data: shirabe_php_shim::PhpMixed) -> Self { + pub fn new( + literal1: i64, + literal2: i64, + reason: shirabe_php_shim::PhpMixed, + reason_data: shirabe_php_shim::PhpMixed, + ) -> Self { let (literal1, literal2) = if literal1 < literal2 { (literal1, literal2) } else { @@ -52,7 +57,11 @@ impl Rule2Literals { } pub fn to_string(&self) -> String { - let prefix = if self.inner.is_disabled() { "disabled(" } else { "(" }; + let prefix = if self.inner.is_disabled() { + "disabled(" + } else { + "(" + }; format!("{}{}|{})", prefix, self.literal1, self.literal2) } } diff --git a/crates/shirabe/src/dependency_resolver/rule_set.rs b/crates/shirabe/src/dependency_resolver/rule_set.rs index 36009d9..4fc7928 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set.rs @@ -53,7 +53,8 @@ impl RuleSet { return Err(OutOfBoundsException { message: format!("Unknown rule type: {}", r#type), code: 0, - }.into()); + } + .into()); } let hash = rule.get_hash(); @@ -66,13 +67,19 @@ impl RuleSet { } } - self.rules.entry(r#type).or_insert_with(Vec::new).push(rule.clone()); + self.rules + .entry(r#type) + .or_insert_with(Vec::new) + .push(rule.clone()); rule.set_type(r#type); self.rule_by_id.insert(self.next_rule_id, rule.clone()); self.next_rule_id += 1; - self.rules_by_hash.entry(hash).or_insert_with(Vec::new).push(rule); + self.rules_by_hash + .entry(hash) + .or_insert_with(Vec::new) + .push(rule); Ok(()) } diff --git a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs index a2066ef..9c803d6 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_generator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_generator.rs @@ -12,8 +12,8 @@ use crate::dependency_resolver::policy_interface::PolicyInterface; use crate::dependency_resolver::pool::Pool; use crate::dependency_resolver::request::Request; use crate::dependency_resolver::rule::Rule; -use crate::dependency_resolver::rule2_literals::Rule2Literals; use crate::dependency_resolver::rule_set::RuleSet; +use crate::dependency_resolver::rule2_literals::Rule2Literals; use crate::filter::platform_requirement_filter::ignore_list_platform_requirement_filter::IgnoreListPlatformRequirementFilter; use crate::filter::platform_requirement_filter::platform_requirement_filter_factory::PlatformRequirementFilterFactory; use crate::filter::platform_requirement_filter::platform_requirement_filter_interface::PlatformRequirementFilterInterface; @@ -65,7 +65,11 @@ impl RuleSetGenerator { literals.push(provider.get_id()); } - Some(GenericRule::new(literals, PhpMixed::Int(reason), reason_data)) + Some(GenericRule::new( + literals, + PhpMixed::Int(reason), + reason_data, + )) } /// Creates a rule to install at least one of a set of packages. @@ -126,7 +130,9 @@ impl RuleSetGenerator { reason_data, )) } else { - Rule::from(MultiConflictRule::new(literals, PhpMixed::Int(reason), reason_data).unwrap()) + Rule::from( + MultiConflictRule::new(literals, PhpMixed::Int(reason), reason_data).unwrap(), + ) } } @@ -202,8 +208,8 @@ impl RuleSetGenerator { if platform_requirement_filter.is_ignored(link.get_target()) { continue; } else if let Some(ignore_list_filter) = (platform_requirement_filter as &dyn Any) - .downcast_ref::<IgnoreListPlatformRequirementFilter>() - { + .downcast_ref::<IgnoreListPlatformRequirementFilter>( + ) { constraint = ignore_list_filter .filter_constraint(link.get_target(), constraint, true) .unwrap_or(constraint); @@ -230,11 +236,8 @@ 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_box()).collect(); for package in &packages { for link in package.get_conflicts().values() { @@ -247,8 +250,8 @@ impl RuleSetGenerator { if platform_requirement_filter.is_ignored(link.get_target()) { continue; } else if let Some(ignore_list_filter) = (platform_requirement_filter as &dyn Any) - .downcast_ref::<IgnoreListPlatformRequirementFilter>() - { + .downcast_ref::<IgnoreListPlatformRequirementFilter>( + ) { constraint = ignore_list_filter .filter_constraint(link.get_target(), constraint, false) .unwrap_or(constraint); @@ -286,11 +289,8 @@ impl RuleSetGenerator { for (name, packages) in names_packages { if packages.len() > 1 { let reason = Rule::RULE_PACKAGE_SAME_NAME; - let rule = self.create_multi_conflict_rule( - &packages, - reason, - PhpMixed::String(name), - ); + let rule = + self.create_multi_conflict_rule(&packages, reason, PhpMixed::String(name)); self.add_rule(RuleSet::TYPE_PACKAGE, Some(rule)); } } @@ -309,15 +309,13 @@ impl RuleSetGenerator { } // otherwise, looks like a bug - return Err(anyhow::anyhow!( - shirabe_php_shim::LogicException { - message: format!( - "Fixed package {} was not added to solver pool.", - package.get_pretty_string() - ), - code: 0, - } - )); + return Err(anyhow::anyhow!(shirabe_php_shim::LogicException { + message: format!( + "Fixed package {} was not added to solver pool.", + package.get_pretty_string() + ), + code: 0, + })); } self.add_rules_for_package(package.clone_box(), platform_requirement_filter); @@ -340,8 +338,8 @@ impl RuleSetGenerator { if platform_requirement_filter.is_ignored(package_name) { continue; } else if let Some(ignore_list_filter) = (platform_requirement_filter as &dyn Any) - .downcast_ref::<IgnoreListPlatformRequirementFilter>() - { + .downcast_ref::<IgnoreListPlatformRequirementFilter>( + ) { constraint = ignore_list_filter .filter_constraint(package_name, constraint, true) .unwrap_or(constraint); @@ -406,8 +404,8 @@ impl RuleSetGenerator { request: &Request, platform_requirement_filter: Option<Box<dyn PlatformRequirementFilterInterface>>, ) -> anyhow::Result<RuleSet> { - let platform_requirement_filter = - platform_requirement_filter.unwrap_or_else(PlatformRequirementFilterFactory::ignore_nothing); + let platform_requirement_filter = platform_requirement_filter + .unwrap_or_else(PlatformRequirementFilterFactory::ignore_nothing); self.add_rules_for_request(request, &*platform_requirement_filter)?; diff --git a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs index e2b67f4..f66a277 100644 --- a/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs +++ b/crates/shirabe/src/dependency_resolver/rule_set_iterator.rs @@ -1,7 +1,7 @@ //! ref: composer/src/Composer/DependencyResolver/RuleSetIterator.php -use indexmap::IndexMap; use crate::dependency_resolver::rule::Rule; +use indexmap::IndexMap; /// Implements PHP \Iterator over a grouped rule set. #[derive(Debug)] diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs index 5428ca1..80c9bee 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_graph.rs @@ -27,24 +27,38 @@ impl RuleWatchGraph { return; } - if (node.get_rule().as_any() as &dyn Any).downcast_ref::<MultiConflictRule>().is_none() { + if (node.get_rule().as_any() as &dyn Any) + .downcast_ref::<MultiConflictRule>() + .is_none() + { for literal in [node.watch1, node.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()); + self.watch_chains + .get_mut(&literal) + .unwrap() + .unshift(node.clone()); } } else { for literal in node.get_rule().get_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()); + self.watch_chains + .get_mut(&literal) + .unwrap() + .unshift(node.clone()); } } } - pub fn propagate_literal(&mut self, decided_literal: i64, level: i64, decisions: &mut Decisions) -> Option<Box<dyn Rule>> { + pub fn propagate_literal( + &mut self, + decided_literal: i64, + level: i64, + decisions: &mut Decisions, + ) -> Option<Box<dyn Rule>> { let literal = -decided_literal; if !self.watch_chains.contains_key(&literal) { @@ -56,13 +70,17 @@ impl RuleWatchGraph { chain.rewind(); while chain.valid() { let node = chain.current(); - if (node.get_rule().as_any() as &dyn Any).downcast_ref::<MultiConflictRule>().is_none() { + if (node.get_rule().as_any() as &dyn Any) + .downcast_ref::<MultiConflictRule>() + .is_none() + { let other_watch = node.get_other_watch(literal); if !node.get_rule().is_disabled() && !decisions.satisfy(other_watch) { let rule_literals = node.get_rule().get_literals(); - let alternative_literals: Vec<i64> = rule_literals.into_iter() + let alternative_literals: Vec<i64> = rule_literals + .into_iter() .filter(|&rule_literal| { literal != rule_literal && other_watch != rule_literal @@ -107,6 +125,9 @@ impl RuleWatchGraph { node.move_watch(from_literal, to_literal); self.watch_chains.get_mut(&from_literal).unwrap().remove(); - self.watch_chains.get_mut(&to_literal).unwrap().unshift(node); + self.watch_chains + .get_mut(&to_literal) + .unwrap() + .unshift(node); } } diff --git a/crates/shirabe/src/dependency_resolver/rule_watch_node.rs b/crates/shirabe/src/dependency_resolver/rule_watch_node.rs index 4161268..12dd83f 100644 --- a/crates/shirabe/src/dependency_resolver/rule_watch_node.rs +++ b/crates/shirabe/src/dependency_resolver/rule_watch_node.rs @@ -25,7 +25,11 @@ impl RuleWatchNode { let watch1 = if literal_count > 0 { literals[0] } else { 0 }; let watch2 = if literal_count > 1 { literals[1] } else { 0 }; - Self { watch1, watch2, rule } + Self { + watch1, + watch2, + rule, + } } pub fn watch2_on_highest(&mut self, decisions: &Decisions) { 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 8c30f60..8caf6bd 100644 --- a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs +++ b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs @@ -1,8 +1,5 @@ //! ref: composer/src/Composer/DependencyResolver/SecurityAdvisoryPoolFilter.php -use indexmap::IndexMap; -use shirabe_php_shim::PhpMixed; -use shirabe_semver::constraint::constraint::Constraint; use crate::advisory::audit_config::AuditConfig; use crate::advisory::auditor::Auditor; use crate::dependency_resolver::pool::Pool; @@ -11,6 +8,9 @@ use crate::package::package_interface::PackageInterface; use crate::repository::platform_repository::PlatformRepository; use crate::repository::repository_interface::RepositoryInterface; use crate::repository::repository_set::RepositorySet; +use indexmap::IndexMap; +use shirabe_php_shim::PhpMixed; +use shirabe_semver::constraint::constraint::Constraint; #[derive(Debug)] pub struct SecurityAdvisoryPoolFilter { @@ -20,10 +20,18 @@ pub struct SecurityAdvisoryPoolFilter { impl SecurityAdvisoryPoolFilter { pub fn new(auditor: Auditor, audit_config: AuditConfig) -> Self { - Self { auditor, audit_config } + Self { + auditor, + audit_config, + } } - pub fn filter(&self, pool: Pool, repositories: Vec<Box<dyn RepositoryInterface>>, request: &Request) -> Pool { + pub fn filter( + &self, + pool: Pool, + repositories: Vec<Box<dyn RepositoryInterface>>, + request: &Request, + ) -> Pool { if !self.audit_config.block_insecure { return pool; } @@ -35,15 +43,23 @@ impl SecurityAdvisoryPoolFilter { let mut packages_for_advisories: Vec<Box<dyn PackageInterface>> = vec![]; for package in pool.get_packages() { - if !package.is_root() && !PlatformRepository::is_platform_package(package.get_name()) && !request.is_locked_package(package.as_ref()) { + if !package.is_root() + && !PlatformRepository::is_platform_package(package.get_name()) + && !request.is_locked_package(package.as_ref()) + { packages_for_advisories.push(package); } } // all_advisories: ['advisories' => array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>, ...] - let mut all_advisories: IndexMap<String, PhpMixed> = repo_set.get_matching_security_advisories(&packages_for_advisories, true, true); - if self.auditor.needs_complete_advisory_load(&all_advisories["advisories"], &self.audit_config.ignore_list_for_blocking) { - all_advisories = repo_set.get_matching_security_advisories(&packages_for_advisories, false, true); + let mut all_advisories: IndexMap<String, PhpMixed> = + repo_set.get_matching_security_advisories(&packages_for_advisories, true, true); + if self.auditor.needs_complete_advisory_load( + &all_advisories["advisories"], + &self.audit_config.ignore_list_for_blocking, + ) { + all_advisories = + repo_set.get_matching_security_advisories(&packages_for_advisories, false, true); } // advisory_map: array<string, array<PartialSecurityAdvisory|SecurityAdvisory>> @@ -51,20 +67,35 @@ impl SecurityAdvisoryPoolFilter { &all_advisories["advisories"], &self.audit_config.ignore_list_for_blocking, &self.audit_config.ignore_severity_for_blocking, - )["advisories"].clone().into(); + )["advisories"] + .clone() + .into(); let mut packages: Vec<Box<dyn PackageInterface>> = vec![]; // security_removed_versions: array<string, array<string, array<PartialSecurityAdvisory|SecurityAdvisory>>> - let mut security_removed_versions: IndexMap<String, IndexMap<String, Vec<PhpMixed>>> = IndexMap::new(); + let mut security_removed_versions: IndexMap<String, IndexMap<String, Vec<PhpMixed>>> = + IndexMap::new(); // abandoned_removed_versions: array<string, array<string, string>> - let mut abandoned_removed_versions: IndexMap<String, IndexMap<String, String>> = IndexMap::new(); + let mut abandoned_removed_versions: IndexMap<String, IndexMap<String, String>> = + IndexMap::new(); for package in pool.get_packages() { - if self.audit_config.block_abandoned && !self.auditor.filter_abandoned_packages(vec![package.as_ref()], &self.audit_config.ignore_abandoned_for_blocking).is_empty() { + if self.audit_config.block_abandoned + && !self + .auditor + .filter_abandoned_packages( + vec![package.as_ref()], + &self.audit_config.ignore_abandoned_for_blocking, + ) + .is_empty() + { for package_name in package.get_names(false) { abandoned_removed_versions .entry(package_name) .or_default() - .insert(package.get_version().to_string(), package.get_pretty_version().to_string()); + .insert( + package.get_version().to_string(), + package.get_pretty_version().to_string(), + ); } continue; } @@ -75,7 +106,10 @@ impl SecurityAdvisoryPoolFilter { security_removed_versions .entry(package_name) .or_default() - .insert(package.get_version().to_string(), matching_advisories.clone()); + .insert( + package.get_version().to_string(), + matching_advisories.clone(), + ); } continue; } @@ -83,10 +117,21 @@ impl SecurityAdvisoryPoolFilter { packages.push(package); } - Pool::new(packages, pool.get_unacceptable_fixed_or_locked_packages(), pool.get_all_removed_versions(), pool.get_all_removed_versions_by_package(), security_removed_versions, abandoned_removed_versions) + Pool::new( + packages, + pool.get_unacceptable_fixed_or_locked_packages(), + pool.get_all_removed_versions(), + pool.get_all_removed_versions_by_package(), + security_removed_versions, + abandoned_removed_versions, + ) } - fn get_matching_advisories(&self, package: &dyn PackageInterface, advisory_map: &IndexMap<String, Vec<PhpMixed>>) -> Vec<PhpMixed> { + fn get_matching_advisories( + &self, + package: &dyn PackageInterface, + advisory_map: &IndexMap<String, Vec<PhpMixed>>, + ) -> Vec<PhpMixed> { if package.is_dev() { return vec![]; } diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index 76de9de..388cccd 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -2,7 +2,9 @@ use indexmap::IndexMap; -use shirabe_php_shim::{array_pop, array_shift, array_unshift, microtime, spl_object_hash, sprintf, PhpMixed}; +use shirabe_php_shim::{ + PhpMixed, array_pop, array_shift, array_unshift, microtime, spl_object_hash, sprintf, +}; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; use crate::dependency_resolver::decisions::Decisions; @@ -183,8 +185,8 @@ impl Solver { continue; } else if let Some(ignore_filter) = platform_requirement_filter .as_any() - .downcast_ref::<IgnoreListPlatformRequirementFilter>() - { + .downcast_ref::<IgnoreListPlatformRequirementFilter>( + ) { constraint = ignore_filter.filter_constraint(package_name, constraint); } @@ -201,8 +203,7 @@ impl Solver { ); // TODO(phase-b): store the constraint inside reason_data; PhpMixed needs to // accept a `dyn ConstraintInterface` wrapper. - reason_data - .insert("constraint".to_string(), PhpMixed::Null); + reason_data.insert("constraint".to_string(), PhpMixed::Null); problem.add_rule(Rule::generic(GenericRule::new( Vec::new(), PhpMixed::Int(Rule::RULE_ROOT_REQUIRE), @@ -233,7 +234,8 @@ impl Solver { true, <dyn IOInterface>::DEBUG, ); - let mut rule_set_generator = RuleSetGenerator::new(self.policy.clone_box(), self.pool.clone()); + let mut rule_set_generator = + RuleSetGenerator::new(self.policy.clone_box(), self.pool.clone()); self.rules = rule_set_generator.get_rules_for(request, platform_requirement_filter.as_ref())?; drop(rule_set_generator); @@ -242,8 +244,7 @@ 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(RuleWatchNode::new(rule.clone()))?; } // make decisions based on root require/fix assertions @@ -298,11 +299,9 @@ impl Solver { .at_offset(self.propagate_index as usize) .clone(); - let conflict = self.watch_graph.propagate_literal( - decision.0, - level, - &mut self.decisions, - ); + let conflict = + self.watch_graph + .propagate_literal(decision.0, level, &mut self.decisions); self.propagate_index += 1; @@ -333,9 +332,7 @@ impl Solver { self.propagate_index = self.decisions.count() as i64; } - while !self.branches.is_empty() - && self.branches[self.branches.len() - 1].1 >= level - { + while !self.branches.is_empty() && self.branches[self.branches.len() - 1].1 >= level { // PHP: array_pop($this->branches) self.branches.pop(); } @@ -388,8 +385,7 @@ impl Solver { self.rules .add(new_rule.clone().into(), RuleSet::TYPE_LEARNED)?; - self.learned_why - .insert(spl_object_hash(&new_rule), why); + self.learned_why.insert(spl_object_hash(&new_rule), why); let mut rule_node = RuleWatchNode::new(new_rule.clone().into()); rule_node.watch2_on_highest(&self.decisions); @@ -408,9 +404,11 @@ impl Solver { rule: Rule, ) -> anyhow::Result<i64> { // choose best package to install from decisionQueue - let mut literals = - self.policy - .select_preferred_packages(&self.pool, decision_queue, rule.get_required_package()); + let mut literals = self.policy.select_preferred_packages( + &self.pool, + decision_queue, + rule.get_required_package(), + ); let selected_literal = array_shift::<i64>(&mut literals); @@ -422,11 +420,7 @@ impl Solver { self.set_propagate_learn(level, selected_literal, rule) } - fn analyze( - &mut self, - level: i64, - rule: Rule, - ) -> anyhow::Result<(i64, i64, GenericRule, i64)> { + fn analyze(&mut self, level: i64, rule: Rule) -> anyhow::Result<(i64, i64, GenericRule, i64)> { let analyzed_rule = rule.clone(); let mut rule = rule; let mut rule_level = 1_i64; diff --git a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs index 37cbbfe..ddc8746 100644 --- a/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs +++ b/crates/shirabe/src/dependency_resolver/solver_problems_exception.rs @@ -50,10 +50,18 @@ impl SolverProblemsException { for problem in &self.problems { problems.push(format!( "{}\n", - problem.get_pretty_string(repository_set, request, pool, is_verbose, &installed_map, &self.learned_pool) + problem.get_pretty_string( + repository_set, + request, + pool, + is_verbose, + &installed_map, + &self.learned_pool + ) )); missing_extensions.extend(self.get_extension_problems(problem.get_reasons())); - is_caused_by_lock = is_caused_by_lock || problem.is_caused_by_lock(repository_set, request, pool); + is_caused_by_lock = + is_caused_by_lock || problem.is_caused_by_lock(repository_set, request, pool); } let mut i = 1; @@ -66,7 +74,9 @@ impl SolverProblemsException { } let mut hints: Vec<String> = Vec::new(); - if !is_dev_extraction && (text.contains("could not be found") || text.contains("no matching package found")) { + if !is_dev_extraction + && (text.contains("could not be found") || text.contains("no matching package found")) + { hints.push("Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.".to_string()); } @@ -74,11 +84,16 @@ impl SolverProblemsException { hints.push(self.create_extension_hint(&missing_extensions)); } - if is_caused_by_lock && !is_dev_extraction && !request.get_update_allow_transitive_root_dependencies() { + if is_caused_by_lock + && !is_dev_extraction + && !request.get_update_allow_transitive_root_dependencies() + { hints.push("Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.".to_string()); } - if text.contains("found composer-plugin-api[2.0.0] but it does not match") && text.contains("- ocramius/package-versions") { + if text.contains("found composer-plugin-api[2.0.0] but it does not match") + && text.contains("- ocramius/package-versions") + { hints.push("<warning>ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.</warning>\nIf you can not upgrade PHP you can require <info>composer/package-versions-deprecated</info> to resolve this with PHP 7.0+.".to_string()); } @@ -118,7 +133,9 @@ impl SolverProblemsException { .collect::<Vec<_>>() .join(" "); - let mut text = "To enable extensions, verify that they are enabled in your .ini files:\n - ".to_string(); + let mut text = + "To enable extensions, verify that they are enabled in your .ini files:\n - " + .to_string(); text.push_str(&paths.join("\n - ")); text.push_str("\nYou can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode."); text.push_str(&format!("\nAlternatively, you can run Composer with `{}` to temporarily ignore these required extensions.", ignore_extensions_arguments)); diff --git a/crates/shirabe/src/dependency_resolver/transaction.rs b/crates/shirabe/src/dependency_resolver/transaction.rs index 1b7ed02..7c93114 100644 --- a/crates/shirabe/src/dependency_resolver/transaction.rs +++ b/crates/shirabe/src/dependency_resolver/transaction.rs @@ -4,8 +4,8 @@ use std::any::Any; use indexmap::IndexMap; use shirabe_php_shim::{ - array_filter, array_intersect, array_keys, array_pop, array_unshift, spl_object_hash, strcmp, - uasort, PhpMixed, + PhpMixed, array_filter, array_intersect, array_keys, array_pop, array_unshift, spl_object_hash, + strcmp, uasort, }; use crate::dependency_resolver::operation::install_operation::InstallOperation; @@ -150,9 +150,7 @@ impl Transaction { visited.insert(spl_object_hash(package.as_ref()), true); stack.push(package.clone_box()); - if let Some(alias) = - (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() - { + if let Some(alias) = (package.as_any() as &dyn Any).downcast_ref::<AliasPackage>() { stack.push(alias.get_alias_of().clone_box()); } else { for link in package.get_requires().values() { @@ -170,15 +168,14 @@ impl Transaction { .downcast_ref::<AliasPackage>() .is_some() { - let alias_key = - format!("{}::{}", package.get_name(), package.get_version()); + let alias_key = format!("{}::{}", package.get_name(), package.get_version()); if present_alias_map.contains_key(&alias_key) { remove_alias_map.shift_remove(&alias_key); } else { // TODO(phase-b): MarkAliasInstalledOperation::new expects AliasPackage by value - operations.push(Box::new(MarkAliasInstalledOperation::new( - todo!("package as AliasPackage by value"), - ))); + operations.push(Box::new(MarkAliasInstalledOperation::new(todo!( + "package as AliasPackage by value" + )))); } } else if let Some(source) = present_package_map.get(package.get_name()) { // do we need to update? @@ -187,9 +184,8 @@ impl Transaction { // TODO(phase-b): downcast to CompletePackageInterface trait object let package_is_complete = false; let present_is_complete = false; - let abandoned_or_replacement_changed = package_is_complete - && present_is_complete - && { + let abandoned_or_replacement_changed = + package_is_complete && present_is_complete && { // PHP: $package->isAbandoned() !== $presentPackageMap[$package->getName()]->isAbandoned() // || $package->getReplacementPackage() !== $presentPackageMap[$package->getName()]->getReplacementPackage() todo!("compare abandoned/replacement across CompletePackageInterface") @@ -221,9 +217,9 @@ impl Transaction { } for (_name_version, _package) in remove_alias_map { // TODO(phase-b): MarkAliasUninstalledOperation::new expects AliasPackage by value - operations.push(Box::new(MarkAliasUninstalledOperation::new( - todo!("package as AliasPackage by value"), - ))); + operations.push(Box::new(MarkAliasUninstalledOperation::new(todo!( + "package as AliasPackage by value" + )))); } let operations = self.move_plugins_to_front(operations); @@ -368,9 +364,7 @@ impl Transaction { || package.get_type() == "composer-installer"; // is this a plugin or a dependency of a plugin? - if is_plugin - || array_intersect(&package.get_names(true), &plugin_requires).len() > 0 - { + if is_plugin || array_intersect(&package.get_names(true), &plugin_requires).len() > 0 { // get the package's requires, but filter out any platform requirements let requires: Vec<String> = array_filter( &array_keys(&package.get_requires()), |
