diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-07 13:37:11 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-07 13:37:11 +0900 |
| commit | 86961b16b2f5c9c26a776193934d13ff87ab7fea (patch) | |
| tree | 5a45b3aed39a6413e126c7992a8ac6ebcd30b0ad /crates/shirabe | |
| parent | 14138dde4a8c874bdc498edd25d1a2d7dc9022be (diff) | |
| download | php-shirabe-86961b16b2f5c9c26a776193934d13ff87ab7fea.tar.gz php-shirabe-86961b16b2f5c9c26a776193934d13ff87ab7fea.tar.zst php-shirabe-86961b16b2f5c9c26a776193934d13ff87ab7fea.zip | |
refactor(phase-c): resolve shared-ownership TODOs via handle/Rc clones
Resolve the resolvable subset of category A (shared ownership / non-cloneable
PHP class) TODOs by leaning on values that are already shared behind Rc/handle
wrappers, where cloning preserves PHP reference semantics:
- solver: call IgnoreListPlatformRequirementFilter::filter_constraint with a
cloned AnyConstraint (a Clone enum) and propagate the Result
- update_command: filter PlatformRepository out of the repository manager's
handles into a CompositeRepository (array_filter equivalent)
- package_discovery_trait: pass the real platform_requirement_filter (Rc clone)
instead of substituting ignore_nothing()
- installation_manager: pass the original full operation list (Vec<Rc<_>>
clone) as all_operations
- file_downloader: swap self.io to NullIO and restore via std::mem::replace
- auditor: reuse the PackageInterfaceHandle list across the advisory and
abandoned-package queries
- process_executor: drop the unused, lossy Clone impl
- config / array_repository: demote settled RefCell-design markers to comments
Remaining category A items (factory installer wiring, purge_packages handle
bridge, installer cache identity, reinstall flow, plugin command discovery)
stay as TODOs since correct resolution needs structural refactors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe')
| -rw-r--r-- | crates/shirabe/src/advisory/auditor.rs | 15 | ||||
| -rw-r--r-- | crates/shirabe/src/command/package_discovery_trait.rs | 6 | ||||
| -rw-r--r-- | crates/shirabe/src/command/update_command.rs | 16 | ||||
| -rw-r--r-- | crates/shirabe/src/config.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/dependency_resolver/solver.rs | 19 | ||||
| -rw-r--r-- | crates/shirabe/src/downloader/file_downloader.rs | 13 | ||||
| -rw-r--r-- | crates/shirabe/src/installer/installation_manager.rs | 5 | ||||
| -rw-r--r-- | crates/shirabe/src/repository/array_repository.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/util/process_executor.rs | 17 |
9 files changed, 36 insertions, 59 deletions
diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs index d50fe70..258099d 100644 --- a/crates/shirabe/src/advisory/auditor.rs +++ b/crates/shirabe/src/advisory/auditor.rs @@ -81,10 +81,8 @@ impl Auditor { ignore_unreachable: bool, ignore_abandoned: IndexMap<String, Option<String>>, ) -> Result<i64> { - // TODO(phase-b): packages is moved into get_matching_security_advisories; PHP keeps the - // original $packages alive — needs cloning/borrowing strategy for trait objects let result = repo_set.get_matching_security_advisories( - packages, + packages.clone(), format == Self::FORMAT_SUMMARY, ignore_unreachable, )?; @@ -96,9 +94,11 @@ impl Auditor { if format == Self::FORMAT_SUMMARY && self.needs_complete_advisory_load(&all_advisories, &ignore_list) { - // TODO(phase-b): $packages reused here; see note above - let result = - repo_set.get_matching_security_advisories(vec![], false, ignore_unreachable)?; + let result = repo_set.get_matching_security_advisories( + packages.clone(), + false, + ignore_unreachable, + )?; all_advisories = result.advisories; unreachable_repos.extend(result.unreachable_repos); } @@ -112,8 +112,7 @@ impl Auditor { if abandoned == Self::ABANDONED_IGNORE { abandoned_packages = vec![]; } else { - // TODO(phase-b): $packages reused here; see note above - abandoned_packages = self.filter_abandoned_packages(&[], &ignore_abandoned)?; + abandoned_packages = self.filter_abandoned_packages(&packages, &ignore_abandoned)?; if abandoned == Self::ABANDONED_FAIL { abandoned_count = abandoned_packages.len() as i64; } diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index cd6c5a0..58361b5 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -531,8 +531,7 @@ pub trait PackageDiscoveryTrait { name, None, preferred_stability, - // TODO(phase-b): Box<dyn ...> cannot be cloned; original PHP shares reference - Some(PlatformRequirementFilterFactory::ignore_nothing()), + Some(platform_requirement_filter.clone()), 0, None, shirabe_php_shim::PhpMixed::Null, @@ -620,8 +619,7 @@ pub trait PackageDiscoveryTrait { name, None, preferred_stability, - // TODO(phase-b): Box<dyn ...> cannot be cloned; reusing factory result - Some(PlatformRequirementFilterFactory::ignore_nothing()), + Some(platform_requirement_filter.clone()), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES, None, shirabe_php_shim::PhpMixed::Null, diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index b2dab1c..e7a7437 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -718,19 +718,17 @@ impl UpdateCommand { IndexMap::new(), IndexMap::new(), ); - // TODO(phase-b): array_filter requires Clone on Box<dyn RepositoryInterface> - // which PHP classes must not implement. Skipping the repo filter for now. - let _ = &composer + let repositories: Vec<crate::repository::RepositoryInterfaceHandle> = composer .get_repository_manager() .borrow() - .get_repositories(); - let _ = |repository: &crate::repository::RepositoryInterfaceHandle| -> bool { - !repository.is::<PlatformRepository>() - }; + .get_repositories() + .iter() + .filter(|repository| !repository.is::<PlatformRepository>()) + .cloned() + .collect(); repository_set.add_repository(crate::repository::RepositoryInterfaceHandle::new( - CompositeRepository::new(Vec::new()), + CompositeRepository::new(repositories), ))?; - let _ = array_filter::<i64, fn(&i64) -> bool>; VersionSelector::new( std::rc::Rc::new(std::cell::RefCell::new(repository_set)), diff --git a/crates/shirabe/src/config.rs b/crates/shirabe/src/config.rs index 1cfb8cc..d1f0702 100644 --- a/crates/shirabe/src/config.rs +++ b/crates/shirabe/src/config.rs @@ -41,8 +41,6 @@ pub struct Config { warned_hosts: IndexMap<String, bool>, /// @var array<string, true> ssl_verify_warned_hosts: IndexMap<String, bool>, - /// @var array<string, string> - // TODO(phase-b): RefCell to allow `&self` access from Config::get / get_with_flags. source_of_config_value: RefCell<IndexMap<String, String>>, } diff --git a/crates/shirabe/src/dependency_resolver/solver.rs b/crates/shirabe/src/dependency_resolver/solver.rs index d88d9bb..def586a 100644 --- a/crates/shirabe/src/dependency_resolver/solver.rs +++ b/crates/shirabe/src/dependency_resolver/solver.rs @@ -185,11 +185,8 @@ impl Solver { &mut self, request: &Request, platform_requirement_filter: &dyn PlatformRequirementFilterInterface, - ) { + ) -> anyhow::Result<()> { for (package_name, constraint) in request.get_requires() { - // TODO(phase-b): ConstraintInterface is a PHP class — Box<dyn ConstraintInterface> - // cannot be cloned. We borrow the original constraint and only allocate a fresh - // box when the ignore filter rewrites it. let mut filtered: Option<AnyConstraint> = None; let constraint_ref: &AnyConstraint = constraint; if platform_requirement_filter.is_ignored(package_name) { @@ -198,11 +195,11 @@ impl Solver { .as_any() .downcast_ref::<IgnoreListPlatformRequirementFilter>( ) { - // TODO(phase-b): filter_constraint consumes its boxed constraint and would - // need an owned clone of the original. Skipping rewrite until Constraint - // ownership is reworked. - let _ = ignore_filter; - let _ = &mut filtered; + filtered = Some(ignore_filter.filter_constraint( + package_name, + constraint.clone(), + true, + )?); } let active_constraint: &AnyConstraint = filtered.as_ref().unwrap_or(constraint_ref); @@ -235,6 +232,8 @@ impl Solver { self.problems.push(problem); } } + + Ok(()) } pub fn solve( @@ -255,7 +254,7 @@ impl Solver { let _ = platform_requirement_filter.as_ref(); self.rules = rule_set_generator.get_rules_for(request, None)?; drop(rule_set_generator); - self.check_for_root_require_problems(request, platform_requirement_filter.as_ref()); + self.check_for_root_require_problems(request, platform_requirement_filter.as_ref())?; self.decisions = Decisions::new(self.pool.clone()); self.watch_graph = RuleWatchGraph::new(); diff --git a/crates/shirabe/src/downloader/file_downloader.rs b/crates/shirabe/src/downloader/file_downloader.rs index e0fc0c9..9840cef 100644 --- a/crates/shirabe/src/downloader/file_downloader.rs +++ b/crates/shirabe/src/downloader/file_downloader.rs @@ -621,10 +621,13 @@ impl ChangeReportInterface for FileDownloader { package: PackageInterfaceHandle, path: &str, ) -> Result<Option<String>> { - // TODO(phase-b): swap self.io to NullIO and restore — needs a take/swap helper - - let mut null_io = NullIO::new(); - null_io.load_configuration(&mut *self.config.borrow_mut())?; + let prev_io = std::mem::replace( + &mut self.io, + std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())), + ); + self.io + .borrow_mut() + .load_configuration(&mut *self.config.borrow_mut())?; let target_dir = Filesystem::trim_trailing_slash(path); // PHP attaches an onRejected handler to capture the error and drives the promise via @@ -664,7 +667,7 @@ impl ChangeReportInterface for FileDownloader { Ok(output) })(); - // TODO(phase-b): restore self.io = prev_io + self.io = prev_io; let (e, output) = match result { Ok(output) => (None, output), diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs index 2fc77d9..6f691c6 100644 --- a/crates/shirabe/src/installer/installation_manager.rs +++ b/crates/shirabe/src/installer/installation_manager.rs @@ -197,6 +197,8 @@ impl InstallationManager { }), ); + let all_operations: Vec<std::rc::Rc<dyn OperationInterface>> = operations.clone(); + let result: Result<()> = (|| -> Result<()> { // execute operations in batches to make sure download-modifying-plugins are installed // before the other packages get downloaded @@ -247,8 +249,7 @@ impl InstallationManager { dev_mode, run_scripts, download_only, - // TODO(phase-b): allOperations should be the original full list; would require clone - vec![], + all_operations.clone(), ), )?; } diff --git a/crates/shirabe/src/repository/array_repository.rs b/crates/shirabe/src/repository/array_repository.rs index 8c23eb3..1eeb428 100644 --- a/crates/shirabe/src/repository/array_repository.rs +++ b/crates/shirabe/src/repository/array_repository.rs @@ -24,8 +24,6 @@ use crate::repository::{ /// A repository implementation that simply stores packages in an array #[derive(Debug)] pub struct ArrayRepository { - /// @var ?array<BasePackage> - // TODO(phase-b): RefCell models PHP's lazy init via getPackages()/count() under &self pub(crate) packages: RefCell<Option<Vec<BasePackageHandle>>>, /// @var ?array<BasePackage> indexed by package unique name and used to cache hasPackage calls diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs index 36025ea..0b88b9f 100644 --- a/crates/shirabe/src/util/process_executor.rs +++ b/crates/shirabe/src/util/process_executor.rs @@ -850,23 +850,6 @@ impl ProcessExecutor { } } -impl Clone for ProcessExecutor { - fn clone(&self) -> Self { - // TODO(phase-b): cloning ProcessExecutor is incidental to Phase A — share state - // properly in a Phase B refactor - Self { - capture_output: self.capture_output, - error_output: self.error_output.clone(), - io: None, - jobs: IndexMap::new(), - running_jobs: 0, - max_jobs: self.max_jobs, - id_gen: 0, - allow_async: self.allow_async, - } - } -} - /// Phase B helper trait: convert various command argument forms into `PhpMixed`. pub trait IntoExecCommand { fn into_exec_command(self) -> PhpMixed; |
