aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-29 03:42:14 +0900
committernsfisis <nsfisis@gmail.com>2026-05-29 03:42:14 +0900
commit86fcc80b348a3f00ab81e5447924aa10202d95e8 (patch)
tree0bdb4f7bd11aab799230a97500a380401a93b77e
parent7f83e785a77fbdbcada9c6714703d4e5801af82a (diff)
downloadphp-shirabe-86fcc80b348a3f00ab81e5447924aa10202d95e8.tar.gz
php-shirabe-86fcc80b348a3f00ab81e5447924aa10202d95e8.tar.zst
php-shirabe-86fcc80b348a3f00ab81e5447924aa10202d95e8.zip
refactor(repository): introduce typed LockArrayRepositoryHandle
Share LockArrayRepository via Rc<RefCell<_>> while preserving the PHP ?LockArrayRepository type strength: Request.locked_repository, Locker ::get_locked_repository, and the installer create_* helpers now thread the typed handle instead of an owned LockArrayRepository, and pool builder identity check becomes a strict ptr_eq via widening into RepositoryInterfaceHandle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-rw-r--r--crates/shirabe/src/command/audit_command.rs6
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs4
-rw-r--r--crates/shirabe/src/command/bump_command.rs22
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs22
-rw-r--r--crates/shirabe/src/command/licenses_command.rs2
-rw-r--r--crates/shirabe/src/command/remove_command.rs1
-rw-r--r--crates/shirabe/src/command/require_command.rs17
-rw-r--r--crates/shirabe/src/command/show_command.rs5
-rw-r--r--crates/shirabe/src/command/suggests_command.rs2
-rw-r--r--crates/shirabe/src/command/update_command.rs6
-rw-r--r--crates/shirabe/src/dependency_resolver/pool_builder.rs24
-rw-r--r--crates/shirabe/src/dependency_resolver/request.rs13
-rw-r--r--crates/shirabe/src/installer.rs79
-rw-r--r--crates/shirabe/src/package/locker.rs16
-rw-r--r--crates/shirabe/src/repository/handle.rs63
-rw-r--r--crates/shirabe/src/repository/repository_set.rs6
16 files changed, 167 insertions, 121 deletions
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index 270bacb..786843e 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -157,9 +157,9 @@ impl AuditCommand {
}.into());
}
return Ok(CanonicalPackagesTrait::get_packages(
- &locker.get_locked_repository(
- !input.get_option("no-dev").as_bool().unwrap_or(false),
- )?,
+ &*locker
+ .get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?
+ .borrow(),
));
}
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index ad84953..0b89387 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -71,9 +71,7 @@ pub trait BaseDependencyCommand: BaseCommand {
}));
}
- repos.push(crate::repository::RepositoryInterfaceHandle::new(
- locker.get_locked_repository(true)?,
- ));
+ repos.push(locker.get_locked_repository(true)?.into());
let platform_overrides: IndexMap<String, PhpMixed> = locker
.get_platform_overrides()?
.into_iter()
diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs
index 64ec54b..b91a32a 100644
--- a/crates/shirabe/src/command/bump_command.rs
+++ b/crates/shirabe/src/command/bump_command.rs
@@ -143,12 +143,11 @@ impl BumpCommand {
.as_bool()
.unwrap_or(true);
let repo: crate::repository::RepositoryInterfaceHandle = if !has_lock_file_disabled {
- crate::repository::RepositoryInterfaceHandle::new(
- composer
- .get_locker()
- .borrow_mut()
- .get_locked_repository(true)?,
- )
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?
+ .into()
} else if composer.get_locker().borrow_mut().is_locked() {
if !composer.get_locker().borrow_mut().is_fresh()? {
io.write_error3(
@@ -158,12 +157,11 @@ impl BumpCommand {
);
return Ok(Self::ERROR_LOCK_OUTDATED);
}
- crate::repository::RepositoryInterfaceHandle::new(
- composer
- .get_locker()
- .borrow_mut()
- .get_locked_repository(true)?,
- )
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?
+ .into()
} else {
composer
.get_repository_manager()
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index 15e4225..e53727d 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -72,12 +72,11 @@ impl CheckPlatformReqsCommand {
"<info>Checking {}platform requirements using the lock file</info>",
if no_dev { "non-dev " } else { "" }
));
- crate::repository::RepositoryInterfaceHandle::new(
- composer
- .get_locker()
- .borrow_mut()
- .get_locked_repository(!no_dev)?,
- )
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(!no_dev)?
+ .into()
} else {
let repository_manager = composer.get_repository_manager().clone();
let repository_manager = repository_manager.borrow();
@@ -87,12 +86,11 @@ impl CheckPlatformReqsCommand {
"<warning>No vendor dir present, checking {}platform requirements from the lock file</warning>",
if no_dev { "non-dev " } else { "" }
));
- crate::repository::RepositoryInterfaceHandle::new(
- composer
- .get_locker()
- .borrow_mut()
- .get_locked_repository(!no_dev)?,
- )
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(!no_dev)?
+ .into()
} else {
if no_dev {
remove_packages = local_repo.get_dev_package_names();
diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs
index add5b0b..681ac7a 100644
--- a/crates/shirabe/src/command/licenses_command.rs
+++ b/crates/shirabe/src/command/licenses_command.rs
@@ -106,7 +106,7 @@ impl LicensesCommand {
}
let no_dev = input.get_option("no-dev").as_bool().unwrap_or(false);
let repo = locker.get_locked_repository(!no_dev)?;
- <crate::repository::LockArrayRepository as crate::repository::RepositoryInterface>::get_packages(&repo)
+ <crate::repository::LockArrayRepository as crate::repository::RepositoryInterface>::get_packages(&*repo.borrow())
} else {
let repository_manager = composer.get_repository_manager().clone();
let repository_manager = repository_manager.borrow();
diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs
index a393f0f..faab5fe 100644
--- a/crates/shirabe/src/command/remove_command.rs
+++ b/crates/shirabe/src/command/remove_command.rs
@@ -202,6 +202,7 @@ impl RemoveCommand {
.get_locker()
.borrow_mut()
.get_locked_repository(true)?
+ .borrow()
.get_packages();
let mut required: IndexMap<String, bool> = IndexMap::new();
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index f59d60f..bb90361 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -933,18 +933,17 @@ impl RequireCommand {
),
None,
)?;
- // TODO(phase-b): get_locked_repository returns LockArrayRepository (owned) and
- // get_local_repository returns &dyn InstalledRepositoryInterface; need a common
- // interface for find_package.
- let locked_repo;
- let repo: &dyn RepositoryInterface = if locker_is_locked {
- locked_repo = composer
+ let repo: crate::repository::RepositoryInterfaceHandle = if locker_is_locked {
+ composer
.get_locker()
.borrow_mut()
- .get_locked_repository(true)?;
- &locked_repo
+ .get_locked_repository(true)?
+ .into()
} else {
- todo!("convert &dyn InstalledRepositoryInterface to &dyn RepositoryInterface")
+ composer
+ .get_repository_manager()
+ .borrow()
+ .get_local_repository()
};
for package_name in requirements_to_update {
let mut package = repo.find_package(
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index 19e7712..781ee20 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -284,7 +284,8 @@ impl ShowCommand {
let locker_rc = composer_ref.get_locker().clone();
let mut locker = locker_rc.borrow_mut();
if locker.is_locked() {
- let lr_handle = RepositoryInterfaceHandle::new(locker.get_locked_repository(true)?);
+ let lr_handle: RepositoryInterfaceHandle =
+ locker.get_locked_repository(true)?.into();
installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
lr_handle.clone(),
local_repo,
@@ -348,7 +349,7 @@ impl ShowCommand {
let mut locker = locker_rc.borrow_mut();
let lr =
locker.get_locked_repository(input.get_option("no-dev").as_bool() != Some(true))?;
- let lr_handle = RepositoryInterfaceHandle::new(lr);
+ let lr_handle: RepositoryInterfaceHandle = lr.into();
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.
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index 5006790..0aead77 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -71,7 +71,7 @@ impl SuggestsCommand {
.get_locker()
.borrow_mut()
.get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?;
- installed_repos.push(RepositoryInterfaceHandle::new(locked_repo));
+ installed_repos.push(locked_repo.into());
} else {
// TODO(phase-b): Config::get returns PhpMixed; need to coerce to IndexMap<String, PhpMixed>
let _platform_cfg = composer.get_config().borrow().get("platform");
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index 22ce506..82f98a1 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -212,6 +212,7 @@ impl UpdateCommand {
.get_locker()
.borrow_mut()
.get_locked_repository(true)?
+ .borrow()
.get_canonical_packages()
{
if package.is_dev() {
@@ -500,10 +501,11 @@ impl UpdateCommand {
let installed_packages: Vec<crate::package::PackageInterfaceHandle> =
if composer_ref.get_locker().borrow_mut().is_locked() {
CanonicalPackagesTrait::get_packages(
- &composer_ref
+ &*composer_ref
.get_locker()
.borrow_mut()
- .get_locked_repository(true)?,
+ .get_locked_repository(true)?
+ .borrow(),
)
} else {
let _ = composer_ref
diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs
index 273d19f..a34c281 100644
--- a/crates/shirabe/src/dependency_resolver/pool_builder.rs
+++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs
@@ -34,7 +34,6 @@ 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;
@@ -163,9 +162,10 @@ impl PoolBuilder {
.into());
}
- for locked_package in
- CanonicalPackagesTrait::get_packages(request.get_locked_repository().unwrap())
- {
+ let locked_packages = CanonicalPackagesTrait::get_packages(
+ &*request.get_locked_repository().unwrap().borrow(),
+ );
+ for locked_package in locked_packages {
if !self.is_update_allowed(locked_package.clone()) {
// Path repo packages are never loaded from lock, to force them to always remain in sync
// unless symlinking is disabled in which case we probably should rather treat them like
@@ -491,13 +491,9 @@ 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
- // 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>();
+ let is_locked_repo = request
+ .get_locked_repository()
+ .map_or(false, |h| repository.ptr_eq(&h.into()));
if repository.is::<PlatformRepository>() || is_locked_repo {
continue;
}
@@ -826,9 +822,9 @@ impl PoolBuilder {
let pattern_regexp = base_package::package_name_to_regexp(pattern);
// update pattern matches a locked package? => all good
- for package in
- CanonicalPackagesTrait::get_packages(request.get_locked_repository().unwrap())
- {
+ for package in CanonicalPackagesTrait::get_packages(
+ &*request.get_locked_repository().unwrap().borrow(),
+ ) {
if Preg::is_match3(&pattern_regexp, &package.get_name(), None).unwrap_or(false) {
continue 'outer;
}
diff --git a/crates/shirabe/src/dependency_resolver/request.rs b/crates/shirabe/src/dependency_resolver/request.rs
index 0621775..df26535 100644
--- a/crates/shirabe/src/dependency_resolver/request.rs
+++ b/crates/shirabe/src/dependency_resolver/request.rs
@@ -6,8 +6,7 @@ use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MatchAllConstraint;
use crate::package::BasePackageHandle;
-use crate::repository::CanonicalPackagesTrait;
-use crate::repository::LockArrayRepository;
+use crate::repository::LockArrayRepositoryHandle;
use crate::repository::RepositoryInterface;
/// Identifies a partial update for listed packages only, all dependencies will remain at locked versions
@@ -41,7 +40,7 @@ pub enum UpdateAllowTransitiveDeps {
#[derive(Debug)]
pub struct Request {
- pub(crate) locked_repository: Option<LockArrayRepository>,
+ pub(crate) locked_repository: Option<LockArrayRepositoryHandle>,
pub(crate) requires: IndexMap<String, AnyConstraint>,
pub(crate) fixed_packages: IndexMap<String, BasePackageHandle>,
pub(crate) locked_packages: IndexMap<String, BasePackageHandle>,
@@ -52,7 +51,7 @@ pub struct Request {
}
impl Request {
- pub fn new(locked_repository: Option<LockArrayRepository>) -> Self {
+ pub fn new(locked_repository: Option<LockArrayRepositoryHandle>) -> Self {
Self {
locked_repository,
requires: IndexMap::new(),
@@ -200,7 +199,7 @@ impl Request {
let mut present_map: IndexMap<String, crate::package::BasePackageHandle> = IndexMap::new();
if let Some(ref locked_repository) = self.locked_repository {
- for package in RepositoryInterface::get_packages(locked_repository) {
+ for package in RepositoryInterface::get_packages(&*locked_repository.borrow()) {
let key = if package_ids {
package.get_id().to_string()
} else {
@@ -230,8 +229,8 @@ impl Request {
fixed_packages_map
}
- pub fn get_locked_repository(&self) -> Option<&LockArrayRepository> {
- self.locked_repository.as_ref()
+ pub fn get_locked_repository(&self) -> Option<LockArrayRepositoryHandle> {
+ self.locked_repository.clone()
}
/// Restricts the pool builder from loading other packages than those listed here.
diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs
index f7bcde3..3a8cdc2 100644
--- a/crates/shirabe/src/installer.rs
+++ b/crates/shirabe/src/installer.rs
@@ -91,7 +91,6 @@ use crate::repository::CompositeRepository;
use crate::repository::InstalledArrayRepository;
use crate::repository::InstalledRepository;
use crate::repository::InstalledRepositoryInterface;
-use crate::repository::LockArrayRepository;
use crate::repository::PlatformRepository;
use crate::repository::RepositoryInterface;
use crate::repository::RepositoryManager;
@@ -343,11 +342,11 @@ impl Installer {
}
if self.update {
- let locked_repository_handle = crate::repository::RepositoryInterfaceHandle::new(
- self.locker
- .borrow_mut()
- .get_locked_repository(self.dev_mode)?,
- );
+ let locked_repository_handle: crate::repository::RepositoryInterfaceHandle = self
+ .locker
+ .borrow_mut()
+ .get_locked_repository(self.dev_mode)?
+ .into();
let installed_repo = InstalledRepository::new(vec![
locked_repository_handle,
crate::repository::RepositoryInterfaceHandle::new(self.create_platform_repo(false)),
@@ -365,7 +364,7 @@ impl Installer {
// Find abandoned packages and warn user
let locked_repository = self.locker.borrow_mut().get_locked_repository(true)?;
- for package in CanonicalPackagesTrait::get_packages(&locked_repository) {
+ for package in CanonicalPackagesTrait::get_packages(&*locked_repository.borrow()) {
let complete = match package.as_complete_package() {
Some(p) if p.is_abandoned() => p,
_ => continue,
@@ -489,7 +488,10 @@ impl Installer {
if audit_config.audit {
let (packages, target) = if self.update && !self.install {
- (locked_repository.get_canonical_packages(), "locked")
+ (
+ locked_repository.borrow().get_canonical_packages(),
+ "locked",
+ )
} else {
(
self.repository_manager
@@ -561,10 +563,11 @@ impl Installer {
let platform_repo = self.create_platform_repo(true);
let aliases = self.get_root_aliases(true);
- let mut locked_repository: Option<LockArrayRepository> = None;
+ let mut locked_repository: Option<crate::repository::LockArrayRepositoryHandle> = None;
- let mut try_load_locked =
- || -> anyhow::Result<Result<Option<LockArrayRepository>, ParsingException>> {
+ let mut try_load_locked = || -> anyhow::Result<
+ Result<Option<crate::repository::LockArrayRepositoryHandle>, ParsingException>,
+ > {
if self.locker.borrow_mut().is_locked() {
match self.locker.borrow_mut().get_locked_repository(true) {
Ok(r) => Ok(Ok(Some(r))),
@@ -620,14 +623,8 @@ impl Installer {
for repository in repositories {
repository_set.add_repository(repository.clone())?;
}
- 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"
- )))?;
+ if let Some(ref lr) = locked_repository {
+ repository_set.add_repository(lr.clone().into())?;
}
let fixed_root_package = self.fixed_root_package.clone();
@@ -911,7 +908,7 @@ impl Installer {
platform_repo: &PlatformRepository,
aliases: &Vec<IndexMap<String, String>>,
policy: &dyn PolicyInterface,
- locked_repository: Option<&LockArrayRepository>,
+ locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>,
) -> anyhow::Result<i64> {
if self.package.get_dev_requires().is_empty() {
return Ok(0);
@@ -1005,19 +1002,15 @@ impl Installer {
// creating repository set
let policy = self.create_policy(false, None);
// use aliases from lock file only, so empty root aliases here
+ let locked_repo_borrow = locked_repository.borrow();
let mut repository_set = self.create_repository_set(
false,
&platform_repo,
&vec![],
- Some(&locked_repository),
+ Some(&*locked_repo_borrow),
);
- // 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"
- )))?;
+ drop(locked_repo_borrow);
+ repository_set.add_repository(locked_repository.clone().into())?;
// creating requirements request
let fixed_root_package = self.fixed_root_package.clone();
@@ -1051,7 +1044,7 @@ impl Installer {
}
}
- for package in RepositoryInterface::get_packages(&locked_repository) {
+ for package in RepositoryInterface::get_packages(&*locked_repository.borrow()) {
request.fix_locked_package(package.clone());
}
@@ -1121,8 +1114,9 @@ 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 = {
let local_repo_ref = local_repo.borrow();
+ let locked_repo_ref = locked_repository.borrow();
LocalRepoTransaction::new(
- &locked_repository,
+ &*locked_repo_ref,
local_repo_ref.as_installed_repository_interface().unwrap(),
)
};
@@ -1400,7 +1394,7 @@ impl Installer {
fn create_policy(
&mut self,
for_update: bool,
- locked_repo: Option<&LockArrayRepository>,
+ locked_repo: Option<&crate::repository::LockArrayRepositoryHandle>,
) -> DefaultPolicy {
let mut prefer_stable: Option<bool> = None;
let mut prefer_lowest: Option<bool> = None;
@@ -1420,7 +1414,7 @@ impl Installer {
let mut preferred_versions: Option<IndexMap<String, String>> = None;
if for_update && self.minimal_update && locked_repo.is_some() {
let mut versions: IndexMap<String, String> = IndexMap::new();
- for pkg in CanonicalPackagesTrait::get_packages(locked_repo.unwrap()) {
+ for pkg in CanonicalPackagesTrait::get_packages(&*locked_repo.unwrap().borrow()) {
if pkg.as_alias().is_some()
|| (self.update_allow_list.is_some()
&& self
@@ -1448,19 +1442,14 @@ impl Installer {
&self,
root_package: RootPackageInterfaceHandle,
platform_repo: &PlatformRepository,
- locked_repository: Option<&LockArrayRepository>,
+ locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>,
) -> Request {
- // TODO(phase-b): Request::new takes Option<LockArrayRepository> (owned). PHP class
- // shouldn't Clone. Passing None for now.
- let _ = locked_repository;
- let mut request = Request::new(None);
+ let mut request = Request::new(locked_repository.cloned());
- // TODO(phase-c): request.fix_package wants a BasePackageHandle; root_package is wired in
- // once Request migrates to handles.
- // request.fix_package(root_package);
let root_package_handle: PackageInterfaceHandle = root_package.clone().into();
- if let Some(_alias) = root_package_handle.as_root_alias_package() {
- // request.fix_package(alias.get_alias_of());
+ request.fix_package(root_package_handle.clone());
+ if let Some(alias) = root_package_handle.as_root_alias_package() {
+ request.fix_package(alias.get_alias_of().into());
}
let mut fixed_packages = platform_repo.get_packages();
@@ -1499,7 +1488,7 @@ impl Installer {
fn require_packages_for_update(
&mut self,
request: &mut Request,
- locked_repository: Option<&LockArrayRepository>,
+ locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>,
include_dev_requires: bool,
) -> anyhow::Result<()> {
// if we're updating mirrors we want to keep exactly the same versions installed which are in the lock file, but we want current remote metadata
@@ -1520,7 +1509,9 @@ impl Installer {
IndexMap::new()
};
- for locked_package in CanonicalPackagesTrait::get_packages(locked_repository.unwrap()) {
+ for locked_package in
+ CanonicalPackagesTrait::get_packages(&*locked_repository.unwrap().borrow())
+ {
// exclude alias packages here as for root aliases, both alias and aliased are
// present in the lock repo and we only want to require the aliased version
if locked_package.as_alias().is_none()
diff --git a/crates/shirabe/src/package/locker.rs b/crates/shirabe/src/package/locker.rs
index e5eed78..327f662 100644
--- a/crates/shirabe/src/package/locker.rs
+++ b/crates/shirabe/src/package/locker.rs
@@ -28,7 +28,7 @@ use crate::package::version::VersionParser;
use crate::plugin::plugin_interface::{self, PluginInterface};
use crate::repository::FindPackageConstraint;
use crate::repository::InstalledRepository;
-use crate::repository::LockArrayRepository;
+use crate::repository::LockArrayRepositoryHandle;
use crate::repository::PlatformRepository;
use crate::repository::RootPackageRepository;
use crate::util::Git as GitUtil;
@@ -182,10 +182,14 @@ impl Locker {
}
/// Searches and returns an array of locked packages, retrieved from registered repositories.
- pub fn get_locked_repository(&mut self, with_dev_reqs: bool) -> Result<LockArrayRepository> {
+ pub fn get_locked_repository(
+ &mut self,
+ with_dev_reqs: bool,
+ ) -> Result<LockArrayRepositoryHandle> {
let lock_data = self.get_lock_data()?;
// TODO(phase-b): LockArrayRepository has no `new` constructor yet
- let mut packages: LockArrayRepository = todo!("LockArrayRepository::new(vec![])");
+ let mut packages: LockArrayRepositoryHandle =
+ todo!("LockArrayRepositoryHandle::new(LockArrayRepository::new(vec![]))");
let mut locked_packages = lock_data
.get("packages")
@@ -936,13 +940,13 @@ impl Locker {
let mut missing_requirement_info: Vec<String> = vec![];
let mut missing_requirements = false;
let mut sets: Vec<SetEntry> = vec![SetEntry {
- repo: Box::new(self.get_locked_repository(false)?),
+ repo: self.get_locked_repository(false)?,
method: "getRequires".to_string(),
description: "Required".to_string(),
}];
if include_dev == true {
sets.push(SetEntry {
- repo: Box::new(self.get_locked_repository(true)?),
+ repo: self.get_locked_repository(true)?,
method: "getDevRequires".to_string(),
description: "Required (in require-dev)".to_string(),
});
@@ -1045,7 +1049,7 @@ impl Locker {
}
struct SetEntry {
- repo: Box<LockArrayRepository>,
+ repo: LockArrayRepositoryHandle,
method: String,
description: String,
}
diff --git a/crates/shirabe/src/repository/handle.rs b/crates/shirabe/src/repository/handle.rs
index f7a4104..a4225f7 100644
--- a/crates/shirabe/src/repository/handle.rs
+++ b/crates/shirabe/src/repository/handle.rs
@@ -10,8 +10,8 @@ use shirabe_semver::constraint::AnyConstraint;
use crate::package::BasePackageHandle;
use crate::package::PackageInterfaceHandle;
use crate::repository::{
- FindPackageConstraint, InstalledRepositoryInterface, LoadPackagesResult, ProviderInfo,
- RepositoryInterface, SearchResult, WritableRepositoryInterface,
+ FindPackageConstraint, InstalledRepositoryInterface, LoadPackagesResult, LockArrayRepository,
+ ProviderInfo, RepositoryInterface, SearchResult, WritableRepositoryInterface,
};
/// Shared reference to a repository. Corresponds to PHP `RepositoryInterface`.
@@ -172,3 +172,62 @@ impl std::hash::Hash for RepositoryInterfaceHandle {
self.ptr_id().hash(state);
}
}
+
+/// Typed shared handle over `LockArrayRepository`. Preserves the PHP `?LockArrayRepository`
+/// typing where a `RepositoryInterfaceHandle` would be too wide.
+#[derive(Debug, Clone)]
+pub struct LockArrayRepositoryHandle(Rc<RefCell<LockArrayRepository>>);
+
+impl LockArrayRepositoryHandle {
+ pub fn new(repository: LockArrayRepository) -> Self {
+ let rc: Rc<RefCell<LockArrayRepository>> = Rc::new(RefCell::new(repository));
+ let rc_dyn: Rc<RefCell<dyn RepositoryInterface>> = rc.clone();
+ rc.borrow().set_self_handle(Rc::downgrade(&rc_dyn));
+ Self(rc)
+ }
+
+ pub fn from_rc(rc: Rc<RefCell<LockArrayRepository>>) -> Self {
+ Self(rc)
+ }
+
+ pub fn as_rc(&self) -> &Rc<RefCell<LockArrayRepository>> {
+ &self.0
+ }
+
+ pub fn borrow(&self) -> Ref<'_, LockArrayRepository> {
+ self.0.borrow()
+ }
+
+ pub fn borrow_mut(&self) -> RefMut<'_, LockArrayRepository> {
+ self.0.borrow_mut()
+ }
+
+ pub fn ptr_eq(&self, other: &Self) -> bool {
+ Rc::ptr_eq(&self.0, &other.0)
+ }
+
+ pub fn ptr_id(&self) -> usize {
+ Rc::as_ptr(&self.0) as *const () as usize
+ }
+}
+
+impl From<LockArrayRepositoryHandle> for RepositoryInterfaceHandle {
+ fn from(h: LockArrayRepositoryHandle) -> Self {
+ let rc: Rc<RefCell<dyn RepositoryInterface>> = h.0;
+ RepositoryInterfaceHandle::from_rc(rc)
+ }
+}
+
+impl PartialEq for LockArrayRepositoryHandle {
+ fn eq(&self, other: &Self) -> bool {
+ Rc::ptr_eq(&self.0, &other.0)
+ }
+}
+
+impl Eq for LockArrayRepositoryHandle {}
+
+impl std::hash::Hash for LockArrayRepositoryHandle {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.ptr_id().hash(state);
+ }
+}
diff --git a/crates/shirabe/src/repository/repository_set.rs b/crates/shirabe/src/repository/repository_set.rs
index f4a4057..843af80 100644
--- a/crates/shirabe/src/repository/repository_set.rs
+++ b/crates/shirabe/src/repository/repository_set.rs
@@ -32,7 +32,7 @@ use crate::package::version::StabilityFilter;
use crate::repository::CompositeRepository;
use crate::repository::InstalledRepository;
use crate::repository::InstalledRepositoryInterface;
-use crate::repository::LockArrayRepository;
+use crate::repository::LockArrayRepositoryHandle;
use crate::repository::PlatformRepository;
use crate::repository::{AdvisoryProviderInterface, PartialOrSecurityAdvisory};
use crate::repository::{FindPackageConstraint, RepositoryInterface, RepositoryInterfaceHandle};
@@ -573,7 +573,7 @@ impl RepositorySet {
pub fn create_pool_for_package(
&mut self,
package_name: &str,
- locked_repo: Option<LockArrayRepository>,
+ locked_repo: Option<LockArrayRepositoryHandle>,
) -> Result<Pool> {
// TODO unify this with above in some simpler version without "request"?
self.create_pool_for_packages(vec![package_name.to_string()], locked_repo)
@@ -583,7 +583,7 @@ impl RepositorySet {
pub fn create_pool_for_packages(
&mut self,
package_names: Vec<String>,
- locked_repo: Option<LockArrayRepository>,
+ locked_repo: Option<LockArrayRepositoryHandle>,
) -> Result<Pool> {
let mut request = Request::new(locked_repo);