aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/shirabe/src/command/archive_command.rs7
-rw-r--r--crates/shirabe/src/command/audit_command.rs3
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs49
-rw-r--r--crates/shirabe/src/command/bump_command.rs9
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs25
-rw-r--r--crates/shirabe/src/command/create_project_command.rs16
-rw-r--r--crates/shirabe/src/command/diagnose_command.rs2
-rw-r--r--crates/shirabe/src/command/fund_command.rs2
-rw-r--r--crates/shirabe/src/command/home_command.rs10
-rw-r--r--crates/shirabe/src/command/init_command.rs6
-rw-r--r--crates/shirabe/src/command/package_discovery_trait.rs6
-rw-r--r--crates/shirabe/src/command/reinstall_command.rs2
-rw-r--r--crates/shirabe/src/command/require_command.rs10
-rw-r--r--crates/shirabe/src/command/search_command.rs19
-rw-r--r--crates/shirabe/src/command/show_command.rs207
-rw-r--r--crates/shirabe/src/command/suggests_command.rs16
-rw-r--r--crates/shirabe/src/command/update_command.rs11
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_builder.rs59
-rw-r--r--crates/shirabe/src/dependency_resolver/problem.rs50
-rw-r--r--crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs3
-rw-r--r--crates/shirabe/src/downloader/perforce_downloader.rs7
-rw-r--r--crates/shirabe/src/downloader/svn_downloader.rs6
-rw-r--r--crates/shirabe/src/factory.rs2
-rw-r--r--crates/shirabe/src/installer.rs150
-rw-r--r--crates/shirabe/src/package/alias_package.rs24
-rw-r--r--crates/shirabe/src/package/base_package.rs17
-rw-r--r--crates/shirabe/src/package/complete_package.rs8
-rw-r--r--crates/shirabe/src/package/handle.rs10
-rw-r--r--crates/shirabe/src/package/package.rs49
-rw-r--r--crates/shirabe/src/package/package_interface.rs6
-rw-r--r--crates/shirabe/src/package/root_package.rs10
-rw-r--r--crates/shirabe/src/plugin/plugin_manager.rs28
-rw-r--r--crates/shirabe/src/repository/array_repository.rs43
-rw-r--r--crates/shirabe/src/repository/composer_repository.rs39
-rw-r--r--crates/shirabe/src/repository/composite_repository.rs26
-rw-r--r--crates/shirabe/src/repository/filesystem_repository.rs4
-rw-r--r--crates/shirabe/src/repository/filter_repository.rs25
-rw-r--r--crates/shirabe/src/repository/handle.rs174
-rw-r--r--crates/shirabe/src/repository/installed_array_repository.rs11
-rw-r--r--crates/shirabe/src/repository/installed_filesystem_repository.rs11
-rw-r--r--crates/shirabe/src/repository/installed_repository.rs23
-rw-r--r--crates/shirabe/src/repository/lock_array_repository.rs7
-rw-r--r--crates/shirabe/src/repository/mod.rs2
-rw-r--r--crates/shirabe/src/repository/platform_repository.rs4
-rw-r--r--crates/shirabe/src/repository/repository_factory.rs20
-rw-r--r--crates/shirabe/src/repository/repository_interface.rs15
-rw-r--r--crates/shirabe/src/repository/repository_manager.rs32
-rw-r--r--crates/shirabe/src/repository/repository_set.rs45
-rw-r--r--crates/shirabe/src/repository/repository_utils.rs32
-rw-r--r--crates/shirabe/src/repository/root_package_repository.rs5
-rw-r--r--crates/shirabe/src/repository/writable_array_repository.rs5
51 files changed, 871 insertions, 481 deletions
diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs
index aab7b51..18b69c3 100644
--- a/crates/shirabe/src/command/archive_command.rs
+++ b/crates/shirabe/src/command/archive_command.rs
@@ -247,13 +247,12 @@ impl ArchiveCommand {
let repository_manager = composer.get_repository_manager().clone();
let repository_manager = repository_manager.borrow();
let local_repo = repository_manager.get_local_repository();
- let mut repos: Vec<Box<dyn crate::repository::RepositoryInterface>> =
- vec![local_repo.clone_box()];
+ let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> = vec![local_repo];
repos.extend(
repository_manager
.get_repositories()
.iter()
- .map(|r| r.clone_box()),
+ .map(|r| r.clone()),
);
repo = CompositeRepository::new(repos);
min_stability = composer.get_package().get_minimum_stability().to_string();
@@ -299,7 +298,7 @@ impl ArchiveCommand {
IndexMap::new(),
IndexMap::new(),
);
- repo_set.add_repository(Box::new(repo))?;
+ repo_set.add_repository(crate::repository::RepositoryInterfaceHandle::new(repo))?;
let parser = VersionParser::new();
let constraint: Option<shirabe_semver::constraint::AnyConstraint> = match version.as_deref()
{
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index ec8b495..270bacb 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -74,8 +74,7 @@ impl AuditCommand {
.borrow()
.get_repositories()
{
- // TODO(phase-b): repositories are shared (PHP class semantics); needs Rc wrapper
- repo_set.add_repository(repo.clone_box())?;
+ repo_set.add_repository(repo.clone())?;
}
let audit_config = AuditConfig::from_config(
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index 7a5300a..ad84953 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -53,10 +53,10 @@ pub trait BaseDependencyCommand: BaseCommand {
let mut composer = crate::command::composer_full_mut(&composer);
// TODO(plugin): dispatch CommandEvent(PluginEvents::COMMAND, self.get_name(), input, output) via composer.get_event_dispatcher()
- let mut repos: Vec<Box<dyn RepositoryInterface>> = vec![];
- repos.push(Box::new(RootPackageRepository::new(
- composer.get_package().clone(),
- )));
+ let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> =
+ vec![crate::repository::RepositoryInterfaceHandle::new(
+ RootPackageRepository::new(composer.get_package().clone()),
+ )];
if input.get_option("locked").as_bool().unwrap_or(false) {
let locker = composer.get_locker().clone();
@@ -71,16 +71,17 @@ pub trait BaseDependencyCommand: BaseCommand {
}));
}
- repos.push(Box::new(locker.get_locked_repository(true)?));
+ repos.push(crate::repository::RepositoryInterfaceHandle::new(
+ locker.get_locked_repository(true)?,
+ ));
let platform_overrides: IndexMap<String, PhpMixed> = locker
.get_platform_overrides()?
.into_iter()
.map(|(k, v)| (k, PhpMixed::String(v)))
.collect();
- repos.push(Box::new(PlatformRepository::new(
- vec![],
- platform_overrides,
- )?));
+ repos.push(crate::repository::RepositoryInterfaceHandle::new(
+ PlatformRepository::new(vec![], platform_overrides)?,
+ ));
} else {
let repository_manager = composer.get_repository_manager().clone();
let repository_manager = repository_manager.borrow();
@@ -98,10 +99,7 @@ pub trait BaseDependencyCommand: BaseCommand {
return Ok(1);
}
- // TODO(phase-b): InstalledRepositoryInterface is shared by reference (PHP class
- // semantics); Box<dyn RepositoryInterface> requires owned upcast. Skipping local
- // repo push until clone_box is exposed on InstalledRepositoryInterface.
- let _ = local_repo;
+ repos.push(local_repo);
let platform_overrides = composer
.get_config()
@@ -112,7 +110,9 @@ pub trait BaseDependencyCommand: BaseCommand {
.unwrap_or_default();
// TODO(phase-b): platform_overrides type adjustment; using empty for now
let _ = platform_overrides;
- repos.push(Box::new(PlatformRepository::new(vec![], IndexMap::new())?));
+ repos.push(crate::repository::RepositoryInterfaceHandle::new(
+ PlatformRepository::new(vec![], IndexMap::new())?,
+ ));
}
let mut installed_repo = InstalledRepository::new(repos);
@@ -159,9 +159,11 @@ pub trait BaseDependencyCommand: BaseCommand {
&needle,
FindPackageConstraint::String(text_constraint.clone()),
) {
- installed_repo.add_repository(Box::new(
- InstalledArrayRepository::new_with_packages(vec![r#match.into()])?,
- ))?;
+ installed_repo.add_repository(
+ crate::repository::RepositoryInterfaceHandle::new(
+ InstalledArrayRepository::new_with_packages(vec![r#match.into()])?,
+ ),
+ )?;
} else if PlatformRepository::is_platform_package(&needle) {
let parser = VersionParser::new();
let platform_constraint = parser.parse_constraints(&text_constraint)?;
@@ -171,11 +173,14 @@ pub trait BaseDependencyCommand: BaseCommand {
.get_version()
.to_string();
let temp_platform_pkg = Package::new(needle.clone(), version.clone(), version);
- installed_repo.add_repository(Box::new(
- InstalledArrayRepository::new_with_packages(vec![
- crate::package::PackageHandle::from_package(temp_platform_pkg).into(),
- ])?,
- ))?;
+ installed_repo.add_repository(
+ crate::repository::RepositoryInterfaceHandle::new(
+ InstalledArrayRepository::new_with_packages(vec![
+ crate::package::PackageHandle::from_package(temp_platform_pkg)
+ .into(),
+ ])?,
+ ),
+ )?;
}
} else {
self.get_io().write_error(&format!(
diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs
index a1e5f35..0f62bb8 100644
--- a/crates/shirabe/src/command/bump_command.rs
+++ b/crates/shirabe/src/command/bump_command.rs
@@ -142,8 +142,8 @@ impl BumpCommand {
.get("lock")
.as_bool()
.unwrap_or(true);
- let repo: Box<dyn crate::repository::RepositoryInterface> = if !has_lock_file_disabled {
- Box::new(
+ let repo: crate::repository::RepositoryInterfaceHandle = if !has_lock_file_disabled {
+ crate::repository::RepositoryInterfaceHandle::new(
composer
.get_locker()
.borrow_mut()
@@ -158,20 +158,17 @@ impl BumpCommand {
);
return Ok(Self::ERROR_LOCK_OUTDATED);
}
- Box::new(
+ crate::repository::RepositoryInterfaceHandle::new(
composer
.get_locker()
.borrow_mut()
.get_locked_repository(true)?,
)
} else {
- // TODO(phase-b): get_local_repository returns &dyn InstalledRepositoryInterface;
- // cloning into an owned Box requires clone_box on that trait.
composer
.get_repository_manager()
.borrow()
.get_local_repository()
- .clone_box()
};
if composer.get_package().get_type() != "project" && !dev_only {
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index fd5edd9..15e4225 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -63,7 +63,7 @@ impl CheckPlatformReqsCommand {
let mut requires: IndexMap<String, Vec<Link>> = IndexMap::new();
let mut remove_packages: Vec<String> = vec![];
- let installed_repo_base: Box<dyn crate::repository::RepositoryInterface> = if input
+ let installed_repo_base: crate::repository::RepositoryInterfaceHandle = if input
.get_option("lock")
.as_bool()
.unwrap_or(false)
@@ -72,7 +72,7 @@ impl CheckPlatformReqsCommand {
"<info>Checking {}platform requirements using the lock file</info>",
if no_dev { "non-dev " } else { "" }
));
- Box::new(
+ crate::repository::RepositoryInterfaceHandle::new(
composer
.get_locker()
.borrow_mut()
@@ -87,21 +87,21 @@ impl CheckPlatformReqsCommand {
"<warning>No vendor dir present, checking {}platform requirements from the lock file</warning>",
if no_dev { "non-dev " } else { "" }
));
- Box::new(
+ crate::repository::RepositoryInterfaceHandle::new(
composer
.get_locker()
.borrow_mut()
.get_locked_repository(!no_dev)?,
- ) as Box<dyn crate::repository::RepositoryInterface>
+ )
} else {
if no_dev {
- remove_packages = local_repo.get_dev_package_names().clone();
+ remove_packages = local_repo.get_dev_package_names();
}
io.write_error(&format!(
"<info>Checking {}platform requirements for packages in the vendor dir</info>",
if no_dev { "non-dev " } else { "" }
));
- local_repo.clone_box()
+ local_repo.clone()
}
};
@@ -115,8 +115,10 @@ impl CheckPlatformReqsCommand {
}
let root_pkg_repo = RootPackageRepository::new(composer.get_package().clone());
- let installed_repo =
- InstalledRepository::new(vec![installed_repo_base, Box::new(root_pkg_repo)]);
+ let installed_repo = InstalledRepository::new(vec![
+ installed_repo_base,
+ crate::repository::RepositoryInterfaceHandle::new(root_pkg_repo),
+ ]);
for package in installed_repo.get_packages() {
if remove_packages.contains(&package.get_name().to_string()) {
@@ -134,8 +136,11 @@ impl CheckPlatformReqsCommand {
requires_sorted.sort_by(|a, b| a.0.cmp(&b.0));
let installed_repo_with_platform = InstalledRepository::new(vec![
- Box::new(installed_repo),
- Box::new(PlatformRepository::new(vec![], indexmap::IndexMap::new())?),
+ crate::repository::RepositoryInterfaceHandle::new(installed_repo),
+ crate::repository::RepositoryInterfaceHandle::new(PlatformRepository::new(
+ vec![],
+ indexmap::IndexMap::new(),
+ )?),
]);
let mut results: Vec<CheckResult> = vec![];
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index d5a8a0c..c669aa5 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -304,7 +304,7 @@ impl CreateProjectCommand {
let _ = &composer_json_repositories_config;
let placeholder_existing: IndexMap<
String,
- Box<dyn crate::repository::RepositoryInterface>,
+ crate::repository::RepositoryInterfaceHandle,
> = IndexMap::new();
let name = RepositoryFactory::generate_repository_name(
&PhpMixed::Int(index as i64),
@@ -737,12 +737,14 @@ impl CreateProjectCommand {
if repositories.is_none() {
// TODO(phase-b): default_repos needs &mut RepositoryManager but we hold &RepositoryManager.
let _ = rm;
- repository_set.add_repository(Box::new(CompositeRepository::new(
- RepositoryFactory::default_repos(Some(io.clone()), Some(config.clone()), None)?
- .into_iter()
- .map(|(_, v)| v)
- .collect(),
- )));
+ repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new(
+ CompositeRepository::new(
+ RepositoryFactory::default_repos(Some(io.clone()), Some(config.clone()), None)?
+ .into_iter()
+ .map(|(_, v)| v)
+ .collect(),
+ ),
+ ))?;
} else {
for repo in repositories.unwrap() {
let mut repo_config =
diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs
index c64fc39..945d1e9 100644
--- a/crates/shirabe/src/command/diagnose_command.rs
+++ b/crates/shirabe/src/command/diagnose_command.rs
@@ -946,7 +946,7 @@ impl DiagnoseCommand {
self.http_downloader.clone().unwrap(),
None,
)?;
- let composer_repo_as_repo: Box<dyn crate::repository::RepositoryInterface> =
+ let composer_repo_as_repo: crate::repository::RepositoryInterfaceHandle =
todo!("ComposerRepository as RepositoryInterface");
repo_set.add_repository(composer_repo_as_repo)?;
diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs
index 340424f..9d5720e 100644
--- a/crates/shirabe/src/command/fund_command.rs
+++ b/crates/shirabe/src/command/fund_command.rs
@@ -60,7 +60,7 @@ impl FundCommand {
repository_manager
.get_repositories()
.iter()
- .map(|r| r.clone_box())
+ .map(|r| r.clone())
.collect(),
);
let mut fundings: IndexMap<String, IndexMap<String, Vec<String>>> = IndexMap::new();
diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs
index c048bfd..0038add 100644
--- a/crates/shirabe/src/command/home_command.rs
+++ b/crates/shirabe/src/command/home_command.rs
@@ -203,15 +203,15 @@ impl HomeCommand {
}
}
- fn initialize_repos(&mut self) -> Result<Vec<Box<dyn RepositoryInterface>>> {
+ fn initialize_repos(&mut self) -> Result<Vec<crate::repository::RepositoryInterfaceHandle>> {
let composer = self.try_composer(None, None);
if let Some(composer) = composer {
let composer = crate::command::composer_full(&composer);
- let mut repos: Vec<Box<dyn RepositoryInterface>> = vec![];
- repos.push(Box::new(RootPackageRepository::new(
- composer.get_package().clone(),
- )));
+ let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> = vec![];
+ repos.push(crate::repository::RepositoryInterfaceHandle::new(
+ RootPackageRepository::new(composer.get_package().clone()),
+ ));
// TODO(phase-b): get_local_repository / get_repositories return shared refs; needs Rc<dyn ...> migration
return Ok(repos);
}
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs
index 730658c..38e620b 100644
--- a/crates/shirabe/src/command/init_command.rs
+++ b/crates/shirabe/src/command/init_command.rs
@@ -455,8 +455,10 @@ impl InitCommand {
let mut repo_manager =
RepositoryFactory::manager(io.clone(), &config, None, None, None)?;
- let mut repos: Vec<Box<dyn crate::repository::RepositoryInterface>> =
- vec![Box::new(PlatformRepository::new(vec![], IndexMap::new())?)];
+ let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> =
+ vec![crate::repository::RepositoryInterfaceHandle::new(
+ PlatformRepository::new(vec![], IndexMap::new())?,
+ )];
let mut create_default_packagist_repo = true;
for repo in &repositories {
let repo_config =
diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs
index d0574c6..d656d83 100644
--- a/crates/shirabe/src/command/package_discovery_trait.rs
+++ b/crates/shirabe/src/command/package_discovery_trait.rs
@@ -56,9 +56,11 @@ pub trait PackageDiscoveryTrait {
fn get_repos(&mut self) -> &CompositeRepository {
if self.get_repos_mut().is_none() {
// PHP: array_merge([new PlatformRepository], RepositoryFactory::defaultReposWithDefaultManager($this->getIO()))
- let mut repos: Vec<Box<dyn crate::repository::RepositoryInterface>> = vec![
+ let mut repos: Vec<crate::repository::RepositoryInterfaceHandle> = vec![
// TODO(phase-b): PlatformRepository::new() signature
- Box::new(todo!("PlatformRepository::new()") as PlatformRepository),
+ crate::repository::RepositoryInterfaceHandle::new::<PlatformRepository>(todo!(
+ "PlatformRepository::new()"
+ )),
];
let io_owned: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> = self.get_io();
for (_, repo) in RepositoryFactory::default_repos_with_default_manager(io_owned)
diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs
index ad4739b..29e8129 100644
--- a/crates/shirabe/src/command/reinstall_command.rs
+++ b/crates/shirabe/src/command/reinstall_command.rs
@@ -219,7 +219,7 @@ impl ReinstallCommand {
uninstall_operations,
install_operations,
dev_mode,
- local_repo,
+ local_repo.clone(),
&installation_manager,
);
// installation_manager.execute(local_repo_mut, uninstall_ops_boxed, dev_mode, true, false);
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index bf5f159..93ec469 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -261,10 +261,12 @@ impl RequireCommand {
.unwrap_or_default();
// initialize self.repos as it is used by the PackageDiscoveryTrait
let platform_repo = PlatformRepository::new(vec![], platform_overrides_map)?;
- let mut combined: Vec<Box<dyn crate::repository::RepositoryInterface>> = vec![
- // TODO(phase-b): PlatformRepository should be shared via Rc; use placeholder until
- // CompositeRepository accepts shared references
- Box::new(todo!("share platform_repo with PlatformRepository") as PlatformRepository),
+ let mut combined: Vec<crate::repository::RepositoryInterfaceHandle> = vec![
+ // TODO(phase-c): share this platform_repo as a handle instead of constructing a
+ // separate one; PlatformRepository is held by value here for the requirement below.
+ crate::repository::RepositoryInterfaceHandle::new::<PlatformRepository>(todo!(
+ "share platform_repo with PlatformRepository"
+ )),
];
for _repo in repos {
// TODO(phase-b): repos are borrowed from RepositoryManager; need to take ownership
diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs
index 2033cfc..5d6a31b 100644
--- a/crates/shirabe/src/command/search_command.rs
+++ b/crates/shirabe/src/command/search_command.rs
@@ -10,6 +10,7 @@ use crate::plugin::CommandEvent;
use crate::plugin::PluginEvents;
use crate::repository::CompositeRepository;
use crate::repository::PlatformRepository;
+use crate::repository::RepositoryInterfaceHandle;
use crate::repository::repository_interface::{self, RepositoryInterface};
use anyhow::Result;
use indexmap::IndexMap;
@@ -78,18 +79,22 @@ impl SearchCommand {
self.create_composer_instance(input, io_box, None, false, None)?
};
let composer_ref = crate::command::composer_full(&composer);
- // TODO(phase-b): get_local_repository returns &dyn InstalledRepositoryInterface but we need Box<dyn RepositoryInterface>
- let local_repo: Box<dyn RepositoryInterface> =
- todo!("share local_repo as RepositoryInterface");
- let installed_repo = CompositeRepository::new(vec![local_repo, Box::new(platform_repo)]);
- let mut all_repos: Vec<Box<dyn RepositoryInterface>> = vec![Box::new(installed_repo)];
- // TODO(phase-b): get_repositories returns &Vec<Box<...>>; needs ownership reshape
+ let local_repo = composer_ref
+ .get_repository_manager()
+ .borrow()
+ .get_local_repository();
+ let installed_repo = CompositeRepository::new(vec![
+ local_repo,
+ RepositoryInterfaceHandle::new(platform_repo),
+ ]);
+ let mut all_repos: Vec<RepositoryInterfaceHandle> =
+ vec![RepositoryInterfaceHandle::new(installed_repo)];
for r in composer_ref
.get_repository_manager()
.borrow()
.get_repositories()
{
- all_repos.push(r.clone_box());
+ all_repos.push(r.clone());
}
let repos = CompositeRepository::new(all_repos);
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index b72a986..2b2dd94 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -40,6 +40,7 @@ use crate::repository::InstalledRepository;
use crate::repository::PlatformRepository;
use crate::repository::RepositoryFactory;
use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use crate::repository::RepositorySet;
use crate::repository::RepositoryUtils;
use crate::repository::RootPackageRepository;
@@ -198,13 +199,13 @@ impl ShowCommand {
let make_platform_repo = || -> anyhow::Result<PlatformRepository> {
PlatformRepository::new(vec![], platform_overrides.clone())
};
- let mut locked_repo: Option<Box<dyn RepositoryInterface>> = None;
+ let mut locked_repo: Option<RepositoryInterfaceHandle> = None;
// The single-package $package binding from PHP gets surfaced here.
let mut single_package: Option<crate::package::CompletePackageInterfaceHandle> = None;
let mut versions_map: IndexMap<String, String> = IndexMap::new();
- let installed_repo: Box<InstalledRepository>;
- let repos: Box<dyn RepositoryInterface>;
+ let installed_repo: RepositoryInterfaceHandle;
+ let repos: RepositoryInterfaceHandle;
if input.get_option("self").as_bool() == Some(true)
&& input.get_option("installed").as_bool() != Some(true)
@@ -227,95 +228,95 @@ impl ShowCommand {
}
.into());
}
- installed_repo = Box::new(InstalledRepository::new(vec![Box::new(
- RootPackageRepository::new(package.clone()),
- )]));
- repos = Box::new(InstalledRepository::new(vec![Box::new(
- RootPackageRepository::new(package.clone()),
- )]));
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ RepositoryInterfaceHandle::new(RootPackageRepository::new(package.clone())),
+ ]));
+ repos = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ RepositoryInterfaceHandle::new(RootPackageRepository::new(package.clone())),
+ ]));
// TODO(phase-c): need to convert the root package handle to a CompletePackageInterfaceHandle
single_package = todo!("convert package to CompletePackageInterfaceHandle");
} else if input.get_option("platform").as_bool() == Some(true) {
- installed_repo = Box::new(InstalledRepository::new(vec![Box::new(
- make_platform_repo()?,
- )]));
- repos = Box::new(InstalledRepository::new(vec![Box::new(
- make_platform_repo()?,
- )]));
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ RepositoryInterfaceHandle::new(make_platform_repo()?),
+ ]));
+ repos = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ RepositoryInterfaceHandle::new(make_platform_repo()?),
+ ]));
} else if input.get_option("available").as_bool() == Some(true) {
- let mut ir = InstalledRepository::new(vec![Box::new(make_platform_repo()?)]);
+ let mut ir = InstalledRepository::new(vec![RepositoryInterfaceHandle::new(
+ make_platform_repo()?,
+ )]);
if let Some(ref composer) = composer {
let composer = crate::command::composer_full(composer);
- repos = Box::new(CompositeRepository::new(
+ repos = RepositoryInterfaceHandle::new(CompositeRepository::new(
composer
.get_repository_manager()
.borrow()
.get_repositories()
.iter()
- .map(|r| r.clone_box())
+ .map(|r| r.clone())
.collect(),
));
ir.add_repository(
composer
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box(),
- );
- installed_repo = Box::new(ir);
+ .get_local_repository(),
+ )?;
+ installed_repo = RepositoryInterfaceHandle::new(ir);
} else {
let default_repos =
RepositoryFactory::default_repos_with_default_manager(self.get_io())?;
let names: Vec<String> = default_repos.keys().cloned().collect();
- repos = Box::new(CompositeRepository::new(
+ repos = RepositoryInterfaceHandle::new(CompositeRepository::new(
default_repos.into_values().collect(),
));
self.get_io().write_error(&format!(
"No composer.json found in the current directory, showing available packages from {}",
names.join(", ")
));
- installed_repo = Box::new(ir);
+ installed_repo = RepositoryInterfaceHandle::new(ir);
}
} else if input.get_option("all").as_bool() == Some(true) && composer.is_some() {
let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
- let local_repo_cloned = composer_ref
+ let local_repo = composer_ref
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box();
+ .get_local_repository();
let locker_rc = composer_ref.get_locker().clone();
let mut locker = locker_rc.borrow_mut();
if locker.is_locked() {
- let lr = locker.get_locked_repository(true)?;
- installed_repo = Box::new(InstalledRepository::new(vec![
- lr.clone_box(),
- local_repo_cloned,
- Box::new(make_platform_repo()?),
+ let lr_handle = RepositoryInterfaceHandle::new(locker.get_locked_repository(true)?);
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ lr_handle.clone(),
+ local_repo,
+ RepositoryInterfaceHandle::new(make_platform_repo()?),
]));
- // TODO(phase-b): wrap lr (LockArrayRepository) as Box<dyn RepositoryInterface>
- locked_repo = Some(todo!("share lr as Box<dyn RepositoryInterface>"));
- let _ = lr;
+ locked_repo = Some(lr_handle);
} else {
- installed_repo = Box::new(InstalledRepository::new(vec![
- local_repo_cloned,
- Box::new(make_platform_repo()?),
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ local_repo,
+ RepositoryInterfaceHandle::new(make_platform_repo()?),
]));
}
- let mut composite_input: Vec<Box<dyn RepositoryInterface>> = vec![Box::new(
- FilterRepository::new(installed_repo.clone_box(), {
- let mut m = IndexMap::new();
- m.insert("canonical".to_string(), PhpMixed::Bool(false));
- m
- })?,
- )];
+ let mut composite_input: Vec<RepositoryInterfaceHandle> =
+ vec![RepositoryInterfaceHandle::new(FilterRepository::new(
+ installed_repo.clone(),
+ {
+ let mut m = IndexMap::new();
+ m.insert("canonical".to_string(), PhpMixed::Bool(false));
+ m
+ },
+ )?)];
for r in composer_ref
.get_repository_manager()
.borrow()
.get_repositories()
{
- composite_input.push(r.clone_box());
+ composite_input.push(r.clone());
}
- repos = Box::new(CompositeRepository::new(composite_input));
+ repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
} else if input.get_option("all").as_bool() == Some(true) {
let default_repos =
RepositoryFactory::default_repos_with_default_manager(self.get_io())?;
@@ -324,15 +325,14 @@ impl ShowCommand {
"No composer.json found in the current directory, showing available packages from {}",
names.join(", ")
));
- installed_repo = Box::new(InstalledRepository::new(vec![Box::new(
- make_platform_repo()?,
- )]));
- let mut composite_input: Vec<Box<dyn RepositoryInterface>> =
- vec![installed_repo.clone_box()];
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ RepositoryInterfaceHandle::new(make_platform_repo()?),
+ ]));
+ let mut composite_input: Vec<RepositoryInterfaceHandle> = vec![installed_repo.clone()];
for (_k, v) in default_repos.into_iter() {
composite_input.push(v);
}
- repos = Box::new(CompositeRepository::new(composite_input));
+ repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
} else if input.get_option("locked").as_bool() == Some(true) {
if composer.is_none()
|| !crate::command::composer_full_mut(composer.as_ref().unwrap())
@@ -349,18 +349,19 @@ impl ShowCommand {
let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
let locker_rc = composer_ref.get_locker().clone();
let mut locker = locker_rc.borrow_mut();
- let mut lr =
+ let lr =
locker.get_locked_repository(input.get_option("no-dev").as_bool() != Some(true))?;
+ let lr_handle = RepositoryInterfaceHandle::new(lr);
if input.get_option("self").as_bool() == Some(true) {
// TODO(phase-b): LockArrayRepository needs add_package via WritableRepositoryInterface;
// skipping the insertion here keeps compile clean.
- let _ = &mut lr;
+ let _ = &lr_handle;
}
- installed_repo = Box::new(InstalledRepository::new(vec![lr.clone_box()]));
- repos = Box::new(InstalledRepository::new(vec![lr.clone_box()]));
- // TODO(phase-b): wrap lr (LockArrayRepository) as Box<dyn RepositoryInterface>
- locked_repo = Some(todo!("share lr as Box<dyn RepositoryInterface>"));
- let _ = lr;
+ installed_repo =
+ RepositoryInterfaceHandle::new(InstalledRepository::new(vec![lr_handle.clone()]));
+ repos =
+ RepositoryInterfaceHandle::new(InstalledRepository::new(vec![lr_handle.clone()]));
+ locked_repo = Some(lr_handle);
} else {
// --installed / default case
// TODO(phase-b): PHP shares the Composer object by reference. Phase B
@@ -382,13 +383,13 @@ impl ShowCommand {
};
let root_pkg = composer_local.get_package();
- let root_repo: Box<dyn RepositoryInterface> =
+ let root_repo: RepositoryInterfaceHandle =
if input.get_option("self").as_bool() == Some(true) {
- Box::new(RootPackageRepository::new(
+ RepositoryInterfaceHandle::new(RootPackageRepository::new(
composer_local.get_package().clone(),
))
} else {
- Box::new(InstalledArrayRepository::new()?)
+ RepositoryInterfaceHandle::new(InstalledArrayRepository::new()?)
};
if input.get_option("no-dev").as_bool() == Some(true) {
let local_packages = composer_local
@@ -404,23 +405,28 @@ impl ShowCommand {
);
let cloned: Vec<crate::package::PackageInterfaceHandle> =
packages.into_iter().map(|p| p.into()).collect();
- installed_repo = Box::new(InstalledRepository::new(vec![
- root_repo.clone_box(),
- Box::new(InstalledArrayRepository::new_with_packages(cloned)?),
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ root_repo.clone(),
+ RepositoryInterfaceHandle::new(InstalledArrayRepository::new_with_packages(
+ cloned,
+ )?),
]));
- repos = Box::new(InstalledRepository::new(vec![
+ repos = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
root_repo,
- Box::new(InstalledArrayRepository::new_with_packages(Vec::new())?),
+ RepositoryInterfaceHandle::new(InstalledArrayRepository::new_with_packages(
+ Vec::new(),
+ )?),
]));
} else {
let repository_manager = composer_local.get_repository_manager().clone();
let repository_manager = repository_manager.borrow();
let lr = repository_manager.get_local_repository();
- installed_repo = Box::new(InstalledRepository::new(vec![
- root_repo.clone_box(),
- lr.clone_box(),
+ installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
+ root_repo.clone(),
+ lr.clone(),
]));
- repos = Box::new(InstalledRepository::new(vec![root_repo, lr.clone_box()]));
+ repos =
+ RepositoryInterfaceHandle::new(InstalledRepository::new(vec![root_repo, lr]));
}
if installed_repo.get_packages().is_empty() {
@@ -475,8 +481,12 @@ impl ShowCommand {
versions_map.insert(pkg.get_pretty_version(), pkg.get_version());
} else if let Some(ref pf) = package_filter {
if !pf.contains('*') {
- let (matched_package, vers) =
- self.get_package(&*installed_repo, &*repos, pf, input.get_argument("version"))?;
+ let (matched_package, vers) = self.get_package(
+ &*installed_repo.borrow(),
+ &repos,
+ pf,
+ input.get_argument("version"),
+ )?;
if let Some(ref pkg) = matched_package {
if input.get_option("direct").as_bool() == Some(true) {
@@ -546,8 +556,11 @@ impl ShowCommand {
let mut exit_code: i64 = 0;
if input.get_option("tree").as_bool() == Some(true) {
- let array_tree =
- self.generate_package_tree(package.clone().into(), &*installed_repo, &*repos);
+ let array_tree = self.generate_package_tree(
+ package.clone().into(),
+ &*installed_repo.borrow(),
+ &repos,
+ );
if format == "json" {
let mut wrapper: IndexMap<String, PhpMixed> = IndexMap::new();
@@ -625,14 +638,14 @@ impl ShowCommand {
self.print_package_info_as_json(
package.clone(),
&versions_map,
- &*installed_repo,
+ &*installed_repo.borrow(),
latest_package,
)?;
} else {
self.print_package_info(
package.clone(),
&versions_map,
- &*installed_repo,
+ &*installed_repo.borrow(),
latest_package,
)?;
}
@@ -663,8 +676,8 @@ impl ShowCommand {
) {
array_tree.push(self.generate_package_tree(
package.clone(),
- &*installed_repo,
- &*repos,
+ &*installed_repo.borrow(),
+ &repos,
));
}
}
@@ -715,13 +728,13 @@ impl ShowCommand {
input.set_option("path", PhpMixed::Bool(false));
}
- for repo in RepositoryUtils::flatten_repositories(repos.clone_box(), false) {
+ for repo in RepositoryUtils::flatten_repositories(repos.clone(), false) {
// TODO(phase-b): InstalledRepository needs as_repository_interface / get_repositories
// wired through; placeholder classification until then.
- let r#type = if Self::same_repository(&*repo, &platform_repo) {
+ let r#type = if Self::same_repository(&*repo.borrow(), &platform_repo) {
"platform"
} else if let Some(ref lr) = locked_repo {
- if Self::same_repository_dyn(&*repo, &**lr) {
+ if Self::same_repository_dyn(&*repo.borrow(), &*lr.borrow()) {
"locked"
} else {
"available"
@@ -776,7 +789,7 @@ impl ShowCommand {
}
}
}
- if Self::same_repository(&*repo, &platform_repo) {
+ if Self::same_repository(&*repo.borrow(), &platform_repo) {
for (name, p) in platform_repo.get_disabled_packages() {
packages
.entry(type_owned.clone())
@@ -1470,8 +1483,8 @@ impl ShowCommand {
/// finds a package by name and version if provided
pub(crate) fn get_package(
&mut self,
- installed_repo: &InstalledRepository,
- repos: &dyn RepositoryInterface,
+ installed_repo: &dyn RepositoryInterface,
+ repos: &RepositoryInterfaceHandle,
name: &str,
version: PhpMixed,
) -> anyhow::Result<(
@@ -1498,7 +1511,7 @@ impl ShowCommand {
IndexMap::new(),
);
repository_set.allow_installed_repositories(true);
- repository_set.add_repository(repos.clone_box())?;
+ repository_set.add_repository(repos.clone())?;
let mut matched_package: Option<crate::package::PackageInterfaceHandle> = None;
let mut versions: IndexMap<String, String> = IndexMap::new();
@@ -1555,7 +1568,7 @@ impl ShowCommand {
&mut self,
package: CompletePackageInterfaceHandle,
versions: &IndexMap<String, String>,
- installed_repo: &InstalledRepository,
+ installed_repo: &dyn RepositoryInterface,
latest_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<()> {
self.print_meta(package.clone(), versions, installed_repo, latest_package);
@@ -1585,7 +1598,7 @@ impl ShowCommand {
&mut self,
package: CompletePackageInterfaceHandle,
versions: &IndexMap<String, String>,
- installed_repo: &InstalledRepository,
+ installed_repo: &dyn RepositoryInterface,
latest_package: Option<PackageInterfaceHandle>,
) {
let is_installed_package = !PlatformRepository::is_platform_package(&package.get_name())
@@ -1743,7 +1756,7 @@ impl ShowCommand {
&mut self,
package: CompletePackageInterfaceHandle,
versions: &IndexMap<String, String>,
- installed_repo: &InstalledRepository,
+ installed_repo: &dyn RepositoryInterface,
) {
let mut versions_keys: Vec<String> = versions.keys().cloned().collect();
versions_keys = Semver::rsort(versions_keys);
@@ -1830,7 +1843,7 @@ impl ShowCommand {
&mut self,
package: CompletePackageInterfaceHandle,
versions: &IndexMap<String, String>,
- installed_repo: &InstalledRepository,
+ installed_repo: &dyn RepositoryInterface,
latest_package: Option<PackageInterfaceHandle>,
) -> anyhow::Result<()> {
let mut json: IndexMap<String, PhpMixed> = IndexMap::new();
@@ -2268,8 +2281,8 @@ impl ShowCommand {
pub(crate) fn generate_package_tree(
&mut self,
package: PackageInterfaceHandle,
- installed_repo: &InstalledRepository,
- remote_repos: &dyn RepositoryInterface,
+ installed_repo: &dyn RepositoryInterface,
+ remote_repos: &RepositoryInterfaceHandle,
) -> IndexMap<String, PhpMixed> {
let requires = {
let mut r: IndexMap<String, Link> = package.get_requires().clone();
@@ -2425,8 +2438,8 @@ impl ShowCommand {
&mut self,
name: &str,
link: &Link,
- installed_repo: &InstalledRepository,
- remote_repos: &dyn RepositoryInterface,
+ installed_repo: &dyn RepositoryInterface,
+ remote_repos: &RepositoryInterfaceHandle,
packages_in_tree: &[PhpMixed],
) -> anyhow::Result<Vec<IndexMap<String, PhpMixed>>> {
let mut children: Vec<IndexMap<String, PhpMixed>> = Vec::new();
@@ -2693,13 +2706,13 @@ impl ShowCommand {
IndexMap::new(),
IndexMap::new(),
);
- rs.add_repository(Box::new(CompositeRepository::new(
+ rs.add_repository(RepositoryInterfaceHandle::new(CompositeRepository::new(
composer
.get_repository_manager()
.borrow()
.get_repositories()
.iter()
- .map(|r| r.clone_box())
+ .map(|r| r.clone())
.collect(),
)))?;
self.repository_set = Some(rs);
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index aa1ae15..9105474 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -8,6 +8,7 @@ use crate::io::IOInterface;
use crate::repository::InstalledRepository;
use crate::repository::PlatformRepository;
use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use crate::repository::RootPackageRepository;
use anyhow::Result;
use indexmap::IndexMap;
@@ -49,8 +50,10 @@ impl SuggestsCommand {
let root_package_handle: crate::package::RootPackageInterfaceHandle =
composer.get_package().clone();
- let mut installed_repos: Vec<Box<dyn RepositoryInterface>> =
- vec![Box::new(RootPackageRepository::new(root_package_handle))];
+ let mut installed_repos: Vec<RepositoryInterfaceHandle> =
+ vec![RepositoryInterfaceHandle::new(RootPackageRepository::new(
+ root_package_handle,
+ ))];
if composer.get_locker().borrow_mut().is_locked() {
// TODO(phase-b): get_platform_overrides returns IndexMap<String, String>; PlatformRepository::new expects IndexMap<String, PhpMixed>
@@ -60,7 +63,7 @@ impl SuggestsCommand {
.get_platform_overrides()?;
let platform_overrides: IndexMap<String, PhpMixed> =
todo!("convert IndexMap<String, String> to IndexMap<String, PhpMixed>");
- installed_repos.push(Box::new(PlatformRepository::new(
+ installed_repos.push(RepositoryInterfaceHandle::new(PlatformRepository::new(
vec![],
platform_overrides,
)?));
@@ -68,13 +71,13 @@ impl SuggestsCommand {
.get_locker()
.borrow_mut()
.get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?;
- installed_repos.push(Box::new(locked_repo));
+ installed_repos.push(RepositoryInterfaceHandle::new(locked_repo));
} else {
// TODO(phase-b): Config::get returns PhpMixed; need to coerce to IndexMap<String, PhpMixed>
let _platform_cfg = composer.get_config().borrow().get("platform");
let platform_overrides: IndexMap<String, PhpMixed> =
todo!("extract IndexMap<String, PhpMixed> from PhpMixed config value");
- installed_repos.push(Box::new(PlatformRepository::new(
+ installed_repos.push(RepositoryInterfaceHandle::new(PlatformRepository::new(
vec![],
platform_overrides,
)?));
@@ -82,8 +85,7 @@ impl SuggestsCommand {
composer
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box(),
+ .get_local_repository(),
);
}
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index f879283..f1b05af 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -635,13 +635,12 @@ impl UpdateCommand {
.get_repository_manager()
.borrow()
.get_repositories();
- let _ = |repository: &Box<dyn RepositoryInterface>| -> bool {
- repository
- .as_any()
- .downcast_ref::<PlatformRepository>()
- .is_none()
+ let _ = |repository: &crate::repository::RepositoryInterfaceHandle| -> bool {
+ !repository.is::<PlatformRepository>()
};
- repository_set.add_repository(Box::new(CompositeRepository::new(Vec::new())))?;
+ repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new(
+ CompositeRepository::new(Vec::new()),
+ ))?;
let _ = array_filter::<i64, fn(&i64) -> bool>;
VersionSelector::new(repository_set, None)
diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs
index 489b358..273d19f 100644
--- a/crates/shirabe/src/dependency_resolver/pool_builder.rs
+++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs
@@ -34,8 +34,10 @@ use crate::package::version::StabilityFilter;
use crate::plugin::PluginEvents;
use crate::plugin::PrePoolCreateEvent;
use crate::repository::CanonicalPackagesTrait;
+use crate::repository::LockArrayRepository;
use crate::repository::PlatformRepository;
use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use crate::repository::RootPackageRepository;
#[derive(Debug)]
@@ -134,7 +136,7 @@ impl PoolBuilder {
pub fn build_pool(
&mut self,
- repositories: Vec<Box<dyn RepositoryInterface>>,
+ repositories: Vec<RepositoryInterfaceHandle>,
request: &mut Request,
) -> anyhow::Result<Pool> {
self.restricted_packages_list = if request.get_restricted_packages().is_some() {
@@ -206,13 +208,9 @@ impl PoolBuilder {
// TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to
// specific versions while replace is a conflict with all versions of the name
- // TODO(phase-c): package->repository back-reference not yet on handles
- let in_root_or_platform = None
- .map(|r: &dyn RepositoryInterface| {
- r.as_any().is::<RootPackageRepository>()
- || r.as_any().is::<PlatformRepository>()
- })
- .unwrap_or(false);
+ let in_root_or_platform = package.get_repository().map_or(false, |r| {
+ r.is::<RootPackageRepository>() || r.is::<PlatformRepository>()
+ });
if in_root_or_platform
|| StabilityFilter::is_package_acceptable(
&self.acceptable_stabilities,
@@ -446,7 +444,7 @@ impl PoolBuilder {
fn load_packages_marked_for_loading(
&mut self,
request: &mut Request,
- repositories: &Vec<Box<dyn RepositoryInterface>>,
+ repositories: &Vec<RepositoryInterfaceHandle>,
) -> anyhow::Result<()> {
let to_remove: Vec<String> = self
.packages_to_load
@@ -493,16 +491,14 @@ impl PoolBuilder {
for (repo_index, repository) in repositories.iter().enumerate() {
// these repos have their packages fixed or locked if they need to be loaded so we
// never need to load anything else from them
- let is_locked_repo = request
- .get_locked_repository()
- .map(|lr| {
- std::ptr::eq(
- lr as *const _ as *const u8,
- repository.as_ref() as *const _ as *const u8,
- )
- })
- .unwrap_or(false);
- if repository.as_any().is::<PlatformRepository>() || is_locked_repo {
+ // TODO(phase-c): PHP compares `$request->getLockedRepository() === $repository` by
+ // strict identity, but `Request.locked_repository` is held by value, not as a handle.
+ // This approximates the check by matching any `LockArrayRepository` when the request
+ // has a locked repository set. Tighten to `ptr_eq` once `Request` stores the locked
+ // repository as `RepositoryInterfaceHandle`.
+ let is_locked_repo =
+ request.get_locked_repository().is_some() && repository.is::<LockArrayRepository>();
+ if repository.is::<PlatformRepository>() || is_locked_repo {
continue;
}
@@ -611,7 +607,7 @@ impl PoolBuilder {
fn load_package(
&mut self,
request: &mut Request,
- repositories: &Vec<Box<dyn RepositoryInterface>>,
+ repositories: &Vec<RepositoryInterfaceHandle>,
package: BasePackageHandle,
propagate_update: bool,
) -> anyhow::Result<()> {
@@ -872,7 +868,7 @@ impl PoolBuilder {
fn unlock_package(
&mut self,
request: &mut Request,
- repositories: &Vec<Box<dyn RepositoryInterface>>,
+ repositories: &Vec<RepositoryInterfaceHandle>,
name: &str,
) -> anyhow::Result<()> {
let skipped: Vec<PackageInterfaceHandle> = self
@@ -1029,15 +1025,19 @@ impl PoolBuilder {
fn remove_loaded_package(
&mut self,
_request: &Request,
- repositories: &Vec<Box<dyn RepositoryInterface>>,
+ repositories: &Vec<RepositoryInterfaceHandle>,
package: BasePackageHandle,
index: i64,
) {
- let repos_box: Vec<Box<dyn RepositoryInterface>> =
- repositories.iter().map(|r| r.clone_box()).collect();
- let _ = &repos_box;
- // TODO(phase-c): package->repository back-reference not yet on handles
- let repo_index: i64 = -1;
+ let repo_index: i64 = package
+ .get_repository()
+ .and_then(|pkg_repo| {
+ repositories
+ .iter()
+ .position(|r| r.ptr_eq(&pkg_repo))
+ .map(|i| i as i64)
+ })
+ .unwrap_or(-1);
if repo_index >= 0 {
if let Some(repo_map) = self.loaded_per_repo.get_mut(&repo_index) {
@@ -1115,7 +1115,7 @@ impl PoolBuilder {
fn run_security_advisory_filter(
&mut self,
pool: Pool,
- repositories: &Vec<Box<dyn RepositoryInterface>>,
+ repositories: &Vec<RepositoryInterfaceHandle>,
request: &Request,
) -> Pool {
if self.security_advisory_pool_filter.is_none() {
@@ -1127,8 +1127,7 @@ impl PoolBuilder {
let before = microtime(true);
let total = pool.get_packages().len() as f64;
- let repos_owned: Vec<Box<dyn RepositoryInterface>> =
- repositories.iter().map(|r| r.clone_box()).collect();
+ let repos_owned: Vec<RepositoryInterfaceHandle> = repositories.iter().cloned().collect();
let pool =
self.security_advisory_pool_filter
.as_mut()
diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs
index 58d47f1..740909f 100644
--- a/crates/shirabe/src/dependency_resolver/problem.rs
+++ b/crates/shirabe/src/dependency_resolver/problem.rs
@@ -1127,11 +1127,14 @@ impl Problem {
if available.len() > 0 {
let mut selected: Option<&BasePackageHandle> = None;
- // TODO(phase-c): the handle does not expose get_repository (a `RefCell`-borrowed
- // back-reference); preferring the package from a PlatformRepository needs repository
- // back-references on handles. Falling back to the first candidate for now.
for pkg in &available {
- let _ = pkg;
+ if pkg
+ .get_repository()
+ .map_or(false, |r| r.is::<PlatformRepository>())
+ {
+ selected = Some(pkg);
+ break;
+ }
}
if selected.is_none() {
selected = available.first();
@@ -1240,13 +1243,23 @@ impl Problem {
reason: &str,
constraint: Option<&AnyConstraint>,
) -> (String, String) {
- // TODO(phase-c): selecting the next repository's packages relies on each package's
- // repository back-reference, which the handle does not yet expose (phase-c handoff
- // item #1). Both `next_repo_packages` and `next_repo` are blocked on that decision.
- let _ = all_repos_packages;
- let next_repo_packages: Vec<BasePackageHandle> = Vec::new();
- let next_repo: Box<dyn crate::repository::RepositoryInterface> =
- todo!("repository back-reference on handle pending (phase-c handoff item #1)");
+ let mut next_repo_packages: Vec<BasePackageHandle> = Vec::new();
+ let mut next_repo: Option<crate::repository::RepositoryInterfaceHandle> = None;
+ for package in all_repos_packages {
+ let pkg_repo = package.get_repository();
+ let same_repo = match (&next_repo, &pkg_repo) {
+ (None, _) => true,
+ (Some(nr), Some(pr)) => nr.ptr_eq(pr),
+ _ => false,
+ };
+ if same_repo {
+ next_repo_packages.push(package.clone());
+ next_repo = pkg_repo;
+ } else {
+ break;
+ }
+ }
+ let next_repo = next_repo.expect("next_repo must be set");
if higher_repo_packages.len() > 0 {
let top_package = higher_repo_packages.first().unwrap();
@@ -1274,11 +1287,7 @@ impl Problem {
}
}
- if next_repo
- .as_any()
- .downcast_ref::<LockArrayRepository>()
- .is_some()
- {
+ if next_repo.is::<LockArrayRepository>() {
let singular = higher_repo_packages.len() == 1;
let mut suggestion = format!(
@@ -1351,10 +1360,11 @@ impl Problem {
constraint,
false
),
- // TODO(phase-c): the higher repo's name needs the handle's repository
- // back-reference (phase-c handoff item #1); unreachable until `next_repo` above
- // is resolved.
- String::new(),
+ higher_repo_packages
+ .first()
+ .and_then(|p| p.get_repository())
+ .map(|r| r.get_repo_name())
+ .unwrap_or_default(),
reason
),
)
diff --git a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
index 785e758..ec224b4 100644
--- a/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
+++ b/crates/shirabe/src/dependency_resolver/security_advisory_pool_filter.rs
@@ -6,7 +6,6 @@ use crate::advisory::PartialSecurityAdvisory;
use crate::dependency_resolver::Pool;
use crate::dependency_resolver::Request;
use crate::package::BasePackageHandle;
-use crate::repository::RepositoryInterface;
use indexmap::IndexMap;
use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::SimpleConstraint;
@@ -28,7 +27,7 @@ impl SecurityAdvisoryPoolFilter {
pub fn filter(
&self,
pool: Pool,
- repositories: Vec<Box<dyn RepositoryInterface>>,
+ repositories: Vec<crate::repository::RepositoryInterfaceHandle>,
request: &Request,
) -> Pool {
// TODO(phase-c): port the filter() body. Blockers:
diff --git a/crates/shirabe/src/downloader/perforce_downloader.rs b/crates/shirabe/src/downloader/perforce_downloader.rs
index 4a54511..fcea57c 100644
--- a/crates/shirabe/src/downloader/perforce_downloader.rs
+++ b/crates/shirabe/src/downloader/perforce_downloader.rs
@@ -90,10 +90,10 @@ impl PerforceDownloader {
return;
}
- let package_rc = package.as_rc().borrow();
- let repository = package_rc.as_package_interface().get_repository();
+ let repository = package.get_repository();
let repo_config: Option<IndexMap<String, PhpMixed>> = if let Some(repo) = repository {
- if let Some(vcs_repo) = repo.as_any().downcast_ref::<VcsRepository>() {
+ let repo_ref = repo.borrow();
+ if let Some(vcs_repo) = repo_ref.as_any().downcast_ref::<VcsRepository>() {
Some(self.get_repo_config(vcs_repo))
} else {
None
@@ -101,7 +101,6 @@ impl PerforceDownloader {
} else {
None
};
- drop(package_rc);
self.perforce = Some(Perforce::create(
repo_config.unwrap_or_default(),
url,
diff --git a/crates/shirabe/src/downloader/svn_downloader.rs b/crates/shirabe/src/downloader/svn_downloader.rs
index 9f5d2ed..98456a4 100644
--- a/crates/shirabe/src/downloader/svn_downloader.rs
+++ b/crates/shirabe/src/downloader/svn_downloader.rs
@@ -70,10 +70,10 @@ impl SvnDownloader {
let r#ref = package.get_source_reference();
{
- let package_ref = package.as_rc().borrow();
- let repo = package_ref.as_package_interface().get_repository();
+ let repo = package.get_repository();
if let Some(repo) = repo {
- if let Some(vcs_repo) = repo.as_any().downcast_ref::<VcsRepository>() {
+ let repo_ref = repo.borrow();
+ if let Some(vcs_repo) = repo_ref.as_any().downcast_ref::<VcsRepository>() {
let repo_config = vcs_repo.get_repo_config();
if repo_config.contains_key("svn-cache-credentials") {
if let Some(val) = repo_config
diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs
index 80f1548..f2fa99b 100644
--- a/crates/shirabe/src/factory.rs
+++ b/crates/shirabe/src/factory.rs
@@ -886,7 +886,7 @@ impl Factory {
let fs = process
.map(|p| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(Some(p.clone())))));
- rm.set_local_repository(Box::new(
+ rm.set_local_repository(crate::repository::RepositoryInterfaceHandle::new(
InstalledFilesystemRepository::new(
JsonFile::new(
format!("{}/composer/installed.json", vendor_dir),
diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs
index 14e75c0..f0c07bf 100644
--- a/crates/shirabe/src/installer.rs
+++ b/crates/shirabe/src/installer.rs
@@ -145,7 +145,7 @@ pub struct Installer {
pub(crate) update_allow_transitive_dependencies: i64,
pub(crate) suggested_packages_reporter: SuggestedPackagesReporter,
pub(crate) platform_requirement_filter: Box<dyn PlatformRequirementFilterInterface>,
- pub(crate) additional_fixed_repository: Option<Box<dyn RepositoryInterface>>,
+ pub(crate) additional_fixed_repository: Option<crate::repository::RepositoryInterfaceHandle>,
pub(crate) temporary_constraints: IndexMap<String, AnyConstraint>,
}
@@ -293,17 +293,13 @@ impl Installer {
.borrow_mut()
.set_prefer_dist(self.prefer_dist);
- let local_repo_box = self
- .repository_manager
- .borrow()
- .get_local_repository()
- .clone_installed_repository_box();
+ let local_repo = self.repository_manager.borrow().get_local_repository();
let install = self.install;
let res_result: anyhow::Result<i64> = if self.update {
- self.do_update(local_repo_box, install)
+ self.do_update(local_repo, install)
} else {
- self.do_install(local_repo_box, false)
+ self.do_install(local_repo, false)
};
let res = match res_result {
@@ -347,15 +343,17 @@ impl Installer {
}
if self.update {
- let locked_repository_box = self
- .locker
- .borrow_mut()
- .get_locked_repository(self.dev_mode)?
- .clone_box();
+ let locked_repository_handle = crate::repository::RepositoryInterfaceHandle::new(
+ self.locker
+ .borrow_mut()
+ .get_locked_repository(self.dev_mode)?,
+ );
let installed_repo = InstalledRepository::new(vec![
- locked_repository_box,
- Box::new(self.create_platform_repo(false)),
- Box::new(RootPackageRepository::new(self.package.clone())),
+ locked_repository_handle,
+ crate::repository::RepositoryInterfaceHandle::new(self.create_platform_repo(false)),
+ crate::repository::RepositoryInterfaceHandle::new(RootPackageRepository::new(
+ self.package.clone(),
+ )),
]);
if is_fresh_install {
self.suggested_packages_reporter
@@ -407,9 +405,11 @@ impl Installer {
self.autoload_generator
.borrow_mut()
.set_platform_requirement_filter(self.platform_requirement_filter.clone_box());
+ let local_repo_handle = self.repository_manager.borrow().get_local_repository();
+ let local_repo_ref = local_repo_handle.borrow();
self.autoload_generator.borrow_mut().dump(
&*self.config.borrow(),
- self.repository_manager.borrow().get_local_repository(),
+ local_repo_ref.as_installed_repository_interface().unwrap(),
self.package.clone(),
&mut *self.installation_manager.borrow_mut(),
"composer",
@@ -512,7 +512,7 @@ impl Installer {
let repository_manager = self.repository_manager.clone();
let repository_manager = repository_manager.borrow();
for repo in repository_manager.get_repositories() {
- repo_set.add_repository(repo.clone_box())?;
+ repo_set.add_repository(repo.clone())?;
}
// TODO(phase-b): Auditor::audit takes owned packages/ignore lists; need cloning
@@ -555,7 +555,7 @@ impl Installer {
pub(crate) fn do_update(
&mut self,
- local_repo: Box<dyn InstalledRepositoryInterface>,
+ local_repo: crate::repository::RepositoryInterfaceHandle,
do_install: bool,
) -> anyhow::Result<i64> {
let platform_repo = self.create_platform_repo(true);
@@ -618,10 +618,16 @@ impl Installer {
let repository_manager = repository_manager.borrow();
let repositories = repository_manager.get_repositories();
for repository in repositories {
- repository_set.add_repository(repository.clone_box())?;
+ repository_set.add_repository(repository.clone())?;
}
- if let Some(ref lr) = locked_repository {
- repository_set.add_repository(lr.clone_box())?;
+ if let Some(ref _lr) = locked_repository {
+ // TODO(phase-c): LockArrayRepository is held by value and is not Clone; share it as a
+ // RepositoryInterfaceHandle so it can be added here without copying.
+ repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new::<
+ crate::repository::LockArrayRepository,
+ >(todo!(
+ "share locked LockArrayRepository as a handle"
+ )))?;
}
let fixed_root_package = self.fixed_root_package.clone();
@@ -839,9 +845,11 @@ impl Installer {
if self.io.is_very_verbose()
&& strpos(&operation.get_operation_type(), "Alias").is_none()
{
- // TODO(phase-c): package->repository back-reference not yet on handles
- let repository: Option<&dyn RepositoryInterface> = None;
- if let Some(repo) = repository {
+ let operation_pkg = match operation.as_update_operation() {
+ Some(uo) => uo.get_target_package(),
+ None => operation.get_package(),
+ };
+ if let Some(repo) = operation_pkg.get_repository() {
source_repo = format!(" from {}", repo.get_repo_name());
}
}
@@ -921,7 +929,9 @@ impl Installer {
}
let mut repository_set = self.create_repository_set(true, platform_repo, aliases, None);
- repository_set.add_repository(Box::new(result_repo))?;
+ repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new(
+ result_repo,
+ ))?;
let mut request = self.create_request(self.fixed_root_package.clone(), platform_repo, None);
self.require_packages_for_update(&mut request, locked_repository, false)?;
@@ -959,7 +969,7 @@ impl Installer {
/// Whether the function is called as part of an update command or independently
pub(crate) fn do_install(
&mut self,
- mut local_repo: Box<dyn InstalledRepositoryInterface>,
+ local_repo: crate::repository::RepositoryInterfaceHandle,
already_solved: bool,
) -> anyhow::Result<i64> {
if self
@@ -1001,7 +1011,13 @@ impl Installer {
&vec![],
Some(&locked_repository),
);
- repository_set.add_repository(locked_repository.clone_box())?;
+ // TODO(phase-c): LockArrayRepository is held by value and is not Clone; share it as a
+ // RepositoryInterfaceHandle so it can be added here without copying.
+ repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new::<
+ crate::repository::LockArrayRepository,
+ >(todo!(
+ "share locked LockArrayRepository as a handle"
+ )))?;
// creating requirements request
let fixed_root_package = self.fixed_root_package.clone();
@@ -1103,7 +1119,13 @@ impl Installer {
}
// TODO in how far do we need to do anything here to ensure dev packages being updated to latest in lock without version change are treated correctly?
- let local_repo_transaction = LocalRepoTransaction::new(&locked_repository, &*local_repo);
+ let local_repo_transaction = {
+ let local_repo_ref = local_repo.borrow();
+ LocalRepoTransaction::new(
+ &locked_repository,
+ local_repo_ref.as_installed_repository_interface().unwrap(),
+ )
+ };
// TODO(phase-b): dispatch_installer_event takes owned Transaction, not &LocalRepoTransaction
// self.event_dispatcher.borrow_mut().dispatch_installer_event(
// InstallerEvents::PRE_OPERATIONS_EXEC,
@@ -1172,13 +1194,17 @@ impl Installer {
if self.execute_operations {
local_repo.set_dev_package_names(self.locker.borrow_mut().get_dev_package_names()?);
+ let mut local_repo_ref = local_repo.borrow_mut();
self.installation_manager.borrow_mut().execute(
- &mut *local_repo,
+ local_repo_ref
+ .as_installed_repository_interface_mut()
+ .unwrap(),
local_repo_transaction.get_operations(),
self.dev_mode,
self.run_scripts,
self.download_only,
)?;
+ drop(local_repo_ref);
// see https://github.com/composer/composer/issues/2764
if local_repo_transaction.get_operations().len() > 0 {
@@ -1349,32 +1375,23 @@ impl Installer {
if let Some(ref additional_fixed_repository) = self.additional_fixed_repository {
// allow using installed repos if needed to avoid warnings about installed repositories being used in the RepositorySet
// see https://github.com/composer/composer/pull/9574
- let additional_fixed_repositories: Vec<Box<dyn RepositoryInterface>> =
- if let Some(composite) = additional_fixed_repository
- .as_any()
- .downcast_ref::<CompositeRepository>()
- {
- composite
- .get_repositories()
- .iter()
- .map(|r| r.clone_box())
- .collect()
+ let additional_fixed_repositories: Vec<crate::repository::RepositoryInterfaceHandle> = {
+ let repo_ref = additional_fixed_repository.borrow();
+ if let Some(composite) = repo_ref.as_any().downcast_ref::<CompositeRepository>() {
+ composite.get_repositories().clone()
} else {
- vec![additional_fixed_repository.clone_box()]
- };
+ drop(repo_ref);
+ vec![additional_fixed_repository.clone()]
+ }
+ };
for additional_fixed_repository in &additional_fixed_repositories {
- // TODO(phase-b): as_installed_repository_interface not on RepositoryInterface trait
- if additional_fixed_repository
- .as_any()
- .downcast_ref::<InstalledRepository>()
- .is_some()
- {
+ if additional_fixed_repository.is::<InstalledRepository>() {
repository_set.allow_installed_repositories(true);
break;
}
}
- let _ = repository_set.add_repository(additional_fixed_repository.clone_box());
+ let _ = repository_set.add_repository(additional_fixed_repository.clone());
}
repository_set
@@ -1457,27 +1474,22 @@ impl Installer {
let provided = root_package.get_provides();
for package in fixed_packages {
// skip platform packages that are provided by the root package
- // TODO(phase-c): the handle does not expose get_repository (a `RefCell`-borrowed
- // back-reference); detecting the platform repo needs repository back-refs on handles.
- let pkg_repo_is_platform = false;
+ let pkg_repo_is_platform = package
+ .get_repository()
+ .map_or(false, |r| r.is::<PlatformRepository>());
+ let name = package.get_name();
if !pkg_repo_is_platform
- || !provided.contains_key(&package.get_name())
- || !provided
- .get(&package.get_name())
- .unwrap()
- .get_constraint()
- .matches(
- &SimpleConstraint::new(
- "=".to_string(),
- package.get_version().to_string(),
- None,
- )
- .into(),
+ || !provided.contains_key(&name)
+ || !provided.get(&name).unwrap().get_constraint().matches(
+ &SimpleConstraint::new(
+ "=".to_string(),
+ package.get_version().to_string(),
+ None,
)
+ .into(),
+ )
{
- // TODO(phase-c): wire up once the platform-repo detection above is implemented.
- let _ = &package;
- // request.fix_package(package.clone());
+ request.fix_package(package);
}
}
@@ -1590,7 +1602,7 @@ impl Installer {
packages.insert(key, new_alias_package);
}
}
- rm.set_local_repository(Box::new(
+ rm.set_local_repository(crate::repository::RepositoryInterfaceHandle::new(
InstalledArrayRepository::new_with_packages(packages.into_values().collect())
.expect("InstalledArrayRepository::new_with_packages should not fail"),
));
@@ -1678,7 +1690,7 @@ impl Installer {
pub fn set_additional_fixed_repository(
&mut self,
- additional_fixed_repository: Box<dyn RepositoryInterface>,
+ additional_fixed_repository: crate::repository::RepositoryInterfaceHandle,
) -> &mut Self {
self.additional_fixed_repository = Some(additional_fixed_repository);
diff --git a/crates/shirabe/src/package/alias_package.rs b/crates/shirabe/src/package/alias_package.rs
index 997685b..69e0723 100644
--- a/crates/shirabe/src/package/alias_package.rs
+++ b/crates/shirabe/src/package/alias_package.rs
@@ -11,14 +11,13 @@ use crate::package::Link;
use crate::package::PackageHandle;
use crate::package::PackageInterface;
use crate::package::version::VersionParser;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
#[derive(Debug)]
pub struct AliasPackage {
id: i64,
name: String,
pretty_name: String,
- repository: Option<Box<dyn RepositoryInterface>>,
/// @var string
pub(crate) version: String,
@@ -64,7 +63,6 @@ impl AliasPackage {
id: -1,
name: alias_name.to_lowercase(),
pretty_name: alias_name,
- repository: None,
version,
pretty_version,
dev,
@@ -452,12 +450,12 @@ impl PackageInterface for AliasPackage {
self.alias_of.get_pretty_string()
}
- fn set_repository(&mut self, repository: Box<dyn RepositoryInterface>) -> anyhow::Result<()> {
+ fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> {
self.alias_of.set_repository(repository)
}
- fn get_repository(&self) -> Option<&dyn RepositoryInterface> {
- todo!("AliasPackage::get_repository cannot return a borrow across the aliasOf handle")
+ fn get_repository(&self) -> Option<RepositoryInterfaceHandle> {
+ self.alias_of.get_repository()
}
}
@@ -486,15 +484,17 @@ impl BasePackage for AliasPackage {
&mut self.pretty_name
}
- fn repository_opt(&self) -> Option<&dyn RepositoryInterface> {
- self.repository.as_deref()
+ fn repository_opt(&self) -> Option<RepositoryInterfaceHandle> {
+ // PHP `AliasPackage::getRepository()` delegates to `$this->aliasOf->getRepository()`.
+ self.alias_of.get_repository()
}
- fn set_repository_box(&mut self, repository: Box<dyn RepositoryInterface>) {
- todo!()
+ fn set_repository_box(&mut self, repository: RepositoryInterfaceHandle) {
+ let _ = self.alias_of.set_repository(repository);
}
- fn take_repository(&mut self) -> Option<Box<dyn RepositoryInterface>> {
- todo!()
+ fn take_repository(&mut self) -> Option<RepositoryInterfaceHandle> {
+ // AliasPackage holds no repository of its own; never mutate the aliased package here.
+ None
}
}
diff --git a/crates/shirabe/src/package/base_package.rs b/crates/shirabe/src/package/base_package.rs
index 64a5919..ca6f171 100644
--- a/crates/shirabe/src/package/base_package.rs
+++ b/crates/shirabe/src/package/base_package.rs
@@ -8,7 +8,7 @@ use shirabe_php_shim::{LogicException, UnexpectedValueException, preg_quote};
use crate::package::Link;
use crate::package::PackageInterface;
use crate::repository::PlatformRepository;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
pub struct SupportedLinkType {
pub description: &'static str,
@@ -79,15 +79,9 @@ pub trait BasePackage: PackageInterface + std::fmt::Display {
fn name_mut(&mut self) -> &mut String;
fn pretty_name(&self) -> &str;
fn pretty_name_mut(&mut self) -> &mut String;
- fn repository_opt(&self) -> Option<&dyn RepositoryInterface>;
- fn set_repository_box(&mut self, repository: Box<dyn RepositoryInterface>);
- fn take_repository(&mut self) -> Option<Box<dyn RepositoryInterface>>;
-
- /// PHP `setRepository($this)` from the containing repository — Rust port marker until
- /// the borrow story for repository-package back-references is finalized in phase B.
- fn set_repository_self(&mut self) {
- // TODO(phase-b): wire up a back-reference to the containing repository when needed.
- }
+ fn repository_opt(&self) -> Option<RepositoryInterfaceHandle>;
+ fn set_repository_box(&mut self, repository: RepositoryInterfaceHandle);
+ fn take_repository(&mut self) -> Option<RepositoryInterfaceHandle>;
// as_alias_package / as_complete_package_interface inherited from PackageInterface.
@@ -104,8 +98,7 @@ pub trait BasePackage: PackageInterface + std::fmt::Display {
fn is_platform(&self) -> bool {
self.repository_opt()
- .and_then(|r| r.as_any().downcast_ref::<PlatformRepository>())
- .is_some()
+ .map_or(false, |r| r.is::<PlatformRepository>())
}
fn equals(&self, _package: &dyn PackageInterface) -> bool {
diff --git a/crates/shirabe/src/package/complete_package.rs b/crates/shirabe/src/package/complete_package.rs
index b0adf52..a598389 100644
--- a/crates/shirabe/src/package/complete_package.rs
+++ b/crates/shirabe/src/package/complete_package.rs
@@ -311,13 +311,13 @@ impl PackageInterface for CompletePackage {
fn set_repository(
&mut self,
- repository: Box<dyn crate::repository::RepositoryInterface>,
+ repository: crate::repository::RepositoryInterfaceHandle,
) -> anyhow::Result<()> {
- todo!()
+ self.inner.set_repository(repository)
}
- fn get_repository(&self) -> Option<&dyn crate::repository::RepositoryInterface> {
- todo!()
+ fn get_repository(&self) -> Option<crate::repository::RepositoryInterfaceHandle> {
+ self.inner.get_repository()
}
fn get_binaries(&self) -> Vec<String> {
diff --git a/crates/shirabe/src/package/handle.rs b/crates/shirabe/src/package/handle.rs
index 931e196..e939c3a 100644
--- a/crates/shirabe/src/package/handle.rs
+++ b/crates/shirabe/src/package/handle.rs
@@ -273,11 +273,11 @@ macro_rules! delegate_package_interface_to_inner {
}
fn set_repository(
&mut self,
- repository: Box<dyn crate::repository::RepositoryInterface>,
+ repository: crate::repository::RepositoryInterfaceHandle,
) -> anyhow::Result<()> {
self.$field.set_repository(repository)
}
- fn get_repository(&self) -> Option<&dyn crate::repository::RepositoryInterface> {
+ fn get_repository(&self) -> Option<crate::repository::RepositoryInterfaceHandle> {
self.$field.get_repository()
}
fn get_binaries(&self) -> Vec<String> {
@@ -588,7 +588,7 @@ macro_rules! impl_package_interface_handle {
pub fn set_repository(
&self,
- repository: Box<dyn crate::repository::RepositoryInterface>,
+ repository: crate::repository::RepositoryInterfaceHandle,
) -> anyhow::Result<()> {
self.0
.borrow_mut()
@@ -596,6 +596,10 @@ macro_rules! impl_package_interface_handle {
.set_repository(repository)
}
+ pub fn get_repository(&self) -> Option<crate::repository::RepositoryInterfaceHandle> {
+ self.0.borrow().as_package_interface().get_repository()
+ }
+
pub fn get_binaries(&self) -> Vec<String> {
self.0.borrow().as_package_interface().get_binaries()
}
diff --git a/crates/shirabe/src/package/package.rs b/crates/shirabe/src/package/package.rs
index 92836a2..680443e 100644
--- a/crates/shirabe/src/package/package.rs
+++ b/crates/shirabe/src/package/package.rs
@@ -1,17 +1,20 @@
//! ref: composer/src/Composer/Package/Package.php
+use std::rc::Rc;
+
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::Preg;
use shirabe_external_packages::composer::util::ComposerMirror;
-use shirabe_php_shim::{E_USER_DEPRECATED, PhpMixed, strpos, trigger_error};
+use shirabe_php_shim::{E_USER_DEPRECATED, LogicException, PhpMixed, strpos, trigger_error};
use crate::package::BasePackage;
use crate::package::Link;
use crate::package::PackageInterface;
use crate::package::version::VersionParser;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
+use crate::repository::RepositoryInterfaceWeakHandle;
/// Mirror entry, e.g. `['url' => 'https://...', 'preferred' => true]`.
#[derive(Debug, Clone)]
@@ -26,7 +29,8 @@ pub struct Package {
id: i64,
name: String,
pretty_name: String,
- repository: Option<Box<dyn RepositoryInterface>>,
+ /// Back-reference to the owning repository. `Weak` breaks the repository -> packages cycle.
+ repository: Option<RepositoryInterfaceWeakHandle>,
pub(crate) r#type: Option<String>,
pub(crate) target_dir: Option<String>,
@@ -559,16 +563,22 @@ impl BasePackage for Package {
&mut self.pretty_name
}
- fn repository_opt(&self) -> Option<&dyn RepositoryInterface> {
- self.repository.as_deref()
+ fn repository_opt(&self) -> Option<RepositoryInterfaceHandle> {
+ self.repository
+ .as_ref()
+ .and_then(|w| w.upgrade())
+ .map(RepositoryInterfaceHandle::from_rc)
}
- fn set_repository_box(&mut self, repository: Box<dyn RepositoryInterface>) {
- todo!()
+ fn set_repository_box(&mut self, repository: RepositoryInterfaceHandle) {
+ self.repository = Some(repository.downgrade());
}
- fn take_repository(&mut self) -> Option<Box<dyn RepositoryInterface>> {
- todo!()
+ fn take_repository(&mut self) -> Option<RepositoryInterfaceHandle> {
+ self.repository
+ .take()
+ .and_then(|w| w.upgrade())
+ .map(RepositoryInterfaceHandle::from_rc)
}
}
@@ -696,11 +706,24 @@ impl PackageInterface for Package {
fn get_php_ext(&self) -> Option<IndexMap<String, PhpMixed>> {
todo!()
}
- fn set_repository(&mut self, _repository: Box<dyn RepositoryInterface>) -> anyhow::Result<()> {
- todo!()
+ fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> {
+ if let Some(existing) = self.repository.as_ref().and_then(|w| w.upgrade()) {
+ if !Rc::ptr_eq(&existing, repository.as_rc()) {
+ return Err(LogicException {
+ message: "A package can only be added to one repository".to_string(),
+ code: 0,
+ }
+ .into());
+ }
+ }
+ self.repository = Some(repository.downgrade());
+ Ok(())
}
- fn get_repository(&self) -> Option<&dyn RepositoryInterface> {
- todo!()
+ fn get_repository(&self) -> Option<RepositoryInterfaceHandle> {
+ self.repository
+ .as_ref()
+ .and_then(|w| w.upgrade())
+ .map(RepositoryInterfaceHandle::from_rc)
}
fn get_binaries(&self) -> Vec<String> {
todo!()
diff --git a/crates/shirabe/src/package/package_interface.rs b/crates/shirabe/src/package/package_interface.rs
index 0ec6e26..92729a4 100644
--- a/crates/shirabe/src/package/package_interface.rs
+++ b/crates/shirabe/src/package/package_interface.rs
@@ -5,7 +5,7 @@ use indexmap::IndexMap;
use shirabe_php_shim::PhpMixed;
use crate::package::Link;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
/// Defines the essential information a package has that is used during solving/installation
///
@@ -244,10 +244,10 @@ pub trait PackageInterface: std::fmt::Display + std::fmt::Debug {
fn get_php_ext(&self) -> Option<IndexMap<String, PhpMixed>>;
/// Stores a reference to the repository that owns the package
- fn set_repository(&mut self, repository: Box<dyn RepositoryInterface>) -> anyhow::Result<()>;
+ fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()>;
/// Returns a reference to the repository that owns the package
- fn get_repository(&self) -> Option<&dyn RepositoryInterface>;
+ fn get_repository(&self) -> Option<RepositoryInterfaceHandle>;
/// Returns the package binaries
///
diff --git a/crates/shirabe/src/package/root_package.rs b/crates/shirabe/src/package/root_package.rs
index df676ff..028f43b 100644
--- a/crates/shirabe/src/package/root_package.rs
+++ b/crates/shirabe/src/package/root_package.rs
@@ -9,7 +9,7 @@ use crate::package::CompletePackageInterface;
use crate::package::Link;
use crate::package::PackageInterface;
use crate::package::RootPackageInterface;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
#[derive(Debug)]
pub struct RootPackage {
@@ -351,11 +351,11 @@ impl PackageInterface for RootPackage {
fn get_php_ext(&self) -> Option<IndexMap<String, PhpMixed>> {
todo!()
}
- fn set_repository(&mut self, _repository: Box<dyn RepositoryInterface>) -> anyhow::Result<()> {
- todo!()
+ fn set_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> {
+ self.inner.set_repository(repository)
}
- fn get_repository(&self) -> Option<&dyn RepositoryInterface> {
- todo!()
+ fn get_repository(&self) -> Option<RepositoryInterfaceHandle> {
+ self.inner.get_repository()
}
fn get_binaries(&self) -> Vec<String> {
todo!()
diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs
index e2528ff..611ddfa 100644
--- a/crates/shirabe/src/plugin/plugin_manager.rs
+++ b/crates/shirabe/src/plugin/plugin_manager.rs
@@ -129,30 +129,28 @@ impl PluginManager {
// TODO(phase-b): PHP returns a shared object reference; we clone the repository
// box here to side-step a borrow conflict between `&self.composer` and
// `&mut self`. The Rust port should eventually share via Rc<RefCell<_>>.
- let repo: Box<dyn RepositoryInterface> = self
+ let repo = self
.composer_full()
.borrow()
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box();
+ .get_local_repository();
// The root package borrow is also tied to `self.composer`; clone the package handle
// (shared Rc) for the same reason as above.
let root_package = self.composer_full().borrow().get_package().clone();
- self.load_repository(&*repo, false, Some(root_package))?;
+ self.load_repository(&*repo.borrow(), false, Some(root_package))?;
}
if self.global_composer.is_some() && !self.are_plugins_disabled("global") {
- let repo: Box<dyn RepositoryInterface> = self
+ let repo = self
.global_composer
.as_ref()
.unwrap()
.borrow_partial()
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box();
- self.load_repository(&*repo, true, None)?;
+ .get_local_repository();
+ self.load_repository(&*repo.borrow(), true, None)?;
}
Ok(())
}
@@ -161,27 +159,25 @@ impl PluginManager {
pub fn deactivate_installed_plugins(&mut self) {
// TODO(plugin): deactivation is part of the plugin API
if !self.are_plugins_disabled("local") {
- let repo: Box<dyn RepositoryInterface> = self
+ let repo = self
.composer_full()
.borrow()
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box();
- self.deactivate_repository(&*repo, false);
+ .get_local_repository();
+ self.deactivate_repository(&*repo.borrow(), false);
}
if self.global_composer.is_some() && !self.are_plugins_disabled("global") {
- let repo: Box<dyn RepositoryInterface> = self
+ let repo = self
.global_composer
.as_ref()
.unwrap()
.borrow_partial()
.get_repository_manager()
.borrow()
- .get_local_repository()
- .clone_box();
- self.deactivate_repository(&*repo, true);
+ .get_local_repository();
+ self.deactivate_repository(&*repo.borrow(), true);
}
}
diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs
index 6467c14..3a05513 100644
--- a/crates/shirabe/src/repository/array_repository.rs
+++ b/crates/shirabe/src/repository/array_repository.rs
@@ -2,6 +2,7 @@
use std::any::Any;
use std::cell::RefCell;
+use std::rc::Weak;
use anyhow::Result;
use indexmap::IndexMap;
@@ -17,7 +18,7 @@ use crate::package::version::StabilityFilter;
use crate::package::version::VersionParser;
use crate::repository::{
AbandonedInfo, FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
- SearchResult,
+ RepositoryInterfaceHandle, RepositoryInterfaceWeakHandle, SearchResult,
};
/// A repository implementation that simply stores packages in an array
@@ -29,6 +30,10 @@ pub struct ArrayRepository {
/// @var ?array<BasePackage> indexed by package unique name and used to cache hasPackage calls
pub(crate) package_map: RefCell<Option<IndexMap<String, BasePackageHandle>>>,
+
+ /// Weak reference to the outermost repository handle wrapping this `ArrayRepository`,
+ /// injected via `set_self_handle`. Used to wire package -> repository back-references.
+ self_weak: RefCell<Option<RepositoryInterfaceWeakHandle>>,
}
impl ArrayRepository {
@@ -37,6 +42,7 @@ impl ArrayRepository {
let this = Self {
packages: RefCell::new(None),
package_map: RefCell::new(None),
+ self_weak: RefCell::new(None),
};
for package in packages {
this.add_package(package)?;
@@ -49,8 +55,12 @@ impl ArrayRepository {
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>"))?;
+ // PHP: $package->setRepository($this). The back-reference is wired only once this
+ // repository (or its outermost wrapper) has been put behind a RepositoryInterfaceHandle;
+ // packages added during construction are wired later in set_self_handle.
+ if let Some(handle) = self.self_weak.borrow().as_ref().and_then(Weak::upgrade) {
+ package.set_repository(RepositoryInterfaceHandle::from_rc(handle))?;
+ }
let aliased_package: Option<PackageHandle> =
package.as_alias().map(|alias| alias.get_alias_of());
@@ -59,13 +69,13 @@ impl ArrayRepository {
.borrow_mut()
.as_mut()
.unwrap()
- .push(package.into());
+ .push(package.clone());
if let Some(aliased_package) = aliased_package {
// 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;
+ if aliased_package.get_repository().is_none() {
+ self.add_package(aliased_package.into())?;
+ }
}
// invalidate package map cache
@@ -438,4 +448,23 @@ impl RepositoryInterface for ArrayRepository {
fn as_any(&self) -> &dyn std::any::Any {
self
}
+
+ fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ *self.self_weak.borrow_mut() = Some(weak.clone());
+ // Wire back-references for packages added before this repository was wrapped in a handle
+ // (e.g. those passed to ArrayRepository::new). Reads the field directly to avoid
+ // triggering lazy initialization in wrapper repositories.
+ if let Some(handle) = weak.upgrade() {
+ let handle = RepositoryInterfaceHandle::from_rc(handle);
+ let pkgs: Vec<BasePackageHandle> = self
+ .packages
+ .borrow()
+ .as_ref()
+ .map(|v| v.clone())
+ .unwrap_or_default();
+ for pkg in pkgs {
+ let _ = pkg.set_repository(handle.clone());
+ }
+ }
+ }
}
diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs
index ddf8e31..9931a73 100644
--- a/crates/shirabe/src/repository/composer_repository.rs
+++ b/crates/shirabe/src/repository/composer_repository.rs
@@ -38,6 +38,8 @@ use crate::repository::ConfigurableRepositoryInterface;
use crate::repository::LoadPackagesResult;
use crate::repository::PlatformRepository;
use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
+use crate::repository::RepositoryInterfaceWeakHandle;
use crate::repository::RepositorySecurityException;
use crate::repository::{PartialOrSecurityAdvisory, SecurityAdvisoryResult};
use crate::repository::{SEARCH_FULLTEXT, SEARCH_VENDOR};
@@ -78,6 +80,9 @@ pub struct ProviderListingEntry {
#[derive(Debug)]
pub struct ComposerRepository {
inner: ArrayRepository,
+ /// Weak reference to the outermost repository handle wrapping this `ComposerRepository`,
+ /// injected via `set_self_handle`. Used to wire package -> repository back-references.
+ self_weak: std::cell::RefCell<Option<RepositoryInterfaceWeakHandle>>,
/// @phpstan-var array{url: string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool}
repo_config: IndexMap<String, PhpMixed>,
options: IndexMap<String, PhpMixed>,
@@ -274,6 +279,7 @@ impl ComposerRepository {
let mut this = Self {
inner: inner?,
+ self_weak: std::cell::RefCell::new(None),
repo_config,
options,
url,
@@ -1745,13 +1751,20 @@ impl ComposerRepository {
versions_to_load.values().cloned().collect();
let loaded_packages = self.create_packages_flat(versions_to_load_vec, packages_source)?;
let uids: Vec<String> = versions_to_load.keys().cloned().collect();
+ let self_handle = self.self_handle();
for (index, package) in loaded_packages.into_iter().enumerate() {
- // TODO(phase-c): wire the repository back-reference onto the shared package handle.
+ if let Some(h) = self_handle.as_ref() {
+ package.set_repository(h.clone())?;
+ }
let uid = &uids[index];
if let Some(alias) = package.as_alias() {
let aliased = alias.get_alias_of();
+ if let Some(h) = self_handle.as_ref() {
+ let aliased_pkg: PackageInterfaceHandle = aliased.clone().into();
+ aliased_pkg.set_repository(h.clone())?;
+ }
result.insert(uid.clone(), aliased.into());
result.insert(format!("{}-alias", uid), package);
} else {
@@ -1784,6 +1797,21 @@ impl ComposerRepository {
self.inner.add_package(package.into());
}
+ /// Forwards the outermost handle's weak to the inner `ArrayRepository` so that packages added
+ /// through `add_package` get the back-reference to this `ComposerRepository` wrapper.
+ pub fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ *self.self_weak.borrow_mut() = Some(weak.clone());
+ self.inner.set_self_handle(weak);
+ }
+
+ fn self_handle(&self) -> Option<RepositoryInterfaceHandle> {
+ self.self_weak
+ .borrow()
+ .as_ref()
+ .and_then(std::rc::Weak::upgrade)
+ .map(RepositoryInterfaceHandle::from_rc)
+ }
+
/// @param packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded
fn load_async_packages(
&mut self,
@@ -1976,11 +2004,18 @@ impl ComposerRepository {
let loaded_packages: Vec<BasePackageHandle> =
ComposerRepository::create_packages_static(versions_to_load, packages_source)?;
+ let self_handle = self.self_handle();
for package in loaded_packages.into_iter() {
- // TODO(phase-c): wire the repository back-reference onto the shared package handle.
+ if let Some(h) = self_handle.as_ref() {
+ package.set_repository(h.clone())?;
+ }
let hash_c = package.ptr_id().to_string();
if let Some(alias) = package.as_alias() {
let aliased = alias.get_alias_of();
+ if let Some(h) = self_handle.as_ref() {
+ let aliased_pkg: PackageInterfaceHandle = aliased.clone().into();
+ aliased_pkg.set_repository(h.clone())?;
+ }
let aliased_hash = aliased.ptr_id().to_string();
if !packages.contains_key(&aliased_hash) {
packages.insert(aliased_hash, aliased.into());
diff --git a/crates/shirabe/src/repository/composite_repository.rs b/crates/shirabe/src/repository/composite_repository.rs
index 12f1837..6c167f2 100644
--- a/crates/shirabe/src/repository/composite_repository.rs
+++ b/crates/shirabe/src/repository/composite_repository.rs
@@ -8,16 +8,17 @@ use shirabe_semver::constraint::AnyConstraint;
use crate::package::BasePackageHandle;
use crate::package::PackageInterfaceHandle;
use crate::repository::{
- FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult,
+ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
+ RepositoryInterfaceHandle, SearchResult,
};
#[derive(Debug)]
pub struct CompositeRepository {
- repositories: Vec<Box<dyn RepositoryInterface>>,
+ repositories: Vec<RepositoryInterfaceHandle>,
}
impl CompositeRepository {
- pub fn new(repositories: Vec<Box<dyn RepositoryInterface>>) -> Self {
+ pub fn new(repositories: Vec<RepositoryInterfaceHandle>) -> Self {
let mut this = Self {
repositories: vec![],
};
@@ -27,7 +28,7 @@ impl CompositeRepository {
this
}
- pub fn get_repositories(&self) -> &Vec<Box<dyn RepositoryInterface>> {
+ pub fn get_repositories(&self) -> &Vec<RepositoryInterfaceHandle> {
&self.repositories
}
@@ -39,10 +40,17 @@ impl CompositeRepository {
}
}
- pub fn add_repository(&mut self, repository: Box<dyn RepositoryInterface>) {
- if let Some(composite) = repository.as_any().downcast_ref::<CompositeRepository>() {
- for repo in composite.get_repositories() {
- self.repositories.push(repo.clone_box());
+ pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) {
+ let nested: Option<Vec<RepositoryInterfaceHandle>> = {
+ let repo_ref = repository.borrow();
+ repo_ref
+ .as_any()
+ .downcast_ref::<CompositeRepository>()
+ .map(|composite| composite.get_repositories().clone())
+ };
+ if let Some(nested) = nested {
+ for repo in nested {
+ self.repositories.push(repo);
}
} else {
self.repositories.push(repository);
@@ -163,6 +171,6 @@ impl RepositoryInterface for CompositeRepository {
}
fn as_any(&self) -> &dyn std::any::Any {
- todo!()
+ self
}
}
diff --git a/crates/shirabe/src/repository/filesystem_repository.rs b/crates/shirabe/src/repository/filesystem_repository.rs
index 8232ecf..a721b4f 100644
--- a/crates/shirabe/src/repository/filesystem_repository.rs
+++ b/crates/shirabe/src/repository/filesystem_repository.rs
@@ -78,6 +78,10 @@ impl FilesystemRepository {
self.dev_mode
}
+ pub fn set_self_handle(&self, weak: crate::repository::RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
+
pub fn get_repo_name(&self) -> String {
format!("file ({})", self.file.get_path())
}
diff --git a/crates/shirabe/src/repository/filter_repository.rs b/crates/shirabe/src/repository/filter_repository.rs
index 2a339f5..ecf1f0f 100644
--- a/crates/shirabe/src/repository/filter_repository.rs
+++ b/crates/shirabe/src/repository/filter_repository.rs
@@ -5,7 +5,8 @@ use crate::package::PackageInterfaceHandle;
use crate::package::base_package::{self};
use crate::repository::{AdvisoryProviderInterface, SecurityAdvisoryResult};
use crate::repository::{
- FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult,
+ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
+ RepositoryInterfaceHandle, SearchResult,
};
use anyhow::Result;
use indexmap::IndexMap;
@@ -18,12 +19,12 @@ pub struct FilterRepository {
only: Option<String>,
exclude: Option<String>,
canonical: bool,
- repo: Box<dyn RepositoryInterface>,
+ repo: RepositoryInterfaceHandle,
}
impl FilterRepository {
pub fn new(
- repo: Box<dyn RepositoryInterface>,
+ repo: RepositoryInterfaceHandle,
options: IndexMap<String, PhpMixed>,
) -> Result<Self> {
let mut only: Option<String> = None;
@@ -126,8 +127,8 @@ impl FilterRepository {
})
}
- pub fn get_repository(&self) -> &dyn RepositoryInterface {
- self.repo.as_ref()
+ pub fn get_repository(&self) -> RepositoryInterfaceHandle {
+ self.repo.clone()
}
fn is_allowed(&self, name: &str) -> bool {
@@ -254,7 +255,13 @@ impl RepositoryInterface for FilterRepository {
}
fn as_advisory_provider(&self) -> Option<&dyn AdvisoryProviderInterface> {
- self.repo.as_advisory_provider()
+ // FilterRepository is itself an advisory provider (it filters), but only meaningfully so
+ // when the wrapped repository provides advisories.
+ if self.repo.borrow().as_advisory_provider().is_some() {
+ Some(self)
+ } else {
+ None
+ }
}
fn as_any(&self) -> &dyn std::any::Any {
@@ -264,7 +271,8 @@ impl RepositoryInterface for FilterRepository {
impl AdvisoryProviderInterface for FilterRepository {
fn has_security_advisories(&self) -> bool {
- if let Some(advisory_repo) = self.repo.as_advisory_provider() {
+ let repo = self.repo.borrow();
+ if let Some(advisory_repo) = repo.as_advisory_provider() {
advisory_repo.has_security_advisories()
} else {
false
@@ -276,7 +284,8 @@ impl AdvisoryProviderInterface for FilterRepository {
mut package_constraint_map: IndexMap<String, AnyConstraint>,
allow_partial_advisories: bool,
) -> anyhow::Result<SecurityAdvisoryResult> {
- if let Some(advisory_repo) = self.repo.as_advisory_provider() {
+ let repo = self.repo.borrow();
+ if let Some(advisory_repo) = repo.as_advisory_provider() {
package_constraint_map.retain(|name, _| self.is_allowed(name));
advisory_repo.get_security_advisories(package_constraint_map, allow_partial_advisories)
} else {
diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs
new file mode 100644
index 0000000..f7a4104
--- /dev/null
+++ b/crates/shirabe/src/repository/handle.rs
@@ -0,0 +1,174 @@
+//! Shared handle over `RepositoryInterface`.
+
+use std::cell::{Ref, RefCell, RefMut};
+use std::rc::{Rc, Weak};
+
+use indexmap::IndexMap;
+use shirabe_php_shim::Countable;
+use shirabe_semver::constraint::AnyConstraint;
+
+use crate::package::BasePackageHandle;
+use crate::package::PackageInterfaceHandle;
+use crate::repository::{
+ FindPackageConstraint, InstalledRepositoryInterface, LoadPackagesResult, ProviderInfo,
+ RepositoryInterface, SearchResult, WritableRepositoryInterface,
+};
+
+/// Shared reference to a repository. Corresponds to PHP `RepositoryInterface`.
+#[derive(Debug, Clone)]
+pub struct RepositoryInterfaceHandle(Rc<RefCell<dyn RepositoryInterface>>);
+
+/// Weak back-reference held by packages to the repository that owns them.
+pub type RepositoryInterfaceWeakHandle = Weak<RefCell<dyn RepositoryInterface>>;
+
+impl RepositoryInterfaceHandle {
+ /// Wraps a concrete repository in a shared handle and injects its own weak reference so that
+ /// `add_package` can wire package -> repository back-references (PHP `setRepository($this)`).
+ pub fn new<T: RepositoryInterface + 'static>(repository: T) -> Self {
+ let rc: Rc<RefCell<dyn RepositoryInterface>> = Rc::new(RefCell::new(repository));
+ rc.borrow().set_self_handle(Rc::downgrade(&rc));
+ Self(rc)
+ }
+
+ pub fn from_rc(rc: Rc<RefCell<dyn RepositoryInterface>>) -> Self {
+ Self(rc)
+ }
+
+ pub fn as_rc(&self) -> &Rc<RefCell<dyn RepositoryInterface>> {
+ &self.0
+ }
+
+ pub fn downgrade(&self) -> RepositoryInterfaceWeakHandle {
+ Rc::downgrade(&self.0)
+ }
+
+ pub fn borrow(&self) -> Ref<'_, dyn RepositoryInterface> {
+ self.0.borrow()
+ }
+
+ pub fn borrow_mut(&self) -> RefMut<'_, dyn RepositoryInterface> {
+ self.0.borrow_mut()
+ }
+
+ /// PHP `===` (reference identity).
+ pub fn ptr_eq(&self, other: &Self) -> bool {
+ Rc::ptr_eq(&self.0, &other.0)
+ }
+
+ /// Stable identity usable as a map key (PHP `spl_object_hash`).
+ pub fn ptr_id(&self) -> usize {
+ Rc::as_ptr(&self.0) as *const () as usize
+ }
+
+ /// PHP `instanceof T` for a concrete repository type. Keeps the `RefCell` borrow internal.
+ pub fn is<T: RepositoryInterface + 'static>(&self) -> bool {
+ self.0.borrow().as_any().is::<T>()
+ }
+
+ pub fn count(&self) -> i64 {
+ self.0.borrow().count()
+ }
+
+ pub fn get_repo_name(&self) -> String {
+ self.0.borrow().get_repo_name()
+ }
+
+ pub fn get_packages(&self) -> Vec<BasePackageHandle> {
+ self.0.borrow().get_packages()
+ }
+
+ pub fn has_package(&self, package: PackageInterfaceHandle) -> bool {
+ self.0.borrow().has_package(package)
+ }
+
+ pub fn find_package(
+ &self,
+ name: &str,
+ constraint: FindPackageConstraint,
+ ) -> Option<BasePackageHandle> {
+ self.0.borrow().find_package(name, constraint)
+ }
+
+ pub fn find_packages(
+ &self,
+ name: &str,
+ constraint: Option<FindPackageConstraint>,
+ ) -> Vec<BasePackageHandle> {
+ self.0.borrow().find_packages(name, constraint)
+ }
+
+ pub 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, PackageInterfaceHandle>>,
+ ) -> LoadPackagesResult {
+ self.0.borrow().load_packages(
+ package_name_map,
+ acceptable_stabilities,
+ stability_flags,
+ already_loaded,
+ )
+ }
+
+ pub fn search(&self, query: String, mode: i64, r#type: Option<String>) -> Vec<SearchResult> {
+ self.0.borrow().search(query, mode, r#type)
+ }
+
+ pub fn get_providers(&self, package_name: String) -> IndexMap<String, ProviderInfo> {
+ self.0.borrow().get_providers(package_name)
+ }
+
+ // --- InstalledRepositoryInterface helpers (valid only when the wrapped repository is one) ---
+
+ pub fn is_fresh(&self) -> bool {
+ self.0
+ .borrow()
+ .as_installed_repository_interface()
+ .map_or(false, |r| r.is_fresh())
+ }
+
+ pub fn get_dev_mode(&self) -> Option<bool> {
+ self.0
+ .borrow()
+ .as_installed_repository_interface()
+ .and_then(|r| r.get_dev_mode())
+ }
+
+ pub fn get_canonical_packages(&self) -> Vec<PackageInterfaceHandle> {
+ self.0
+ .borrow()
+ .as_installed_repository_interface()
+ .map(|r| r.get_canonical_packages())
+ .unwrap_or_default()
+ }
+
+ pub fn get_dev_package_names(&self) -> Vec<String> {
+ self.0
+ .borrow()
+ .as_installed_repository_interface()
+ .map(|r| r.get_dev_package_names().clone())
+ .unwrap_or_default()
+ }
+
+ pub fn set_dev_package_names(&self, dev_package_names: Vec<String>) {
+ if let Some(r) = self.0.borrow_mut().as_installed_repository_interface_mut() {
+ r.set_dev_package_names(dev_package_names);
+ }
+ }
+}
+
+impl PartialEq for RepositoryInterfaceHandle {
+ fn eq(&self, other: &Self) -> bool {
+ Rc::ptr_eq(&self.0, &other.0)
+ }
+}
+
+impl Eq for RepositoryInterfaceHandle {}
+
+impl std::hash::Hash for RepositoryInterfaceHandle {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.ptr_id().hash(state);
+ }
+}
diff --git a/crates/shirabe/src/repository/installed_array_repository.rs b/crates/shirabe/src/repository/installed_array_repository.rs
index ca2d8c7..1520497 100644
--- a/crates/shirabe/src/repository/installed_array_repository.rs
+++ b/crates/shirabe/src/repository/installed_array_repository.rs
@@ -133,7 +133,18 @@ impl RepositoryInterface for InstalledArrayRepository {
fn as_advisory_provider(&self) -> Option<&dyn AdvisoryProviderInterface> {
None
}
+ fn as_installed_repository_interface(&self) -> Option<&dyn InstalledRepositoryInterface> {
+ Some(self)
+ }
+ fn as_installed_repository_interface_mut(
+ &mut self,
+ ) -> Option<&mut dyn InstalledRepositoryInterface> {
+ Some(self)
+ }
fn as_any(&self) -> &dyn std::any::Any {
todo!()
}
+ fn set_self_handle(&self, weak: crate::repository::RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
}
diff --git a/crates/shirabe/src/repository/installed_filesystem_repository.rs b/crates/shirabe/src/repository/installed_filesystem_repository.rs
index 352d86f..73a9f1a 100644
--- a/crates/shirabe/src/repository/installed_filesystem_repository.rs
+++ b/crates/shirabe/src/repository/installed_filesystem_repository.rs
@@ -143,7 +143,18 @@ impl RepositoryInterface for InstalledFilesystemRepository {
fn as_advisory_provider(&self) -> Option<&dyn AdvisoryProviderInterface> {
None
}
+ fn as_installed_repository_interface(&self) -> Option<&dyn InstalledRepositoryInterface> {
+ Some(self)
+ }
+ fn as_installed_repository_interface_mut(
+ &mut self,
+ ) -> Option<&mut dyn InstalledRepositoryInterface> {
+ Some(self)
+ }
fn as_any(&self) -> &dyn std::any::Any {
todo!()
}
+ fn set_self_handle(&self, weak: crate::repository::RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
}
diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs
index 486d4bd..b857bc2 100644
--- a/crates/shirabe/src/repository/installed_repository.rs
+++ b/crates/shirabe/src/repository/installed_repository.rs
@@ -16,7 +16,8 @@ use crate::repository::LockArrayRepository;
use crate::repository::PlatformRepository;
use crate::repository::RootPackageRepository;
use crate::repository::{
- FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult,
+ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
+ RepositoryInterfaceHandle, SearchResult,
};
pub enum NeedleInput {
@@ -36,7 +37,7 @@ pub struct InstalledRepository {
}
impl InstalledRepository {
- pub fn new(repositories: Vec<Box<dyn RepositoryInterface>>) -> Self {
+ pub fn new(repositories: Vec<RepositoryInterfaceHandle>) -> Self {
let mut this = Self {
inner: CompositeRepository::new(vec![]),
};
@@ -381,25 +382,21 @@ impl InstalledRepository {
results
}
- pub fn add_repository(
- &mut self,
- repository: Box<dyn RepositoryInterface>,
- ) -> anyhow::Result<()> {
- // TODO(phase-b): cannot Any::is::<dyn InstalledRepositoryInterface>; replace with a
- // dedicated downcast/marker method on RepositoryInterface.
- if repository.as_any().is::<LockArrayRepository>()
- || repository.as_any().is::<RootPackageRepository>()
- || repository.as_any().is::<PlatformRepository>()
+ pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) -> anyhow::Result<()> {
+ if repository.is::<LockArrayRepository>()
+ || repository.is::<RootPackageRepository>()
+ || repository.is::<PlatformRepository>()
{
self.inner.add_repository(repository);
return Ok(());
}
+ let type_name = std::any::type_name_of_val(&*repository.borrow()).to_string();
+ let repo_name = repository.get_repo_name();
Err(anyhow::anyhow!(LogicException {
message: format!(
"An InstalledRepository can not contain a repository of type {} ({})",
- std::any::type_name_of_val(&*repository),
- repository.get_repo_name(),
+ type_name, repo_name,
),
code: 0,
}))
diff --git a/crates/shirabe/src/repository/lock_array_repository.rs b/crates/shirabe/src/repository/lock_array_repository.rs
index cbc8564..f9b64a7 100644
--- a/crates/shirabe/src/repository/lock_array_repository.rs
+++ b/crates/shirabe/src/repository/lock_array_repository.rs
@@ -5,7 +5,8 @@ use crate::package::PackageInterfaceHandle;
use crate::repository::ArrayRepository;
use crate::repository::CanonicalPackagesTrait;
use crate::repository::{
- FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface, SearchResult,
+ FindPackageConstraint, LoadPackagesResult, ProviderInfo, RepositoryInterface,
+ RepositoryInterfaceWeakHandle, SearchResult,
};
use indexmap::IndexMap;
use shirabe_php_shim::Countable;
@@ -89,4 +90,8 @@ impl RepositoryInterface for LockArrayRepository {
fn as_any(&self) -> &dyn std::any::Any {
self
}
+
+ fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
}
diff --git a/crates/shirabe/src/repository/mod.rs b/crates/shirabe/src/repository/mod.rs
index 6f037d0..d678764 100644
--- a/crates/shirabe/src/repository/mod.rs
+++ b/crates/shirabe/src/repository/mod.rs
@@ -7,6 +7,7 @@ pub mod composite_repository;
pub mod configurable_repository_interface;
pub mod filesystem_repository;
pub mod filter_repository;
+pub mod handle;
pub mod installed_array_repository;
pub mod installed_filesystem_repository;
pub mod installed_repository;
@@ -39,6 +40,7 @@ pub use composite_repository::*;
pub use configurable_repository_interface::*;
pub use filesystem_repository::*;
pub use filter_repository::*;
+pub use handle::*;
pub use installed_array_repository::*;
pub use installed_filesystem_repository::*;
pub use installed_repository::*;
diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs
index 1b95ff7..b8c4f52 100644
--- a/crates/shirabe/src/repository/platform_repository.rs
+++ b/crates/shirabe/src/repository/platform_repository.rs
@@ -2012,4 +2012,8 @@ impl crate::repository::RepositoryInterface for PlatformRepository {
fn as_any(&self) -> &dyn std::any::Any {
self
}
+
+ fn set_self_handle(&self, weak: crate::repository::RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
}
diff --git a/crates/shirabe/src/repository/repository_factory.rs b/crates/shirabe/src/repository/repository_factory.rs
index 908704c..1159da1 100644
--- a/crates/shirabe/src/repository/repository_factory.rs
+++ b/crates/shirabe/src/repository/repository_factory.rs
@@ -12,7 +12,7 @@ use crate::factory::Factory;
use crate::io::IOInterface;
use crate::json::JsonFile;
use crate::repository::FilesystemRepository;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use crate::repository::RepositoryManager;
use crate::util::HttpDownloader;
use crate::util::ProcessExecutor;
@@ -102,7 +102,7 @@ impl RepositoryFactory {
repository: &str,
allow_filesystem: bool,
rm: Option<&mut RepositoryManager>,
- ) -> anyhow::Result<Box<dyn RepositoryInterface>> {
+ ) -> anyhow::Result<RepositoryInterfaceHandle> {
let repo_config =
Self::config_from_string(io.clone(), config, repository, allow_filesystem)?;
Self::create_repo(io, config, repo_config, rm)
@@ -113,7 +113,7 @@ impl RepositoryFactory {
config: &std::rc::Rc<std::cell::RefCell<Config>>,
repo_config: IndexMap<String, PhpMixed>,
rm: Option<&mut RepositoryManager>,
- ) -> anyhow::Result<Box<dyn RepositoryInterface>> {
+ ) -> anyhow::Result<RepositoryInterfaceHandle> {
let mut owned_rm;
let rm = if let Some(rm) = rm {
rm
@@ -145,7 +145,7 @@ impl RepositoryFactory {
io: Option<std::rc::Rc<std::cell::RefCell<dyn IOInterface>>>,
config: Option<std::rc::Rc<std::cell::RefCell<Config>>>,
rm: Option<&mut RepositoryManager>,
- ) -> anyhow::Result<IndexMap<String, Box<dyn RepositoryInterface>>> {
+ ) -> anyhow::Result<IndexMap<String, RepositoryInterfaceHandle>> {
let config = match config {
Some(c) => c,
None => std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?)),
@@ -233,7 +233,7 @@ impl RepositoryFactory {
pub fn default_repos_with_default_manager(
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- ) -> anyhow::Result<IndexMap<String, Box<dyn RepositoryInterface>>> {
+ ) -> anyhow::Result<IndexMap<String, RepositoryInterfaceHandle>> {
let config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(
Some(io.clone()),
None,
@@ -247,8 +247,8 @@ impl RepositoryFactory {
fn create_repos(
rm: &mut RepositoryManager,
repo_configs: Vec<PhpMixed>,
- ) -> anyhow::Result<IndexMap<String, Box<dyn RepositoryInterface>>> {
- let mut repo_map: IndexMap<String, Box<dyn RepositoryInterface>> = IndexMap::new();
+ ) -> anyhow::Result<IndexMap<String, RepositoryInterfaceHandle>> {
+ let mut repo_map: IndexMap<String, RepositoryInterfaceHandle> = IndexMap::new();
for (index, repo) in repo_configs.into_iter().enumerate() {
match &repo {
@@ -290,7 +290,7 @@ impl RepositoryFactory {
.to_string();
// TODO(phase-b): FilesystemRepository does not yet implement
// RepositoryInterface; once it does, construct it from JsonFile here.
- let created: Box<dyn RepositoryInterface> =
+ let created: RepositoryInterfaceHandle =
todo!("FilesystemRepository as dyn RepositoryInterface");
repo_map.insert(name, created);
} else {
@@ -323,7 +323,7 @@ impl RepositoryFactory {
pub fn generate_repository_name(
index: &PhpMixed,
repo: &IndexMap<String, PhpMixed>,
- existing_repos: &IndexMap<String, Box<dyn RepositoryInterface>>,
+ existing_repos: &IndexMap<String, RepositoryInterfaceHandle>,
) -> String {
let mut name = match index {
PhpMixed::Int(_) => {
@@ -344,7 +344,7 @@ impl RepositoryFactory {
fn generate_repository_name_indexed(
index: usize,
repo: &IndexMap<String, PhpMixed>,
- existing_repos: &IndexMap<String, Box<dyn RepositoryInterface>>,
+ existing_repos: &IndexMap<String, RepositoryInterfaceHandle>,
) -> String {
let mut name = if let Some(url) = repo.get("url").and_then(|v| v.as_string()) {
Preg::replace("{^https?://}i", "", url).unwrap_or_else(|_| url.to_string())
diff --git a/crates/shirabe/src/repository/repository_interface.rs b/crates/shirabe/src/repository/repository_interface.rs
index 316f509..21914f6 100644
--- a/crates/shirabe/src/repository/repository_interface.rs
+++ b/crates/shirabe/src/repository/repository_interface.rs
@@ -93,8 +93,23 @@ pub trait RepositoryInterface: Countable + std::fmt::Debug {
None
}
+ fn as_installed_repository_interface_mut(
+ &mut self,
+ ) -> Option<&mut dyn crate::repository::InstalledRepositoryInterface> {
+ None
+ }
+
fn as_any(&self) -> &dyn std::any::Any;
+ /// Injects this repository's own weak handle so that `add_package` can wire package ->
+ /// repository back-references (PHP `setRepository($this)`). Called once when the repository is
+ /// wrapped in a [`RepositoryInterfaceHandle`](crate::repository::RepositoryInterfaceHandle).
+ /// Wrapper repositories forward the same weak (the outermost handle) to their inner
+ /// `ArrayRepository`.
+ fn set_self_handle(&self, weak: crate::repository::RepositoryInterfaceWeakHandle) {
+ let _ = weak;
+ }
+
fn clone_box(&self) -> Box<dyn RepositoryInterface> {
todo!()
}
diff --git a/crates/shirabe/src/repository/repository_manager.rs b/crates/shirabe/src/repository/repository_manager.rs
index 72c3643..dd69731 100644
--- a/crates/shirabe/src/repository/repository_manager.rs
+++ b/crates/shirabe/src/repository/repository_manager.rs
@@ -10,15 +10,14 @@ use crate::io::IOInterface;
use crate::io::IOInterfaceImmutable;
use crate::package::PackageInterfaceHandle;
use crate::repository::FilterRepository;
-use crate::repository::InstalledRepositoryInterface;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use crate::util::HttpDownloader;
use crate::util::ProcessExecutor;
#[derive(Debug)]
pub struct RepositoryManager {
- local_repository: Option<Box<dyn InstalledRepositoryInterface>>,
- repositories: Vec<Box<dyn RepositoryInterface>>,
+ local_repository: Option<RepositoryInterfaceHandle>,
+ repositories: Vec<RepositoryInterfaceHandle>,
repository_classes: IndexMap<String, String>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: std::rc::Rc<std::cell::RefCell<Config>>,
@@ -62,7 +61,7 @@ impl RepositoryManager {
name,
crate::repository::FindPackageConstraint::Constraint(constraint.clone()),
) {
- return Some(package.clone().into());
+ return Some(package.into());
}
}
None
@@ -81,17 +80,17 @@ impl RepositoryManager {
constraint.clone(),
)),
) {
- packages.push(p.clone().into());
+ packages.push(p);
}
}
packages
}
- pub fn add_repository(&mut self, repository: Box<dyn RepositoryInterface>) {
+ pub fn add_repository(&mut self, repository: RepositoryInterfaceHandle) {
self.repositories.push(repository);
}
- pub fn prepend_repository(&mut self, repository: Box<dyn RepositoryInterface>) {
+ pub fn prepend_repository(&mut self, repository: RepositoryInterfaceHandle) {
self.repositories.insert(0, repository);
}
@@ -100,7 +99,7 @@ impl RepositoryManager {
r#type: &str,
config: IndexMap<String, PhpMixed>,
name: Option<&str>,
- ) -> anyhow::Result<Box<dyn RepositoryInterface>> {
+ ) -> anyhow::Result<RepositoryInterfaceHandle> {
if !self.repository_classes.contains_key(r#type) {
return Err(InvalidArgumentException {
message: format!("Repository type is not registered: {}", r#type),
@@ -140,7 +139,10 @@ impl RepositoryManager {
let repository = self.create_repository_by_class(&class, cleaned_config)?;
if let Some(filter_config) = filter_config {
- return Ok(Box::new(FilterRepository::new(repository, filter_config)?));
+ return Ok(RepositoryInterfaceHandle::new(FilterRepository::new(
+ repository,
+ filter_config,
+ )?));
}
Ok(repository)
@@ -150,7 +152,7 @@ impl RepositoryManager {
&self,
_class: &str,
_config: IndexMap<String, PhpMixed>,
- ) -> anyhow::Result<Box<dyn RepositoryInterface>> {
+ ) -> anyhow::Result<RepositoryInterfaceHandle> {
todo!("Phase B: dynamic class instantiation by class name")
}
@@ -159,15 +161,15 @@ impl RepositoryManager {
.insert(r#type.to_string(), class.to_string());
}
- pub fn get_repositories(&self) -> &Vec<Box<dyn RepositoryInterface>> {
+ pub fn get_repositories(&self) -> &Vec<RepositoryInterfaceHandle> {
&self.repositories
}
- pub fn set_local_repository(&mut self, repository: Box<dyn InstalledRepositoryInterface>) {
+ pub fn set_local_repository(&mut self, repository: RepositoryInterfaceHandle) {
self.local_repository = Some(repository);
}
- pub fn get_local_repository(&self) -> &dyn InstalledRepositoryInterface {
- self.local_repository.as_ref().unwrap().as_ref()
+ pub fn get_local_repository(&self) -> RepositoryInterfaceHandle {
+ self.local_repository.clone().unwrap()
}
}
diff --git a/crates/shirabe/src/repository/repository_set.rs b/crates/shirabe/src/repository/repository_set.rs
index 3a81eda..f4a4057 100644
--- a/crates/shirabe/src/repository/repository_set.rs
+++ b/crates/shirabe/src/repository/repository_set.rs
@@ -35,7 +35,7 @@ use crate::repository::InstalledRepositoryInterface;
use crate::repository::LockArrayRepository;
use crate::repository::PlatformRepository;
use crate::repository::{AdvisoryProviderInterface, PartialOrSecurityAdvisory};
-use crate::repository::{FindPackageConstraint, RepositoryInterface};
+use crate::repository::{FindPackageConstraint, RepositoryInterface, RepositoryInterfaceHandle};
#[derive(Debug, Clone)]
pub struct RootAliasEntry {
@@ -66,7 +66,7 @@ pub struct RepositorySet {
pub(crate) root_references: IndexMap<String, String>,
/// @var RepositoryInterface[]
- pub(crate) repositories: Vec<Box<dyn RepositoryInterface>>,
+ pub(crate) repositories: Vec<RepositoryInterfaceHandle>,
/// @var int[] array of stability => BasePackage::STABILITY_* value
/// @phpstan-var array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>
@@ -170,7 +170,7 @@ impl RepositorySet {
/// repository the search for that package ends, and following repos will not be consulted.
///
/// @param RepositoryInterface $repo A package repository
- pub fn add_repository(&mut self, repo: Box<dyn RepositoryInterface>) -> Result<()> {
+ pub fn add_repository(&mut self, repo: RepositoryInterfaceHandle) -> Result<()> {
if self.locked {
return Err(RuntimeException {
message: "Pool has already been created from this repository set, it cannot be modified anymore.".to_string(),
@@ -179,17 +179,15 @@ impl RepositorySet {
.into());
}
- let repos: Vec<Box<dyn RepositoryInterface>> =
- if let Some(composite) = repo.as_any().downcast_ref::<CompositeRepository>() {
- // TODO(phase-b): clone composite.get_repositories() — Box<dyn RepositoryInterface> cloning
- composite
- .get_repositories()
- .iter()
- .map(|r| r.clone_box())
- .collect()
+ let repos: Vec<RepositoryInterfaceHandle> = {
+ let repo_ref = repo.borrow();
+ if let Some(composite) = repo_ref.as_any().downcast_ref::<CompositeRepository>() {
+ composite.get_repositories().clone()
} else {
+ drop(repo_ref);
vec![repo]
- };
+ }
+ };
for repo in repos {
self.repositories.push(repo);
@@ -379,7 +377,8 @@ impl RepositorySet {
for repository in &self.repositories {
// TODO(phase-b): use anyhow::Result<Result<T, E>> to model PHP try/catch
let attempt: Result<()> = (|| -> Result<()> {
- let Some(advisory_repo) = repository.as_advisory_provider() else {
+ let repo_ref = repository.borrow();
+ let Some(advisory_repo) = repo_ref.as_advisory_provider() else {
return Ok(());
};
if !advisory_repo.has_security_advisories() {
@@ -480,11 +479,11 @@ impl RepositorySet {
pool_builder.set_allowed_types(allowed_types);
for repo in &self.repositories {
- let is_installed = repo.as_installed_repository_interface().is_some()
- || repo
- .as_any()
- .downcast_ref::<InstalledRepository>()
- .is_some();
+ let is_installed = {
+ let repo_ref = repo.borrow();
+ repo_ref.as_installed_repository_interface().is_some()
+ || repo_ref.as_any().is::<InstalledRepository>()
+ };
if is_installed && !self.allow_installed_repositories {
return Err(LogicException {
message: "The pool can not accept packages from an installed repository"
@@ -507,11 +506,11 @@ impl RepositorySet {
/// Create a pool for dependency resolution from the packages in this repository set.
pub fn create_pool_with_all_packages(&mut self) -> Result<Pool> {
for repo in &self.repositories {
- let is_installed = repo.as_installed_repository_interface().is_some()
- || repo
- .as_any()
- .downcast_ref::<InstalledRepository>()
- .is_some();
+ let is_installed = {
+ let repo_ref = repo.borrow();
+ repo_ref.as_installed_repository_interface().is_some()
+ || repo_ref.as_any().is::<InstalledRepository>()
+ };
if is_installed && !self.allow_installed_repositories {
return Err(LogicException {
message: "The pool can not accept packages from an installed repository"
diff --git a/crates/shirabe/src/repository/repository_utils.rs b/crates/shirabe/src/repository/repository_utils.rs
index 667cea2..4522039 100644
--- a/crates/shirabe/src/repository/repository_utils.rs
+++ b/crates/shirabe/src/repository/repository_utils.rs
@@ -3,7 +3,7 @@
use crate::package::Link;
use crate::repository::CompositeRepository;
use crate::repository::FilterRepository;
-use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceHandle;
use indexmap::IndexMap;
use std::any::Any;
@@ -39,23 +39,31 @@ impl RepositoryUtils {
}
pub fn flatten_repositories(
- repo: Box<dyn RepositoryInterface>,
+ repo: RepositoryInterfaceHandle,
unwrap_filter_repos: bool,
- ) -> Vec<Box<dyn RepositoryInterface>> {
- let repo: Box<dyn RepositoryInterface> = if unwrap_filter_repos {
- if let Some(filter_repo) = repo.as_any().downcast_ref::<FilterRepository>() {
- filter_repo.get_repository().clone_box()
- } else {
- repo
- }
+ ) -> Vec<RepositoryInterfaceHandle> {
+ let repo: RepositoryInterfaceHandle = if unwrap_filter_repos {
+ let unwrapped = {
+ let r = repo.borrow();
+ r.as_any()
+ .downcast_ref::<FilterRepository>()
+ .map(|filter_repo| filter_repo.get_repository())
+ };
+ unwrapped.unwrap_or(repo)
} else {
repo
};
- if let Some(composite_repo) = repo.as_any().downcast_ref::<CompositeRepository>() {
+ let nested = {
+ let r = repo.borrow();
+ r.as_any()
+ .downcast_ref::<CompositeRepository>()
+ .map(|composite_repo| composite_repo.get_repositories().clone())
+ };
+ if let Some(nested) = nested {
let mut repos = Vec::new();
- for r in composite_repo.get_repositories() {
- for r2 in Self::flatten_repositories(r.clone_box(), unwrap_filter_repos) {
+ for r in nested {
+ for r2 in Self::flatten_repositories(r, unwrap_filter_repos) {
repos.push(r2);
}
}
diff --git a/crates/shirabe/src/repository/root_package_repository.rs b/crates/shirabe/src/repository/root_package_repository.rs
index cb01a7c..22ca437 100644
--- a/crates/shirabe/src/repository/root_package_repository.rs
+++ b/crates/shirabe/src/repository/root_package_repository.rs
@@ -4,6 +4,7 @@ use crate::package::BasePackageHandle;
use crate::package::PackageInterfaceHandle;
use crate::package::RootPackageInterfaceHandle;
use crate::repository::ArrayRepository;
+use crate::repository::RepositoryInterfaceWeakHandle;
use crate::repository::{ProviderInfo, RepositoryInterface, SearchResult};
use indexmap::IndexMap;
@@ -85,4 +86,8 @@ impl RepositoryInterface for RootPackageRepository {
fn as_any(&self) -> &dyn std::any::Any {
self
}
+
+ fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
}
diff --git a/crates/shirabe/src/repository/writable_array_repository.rs b/crates/shirabe/src/repository/writable_array_repository.rs
index 282f3c0..ac9df8f 100644
--- a/crates/shirabe/src/repository/writable_array_repository.rs
+++ b/crates/shirabe/src/repository/writable_array_repository.rs
@@ -3,6 +3,7 @@
use crate::installer::InstallationManager;
use crate::repository::ArrayRepository;
use crate::repository::RepositoryInterface;
+use crate::repository::RepositoryInterfaceWeakHandle;
use anyhow::Result;
use shirabe_php_shim::Countable;
@@ -52,6 +53,10 @@ impl WritableArrayRepository {
self.inner.add_package(package)
}
+ pub fn set_self_handle(&self, weak: RepositoryInterfaceWeakHandle) {
+ self.inner.set_self_handle(weak);
+ }
+
pub fn remove_package(
&mut self,
package: crate::package::PackageInterfaceHandle,