aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/repository
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-25 00:58:20 +0900
committernsfisis <nsfisis@gmail.com>2026-05-25 00:58:36 +0900
commit1921f173ea219cb4b25847294d2d3fa465550fbb (patch)
tree0d30486a2cb9a0c106e5d5827be3f655c60cd871 /crates/shirabe/src/repository
parentdbdecaf5a1c54a876b7ee0153d58dd39b1080f97 (diff)
downloadphp-shirabe-1921f173ea219cb4b25847294d2d3fa465550fbb.tar.gz
php-shirabe-1921f173ea219cb4b25847294d2d3fa465550fbb.tar.zst
php-shirabe-1921f173ea219cb4b25847294d2d3fa465550fbb.zip
refactor(package): introduce Rc<RefCell<_>> handles for packages
PHP packages have reference semantics, so introduce shared-ownership handles over an AnyPackage enum (PackageInterfaceHandle and friends) and replace Box<dyn PackageInterface> throughout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/repository')
-rw-r--r--crates/shirabe/src/repository/array_repository.rs157
-rw-r--r--crates/shirabe/src/repository/artifact_repository.rs2
-rw-r--r--crates/shirabe/src/repository/canonical_packages_trait.rs20
-rw-r--r--crates/shirabe/src/repository/composer_repository.rs139
-rw-r--r--crates/shirabe/src/repository/composite_repository.rs27
-rw-r--r--crates/shirabe/src/repository/filesystem_repository.rs66
-rw-r--r--crates/shirabe/src/repository/filter_repository.rs14
-rw-r--r--crates/shirabe/src/repository/installed_array_repository.rs17
-rw-r--r--crates/shirabe/src/repository/installed_filesystem_repository.rs19
-rw-r--r--crates/shirabe/src/repository/installed_repository.rs66
-rw-r--r--crates/shirabe/src/repository/lock_array_repository.rs13
-rw-r--r--crates/shirabe/src/repository/package_repository.rs3
-rw-r--r--crates/shirabe/src/repository/platform_repository.rs99
-rw-r--r--crates/shirabe/src/repository/repository_interface.rs13
-rw-r--r--crates/shirabe/src/repository/repository_manager.rs12
-rw-r--r--crates/shirabe/src/repository/repository_set.rs72
-rw-r--r--crates/shirabe/src/repository/repository_utils.rs16
-rw-r--r--crates/shirabe/src/repository/root_package_repository.rs21
-rw-r--r--crates/shirabe/src/repository/vcs_repository.rs21
-rw-r--r--crates/shirabe/src/repository/writable_array_repository.rs14
-rw-r--r--crates/shirabe/src/repository/writable_repository_interface.rs5
21 files changed, 382 insertions, 434 deletions
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<BasePackage>
// TODO(phase-b): RefCell models PHP's lazy init via getPackages()/count() under &self
- pub(crate) packages: RefCell<Option<Vec<Box<dyn BasePackage>>>>,
+ pub(crate) packages: RefCell<Option<Vec<BasePackageHandle>>>,
/// @var ?array<BasePackage> indexed by package unique name and used to cache hasPackage calls
- pub(crate) package_map: RefCell<Option<IndexMap<String, Box<dyn BasePackage>>>>,
+ pub(crate) package_map: RefCell<Option<IndexMap<String, BasePackageHandle>>>,
}
impl ArrayRepository {
/// @param array<PackageInterface> $packages
- pub fn new(packages: Vec<Box<dyn PackageInterface>>) -> Result<Self> {
+ pub fn new(packages: Vec<PackageInterfaceHandle>) -> Result<Self> {
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<dyn PackageInterface>) -> 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<dyn PackageInterface> to Box<dyn BasePackage>
- let mut package: Box<dyn BasePackage> =
- todo!("downcast Box<dyn PackageInterface> to Box<dyn BasePackage>");
-
+ 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<dyn RepositoryInterface>"))?;
- let aliased_package: Option<Box<dyn BasePackage>> =
- if let Some(alias) = package.as_any().downcast_ref::<AliasPackage>() {
- Some(alias.get_alias_of().clone_box())
- } else {
- None
- };
+ let aliased_package: Option<PackageHandle> =
+ 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<dyn PackageInterface>
- self.add_package(todo!("Box<BasePackage> -> Box<dyn PackageInterface>"))?;
- }
+ // 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<dyn BasePackage>,
+ package: BasePackageHandle,
alias: String,
pretty_alias: String,
- ) -> Box<dyn BasePackage> {
- while let Some(alias_pkg) = package.as_any().downcast_ref::<AliasPackage>() {
- 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::<CompletePackage>().is_some() {
- // TODO(phase-b): construct CompleteAliasPackage/AliasPackage and return as Box<BasePackage>
+ 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<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> LoadPackagesResult {
let packages = self.get_packages();
- let mut result: IndexMap<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut result: IndexMap<String, BasePackageHandle> = IndexMap::new();
let mut names_found: IndexMap<String, bool> = 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::<AliasPackage>() {
+ 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::<AliasPackage>() {
+ 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<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
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<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
// 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<String, SearchResult> = 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::<CompletePackage>();
+ let complete = package.as_complete();
let fulltext_match = mode == crate::repository::SEARCH_FULLTEXT
&& complete.is_some()
@@ -337,8 +315,12 @@ impl RepositoryInterface for ArrayRepository {
&regex,
&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<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut map: IndexMap<String, BasePackageHandle> = 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<String, ProviderInfo> = 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::<CompletePackage>();
- 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<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
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<Option<Box<dyn BasePackage>>> {
+ ) -> anyhow::Result<Option<crate::package::PackageInterfaceHandle>> {
let mut json: Option<String> = 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<Box<dyn PackageInterface>>;
+ fn get_packages(&self) -> Vec<PackageInterfaceHandle>;
/// Get unique packages (at most one package of each name), with aliases resolved and removed.
- fn get_canonical_packages(&self) -> Vec<Box<dyn PackageInterface>> {
+ fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle> {
let packages = self.get_packages();
// get at most one package of each name, preferring non-aliased ones
- let mut packages_by_name: IndexMap<String, Box<dyn PackageInterface>> = IndexMap::new();
+ let mut packages_by_name: IndexMap<String, PackageInterfaceHandle> = 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<dyn PackageInterface>` 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<dyn BasePackage>),
- Packages(Vec<Box<dyn BasePackage>>),
+ Package(BasePackageHandle),
+ Packages(Vec<BasePackageHandle>),
None,
}
#[derive(Debug)]
pub struct LoadAsyncPackagesResult {
pub names_found: IndexMap<String, bool>,
- pub packages: IndexMap<String, Box<dyn BasePackage>>,
+ pub packages: IndexMap<String, BasePackageHandle>,
}
impl ConfigurableRepositoryInterface for ComposerRepository {
@@ -322,7 +324,7 @@ impl ComposerRepository {
&mut self,
name: String,
constraint: PhpMixed,
- ) -> anyhow::Result<Option<Box<dyn BasePackage>>> {
+ ) -> anyhow::Result<Option<BasePackageHandle>> {
// 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<Box<dyn BasePackage>> = packages.into_values().collect();
+ let packages_vec: Vec<BasePackageHandle> = 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<Box<dyn BasePackage>> = packages.into_values().collect();
+ let packages_vec: Vec<BasePackageHandle> = 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<PhpMixed>,
- ) -> anyhow::Result<Vec<Box<dyn BasePackage>>> {
+ ) -> anyhow::Result<Vec<BasePackageHandle>> {
// 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<Box<dyn BasePackage>> = packages.into_values().collect();
+ let packages_vec: Vec<BasePackageHandle> = 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<Box<dyn BasePackage>> = packages.into_values().collect();
+ let packages_vec: Vec<BasePackageHandle> = 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<Box<dyn BasePackage>>,
+ packages: Vec<BasePackageHandle>,
constraint: Option<&AnyConstraint>,
return_first_match: bool,
) -> FindPackageReturn {
@@ -477,7 +479,7 @@ impl ComposerRepository {
}
let constraint = constraint.unwrap();
- let mut filtered_packages: Vec<Box<dyn BasePackage>> = Vec::new();
+ let mut filtered_packages: Vec<BasePackageHandle> = 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<Vec<Box<dyn BasePackage>>> {
+ pub fn get_packages(&mut self) -> anyhow::Result<Vec<BasePackageHandle>> {
let has_providers = self.has_providers()?;
if self.lazy_providers_url.is_some() {
@@ -712,7 +714,7 @@ impl ComposerRepository {
mut package_name_map: IndexMap<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> anyhow::Result<LoadPackagesResult> {
// 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<Box<dyn BasePackage>>
- // 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<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut packages: IndexMap<String, BasePackageHandle> = IndexMap::new();
let mut names_found: IndexMap<String, bool> = IndexMap::new();
if has_providers || self.has_partial_packages()? {
let names: Vec<String> = package_name_map.keys().cloned().collect();
for name in names {
- let mut matches: IndexMap<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut matches: IndexMap<String, BasePackageHandle> = 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<dyn PackageInterface> 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<dyn PackageInterface>"),
+ 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<String, i64>>,
stability_flags: Option<&IndexMap<String, i64>>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
- ) -> anyhow::Result<IndexMap<String, Box<dyn BasePackage>>> {
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
+ ) -> anyhow::Result<IndexMap<String, BasePackageHandle>> {
let mut packages_source: Option<String> = None;
let packages: IndexMap<String, PhpMixed>;
let loading_partial_package: bool;
@@ -1635,7 +1630,7 @@ impl ComposerRepository {
loading_partial_package = true;
}
- let mut result: IndexMap<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut result: IndexMap<String, BasePackageHandle> = IndexMap::new();
let mut versions_to_load: IndexMap<String, IndexMap<String, PhpMixed>> = 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<String> = 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<dyn BasePackage>) {
- // 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<String, Option<AnyConstraint>>,
acceptable_stabilities: Option<&IndexMap<String, i64>>,
stability_flags: Option<&IndexMap<String, i64>>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> anyhow::Result<LoadAsyncPackagesResult> {
self.load_root_server_file(None)?;
- let mut packages: IndexMap<String, Box<dyn BasePackage>> = IndexMap::new();
+ let mut packages: IndexMap<String, BasePackageHandle> = IndexMap::new();
let mut names_found: IndexMap<String, bool> = IndexMap::new();
if self.lazy_providers_url.is_none() {
@@ -1980,17 +1974,16 @@ impl ComposerRepository {
}
}
- let loaded_packages: Vec<Box<dyn BasePackage>> =
+ let loaded_packages: Vec<BasePackageHandle> =
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<IndexMap<String, PhpMixed>>,
source: Option<String>,
- ) -> anyhow::Result<Vec<Box<dyn BasePackage>>> {
+ ) -> anyhow::Result<Vec<BasePackageHandle>> {
if packages.is_empty() {
return Ok(vec![]);
}
let mut packages = packages;
- let result = (|| -> anyhow::Result<Vec<Box<dyn BasePackage>>> {
+ let result = (|| -> anyhow::Result<Vec<BasePackageHandle>> {
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<Box<dyn BasePackage>> = Vec::new();
- for mut package in package_instances.into_iter() {
+ let mut results: Vec<BasePackageHandle> = 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<IndexMap<String, PhpMixed>> = 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<IndexMap<String, PhpMixed>>,
_source: Option<String>,
- ) -> anyhow::Result<Vec<Box<dyn BasePackage>>> {
+ ) -> anyhow::Result<Vec<BasePackageHandle>> {
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<dyn BasePackage> {
- 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<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
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<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
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<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
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<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<String, Option<AnyConstraint>> = package_name_map
.iter()
.map(|(k, v)| (k.clone(), v.as_ref().map(|c| c.clone())))
.collect();
- let already_loaded_cloned: IndexMap<
- String,
- IndexMap<String, Box<dyn PackageInterface>>,
- > = already_loaded
- .iter()
- .map(|(k, inner)| {
- let inner_cloned: IndexMap<String, Box<dyn PackageInterface>> = 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<Box<dyn RootPackageInterface>>,
+ root_package: Option<RootPackageInterfaceHandle>,
/// @var Filesystem
filesystem: std::rc::Rc<std::cell::RefCell<Filesystem>>,
/// @var bool|null
@@ -53,7 +53,7 @@ impl FilesystemRepository {
pub fn new(
repository_file: JsonFile,
dump_versions: bool,
- root_package: Option<Box<dyn RootPackageInterface>>,
+ root_package: Option<RootPackageInterfaceHandle>,
filesystem: Option<std::rc::Rc<std::cell::RefCell<Filesystem>>>,
) -> Result<Self> {
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<String, Option<String>> = 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<String> = 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<Box<dyn PackageInterface>> = self
+ let mut packages: Vec<PackageInterfaceHandle> = self
.inner
.get_packages()
.into_iter()
- // TODO(phase-b): Box<BasePackage> -> Box<dyn PackageInterface>
- .map(|p| todo!("Box<BasePackage> to Box<dyn PackageInterface>"))
+ .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<dyn RootPackageInterface> = root_package;
- // packages.push(current_root.clone_box());
+ packages.push(current_root.clone().into());
- while let Some(_alias) = current_root.as_any().downcast_ref::<RootAliasPackage>() {
- current_root =
- todo!("RootAliasPackage::get_alias_of() returning Box<dyn RootPackageInterface>");
- // packages.push(current_root.clone_box());
+ 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<String, PhpMixed> = 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::<AliasPackage>().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::<AliasPackage>() 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<String, PhpMixed> {
- 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<String, PhpMixed> = 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<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
if !self.is_allowed(name) {
return None;
}
@@ -177,7 +179,7 @@ impl RepositoryInterface for FilterRepository {
&self,
name: &str,
constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
if !self.is_allowed(name) {
return Vec::new();
}
@@ -190,7 +192,7 @@ impl RepositoryInterface for FilterRepository {
mut package_name_map: IndexMap<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> LoadPackagesResult {
package_name_map.retain(|name, _| self.is_allowed(name));
@@ -226,10 +228,10 @@ impl RepositoryInterface for FilterRepository {
result
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
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<Box<dyn PackageInterface>>) -> anyhow::Result<Self> {
+ pub fn new_with_packages(packages: Vec<PackageInterfaceHandle>) -> anyhow::Result<Self> {
Ok(Self {
inner: WritableArrayRepository::new(packages)?,
})
@@ -56,7 +57,7 @@ impl WritableRepositoryInterface for InstalledArrayRepository {
fn add_package(
&mut self,
- package: Box<dyn crate::package::PackageInterface>,
+ package: crate::package::PackageInterfaceHandle,
) -> anyhow::Result<()> {
todo!()
}
@@ -68,7 +69,7 @@ impl WritableRepositoryInterface for InstalledArrayRepository {
todo!()
}
- fn get_canonical_packages(&self) -> Vec<Box<dyn crate::package::PackageInterface>> {
+ fn get_canonical_packages(&self) -> Vec<crate::package::PackageInterfaceHandle> {
todo!()
}
@@ -99,17 +100,17 @@ impl RepositoryInterface for InstalledArrayRepository {
&self,
_name: &str,
_constraint: FindPackageConstraint,
- ) -> Option<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
todo!()
}
fn find_packages(
&self,
_name: &str,
_constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
todo!()
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
todo!()
}
fn load_packages(
@@ -117,7 +118,7 @@ impl RepositoryInterface for InstalledArrayRepository {
_package_name_map: IndexMap<String, Option<AnyConstraint>>,
_acceptable_stabilities: IndexMap<String, i64>,
_stability_flags: IndexMap<String, i64>,
- _already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ _already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<Box<dyn RootPackageInterface>>,
+ root_package: Option<RootPackageInterfaceHandle>,
filesystem: Option<std::rc::Rc<std::cell::RefCell<Filesystem>>>,
) -> Result<Self> {
Ok(Self {
@@ -66,7 +67,7 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository {
fn add_package(
&mut self,
- package: Box<dyn crate::package::PackageInterface>,
+ package: crate::package::PackageInterfaceHandle,
) -> anyhow::Result<()> {
todo!()
}
@@ -78,7 +79,7 @@ impl WritableRepositoryInterface for InstalledFilesystemRepository {
todo!()
}
- fn get_canonical_packages(&self) -> Vec<Box<dyn crate::package::PackageInterface>> {
+ fn get_canonical_packages(&self) -> Vec<crate::package::PackageInterfaceHandle> {
todo!()
}
@@ -109,17 +110,17 @@ impl RepositoryInterface for InstalledFilesystemRepository {
&self,
_name: &str,
_constraint: FindPackageConstraint,
- ) -> Option<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
todo!()
}
fn find_packages(
&self,
_name: &str,
_constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
todo!()
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
todo!()
}
fn load_packages(
@@ -127,7 +128,7 @@ impl RepositoryInterface for InstalledFilesystemRepository {
_package_name_map: IndexMap<String, Option<AnyConstraint>>,
_acceptable_stabilities: IndexMap<String, i64>,
_stability_flags: IndexMap<String, i64>,
- _already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ _already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<dyn BasePackage>,
+ pub BasePackageHandle,
pub Link,
pub Option<Vec<DependentsEntry>>,
);
@@ -53,7 +53,7 @@ impl InstalledRepository {
&self,
name: &str,
constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
let name = name.to_lowercase();
let constraint: Option<AnyConstraint> = 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<Box<dyn BasePackage>> = None;
+ let mut root_package: Option<BasePackageHandle> = 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<String, Link> =
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<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
self.inner.find_package(name, constraint)
}
@@ -452,11 +440,11 @@ impl RepositoryInterface for InstalledRepository {
&self,
name: &str,
constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
self.inner.find_packages(name, constraint)
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
self.inner.get_packages()
}
@@ -465,7 +453,7 @@ impl RepositoryInterface for InstalledRepository {
package_name_map: IndexMap<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<Box<dyn PackageInterface>> {
+ fn get_packages(&self) -> Vec<PackageInterfaceHandle> {
todo!()
}
}
@@ -43,7 +44,7 @@ impl RepositoryInterface for LockArrayRepository {
&self,
name: &str,
constraint: FindPackageConstraint,
- ) -> Option<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
self.inner.find_package(name, constraint)
}
@@ -51,11 +52,11 @@ impl RepositoryInterface for LockArrayRepository {
&self,
name: &str,
constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
self.inner.find_packages(name, constraint)
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
RepositoryInterface::get_packages(&self.inner)
}
@@ -64,7 +65,7 @@ impl RepositoryInterface for LockArrayRepository {
package_name_map: IndexMap<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<dyn PackageInterface>; loader returns Box<dyn BasePackage>
- 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<VersionParser>,
pub(crate) overrides: IndexMap<String, PlatformOverride>,
- pub(crate) disabled_packages: IndexMap<String, Box<dyn CompletePackageInterface>>,
+ pub(crate) disabled_packages: IndexMap<String, CompletePackageInterfaceHandle>,
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<Box<dyn PackageInterface>>,
+ packages: Vec<PackageInterfaceHandle>,
overrides: IndexMap<String, PhpMixed>,
) -> anyhow::Result<Self> {
Self::new4(packages, overrides, None, None)
}
pub fn new4(
- packages: Vec<Box<dyn PackageInterface>>,
+ packages: Vec<PackageInterfaceHandle>,
overrides: IndexMap<String, PhpMixed>,
runtime: Option<Runtime>,
hhvm_detector: Option<HhvmDetector>,
@@ -117,7 +120,7 @@ impl PlatformRepository {
self.disabled_packages.contains_key(name)
}
- pub fn get_disabled_packages(&self) -> &IndexMap<String, Box<dyn CompletePackageInterface>> {
+ pub fn get_disabled_packages(&self) -> &IndexMap<String, CompletePackageInterfaceHandle> {
&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<dyn PackageInterface>) -> 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<dyn PackageInterface>) {
- // 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!(
"{}. <warning>Package disabled via config.platform</warning>",
current_description
));
let mut extra: IndexMap<String, PhpMixed> = 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<Box<dyn crate::package::BasePackage>> {
+ ) -> Option<crate::package::BasePackageHandle> {
self.inner.find_package(name, constraint)
}
@@ -1953,11 +1966,11 @@ impl crate::repository::RepositoryInterface for PlatformRepository {
&self,
name: &str,
constraint: Option<crate::repository::FindPackageConstraint>,
- ) -> Vec<Box<dyn crate::package::BasePackage>> {
+ ) -> Vec<crate::package::BasePackageHandle> {
self.inner.find_packages(name, constraint)
}
- fn get_packages(&self) -> Vec<Box<dyn crate::package::BasePackage>> {
+ fn get_packages(&self) -> Vec<crate::package::BasePackageHandle> {
self.inner.get_packages()
}
@@ -1966,7 +1979,7 @@ impl crate::repository::RepositoryInterface for PlatformRepository {
package_name_map: IndexMap<String, Option<shirabe_semver::constraint::AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, crate::package::PackageInterfaceHandle>>,
) -> 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<String>,
- pub packages: IndexMap<String, Box<dyn BasePackage>>,
+ pub packages: IndexMap<String, BasePackageHandle>,
}
#[derive(Debug, Clone)]
@@ -59,22 +60,22 @@ pub trait RepositoryInterface: Countable + std::fmt::Debug {
&self,
name: &str,
constraint: FindPackageConstraint,
- ) -> Option<Box<dyn BasePackage>>;
+ ) -> Option<BasePackageHandle>;
fn find_packages(
&self,
name: &str,
constraint: Option<FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>>;
+ ) -> Vec<BasePackageHandle>;
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>>;
+ fn get_packages(&self) -> Vec<BasePackageHandle>;
fn load_packages(
&self,
package_name_map: IndexMap<String, Option<AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> LoadPackagesResult;
fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult>;
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<Box<dyn PackageInterface>> {
+ ) -> Option<PackageInterfaceHandle> {
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<Box<dyn PackageInterface>> {
- let mut packages: Vec<Box<dyn PackageInterface>> = vec![];
+ ) -> Vec<PackageInterfaceHandle> {
+ let mut packages: Vec<PackageInterfaceHandle> = 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<AnyConstraint>,
flags: i64,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
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<Box<dyn BasePackage>>> = vec![];
+ let mut packages: Vec<Vec<BasePackageHandle>> = 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<Box<dyn BasePackage>> = if !packages.is_empty() {
+ let candidates: Vec<BasePackageHandle> = if !packages.is_empty() {
packages.into_iter().flatten().collect()
} else {
vec![]
@@ -271,9 +270,9 @@ impl RepositorySet {
return candidates;
}
- let mut result: Vec<Box<dyn BasePackage>> = vec![];
+ let mut result: Vec<BasePackageHandle> = 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<string, array<PartialSecurityAdvisory|SecurityAdvisory>>, unreachableRepos: array<string>} : array{advisories: array<string, array<SecurityAdvisory>>, unreachableRepos: array<string>})
pub fn get_matching_security_advisories(
&self,
- packages: Vec<Box<dyn PackageInterface>>,
+ packages: Vec<PackageInterfaceHandle>,
allow_partial_advisories: bool,
ignore_unreachable: bool,
) -> Result<SecurityAdvisoriesResult> {
let mut map: IndexMap<String, AnyConstraint> = 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::<AliasPackage>() {
+ 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<Box<dyn BasePackage>> = vec![];
+ let mut packages: Vec<BasePackageHandle> = 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::<AliasPackage>()
- {
- 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<dyn BasePackage> = if package
- .as_any()
- .downcast_ref::<CompletePackage>()
- .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<dyn crate::package::BasePackage>],
+ packages: &[crate::package::BasePackageHandle],
requirer: &dyn PackageInterface,
include_require_dev: bool,
- mut bucket: Vec<Box<dyn crate::package::BasePackage>>,
- ) -> Vec<Box<dyn crate::package::BasePackage>> {
+ mut bucket: Vec<crate::package::BasePackageHandle>,
+ ) -> Vec<crate::package::BasePackageHandle> {
let mut requires: IndexMap<String, Link> = 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<dyn RootPackageInterface>) -> 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<dyn RootPackageInterface> to Box<dyn BasePackage>"
- )])
- .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<Box<dyn BasePackage>> {
+ ) -> Option<BasePackageHandle> {
self.inner.find_package(name, constraint)
}
@@ -51,11 +48,11 @@ impl RepositoryInterface for RootPackageRepository {
&self,
name: &str,
constraint: Option<crate::repository::FindPackageConstraint>,
- ) -> Vec<Box<dyn BasePackage>> {
+ ) -> Vec<BasePackageHandle> {
self.inner.find_packages(name, constraint)
}
- fn get_packages(&self) -> Vec<Box<dyn BasePackage>> {
+ fn get_packages(&self) -> Vec<BasePackageHandle> {
self.inner.get_packages()
}
@@ -64,7 +61,7 @@ impl RepositoryInterface for RootPackageRepository {
package_name_map: IndexMap<String, Option<shirabe_semver::constraint::AnyConstraint>>,
acceptable_stabilities: IndexMap<String, i64>,
stability_flags: IndexMap<String, i64>,
- already_loaded: IndexMap<String, IndexMap<String, Box<dyn PackageInterface>>>,
+ already_loaded: IndexMap<String, IndexMap<String, PackageInterfaceHandle>>,
) -> 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<dyn BasePackage> -> Box<dyn PackageInterface>
- let pkg_pi: Box<dyn crate::package::PackageInterface> = 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<dyn BasePackage> -> Box<dyn PackageInterface>
- let loaded_pi: Box<dyn crate::package::PackageInterface> =
- 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<dyn BasePackage> -> Box<dyn PackageInterface>
- let pkg_pi: Box<dyn crate::package::PackageInterface> = 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<dyn BasePackage> -> Box<dyn PackageInterface>
- let package_pi: Box<dyn crate::package::PackageInterface> =
- 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<dyn BasePackage>),
+ 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<Box<dyn crate::package::PackageInterface>>) -> Result<Self> {
+ pub fn new(packages: Vec<crate::package::PackageInterfaceHandle>) -> Result<Self> {
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<dyn crate::package::PackageInterface>,
- ) -> 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<Box<dyn crate::package::PackageInterface>> {
+ pub fn get_canonical_packages(&self) -> Vec<crate::package::PackageInterfaceHandle> {
// TODO(phase-b): delegate to inner once it exposes get_canonical_packages
Vec::new()
}
- pub fn get_packages(&self) -> Vec<Box<dyn crate::package::PackageInterface>> {
- // TODO(phase-b): delegate to inner ArrayRepository::get_packages
- Vec::new()
+ pub fn get_packages(&self) -> Vec<crate::package::BasePackageHandle> {
+ 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<dyn PackageInterface>) -> Result<()>;
+ fn add_package(&mut self, package: PackageInterfaceHandle) -> Result<()>;
fn remove_package(&mut self, package: &dyn PackageInterface) -> Result<()>;
- fn get_canonical_packages(&self) -> Vec<Box<dyn PackageInterface>>;
+ fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle>;
fn reload(&mut self);