diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-28 22:43:11 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-28 22:43:43 +0900 |
| commit | eea4efe87e455742ec17881ee93d8095925e8516 (patch) | |
| tree | 6d242f4fdd0bf32f0494a6fbbd62bce9ed6e1dc7 /crates/shirabe/src/dependency_resolver | |
| parent | cc5d73c05a0abca2eebcc8a6afa0b1543ee49850 (diff) | |
| download | php-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.tar.gz php-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.tar.zst php-shirabe-eea4efe87e455742ec17881ee93d8095925e8516.zip | |
refactor(repository): introduce Rc<RefCell<_>> handles for repositories
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/dependency_resolver')
3 files changed, 60 insertions, 52 deletions
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: |
