From 1921f173ea219cb4b25847294d2d3fa465550fbb Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 25 May 2026 00:58:20 +0900 Subject: refactor(package): introduce Rc> handles for packages PHP packages have reference semantics, so introduce shared-ownership handles over an AnyPackage enum (PackageInterfaceHandle and friends) and replace Box throughout. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/shirabe/src/repository/array_repository.rs | 157 +++++++++------------ .../shirabe/src/repository/artifact_repository.rs | 2 +- .../src/repository/canonical_packages_trait.rs | 20 +-- .../shirabe/src/repository/composer_repository.rs | 139 +++++++++--------- .../shirabe/src/repository/composite_repository.rs | 27 +--- .../src/repository/filesystem_repository.rs | 68 ++++----- crates/shirabe/src/repository/filter_repository.rs | 14 +- .../src/repository/installed_array_repository.rs | 17 +-- .../repository/installed_filesystem_repository.rs | 19 +-- .../shirabe/src/repository/installed_repository.rs | 66 ++++----- .../src/repository/lock_array_repository.rs | 13 +- .../shirabe/src/repository/package_repository.rs | 3 +- .../shirabe/src/repository/platform_repository.rs | 99 +++++++------ .../shirabe/src/repository/repository_interface.rs | 13 +- .../shirabe/src/repository/repository_manager.rs | 12 +- crates/shirabe/src/repository/repository_set.rs | 72 +++++----- crates/shirabe/src/repository/repository_utils.rs | 16 +-- .../src/repository/root_package_repository.rs | 21 ++- crates/shirabe/src/repository/vcs_repository.rs | 21 +-- .../src/repository/writable_array_repository.rs | 14 +- .../repository/writable_repository_interface.rs | 5 +- 21 files changed, 383 insertions(+), 435 deletions(-) (limited to 'crates/shirabe/src/repository') diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs index fe45849..16f5f30 100644 --- a/crates/shirabe/src/repository/array_repository.rs +++ b/crates/shirabe/src/repository/array_repository.rs @@ -6,19 +6,14 @@ use std::cell::RefCell; use anyhow::Result; use indexmap::IndexMap; use shirabe_external_packages::composer::pcre::Preg; -use shirabe_php_shim::{ - Countable, InvalidArgumentException, LogicException, implode, preg_quote, spl_object_hash, - strtolower, -}; +use shirabe_php_shim::{Countable, LogicException, implode, preg_quote, strtolower}; use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::SimpleConstraint; -use crate::package::AliasPackage; -use crate::package::BasePackage; -use crate::package::CompleteAliasPackage; -use crate::package::CompletePackage; -use crate::package::CompletePackageInterface; +use crate::package::BasePackageHandle; +use crate::package::PackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::package::version::StabilityFilter; use crate::package::version::VersionParser; use crate::repository::{ @@ -31,15 +26,15 @@ use crate::repository::{ pub struct ArrayRepository { /// @var ?array // TODO(phase-b): RefCell models PHP's lazy init via getPackages()/count() under &self - pub(crate) packages: RefCell>>>, + pub(crate) packages: RefCell>>, /// @var ?array indexed by package unique name and used to cache hasPackage calls - pub(crate) package_map: RefCell>>>, + pub(crate) package_map: RefCell>>, } impl ArrayRepository { /// @param array $packages - pub fn new(packages: Vec>) -> Result { + pub fn new(packages: Vec) -> Result { let this = Self { packages: RefCell::new(None), package_map: RefCell::new(None), @@ -51,41 +46,27 @@ impl ArrayRepository { } /// Adds a new package to the repository - pub fn add_package(&self, package: Box) -> Result<()> { - // PHP: if (!$package instanceof BasePackage) throw new \InvalidArgumentException(...) - // TODO(phase-b): need a real `instanceof BasePackage` check on dyn PackageInterface; - // dyn-trait downcast requires Sized. Defer until BasePackage exposes an `as_base_package`. - if false { - return Err(InvalidArgumentException { - message: "Only subclasses of BasePackage are supported".to_string(), - code: 0, - } - .into()); - } - // TODO(phase-b): convert Box to Box - let mut package: Box = - todo!("downcast Box to Box"); - + pub fn add_package(&self, package: PackageInterfaceHandle) -> Result<()> { if self.packages.borrow().is_none() { self.initialize(); } // TODO(phase-b): pass a reference to self, not a clone package.set_repository(todo!("self as Box"))?; - let aliased_package: Option> = - if let Some(alias) = package.as_any().downcast_ref::() { - Some(alias.get_alias_of().clone_box()) - } else { - None - }; + let aliased_package: Option = + package.as_alias().map(|alias| alias.get_alias_of()); - self.packages.borrow_mut().as_mut().unwrap().push(package); + self.packages + .borrow_mut() + .as_mut() + .unwrap() + .push(package.into()); if let Some(aliased_package) = aliased_package { - if aliased_package.get_repository().is_none() { - // TODO(phase-b): pass aliased_package as Box - self.add_package(todo!("Box -> Box"))?; - } + // PHP: if ($aliasedPackage->getRepository() === null) $this->addPackage($aliasedPackage); + // TODO(phase-c): the handle does not expose get_repository (a `RefCell`-borrowed + // back-reference); this needs repository back-references on handles. + let _ = aliased_package; } // invalidate package map cache @@ -96,16 +77,18 @@ impl ArrayRepository { /// @return AliasPackage|CompleteAliasPackage pub(crate) fn create_alias_package( &self, - mut package: Box, + package: BasePackageHandle, alias: String, pretty_alias: String, - ) -> Box { - while let Some(alias_pkg) = package.as_any().downcast_ref::() { - package = alias_pkg.get_alias_of().clone_box(); + ) -> BasePackageHandle { + let mut package = package; + while let Some(alias_pkg) = package.as_alias() { + package = alias_pkg.get_alias_of().into(); } - if package.as_any().downcast_ref::().is_some() { - // TODO(phase-b): construct CompleteAliasPackage/AliasPackage and return as Box + let _ = (&package, &alias, &pretty_alias); + if package.as_complete_package().is_some() { + // TODO(phase-b): construct CompleteAliasPackage/AliasPackage and return as a handle return todo!("new CompleteAliasPackage(package, alias, pretty_alias)"); } @@ -165,17 +148,15 @@ impl RepositoryInterface for ArrayRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult { let packages = self.get_packages(); - let mut result: IndexMap> = IndexMap::new(); + let mut result: IndexMap = IndexMap::new(); let mut names_found: IndexMap = IndexMap::new(); for package in &packages { - if package_name_map.contains_key(PackageInterface::get_name(package.as_ref())) { - let constraint_opt = package_name_map - .get(PackageInterface::get_name(package.as_ref())) - .unwrap(); + if package_name_map.contains_key(&package.get_name()) { + let constraint_opt = package_name_map.get(&package.get_name()).unwrap(); let constraint_matches = match constraint_opt { None => true, Some(c) => c.matches( @@ -191,38 +172,35 @@ impl RepositoryInterface for ArrayRepository { && StabilityFilter::is_package_acceptable( &acceptable_stabilities, &stability_flags, - &PackageInterface::get_names(package.as_ref(), true), - package.get_stability(), + &package.get_names(true), + &package.get_stability(), ) && !already_loaded - .get(PackageInterface::get_name(package.as_ref())) - .map(|v| v.contains_key(package.get_version())) + .get(&package.get_name()) + .map(|v| v.contains_key(&package.get_version())) .unwrap_or(false) { // add selected packages which match stability requirements - result.insert(spl_object_hash(package.as_ref()), package.clone_box()); + result.insert(package.ptr_id().to_string(), package.clone()); // add the aliased package for packages where the alias matches - if let Some(alias) = package.as_any().downcast_ref::() { + if let Some(alias) = package.as_alias() { let aliased = alias.get_alias_of(); - if !result.contains_key(&spl_object_hash(aliased)) { - result.insert(spl_object_hash(aliased), aliased.clone_box()); + if !result.contains_key(&aliased.ptr_id().to_string()) { + result.insert(aliased.ptr_id().to_string(), aliased.into()); } } } - names_found.insert( - PackageInterface::get_name(package.as_ref()).to_string(), - true, - ); + names_found.insert(package.get_name(), true); } } // add aliases of packages that were selected, even if the aliases did not match for package in &packages { - if let Some(alias) = package.as_any().downcast_ref::() { + if let Some(alias) = package.as_alias() { let aliased = alias.get_alias_of(); - if result.contains_key(&spl_object_hash(aliased)) { - result.insert(spl_object_hash(package.as_ref()), package.clone_box()); + if result.contains_key(&aliased.ptr_id().to_string()) { + result.insert(package.ptr_id().to_string(), package.clone()); } } } @@ -237,7 +215,7 @@ impl RepositoryInterface for ArrayRepository { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { let name = strtolower(name); let constraint: AnyConstraint = match constraint { @@ -249,7 +227,7 @@ impl RepositoryInterface for ArrayRepository { }; for package in self.get_packages() { - if name == PackageInterface::get_name(package.as_ref()) { + if name == package.get_name() { let pkg_constraint = SimpleConstraint::new( "==".to_string(), package.get_version().to_string(), @@ -268,7 +246,7 @@ impl RepositoryInterface for ArrayRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { // normalize name let name = strtolower(name); let mut packages = vec![]; @@ -283,7 +261,7 @@ impl RepositoryInterface for ArrayRepository { }; for package in self.get_packages() { - if name == PackageInterface::get_name(package.as_ref()) { + if name == package.get_name() { if constraint.is_none() || constraint.as_ref().unwrap().matches( &SimpleConstraint::new( @@ -314,7 +292,7 @@ impl RepositoryInterface for ArrayRepository { let mut matches: IndexMap = IndexMap::new(); for package in self.get_packages() { - let mut name = PackageInterface::get_name(package.as_ref()).to_string(); + let mut name = package.get_name(); if mode == crate::repository::SEARCH_VENDOR { // PHP: [$name] = explode('/', $name); let parts: Vec<&str> = name.splitn(2, '/').collect(); @@ -329,7 +307,7 @@ impl RepositoryInterface for ArrayRepository { } } - let complete = package.as_any().downcast_ref::(); + let complete = package.as_complete(); let fulltext_match = mode == crate::repository::SEARCH_FULLTEXT && complete.is_some() @@ -337,8 +315,12 @@ impl RepositoryInterface for ArrayRepository { ®ex, &format!( "{} {}", - implode(" ", &complete.unwrap().get_keywords()), - complete.unwrap().get_description().unwrap_or("") + implode(" ", &complete.as_ref().unwrap().get_keywords()), + complete + .as_ref() + .unwrap() + .get_description() + .unwrap_or_default() ), ) .unwrap_or(false); @@ -355,14 +337,12 @@ impl RepositoryInterface for ArrayRepository { }, ); } else { - let description = complete.and_then(|c| c.get_description().map(String::from)); - let abandoned = if let Some(c) = complete { + let description = complete.as_ref().and_then(|c| c.get_description()); + let abandoned = if let Some(c) = &complete { if c.is_abandoned() { // PHP: $package->getReplacementPackage() ?: true match c.get_replacement_package() { - Some(s) if !s.is_empty() => { - Some(AbandonedInfo::Replacement(s.to_string())) - } + Some(s) if !s.is_empty() => Some(AbandonedInfo::Replacement(s)), _ => Some(AbandonedInfo::Abandoned), } } else { @@ -374,7 +354,7 @@ impl RepositoryInterface for ArrayRepository { matches.insert( name.clone(), SearchResult { - name: package.get_pretty_name().to_string(), + name: package.get_pretty_name(), description, abandoned, url: None, @@ -389,7 +369,7 @@ impl RepositoryInterface for ArrayRepository { fn has_package(&self, package: &dyn PackageInterface) -> bool { if self.package_map.borrow().is_none() { - let mut map: IndexMap> = IndexMap::new(); + let mut map: IndexMap = IndexMap::new(); for repo_package in self.get_packages() { map.insert(repo_package.get_unique_name(), repo_package); } @@ -407,19 +387,19 @@ impl RepositoryInterface for ArrayRepository { let mut result: IndexMap = IndexMap::new(); 'candidates: for candidate in self.get_packages() { - if result.contains_key(PackageInterface::get_name(candidate.as_ref())) { + if result.contains_key(&candidate.get_name()) { continue; } for link in candidate.get_provides().values() { if package_name == link.get_target() { - let complete = candidate.as_any().downcast_ref::(); - let description = complete.and_then(|c| c.get_description().map(String::from)); + let complete = candidate.as_complete(); + let description = complete.and_then(|c| c.get_description()); result.insert( - PackageInterface::get_name(candidate.as_ref()).to_string(), + candidate.get_name(), ProviderInfo { - name: PackageInterface::get_name(candidate.as_ref()).to_string(), + name: candidate.get_name(), description, - r#type: candidate.get_type().to_string(), + r#type: candidate.get_type(), }, ); continue 'candidates; @@ -430,7 +410,7 @@ impl RepositoryInterface for ArrayRepository { result } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { if self.packages.borrow().is_none() { self.initialize(); } @@ -447,13 +427,12 @@ impl RepositoryInterface for ArrayRepository { ); } - // TODO(phase-b): return references rather than cloning the whole vector self.packages .borrow() .as_ref() .unwrap() .iter() - .map(|p| p.clone_box()) + .map(|p| p.clone()) .collect() } diff --git a/crates/shirabe/src/repository/artifact_repository.rs b/crates/shirabe/src/repository/artifact_repository.rs index 674325d..eff8fef 100644 --- a/crates/shirabe/src/repository/artifact_repository.rs +++ b/crates/shirabe/src/repository/artifact_repository.rs @@ -132,7 +132,7 @@ impl ArtifactRepository { fn get_composer_information( &self, file: &Path, - ) -> anyhow::Result>> { + ) -> anyhow::Result> { let mut json: Option = None; let file_extension = file .extension() diff --git a/crates/shirabe/src/repository/canonical_packages_trait.rs b/crates/shirabe/src/repository/canonical_packages_trait.rs index 8c6e7c2..5f0ecff 100644 --- a/crates/shirabe/src/repository/canonical_packages_trait.rs +++ b/crates/shirabe/src/repository/canonical_packages_trait.rs @@ -1,23 +1,23 @@ //! ref: composer/src/Composer/Repository/CanonicalPackagesTrait.php -use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use indexmap::IndexMap; /// Provides get_canonical_packages() to various repository implementations. pub trait CanonicalPackagesTrait { - fn get_packages(&self) -> Vec>; + fn get_packages(&self) -> Vec; /// Get unique packages (at most one package of each name), with aliases resolved and removed. - fn get_canonical_packages(&self) -> Vec> { + fn get_canonical_packages(&self) -> Vec { let packages = self.get_packages(); // get at most one package of each name, preferring non-aliased ones - let mut packages_by_name: IndexMap> = IndexMap::new(); + let mut packages_by_name: IndexMap = IndexMap::new(); for package in packages { - let name = package.get_name().to_string(); + let name = package.get_name(); let prefer_replace = packages_by_name .get(&name) - .map(|existing| existing.as_alias_package().is_some()) + .map(|existing| existing.as_alias().is_some()) .unwrap_or(true); if prefer_replace { packages_by_name.insert(name, package); @@ -27,10 +27,10 @@ pub trait CanonicalPackagesTrait { let mut canonical_packages = Vec::new(); // unfold aliased packages - for package in packages_by_name.into_values() { - // TODO(phase-b): unfolding requires `Box` traversal of - // `AliasPackage::get_alias_of()` (currently returns `&BasePackage`, not an - // ownable trait object). Push the alias as-is for now. + for mut package in packages_by_name.into_values() { + while let Some(alias) = package.as_alias() { + package = alias.get_alias_of().into(); + } canonical_packages.push(package); } diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index 9752bc0..5c16f8e 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -7,7 +7,7 @@ use shirabe_php_shim::{ Countable, InvalidArgumentException, JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE, LogicException, PHP_EOL, PhpMixed, RuntimeException, UnexpectedValueException, extension_loaded, hash, http_build_query, in_array, json_decode, parse_url_all, realpath, - spl_object_hash, strtolower, strtr, urlencode, var_export, + strtolower, strtr, urlencode, var_export, }; use shirabe_semver::compiling_matcher::CompilingMatcher; @@ -22,7 +22,9 @@ use crate::downloader::TransportException; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; use crate::json::JsonFile; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::package::base_package::{self, BasePackage}; use crate::package::loader::ArrayLoader; use crate::package::version::StabilityFilter; @@ -119,15 +121,15 @@ pub struct ComposerRepository { #[derive(Debug)] pub enum FindPackageReturn { - Package(Box), - Packages(Vec>), + Package(BasePackageHandle), + Packages(Vec), None, } #[derive(Debug)] pub struct LoadAsyncPackagesResult { pub names_found: IndexMap, - pub packages: IndexMap>, + pub packages: IndexMap, } impl ConfigurableRepositoryInterface for ComposerRepository { @@ -322,7 +324,7 @@ impl ComposerRepository { &mut self, name: String, constraint: PhpMixed, - ) -> anyhow::Result>> { + ) -> anyhow::Result> { // this call initializes loadRootServerFile which is needed for the rest below to work let has_providers = self.has_providers()?; @@ -343,7 +345,7 @@ impl ComposerRepository { .map_or(false, |m| m.contains_key(&name)) { let packages = self.what_provides(&name, None, None, IndexMap::new())?; - let packages_vec: Vec> = packages.into_values().collect(); + let packages_vec: Vec = packages.into_values().collect(); return Ok( match self.filter_packages(packages_vec, Some(&constraint), true) { FindPackageReturn::Package(p) => Some(p), @@ -372,7 +374,7 @@ impl ComposerRepository { if name == provider_name { let packages = self.what_provides(&provider_name, None, None, IndexMap::new())?; - let packages_vec: Vec> = packages.into_values().collect(); + let packages_vec: Vec = packages.into_values().collect(); return Ok( match self.filter_packages(packages_vec, Some(&constraint), true) { FindPackageReturn::Package(p) => Some(p), @@ -396,7 +398,7 @@ impl ComposerRepository { &mut self, name: String, constraint: Option, - ) -> anyhow::Result>> { + ) -> anyhow::Result> { // this call initializes loadRootServerFile which is needed for the rest below to work let has_providers = self.has_providers()?; @@ -415,7 +417,7 @@ impl ComposerRepository { .map_or(false, |m| m.contains_key(&name)) { let packages = self.what_provides(&name, None, None, IndexMap::new())?; - let packages_vec: Vec> = packages.into_values().collect(); + let packages_vec: Vec = packages.into_values().collect(); return Ok( match self.filter_packages(packages_vec, constraint.as_ref(), false) { FindPackageReturn::Packages(v) => v, @@ -440,7 +442,7 @@ impl ComposerRepository { if name == provider_name { let packages = self.what_provides(&provider_name, None, None, IndexMap::new())?; - let packages_vec: Vec> = packages.into_values().collect(); + let packages_vec: Vec = packages.into_values().collect(); return Ok( match self.filter_packages(packages_vec, constraint.as_ref(), false) { FindPackageReturn::Packages(v) => v, @@ -461,7 +463,7 @@ impl ComposerRepository { fn filter_packages( &self, - packages: Vec>, + packages: Vec, constraint: Option<&AnyConstraint>, return_first_match: bool, ) -> FindPackageReturn { @@ -477,7 +479,7 @@ impl ComposerRepository { } let constraint = constraint.unwrap(); - let mut filtered_packages: Vec> = Vec::new(); + let mut filtered_packages: Vec = Vec::new(); for package in packages.into_iter() { let pkg_constraint = @@ -499,7 +501,7 @@ impl ComposerRepository { FindPackageReturn::Packages(filtered_packages) } - pub fn get_packages(&mut self) -> anyhow::Result>> { + pub fn get_packages(&mut self) -> anyhow::Result> { let has_providers = self.has_providers()?; if self.lazy_providers_url.is_some() { @@ -712,7 +714,7 @@ impl ComposerRepository { mut package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> anyhow::Result { // this call initializes loadRootServerFile which is needed for the rest below to work let has_providers = self.has_providers()?; @@ -724,22 +726,16 @@ impl ComposerRepository { stability_flags, already_loaded, ); - // TODO(phase-b): repository_interface::LoadPackagesResult uses Vec> - // for `packages`; this fn returns IndexMap. Reconciliation needs structural changes. - let _ = inner_result; - return Ok(LoadPackagesResult { - names_found: Vec::new(), - packages: IndexMap::new(), - }); + return Ok(inner_result); } - let mut packages: IndexMap> = IndexMap::new(); + let mut packages: IndexMap = IndexMap::new(); let mut names_found: IndexMap = IndexMap::new(); if has_providers || self.has_partial_packages()? { let names: Vec = package_name_map.keys().cloned().collect(); for name in names { - let mut matches: IndexMap> = IndexMap::new(); + let mut matches: IndexMap = IndexMap::new(); // if a repo has no providers but only partial packages and the partial packages are missing // then we don't want to call whatProvides as it would try to load from the providers and fail @@ -752,12 +748,11 @@ impl ComposerRepository { continue; } - // TODO(phase-b): Box is not Clone; share via Rc let candidates = self.what_provides( &name, Some(&acceptable_stabilities), Some(&stability_flags), - todo!("clone of already_loaded requires sharing Box"), + already_loaded.clone(), )?; let constraint = package_name_map .get(&name) @@ -783,13 +778,13 @@ impl ComposerRepository { } }; if matches_constraint { - let hash_c = spl_object_hash(&**candidate); - matches.insert(hash_c, dyn_clone_box(&**candidate)); - if let Some(alias) = candidate.as_alias_package() { + let hash_c = candidate.ptr_id().to_string(); + matches.insert(hash_c, candidate.clone()); + if let Some(alias) = candidate.as_alias() { let aliased = alias.get_alias_of(); - let aliased_hash = spl_object_hash(aliased); + let aliased_hash = aliased.ptr_id().to_string(); if !matches.contains_key(&aliased_hash) { - matches.insert(aliased_hash, dyn_clone_box(aliased)); + matches.insert(aliased_hash, aliased.into()); } } } @@ -797,12 +792,12 @@ impl ComposerRepository { // add aliases of matched packages even if they did not match the constraint for (_uid, candidate) in candidates.iter() { - if let Some(alias) = candidate.as_alias_package() { + if let Some(alias) = candidate.as_alias() { let aliased = alias.get_alias_of(); - let aliased_hash = spl_object_hash(aliased); + let aliased_hash = aliased.ptr_id().to_string(); if matches.contains_key(&aliased_hash) { - let hash_c = spl_object_hash(&**candidate); - matches.insert(hash_c, dyn_clone_box(&**candidate)); + let hash_c = candidate.ptr_id().to_string(); + matches.insert(hash_c, candidate.clone()); } } } @@ -1412,8 +1407,8 @@ impl ComposerRepository { name: &str, acceptable_stabilities: Option<&IndexMap>, stability_flags: Option<&IndexMap>, - already_loaded: IndexMap>>, - ) -> anyhow::Result>> { + already_loaded: IndexMap>, + ) -> anyhow::Result> { let mut packages_source: Option = None; let packages: IndexMap; let loading_partial_package: bool; @@ -1635,7 +1630,7 @@ impl ComposerRepository { loading_partial_package = true; } - let mut result: IndexMap> = IndexMap::new(); + let mut result: IndexMap = IndexMap::new(); let mut versions_to_load: IndexMap> = IndexMap::new(); let packages_inner = packages .get("packages") @@ -1749,15 +1744,13 @@ impl ComposerRepository { let loaded_packages = self.create_packages_flat(versions_to_load_vec, packages_source)?; let uids: Vec = versions_to_load.keys().cloned().collect(); - for (index, mut package) in loaded_packages.into_iter().enumerate() { - package.set_repository_self(); + for (index, package) in loaded_packages.into_iter().enumerate() { + // TODO(phase-c): wire the repository back-reference onto the shared package handle. let uid = &uids[index]; - if let Some(alias) = package.as_alias_package_mut() { - let aliased = alias.get_alias_of_mut(); - aliased.set_repository_self(); - - result.insert(uid.clone(), dyn_clone_box(aliased)); + if let Some(alias) = package.as_alias() { + let aliased = alias.get_alias_of(); + result.insert(uid.clone(), aliased.into()); result.insert(format!("{}-alias", uid), package); } else { result.insert(uid.clone(), package); @@ -1784,10 +1777,11 @@ impl ComposerRepository { } /// Adds a new package to the repository - pub fn add_package(&mut self, mut package: Box) { - // configurePackageTransportOptions(*package); - self.configure_package_transport_options(&mut *package); - self.inner.add_package(package); + pub fn add_package(&mut self, package: BasePackageHandle) { + self.configure_package_transport_options( + package.as_rc().borrow_mut().as_package_interface_mut(), + ); + self.inner.add_package(package.into()); } /// @param packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded @@ -1796,11 +1790,11 @@ impl ComposerRepository { mut package_names: IndexMap>, acceptable_stabilities: Option<&IndexMap>, stability_flags: Option<&IndexMap>, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> anyhow::Result { self.load_root_server_file(None)?; - let mut packages: IndexMap> = IndexMap::new(); + let mut packages: IndexMap = IndexMap::new(); let mut names_found: IndexMap = IndexMap::new(); if self.lazy_providers_url.is_none() { @@ -1980,17 +1974,16 @@ impl ComposerRepository { } } - let loaded_packages: Vec> = + let loaded_packages: Vec = ComposerRepository::create_packages_static(versions_to_load, packages_source)?; - for mut package in loaded_packages.into_iter() { - package.set_repository_self(); - let hash_c = spl_object_hash(&*package); - if let Some(alias) = package.as_alias_package_mut() { - let aliased_hash = spl_object_hash(alias.get_alias_of()); + for package in loaded_packages.into_iter() { + // TODO(phase-c): wire the repository back-reference onto the shared package handle. + let hash_c = package.ptr_id().to_string(); + if let Some(alias) = package.as_alias() { + let aliased = alias.get_alias_of(); + let aliased_hash = aliased.ptr_id().to_string(); if !packages.contains_key(&aliased_hash) { - alias.get_alias_of_mut().set_repository_self(); - let aliased_clone = dyn_clone_box(alias.get_alias_of()); - packages.insert(aliased_hash, aliased_clone); + packages.insert(aliased_hash, aliased.into()); } } packages.insert(hash_c, package); @@ -2716,13 +2709,13 @@ impl ComposerRepository { &mut self, packages: Vec>, source: Option, - ) -> anyhow::Result>> { + ) -> anyhow::Result> { if packages.is_empty() { return Ok(vec![]); } let mut packages = packages; - let result = (|| -> anyhow::Result>> { + let result = (|| -> anyhow::Result> { for data in packages.iter_mut() { if !data.contains_key("notification-url") { data.insert( @@ -2737,11 +2730,11 @@ impl ComposerRepository { let package_instances = self.loader.load_packages(packages.clone())?; - let mut results: Vec> = Vec::new(); - for mut package in package_instances.into_iter() { + let mut results: Vec = Vec::new(); + for package in package_instances.into_iter() { if let Some(src_type) = package.get_source_type() { if let Some(mirrors) = - self.source_mirrors.as_ref().and_then(|m| m.get(src_type)) + self.source_mirrors.as_ref().and_then(|m| m.get(&src_type)) { let converted: Vec> = mirrors .iter() @@ -2767,8 +2760,10 @@ impl ComposerRepository { .collect(); package.set_dist_mirrors(Some(converted)); } - self.configure_package_transport_options(&mut *package); - results.push(package); + self.configure_package_transport_options( + package.as_rc().borrow_mut().as_package_interface_mut(), + ); + results.push(package.into()); } Ok(results) })(); @@ -2794,12 +2789,16 @@ impl ComposerRepository { fn create_packages_static( packages: Vec>, _source: Option, - ) -> anyhow::Result>> { + ) -> anyhow::Result> { if packages.is_empty() { return Ok(vec![]); } let loader = ArrayLoader::new(Some(VersionParser::new()), true); - Ok(loader.load_packages(packages)?) + Ok(loader + .load_packages(packages)? + .into_iter() + .map(|p| p.into()) + .collect()) } fn fetch_file( @@ -3485,7 +3484,3 @@ fn clone_root_data(rd: &RootData) -> RootData { RootData::Data(d) => RootData::Data(d.clone()), } } - -fn dyn_clone_box(_pkg: &dyn BasePackage) -> Box { - todo!() -} diff --git a/crates/shirabe/src/repository/composite_repository.rs b/crates/shirabe/src/repository/composite_repository.rs index 6671895..024f89a 100644 --- a/crates/shirabe/src/repository/composite_repository.rs +++ b/crates/shirabe/src/repository/composite_repository.rs @@ -5,8 +5,9 @@ use std::any::Any; use indexmap::IndexMap; use shirabe_semver::constraint::AnyConstraint; -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::{ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult, }; @@ -79,7 +80,7 @@ impl RepositoryInterface for CompositeRepository { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { for repository in &self.repositories { let package = repository.find_package(name, constraint.clone()); if package.is_some() { @@ -93,7 +94,7 @@ impl RepositoryInterface for CompositeRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { let mut packages = vec![]; for repository in &self.repositories { packages.extend(repository.find_packages(name, constraint.clone())); @@ -101,7 +102,7 @@ impl RepositoryInterface for CompositeRepository { packages } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { let mut packages = vec![]; for repository in &self.repositories { packages.extend(repository.get_packages()); @@ -114,35 +115,21 @@ impl RepositoryInterface for CompositeRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult { let mut all_packages = IndexMap::new(); let mut all_names_found = vec![]; for repository in &self.repositories { - // TODO(phase-b): manual deep clone since trait objects in maps don't derive Clone. let name_map_cloned: IndexMap> = package_name_map .iter() .map(|(k, v)| (k.clone(), v.as_ref().map(|c| c.clone()))) .collect(); - let already_loaded_cloned: IndexMap< - String, - IndexMap>, - > = already_loaded - .iter() - .map(|(k, inner)| { - let inner_cloned: IndexMap> = inner - .iter() - .map(|(ik, iv)| (ik.clone(), iv.clone_package_box())) - .collect(); - (k.clone(), inner_cloned) - }) - .collect(); let result = repository.load_packages( name_map_cloned, acceptable_stabilities.clone(), stability_flags.clone(), - already_loaded_cloned, + already_loaded.clone(), ); all_packages.extend(result.packages); all_names_found.extend(result.names_found); diff --git a/crates/shirabe/src/repository/filesystem_repository.rs b/crates/shirabe/src/repository/filesystem_repository.rs index 96c7b61..c8ffb7c 100644 --- a/crates/shirabe/src/repository/filesystem_repository.rs +++ b/crates/shirabe/src/repository/filesystem_repository.rs @@ -16,10 +16,10 @@ use shirabe_php_shim::{ use crate::installed_versions::InstalledVersions; use crate::installer::InstallationManager; use crate::json::JsonFile; -use crate::package::AliasPackage; use crate::package::PackageInterface; -use crate::package::RootAliasPackage; +use crate::package::PackageInterfaceHandle; use crate::package::RootPackageInterface; +use crate::package::RootPackageInterfaceHandle; use crate::package::dumper::ArrayDumper; use crate::package::loader::ArrayLoader; use crate::package::loader::LoaderInterface; @@ -38,7 +38,7 @@ pub struct FilesystemRepository { /// @var bool dump_versions: bool, /// @var ?RootPackageInterface - root_package: Option>, + root_package: Option, /// @var Filesystem filesystem: std::rc::Rc>, /// @var bool|null @@ -53,7 +53,7 @@ impl FilesystemRepository { pub fn new( repository_file: JsonFile, dump_versions: bool, - root_package: Option>, + root_package: Option, filesystem: Option>>, ) -> Result { let filesystem = filesystem @@ -66,8 +66,7 @@ impl FilesystemRepository { .into()); } Ok(Self { - // TODO(phase-b): WritableArrayRepository::new() needs to be exposed - inner: todo!("WritableArrayRepository::new()"), + inner: WritableArrayRepository::new(vec![])?, file: repository_file, dump_versions, root_package, @@ -220,8 +219,9 @@ impl FilesystemRepository { let mut install_paths: IndexMap> = IndexMap::new(); for package in self.inner.get_canonical_packages() { - let mut pkg_array = dumper.dump(&*package); - let path = installation_manager.get_install_path(&*package); + let mut pkg_array = dumper.dump(package.as_rc().borrow().as_package_interface()); + let path = installation_manager + .get_install_path(package.as_rc().borrow().as_package_interface()); let mut install_path: Option = None; if let Some(path_str) = &path { if !path_str.is_empty() { @@ -476,14 +476,13 @@ impl FilesystemRepository { .map(|s| Box::new(PhpMixed::String(s.clone()))) .collect(), )); - let mut packages: Vec> = self + let mut packages: Vec = self .inner .get_packages() .into_iter() - // TODO(phase-b): Box -> Box - .map(|p| todo!("Box to Box")) + .map(|p| p.into()) .collect(); - let mut root_package = match &self.root_package { + let mut current_root: RootPackageInterfaceHandle = match &self.root_package { None => { return Err(LogicException { message: @@ -493,25 +492,27 @@ impl FilesystemRepository { } .into()); } - // TODO(phase-b): clone root_package to push into packages list - Some(_r) => todo!("clone root_package"), + Some(r) => r.clone(), }; // packages[] = $rootPackage = $this->rootPackage; - // TODO(phase-b): track current root_package in mutable variable - let mut current_root: Box = root_package; - // packages.push(current_root.clone_box()); - - while let Some(_alias) = current_root.as_any().downcast_ref::() { - current_root = - todo!("RootAliasPackage::get_alias_of() returning Box"); - // packages.push(current_root.clone_box()); + packages.push(current_root.clone().into()); + + while let Some(root_alias) = + PackageInterfaceHandle::from(current_root.clone()).as_root_alias_package() + { + current_root = root_alias.get_alias_of().into(); + packages.push(current_root.clone().into()); } let mut versions: IndexMap = IndexMap::new(); versions.insert( "root".to_string(), PhpMixed::Array( self.dump_root_package( - &*current_root, + current_root + .as_rc() + .borrow() + .as_root_package_interface() + .expect("current_root is a RootPackageInterface"), install_paths, dev_mode, repo_dir, @@ -526,12 +527,16 @@ impl FilesystemRepository { // add real installed packages for package in &packages { - if package.as_any().downcast_ref::().is_some() { + if package.as_alias().is_some() { continue; } - let dumped = - self.dump_installed_package(&**package, install_paths, repo_dir, &dev_packages); + let dumped = self.dump_installed_package( + package.as_rc().borrow().as_package_interface(), + install_paths, + repo_dir, + &dev_packages, + ); if let Some(PhpMixed::Array(versions_map)) = versions.get_mut("versions") { versions_map.insert( package.get_name().to_string(), @@ -546,7 +551,7 @@ impl FilesystemRepository { for package in &packages { let is_dev_package = dev_packages .as_array() - .map(|m| m.contains_key(package.get_name())) + .map(|m| m.contains_key(&package.get_name())) .unwrap_or(false); for (_, replace) in package.get_replaces() { // exclude platform replaces as when they are really there we can not check for their presence @@ -587,12 +592,13 @@ impl FilesystemRepository { // add aliases for package in &packages { - let Some(alias) = package.as_any().downcast_ref::() else { + let Some(_alias) = package.as_alias() else { continue; }; // TODO(phase-b): mutate nested versions['versions'][name]['aliases'] todo!("append alias->getPrettyVersion() to versions['versions'][name]['aliases']"); - if package.as_root_package_interface().is_some() { + #[allow(unreachable_code)] + if package.as_root().is_some() { // TODO(phase-b): same mutation on versions['root']['aliases'] todo!("append alias->getPrettyVersion() to versions['root']['aliases']"); } @@ -721,9 +727,7 @@ impl FilesystemRepository { repo_dir: &str, dev_packages: &PhpMixed, ) -> IndexMap { - let data = - // TODO(phase-b): RootPackageInterface trait bound — pass as &dyn PackageInterface - self.dump_installed_package(todo!("package as &dyn PackageInterface"), install_paths, repo_dir, dev_packages); + let data = self.dump_installed_package(package, install_paths, repo_dir, dev_packages); let mut result: IndexMap = IndexMap::new(); result.insert( diff --git a/crates/shirabe/src/repository/filter_repository.rs b/crates/shirabe/src/repository/filter_repository.rs index a3cb18b..c67e4ff 100644 --- a/crates/shirabe/src/repository/filter_repository.rs +++ b/crates/shirabe/src/repository/filter_repository.rs @@ -1,7 +1,9 @@ //! ref: composer/src/Composer/Repository/FilterRepository.php +use crate::package::BasePackageHandle; use crate::package::PackageInterface; -use crate::package::base_package::{self, BasePackage}; +use crate::package::PackageInterfaceHandle; +use crate::package::base_package::{self}; use crate::repository::{AdvisoryProviderInterface, SecurityAdvisoryResult}; use crate::repository::{ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult, @@ -165,7 +167,7 @@ impl RepositoryInterface for FilterRepository { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { if !self.is_allowed(name) { return None; } @@ -177,7 +179,7 @@ impl RepositoryInterface for FilterRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { if !self.is_allowed(name) { return Vec::new(); } @@ -190,7 +192,7 @@ impl RepositoryInterface for FilterRepository { mut package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult { package_name_map.retain(|name, _| self.is_allowed(name)); @@ -226,10 +228,10 @@ impl RepositoryInterface for FilterRepository { result } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { let mut result = Vec::new(); for package in self.repo.get_packages() { - if self.is_allowed(PackageInterface::get_name(package.as_ref())) { + if self.is_allowed(&package.get_name()) { result.push(package); } } diff --git a/crates/shirabe/src/repository/installed_array_repository.rs b/crates/shirabe/src/repository/installed_array_repository.rs index b089df6..f0244b6 100644 --- a/crates/shirabe/src/repository/installed_array_repository.rs +++ b/crates/shirabe/src/repository/installed_array_repository.rs @@ -4,8 +4,9 @@ use indexmap::IndexMap; use shirabe_php_shim::Countable; use shirabe_semver::constraint::AnyConstraint; -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::AdvisoryProviderInterface; use crate::repository::InstalledRepositoryInterface; use crate::repository::WritableArrayRepository; @@ -24,7 +25,7 @@ impl InstalledArrayRepository { Self::new_with_packages(Vec::new()) } - pub fn new_with_packages(packages: Vec>) -> anyhow::Result { + pub fn new_with_packages(packages: Vec) -> anyhow::Result { Ok(Self { inner: WritableArrayRepository::new(packages)?, }) @@ -56,7 +57,7 @@ impl WritableRepositoryInterface for InstalledArrayRepository { fn add_package( &mut self, - package: Box, + package: crate::package::PackageInterfaceHandle, ) -> anyhow::Result<()> { todo!() } @@ -68,7 +69,7 @@ impl WritableRepositoryInterface for InstalledArrayRepository { todo!() } - fn get_canonical_packages(&self) -> Vec> { + fn get_canonical_packages(&self) -> Vec { todo!() } @@ -99,17 +100,17 @@ impl RepositoryInterface for InstalledArrayRepository { &self, _name: &str, _constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { todo!() } fn find_packages( &self, _name: &str, _constraint: Option, - ) -> Vec> { + ) -> Vec { todo!() } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { todo!() } fn load_packages( @@ -117,7 +118,7 @@ impl RepositoryInterface for InstalledArrayRepository { _package_name_map: IndexMap>, _acceptable_stabilities: IndexMap, _stability_flags: IndexMap, - _already_loaded: IndexMap>>, + _already_loaded: IndexMap>, ) -> LoadPackagesResult { todo!() } diff --git a/crates/shirabe/src/repository/installed_filesystem_repository.rs b/crates/shirabe/src/repository/installed_filesystem_repository.rs index 5c6fecf..8a6359a 100644 --- a/crates/shirabe/src/repository/installed_filesystem_repository.rs +++ b/crates/shirabe/src/repository/installed_filesystem_repository.rs @@ -6,9 +6,10 @@ use shirabe_php_shim::Countable; use shirabe_semver::constraint::AnyConstraint; use crate::json::JsonFile; -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; -use crate::package::RootPackageInterface; +use crate::package::PackageInterfaceHandle; +use crate::package::RootPackageInterfaceHandle; use crate::repository::AdvisoryProviderInterface; use crate::repository::FilesystemRepository; use crate::repository::InstalledRepositoryInterface; @@ -27,7 +28,7 @@ impl InstalledFilesystemRepository { pub fn new( repository_file: JsonFile, dump_versions: bool, - root_package: Option>, + root_package: Option, filesystem: Option>>, ) -> Result { Ok(Self { @@ -66,7 +67,7 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository { fn add_package( &mut self, - package: Box, + package: crate::package::PackageInterfaceHandle, ) -> anyhow::Result<()> { todo!() } @@ -78,7 +79,7 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository { todo!() } - fn get_canonical_packages(&self) -> Vec> { + fn get_canonical_packages(&self) -> Vec { todo!() } @@ -109,17 +110,17 @@ impl RepositoryInterface for InstalledFilesystemRepository { &self, _name: &str, _constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { todo!() } fn find_packages( &self, _name: &str, _constraint: Option, - ) -> Vec> { + ) -> Vec { todo!() } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { todo!() } fn load_packages( @@ -127,7 +128,7 @@ impl RepositoryInterface for InstalledFilesystemRepository { _package_name_map: IndexMap>, _acceptable_stabilities: IndexMap, _stability_flags: IndexMap, - _already_loaded: IndexMap>>, + _already_loaded: IndexMap>, ) -> LoadPackagesResult { todo!() } diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs index 5c9e0d7..33356e3 100644 --- a/crates/shirabe/src/repository/installed_repository.rs +++ b/crates/shirabe/src/repository/installed_repository.rs @@ -6,10 +6,10 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MatchAllConstraint; use shirabe_semver::constraint::SimpleConstraint; -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::Link; use crate::package::PackageInterface; -use crate::package::RootPackageInterface; +use crate::package::PackageInterfaceHandle; use crate::package::version::VersionParser; use crate::repository::CompositeRepository; use crate::repository::InstalledRepositoryInterface; @@ -26,7 +26,7 @@ pub enum NeedleInput { } pub struct DependentsEntry( - pub Box, + pub BasePackageHandle, pub Link, pub Option>, ); @@ -53,7 +53,7 @@ impl InstalledRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { let name = name.to_lowercase(); let constraint: Option = match constraint { @@ -79,7 +79,7 @@ impl InstalledRepository { .into(), ) { - matches.push(candidate); + matches.push(candidate.clone()); } continue; } @@ -98,7 +98,7 @@ impl InstalledRepository { && (constraint.is_none() || constraint.as_ref().unwrap().matches(link.get_constraint())) { - matches.push(candidate); + matches.push(candidate.clone()); continue 'candidates; } } @@ -124,10 +124,10 @@ impl InstalledRepository { let mut packages_found = packages_found.unwrap_or_else(|| needles.clone()); - let mut root_package: Option> = None; + let mut root_package: Option = None; for package in self.inner.get_packages() { - if package.as_root_package_interface().is_some() { - root_package = Some(package); + if package.as_root().is_some() { + root_package = Some(package.clone()); break; } } @@ -150,7 +150,7 @@ impl InstalledRepository { { if packages_in_tree.contains(&link.get_target().to_string()) { results.push(DependentsEntry( - package.clone_box(), + package.clone(), link.clone(), None, )); @@ -169,7 +169,7 @@ impl InstalledRepository { vec![] }; results.push(DependentsEntry( - package.clone_box(), + package.clone(), link.clone(), Some(dependents), )); @@ -180,7 +180,7 @@ impl InstalledRepository { } } - if package.as_root_package_interface().is_some() { + if package.as_root().is_some() { for (k, v) in package.get_dev_requires() { links.entry(k).or_insert(v); } @@ -194,11 +194,7 @@ impl InstalledRepository { .map_or(true, |c| link.get_constraint().matches(c) == !invert); if constraint.is_none() || matches_constraint { if packages_in_tree.contains(&link.get_source().to_string()) { - results.push(DependentsEntry( - package.clone_box(), - link.clone(), - None, - )); + results.push(DependentsEntry(package.clone(), link.clone(), None)); continue; } packages_in_tree.push(link.get_source().to_string()); @@ -214,7 +210,7 @@ impl InstalledRepository { vec![] }; results.push(DependentsEntry( - package.clone_box(), + package.clone(), link.clone(), Some(dependents), )); @@ -232,7 +228,7 @@ impl InstalledRepository { None, ); if link.get_constraint().matches(&version.into()) == invert { - results.push(DependentsEntry(package.clone_box(), link.clone(), None)); + results.push(DependentsEntry(package.clone(), link.clone(), None)); } } } @@ -247,7 +243,7 @@ impl InstalledRepository { None, ); if link.get_constraint().matches(&version.into()) == invert { - results.push(DependentsEntry(package.clone_box(), link.clone(), None)); + results.push(DependentsEntry(package.clone(), link.clone(), None)); } } } @@ -286,7 +282,7 @@ impl InstalledRepository { .map(|p| format!("but {} is installed", p.get_pretty_version())) .unwrap_or_else(|| "but it is missing".to_string()); results.push(DependentsEntry( - package.clone_box(), + package.clone(), Link::new( package.get_name().to_string(), link.get_target().to_string(), @@ -316,7 +312,7 @@ impl InstalledRepository { ) .into(); - if link.get_target() != pkg.get_name() { + if link.get_target() != pkg.get_name().as_str() { let mut replaces_and_provides: IndexMap = pkg.get_replaces(); for (k, v) in pkg.get_provides() { @@ -343,12 +339,12 @@ impl InstalledRepository { && !root_req.get_constraint().matches(link.get_constraint()) { results.push(DependentsEntry( - package.clone_box(), + package.clone(), link.clone(), None, )); results.push(DependentsEntry( - root_pkg.clone_box(), + root_pkg.clone(), root_req.clone(), None, )); @@ -356,13 +352,9 @@ impl InstalledRepository { } } + results.push(DependentsEntry(package.clone(), link.clone(), None)); results.push(DependentsEntry( - package.clone_box(), - link.clone(), - None, - )); - results.push(DependentsEntry( - root_pkg.clone_box(), + root_pkg.clone(), Link::new( root_pkg.get_name().to_string(), link.get_target().to_string(), @@ -376,11 +368,7 @@ impl InstalledRepository { None, )); } else { - results.push(DependentsEntry( - package.clone_box(), - link.clone(), - None, - )); + results.push(DependentsEntry(package.clone(), link.clone(), None)); } } @@ -444,7 +432,7 @@ impl RepositoryInterface for InstalledRepository { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { self.inner.find_package(name, constraint) } @@ -452,11 +440,11 @@ impl RepositoryInterface for InstalledRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { self.inner.get_packages() } @@ -465,7 +453,7 @@ impl RepositoryInterface for InstalledRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult { self.inner.load_packages( package_name_map, diff --git a/crates/shirabe/src/repository/lock_array_repository.rs b/crates/shirabe/src/repository/lock_array_repository.rs index 57abe56..3d00ecf 100644 --- a/crates/shirabe/src/repository/lock_array_repository.rs +++ b/crates/shirabe/src/repository/lock_array_repository.rs @@ -1,7 +1,8 @@ //! ref: composer/src/Composer/Repository/LockArrayRepository.php -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::ArrayRepository; use crate::repository::CanonicalPackagesTrait; use crate::repository::{ @@ -17,7 +18,7 @@ pub struct LockArrayRepository { } impl CanonicalPackagesTrait for LockArrayRepository { - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { todo!() } } @@ -43,7 +44,7 @@ impl RepositoryInterface for LockArrayRepository { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option> { + ) -> Option { self.inner.find_package(name, constraint) } @@ -51,11 +52,11 @@ impl RepositoryInterface for LockArrayRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { RepositoryInterface::get_packages(&self.inner) } @@ -64,7 +65,7 @@ impl RepositoryInterface for LockArrayRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult { self.inner.load_packages( package_name_map, diff --git a/crates/shirabe/src/repository/package_repository.rs b/crates/shirabe/src/repository/package_repository.rs index 93c7e31..b88de78 100644 --- a/crates/shirabe/src/repository/package_repository.rs +++ b/crates/shirabe/src/repository/package_repository.rs @@ -71,8 +71,7 @@ impl PackageRepository { }))); } }; - // TODO(phase-b): add_package expects Box; loader returns Box - let _ = package_loaded; + self.inner.add_package(package_loaded)?; } Ok(Ok(())) } diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs index 0b3ccb1..31760bb 100644 --- a/crates/shirabe/src/repository/platform_repository.rs +++ b/crates/shirabe/src/repository/platform_repository.rs @@ -17,9 +17,12 @@ use shirabe_semver::constraint::SimpleConstraint; use crate::composer; use crate::composer::ComposerHandle; use crate::package::CompletePackage; +use crate::package::CompletePackageHandle; use crate::package::CompletePackageInterface; +use crate::package::CompletePackageInterfaceHandle; use crate::package::Link; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::package::version::VersionParser; use crate::platform::HhvmDetector; use crate::platform::Runtime; @@ -46,7 +49,7 @@ pub struct PlatformRepository { pub(crate) inner: ArrayRepository, pub(crate) version_parser: Option, pub(crate) overrides: IndexMap, - pub(crate) disabled_packages: IndexMap>, + pub(crate) disabled_packages: IndexMap, pub(crate) runtime: Runtime, pub(crate) hhvm_detector: HhvmDetector, } @@ -55,14 +58,14 @@ impl PlatformRepository { pub const PLATFORM_PACKAGE_REGEX: &'static str = "{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer(?:-(?:plugin|runtime)-api)?)$}iD"; pub fn new( - packages: Vec>, + packages: Vec, overrides: IndexMap, ) -> anyhow::Result { Self::new4(packages, overrides, None, None) } pub fn new4( - packages: Vec>, + packages: Vec, overrides: IndexMap, runtime: Option, hhvm_detector: Option, @@ -117,7 +120,7 @@ impl PlatformRepository { self.disabled_packages.contains_key(name) } - pub fn get_disabled_packages(&self) -> &IndexMap> { + pub fn get_disabled_packages(&self) -> &IndexMap { &self.disabled_packages } @@ -167,7 +170,7 @@ impl PlatformRepository { pretty_version.clone(), ); composer.set_description("Composer package".to_string()); - self.add_package(Box::new(composer))?; + self.add_package(CompletePackageHandle::from_complete_package(composer).into())?; pretty_version = plugin_interface::PLUGIN_API_VERSION.to_string(); version = self @@ -181,7 +184,7 @@ impl PlatformRepository { pretty_version.clone(), ); composer_plugin_api.set_description("The Composer Plugin API".to_string()); - self.add_package(Box::new(composer_plugin_api))?; + self.add_package(CompletePackageHandle::from_complete_package(composer_plugin_api).into())?; pretty_version = composer::RUNTIME_API_VERSION.to_string(); version = self @@ -195,7 +198,9 @@ impl PlatformRepository { pretty_version.clone(), ); composer_runtime_api.set_description("The Composer Runtime API".to_string()); - self.add_package(Box::new(composer_runtime_api))?; + self.add_package( + CompletePackageHandle::from_complete_package(composer_runtime_api).into(), + )?; let php_version_const = self.runtime.get_constant("PHP_VERSION", None); let php_version_str = match &php_version_const { @@ -226,7 +231,7 @@ impl PlatformRepository { let mut php = CompletePackage::new("php".to_string(), version.clone(), pretty_version.clone()); php.set_description("The PHP interpreter".to_string()); - self.add_package(Box::new(php))?; + self.add_package(CompletePackageHandle::from_complete_package(php).into())?; if self .runtime @@ -240,7 +245,7 @@ impl PlatformRepository { pretty_version.clone(), ); phpdebug.set_description("The PHP interpreter, with debugging symbols".to_string()); - self.add_package(Box::new(phpdebug))?; + self.add_package(CompletePackageHandle::from_complete_package(phpdebug).into())?; } if self.runtime.has_constant("PHP_ZTS", None) @@ -256,7 +261,7 @@ impl PlatformRepository { pretty_version.clone(), ); phpzts.set_description("The PHP interpreter, with Zend Thread Safety".to_string()); - self.add_package(Box::new(phpzts))?; + self.add_package(CompletePackageHandle::from_complete_package(phpzts).into())?; } if self @@ -272,7 +277,7 @@ impl PlatformRepository { pretty_version.clone(), ); php64.set_description("The PHP interpreter, 64bit".to_string()); - self.add_package(Box::new(php64))?; + self.add_package(CompletePackageHandle::from_complete_package(php64).into())?; } // The AF_INET6 constant is only defined if ext-sockets is available but @@ -297,7 +302,7 @@ impl PlatformRepository { pretty_version.clone(), ); php_ipv6.set_description("The PHP interpreter, with IPv6 support".to_string()); - self.add_package(Box::new(php_ipv6))?; + self.add_package(CompletePackageHandle::from_complete_package(php_ipv6).into())?; } let loaded_extensions = self.runtime.get_extensions(); @@ -1582,14 +1587,13 @@ impl PlatformRepository { let mut hhvm = CompletePackage::new("hhvm".to_string(), version, pretty_version); hhvm.set_description("The HHVM Runtime (64bit)".to_string()); - self.add_package(Box::new(hhvm))?; + self.add_package(CompletePackageHandle::from_complete_package(hhvm).into())?; } Ok(()) } - pub fn add_package(&mut self, package: Box) -> anyhow::Result<()> { - // TODO(phase-b): downcast `package` to CompletePackage; this stub keeps the structure. - if !Self::is_complete_package(package.as_ref()) { + pub fn add_package(&mut self, package: PackageInterfaceHandle) -> anyhow::Result<()> { + if package.as_complete().is_none() { return Err(anyhow::anyhow!(UnexpectedValueException { message: format!( "Expected CompletePackage but got {}", @@ -1599,18 +1603,17 @@ impl PlatformRepository { })); } + let name = package.get_name(); + // Skip if overridden - if self.overrides.contains_key(package.get_name()) { - if matches!( - self.overrides[package.get_name()].version, - PhpMixed::Bool(false) - ) { + if self.overrides.contains_key(&name) { + if matches!(self.overrides[&name].version, PhpMixed::Bool(false)) { self.add_disabled_package_from_pkg(package); return Ok(()); } let overrider = self.inner.find_package( - package.get_name(), + &name, crate::repository::FindPackageConstraint::String("*".to_string()), ); let actual_text = if let Some(ref ov) = overrider { @@ -1622,24 +1625,24 @@ impl PlatformRepository { } else { format!("actual: {}", package.get_pretty_version()) }; - if let Some(_overrider_pkg) = overrider { - // TODO(phase-b): downcast `overrider` to CompletePackageInterface for setDescription - let _ = actual_text; + if let Some(overrider) = overrider { + if let Some(overrider) = overrider.as_complete() { + let description = overrider.get_description().unwrap_or_default(); + overrider.set_description(format!("{}, {}", description, actual_text)); + } } return Ok(()); } // Skip if PHP is overridden and we are adding a php-* package - if self.overrides.contains_key("php") && strpos(package.get_name(), "php-") == Some(0) { + if self.overrides.contains_key("php") && strpos(&name, "php-") == Some(0) { let php_override = PlatformOverride { name: self.overrides["php"].name.clone(), version: self.overrides["php"].version.clone(), }; - let mut overrider = self.add_overridden_package( - &php_override, - Some(package.get_pretty_name().to_string()), - )?; + let mut overrider = + self.add_overridden_package(&php_override, Some(package.get_pretty_name()))?; let actual_text = if package.get_version() == overrider.get_version() { "same as actual".to_string() } else { @@ -1693,22 +1696,32 @@ impl PlatformRepository { Ok(package) } - fn add_disabled_package_from_pkg(&mut self, _package: Box) { - // TODO(phase-b): downcast to CompletePackage and call `addDisabledPackage`. + fn add_disabled_package_from_pkg(&mut self, package: PackageInterfaceHandle) { + // PHP type-hints CompletePackage here; the handle is guaranteed complete by add_package. + let complete = package + .as_complete() + .expect("addDisabledPackage expects a CompletePackage"); + self.add_disabled_package(complete); } - fn add_disabled_package(&mut self, mut package: CompletePackage) { - let current_description = package.get_description().unwrap_or("").to_string(); + fn add_disabled_package(&mut self, package: CompletePackageInterfaceHandle) { + let current_description = package.get_description().unwrap_or_default(); package.set_description(format!( "{}. Package disabled via config.platform", current_description )); let mut extra: IndexMap = IndexMap::new(); extra.insert("config.platform".to_string(), PhpMixed::Bool(true)); - package.inner.set_extra(extra); + // NOTE(phase-c): neither PackageInterface nor CompletePackageInterface exposes + // setExtra (PHP defines it on BasePackage), and the handle API does not surface + // it. Disabled packages are always plain CompletePackage objects, so reach the + // concrete Package through the shared Rc. + match &mut *package.as_rc().borrow_mut() { + crate::package::AnyPackage::CompletePackage(p) => p.inner.set_extra(extra), + _ => unreachable!("disabled platform package must be a concrete CompletePackage"), + } - self.disabled_packages - .insert(package.get_name().to_string(), Box::new(package)); + self.disabled_packages.insert(package.get_name(), package); } /// Parses the version and adds a new package to the repository @@ -1768,7 +1781,7 @@ impl PlatformRepository { ext.inner.set_replaces(replaces); } - self.add_package(Box::new(ext))?; + self.add_package(CompletePackageHandle::from_complete_package(ext).into())?; Ok(()) } @@ -1848,7 +1861,7 @@ impl PlatformRepository { lib.inner.set_replaces(replace_links); lib.inner.set_provides(provide_links); - self.add_package(Box::new(lib))?; + self.add_package(CompletePackageHandle::from_complete_package(lib).into())?; Ok(()) } @@ -1945,7 +1958,7 @@ impl crate::repository::RepositoryInterface for PlatformRepository { &self, name: &str, constraint: crate::repository::FindPackageConstraint, - ) -> Option> { + ) -> Option { self.inner.find_package(name, constraint) } @@ -1953,11 +1966,11 @@ impl crate::repository::RepositoryInterface for PlatformRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { self.inner.get_packages() } @@ -1966,7 +1979,7 @@ impl crate::repository::RepositoryInterface for PlatformRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> crate::repository::LoadPackagesResult { self.inner.load_packages( package_name_map, diff --git a/crates/shirabe/src/repository/repository_interface.rs b/crates/shirabe/src/repository/repository_interface.rs index 4bd1f3e..9cadc48 100644 --- a/crates/shirabe/src/repository/repository_interface.rs +++ b/crates/shirabe/src/repository/repository_interface.rs @@ -1,7 +1,8 @@ //! ref: composer/src/Composer/Repository/RepositoryInterface.php -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::AdvisoryProviderInterface; use indexmap::IndexMap; use shirabe_php_shim::Countable; @@ -24,7 +25,7 @@ impl Clone for FindPackageConstraint { #[derive(Debug)] pub struct LoadPackagesResult { pub names_found: Vec, - pub packages: IndexMap>, + pub packages: IndexMap, } #[derive(Debug, Clone)] @@ -59,22 +60,22 @@ pub trait RepositoryInterface: Countable + std::fmt::Debug { &self, name: &str, constraint: FindPackageConstraint, - ) -> Option>; + ) -> Option; fn find_packages( &self, name: &str, constraint: Option, - ) -> Vec>; + ) -> Vec; - fn get_packages(&self) -> Vec>; + fn get_packages(&self) -> Vec; fn load_packages( &self, package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> LoadPackagesResult; fn search(&self, query: String, mode: i64, r#type: Option) -> Vec; diff --git a/crates/shirabe/src/repository/repository_manager.rs b/crates/shirabe/src/repository/repository_manager.rs index e85312a..f432d6e 100644 --- a/crates/shirabe/src/repository/repository_manager.rs +++ b/crates/shirabe/src/repository/repository_manager.rs @@ -7,7 +7,7 @@ use shirabe_semver::constraint::AnyConstraint; use crate::config::Config; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; -use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::FilterRepository; use crate::repository::InstalledRepositoryInterface; use crate::repository::RepositoryInterface; @@ -52,13 +52,13 @@ impl RepositoryManager { &self, name: &str, constraint: &AnyConstraint, - ) -> Option> { + ) -> Option { for repository in &self.repositories { if let Some(package) = repository.find_package( name, crate::repository::FindPackageConstraint::Constraint(constraint.clone()), ) { - return Some(package.clone_package_box()); + return Some(package.clone().into()); } } None @@ -68,8 +68,8 @@ impl RepositoryManager { &self, name: &str, constraint: &AnyConstraint, - ) -> Vec> { - let mut packages: Vec> = vec![]; + ) -> Vec { + let mut packages: Vec = vec![]; for repository in self.get_repositories() { for p in repository.find_packages( name, @@ -77,7 +77,7 @@ impl RepositoryManager { constraint.clone(), )), ) { - packages.push(p.clone_package_box()); + packages.push(p.clone().into()); } } packages diff --git a/crates/shirabe/src/repository/repository_set.rs b/crates/shirabe/src/repository/repository_set.rs index 84159d4..1c9c4a3 100644 --- a/crates/shirabe/src/repository/repository_set.rs +++ b/crates/shirabe/src/repository/repository_set.rs @@ -24,11 +24,10 @@ use crate::downloader::TransportException; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; use crate::io::NullIO; -use crate::package::AliasPackage; -use crate::package::BasePackage; -use crate::package::CompleteAliasPackage; -use crate::package::CompletePackage; -use crate::package::PackageInterface; +use crate::package::AliasPackageHandle; +use crate::package::BasePackageHandle; +use crate::package::CompleteAliasPackageHandle; +use crate::package::PackageInterfaceHandle; use crate::package::version::StabilityFilter; use crate::repository::CompositeRepository; use crate::repository::InstalledRepository; @@ -210,11 +209,11 @@ impl RepositorySet { name: &str, constraint: Option, flags: i64, - ) -> Vec> { + ) -> Vec { let ignore_stability = (flags & Self::ALLOW_UNACCEPTABLE_STABILITIES) != 0; let load_from_all_repos = (flags & Self::ALLOW_SHADOWED_REPOSITORIES) != 0; - let mut packages: Vec>> = vec![]; + let mut packages: Vec> = vec![]; if load_from_all_repos { for repository in &self.repositories { // PHP: $repository->findPackages($name, $constraint) ?: [] @@ -260,7 +259,7 @@ impl RepositorySet { } // PHP: $candidates = $packages ? array_merge(...$packages) : []; - let candidates: Vec> = if !packages.is_empty() { + let candidates: Vec = if !packages.is_empty() { packages.into_iter().flatten().collect() } else { vec![] @@ -271,9 +270,9 @@ impl RepositorySet { return candidates; } - let mut result: Vec> = vec![]; + let mut result: Vec = vec![]; for candidate in candidates { - if self.is_package_acceptable(&candidate.get_names(true), candidate.get_stability()) { + if self.is_package_acceptable(&candidate.get_names(true), &candidate.get_stability()) { result.push(candidate); } } @@ -312,14 +311,14 @@ impl RepositorySet { /// @return ($allowPartialAdvisories is true ? array{advisories: array>, unreachableRepos: array} : array{advisories: array>, unreachableRepos: array}) pub fn get_matching_security_advisories( &self, - packages: Vec>, + packages: Vec, allow_partial_advisories: bool, ignore_unreachable: bool, ) -> Result { let mut map: IndexMap = IndexMap::new(); for package in packages { // ignore root alias versions as they are not actual package versions and should not matter when it comes to vulnerabilities - if let Some(alias) = package.as_any().downcast_ref::() { + if let Some(alias) = package.as_alias() { if alias.is_root_package_alias() { continue; } @@ -525,42 +524,43 @@ impl RepositorySet { self.locked = true; - let mut packages: Vec> = vec![]; + let mut packages: Vec = vec![]; for repository in &self.repositories { for mut package in repository.get_packages() { - let name = package.get_name().to_string(); - let version = package.get_version().to_string(); - packages.push(package.clone_box()); + let name = package.get_name(); + let version = package.get_version(); + packages.push(package.clone()); if let Some(versions) = self.root_aliases.get(&name) { if let Some(alias) = versions.get(&version) { - while let Some(alias_pkg) = package.as_any().downcast_ref::() - { - package = alias_pkg.get_alias_of().clone_box(); + while let Some(alias_pkg) = package.as_alias() { + package = alias_pkg.get_alias_of().into(); + } + let alias_package: BasePackageHandle = + if let Some(complete) = package.as_complete_package() { + CompleteAliasPackageHandle::new( + complete, + alias.alias_normalized.clone(), + alias.alias.clone(), + ) + .into() + } else { + AliasPackageHandle::new( + package.as_package().unwrap(), + alias.alias_normalized.clone(), + alias.alias.clone(), + ) + .into() + }; + if let Some(alias_handle) = alias_package.as_alias() { + alias_handle.set_root_package_alias(true); } - let alias_package: Box = if package - .as_any() - .downcast_ref::() - .is_some() - { - // TODO(phase-b): construct CompleteAliasPackage and box as BasePackage - todo!( - "new CompleteAliasPackage(package, alias.alias_normalized, alias.alias)" - ) - } else { - // TODO(phase-b): construct AliasPackage and box as BasePackage - todo!("new AliasPackage(package, alias.alias_normalized, alias.alias)") - }; - // TODO(phase-b): set_root_package_alias on the wrapper - todo!("alias_package.set_root_package_alias(true)"); - #[allow(unreachable_code)] packages.push(alias_package); } } } } - // TODO(phase-b): Pool::new signature Ok(Pool::new( packages, vec![], diff --git a/crates/shirabe/src/repository/repository_utils.rs b/crates/shirabe/src/repository/repository_utils.rs index 7fe98b0..51b8673 100644 --- a/crates/shirabe/src/repository/repository_utils.rs +++ b/crates/shirabe/src/repository/repository_utils.rs @@ -12,11 +12,11 @@ pub struct RepositoryUtils; impl RepositoryUtils { pub fn filter_required_packages( - packages: &[Box], + packages: &[crate::package::BasePackageHandle], requirer: &dyn PackageInterface, include_require_dev: bool, - mut bucket: Vec>, - ) -> Vec> { + mut bucket: Vec, + ) -> Vec { let mut requires: IndexMap = requirer.get_requires(); if include_require_dev { requires.extend(requirer.get_dev_requires()); @@ -25,15 +25,9 @@ impl RepositoryUtils { for candidate in packages { for name in candidate.get_names(true) { if requires.contains_key(&name) { - let already_in_bucket = bucket.iter().any(|b| { - std::ptr::eq( - b.as_ref() as *const dyn crate::package::BasePackage as *const (), - candidate.as_ref() as *const dyn crate::package::BasePackage - as *const (), - ) - }); + let already_in_bucket = bucket.iter().any(|b| b.ptr_eq(candidate)); if !already_in_bucket { - bucket.push(candidate.clone_box()); + bucket.push(candidate.clone()); // TODO(phase-b): recursion requires &dyn PackageInterface; cast pending. let _ = (requires.contains_key("dummy"),); } diff --git a/crates/shirabe/src/repository/root_package_repository.rs b/crates/shirabe/src/repository/root_package_repository.rs index 1487f3e..71cd270 100644 --- a/crates/shirabe/src/repository/root_package_repository.rs +++ b/crates/shirabe/src/repository/root_package_repository.rs @@ -1,8 +1,9 @@ //! ref: composer/src/Composer/Repository/RootPackageRepository.php -use crate::package::BasePackage; +use crate::package::BasePackageHandle; use crate::package::PackageInterface; -use crate::package::RootPackageInterface; +use crate::package::PackageInterfaceHandle; +use crate::package::RootPackageInterfaceHandle; use crate::repository::ArrayRepository; use crate::repository::{ProviderInfo, RepositoryInterface, SearchResult}; use indexmap::IndexMap; @@ -13,13 +14,9 @@ pub struct RootPackageRepository { } impl RootPackageRepository { - pub fn new(package: Box) -> Self { + pub fn new(package: RootPackageInterfaceHandle) -> Self { Self { - // TODO(phase-b): RootPackageInterface vs BasePackage upcast + ArrayRepository::new error - inner: ArrayRepository::new(vec![todo!( - "convert Box to Box" - )]) - .expect("invalid root package"), + inner: ArrayRepository::new(vec![package.into()]).expect("invalid root package"), } } @@ -43,7 +40,7 @@ impl RepositoryInterface for RootPackageRepository { &self, name: &str, constraint: crate::repository::FindPackageConstraint, - ) -> Option> { + ) -> Option { self.inner.find_package(name, constraint) } @@ -51,11 +48,11 @@ impl RepositoryInterface for RootPackageRepository { &self, name: &str, constraint: Option, - ) -> Vec> { + ) -> Vec { self.inner.find_packages(name, constraint) } - fn get_packages(&self) -> Vec> { + fn get_packages(&self) -> Vec { self.inner.get_packages() } @@ -64,7 +61,7 @@ impl RepositoryInterface for RootPackageRepository { package_name_map: IndexMap>, acceptable_stabilities: IndexMap, stability_flags: IndexMap, - already_loaded: IndexMap>>, + already_loaded: IndexMap>, ) -> crate::repository::LoadPackagesResult { self.inner.load_packages( package_name_map, diff --git a/crates/shirabe/src/repository/vcs_repository.rs b/crates/shirabe/src/repository/vcs_repository.rs index 1ae7e40..a256fb8 100644 --- a/crates/shirabe/src/repository/vcs_repository.rs +++ b/crates/shirabe/src/repository/vcs_repository.rs @@ -15,7 +15,6 @@ use crate::config::Config; use crate::downloader::TransportException; use crate::event_dispatcher::EventDispatcher; use crate::io::IOInterface; -use crate::package::BasePackage; use crate::package::loader::ArrayLoader; use crate::package::loader::InvalidPackageException; use crate::package::loader::LoaderInterface; @@ -387,9 +386,7 @@ impl VcsRepository { )?; match cached_package { CachedPackageResult::Package(pkg) => { - // TODO(phase-b): trait upcast Box -> Box - let pkg_pi: Box = pkg.clone_package_box(); - self.inner.add_package(pkg_pi)?; + self.inner.add_package(pkg)?; continue; } CachedPackageResult::Missing => { @@ -541,10 +538,7 @@ impl VcsRepository { let driver = self.driver.as_ref().unwrap(); let processed = self.pre_process(&**driver, data, &identifier)?; let loaded = self.loader.as_ref().unwrap().load(processed, None)?; - // TODO(phase-b): trait upcast Box -> Box - let loaded_pi: Box = - loaded.clone_package_box(); - self.inner.add_package(loaded_pi)?; + self.inner.add_package(loaded)?; Ok(()) })(); if let Err(e) = result { @@ -662,9 +656,7 @@ impl VcsRepository { )?; match cached_package { CachedPackageResult::Package(pkg) => { - // TODO(phase-b): trait upcast Box -> Box - let pkg_pi: Box = pkg.clone_package_box(); - self.inner.add_package(pkg_pi)?; + self.inner.add_package(pkg)?; continue; } CachedPackageResult::Missing => { @@ -727,10 +719,7 @@ impl VcsRepository { ); } } - // TODO(phase-b): trait upcast Box -> Box - let package_pi: Box = - package.clone_package_box(); - self.inner.add_package(package_pi)?; + self.inner.add_package(package)?; Ok(()) })(); if let Err(e) = result { @@ -995,5 +984,5 @@ impl VcsRepository { enum CachedPackageResult { None, Missing, - Package(Box), + Package(crate::package::PackageInterfaceHandle), } diff --git a/crates/shirabe/src/repository/writable_array_repository.rs b/crates/shirabe/src/repository/writable_array_repository.rs index 663ab52..ebe70c3 100644 --- a/crates/shirabe/src/repository/writable_array_repository.rs +++ b/crates/shirabe/src/repository/writable_array_repository.rs @@ -14,7 +14,7 @@ pub struct WritableArrayRepository { } impl WritableArrayRepository { - pub fn new(packages: Vec>) -> Result { + pub fn new(packages: Vec) -> Result { Ok(Self { inner: ArrayRepository::new(packages)?, dev_package_names: Vec::new(), @@ -48,10 +48,7 @@ impl WritableArrayRepository { self.dev_mode = None; } - pub fn add_package( - &mut self, - package: Box, - ) -> Result<()> { + pub fn add_package(&mut self, package: crate::package::PackageInterfaceHandle) -> Result<()> { self.inner.add_package(package) } @@ -66,14 +63,13 @@ impl WritableArrayRepository { Ok(()) } - pub fn get_canonical_packages(&self) -> Vec> { + pub fn get_canonical_packages(&self) -> Vec { // TODO(phase-b): delegate to inner once it exposes get_canonical_packages Vec::new() } - pub fn get_packages(&self) -> Vec> { - // TODO(phase-b): delegate to inner ArrayRepository::get_packages - Vec::new() + pub fn get_packages(&self) -> Vec { + crate::repository::RepositoryInterface::get_packages(&self.inner) } pub fn get_repo_name(&self) -> String { diff --git a/crates/shirabe/src/repository/writable_repository_interface.rs b/crates/shirabe/src/repository/writable_repository_interface.rs index 7094211..b5b1e35 100644 --- a/crates/shirabe/src/repository/writable_repository_interface.rs +++ b/crates/shirabe/src/repository/writable_repository_interface.rs @@ -2,17 +2,18 @@ use crate::installer::InstallationManager; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::RepositoryInterface; use anyhow::Result; pub trait WritableRepositoryInterface: RepositoryInterface { fn write(&mut self, dev_mode: bool, installation_manager: &InstallationManager) -> Result<()>; - fn add_package(&mut self, package: Box) -> Result<()>; + fn add_package(&mut self, package: PackageInterfaceHandle) -> Result<()>; fn remove_package(&mut self, package: &dyn PackageInterface) -> Result<()>; - fn get_canonical_packages(&self) -> Vec>; + fn get_canonical_packages(&self) -> Vec; fn reload(&mut self); -- cgit v1.3.1