From 86fcc80b348a3f00ab81e5447924aa10202d95e8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 29 May 2026 03:42:14 +0900 Subject: refactor(repository): introduce typed LockArrayRepositoryHandle Share LockArrayRepository via Rc> 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) --- crates/shirabe/src/command/audit_command.rs | 6 +- .../shirabe/src/command/base_dependency_command.rs | 4 +- crates/shirabe/src/command/bump_command.rs | 22 +++--- .../src/command/check_platform_reqs_command.rs | 22 +++--- crates/shirabe/src/command/licenses_command.rs | 2 +- crates/shirabe/src/command/remove_command.rs | 1 + crates/shirabe/src/command/require_command.rs | 17 +++-- crates/shirabe/src/command/show_command.rs | 5 +- crates/shirabe/src/command/suggests_command.rs | 2 +- crates/shirabe/src/command/update_command.rs | 6 +- .../src/dependency_resolver/pool_builder.rs | 24 +++---- crates/shirabe/src/dependency_resolver/request.rs | 13 ++-- crates/shirabe/src/installer.rs | 81 ++++++++++------------ crates/shirabe/src/package/locker.rs | 16 +++-- crates/shirabe/src/repository/handle.rs | 63 ++++++++++++++++- crates/shirabe/src/repository/repository_set.rs | 6 +- 16 files changed, 168 insertions(+), 122 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 = 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 { "Checking {}platform requirements using the lock file", 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 { "No vendor dir present, checking {}platform requirements from the lock file", 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)?; - ::get_packages(&repo) + ::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 = 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 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 = 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::(); + let is_locked_repo = request + .get_locked_repository() + .map_or(false, |h| repository.ptr_eq(&h.into())); if repository.is::() || 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, + pub(crate) locked_repository: Option, pub(crate) requires: IndexMap, pub(crate) fixed_packages: IndexMap, pub(crate) locked_packages: IndexMap, @@ -52,7 +51,7 @@ pub struct Request { } impl Request { - pub fn new(locked_repository: Option) -> Self { + pub fn new(locked_repository: Option) -> Self { Self { locked_repository, requires: IndexMap::new(), @@ -200,7 +199,7 @@ impl Request { let mut present_map: IndexMap = 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 { + 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 = None; + let mut locked_repository: Option = None; - let mut try_load_locked = - || -> anyhow::Result, ParsingException>> { + let mut try_load_locked = || -> anyhow::Result< + Result, 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>, policy: &dyn PolicyInterface, - locked_repository: Option<&LockArrayRepository>, + locked_repository: Option<&crate::repository::LockArrayRepositoryHandle>, ) -> anyhow::Result { 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 = None; let mut prefer_lowest: Option = None; @@ -1420,7 +1414,7 @@ impl Installer { let mut preferred_versions: Option> = None; if for_update && self.minimal_update && locked_repo.is_some() { let mut versions: IndexMap = 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 (owned). PHP class - // shouldn't Clone. Passing None for now. - let _ = locked_repository; - let mut request = Request::new(None); - - // 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 mut request = Request::new(locked_repository.cloned()); + 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 { + pub fn get_locked_repository( + &mut self, + with_dev_reqs: bool, + ) -> Result { 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 = vec![]; let mut missing_requirements = false; let mut sets: Vec = 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, + 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>); + +impl LockArrayRepositoryHandle { + pub fn new(repository: LockArrayRepository) -> Self { + let rc: Rc> = Rc::new(RefCell::new(repository)); + let rc_dyn: Rc> = rc.clone(); + rc.borrow().set_self_handle(Rc::downgrade(&rc_dyn)); + Self(rc) + } + + pub fn from_rc(rc: Rc>) -> Self { + Self(rc) + } + + pub fn as_rc(&self) -> &Rc> { + &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 for RepositoryInterfaceHandle { + fn from(h: LockArrayRepositoryHandle) -> Self { + let rc: Rc> = 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(&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, + locked_repo: Option, ) -> Result { // 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, - locked_repo: Option, + locked_repo: Option, ) -> Result { let mut request = Request::new(locked_repo); -- cgit v1.3.1