From 1921f173ea219cb4b25847294d2d3fa465550fbb Mon Sep 17 00:00:00 2001 From: nsfisis Date: Mon, 25 May 2026 00:58:20 +0900 Subject: refactor(package): introduce Rc> handles for packages PHP packages have reference semantics, so introduce shared-ownership handles over an AnyPackage enum (PackageInterfaceHandle and friends) and replace Box throughout. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../shirabe/src/installer/installation_manager.rs | 98 +++++++++++----------- 1 file changed, 50 insertions(+), 48 deletions(-) (limited to 'crates/shirabe/src/installer/installation_manager.rs') diff --git a/crates/shirabe/src/installer/installation_manager.rs b/crates/shirabe/src/installer/installation_manager.rs index 7a05324..3e455b4 100644 --- a/crates/shirabe/src/installer/installation_manager.rs +++ b/crates/shirabe/src/installer/installation_manager.rs @@ -23,8 +23,8 @@ use crate::installer::PackageEvents; use crate::installer::PluginInstaller; use crate::io::ConsoleIO; use crate::io::IOInterface; -use crate::package::AliasPackage; use crate::package::PackageInterface; +use crate::package::PackageInterfaceHandle; use crate::repository::InstalledRepositoryInterface; use crate::util::Platform; use crate::util::r#loop::Loop; @@ -37,7 +37,7 @@ pub struct InstallationManager { /// @var array cache: IndexMap>, /// @var array> - notifiable_packages: IndexMap>>, + notifiable_packages: IndexMap>, loop_: std::rc::Rc>, io: Box, event_dispatcher: Option>>, @@ -133,18 +133,19 @@ impl InstallationManager { pub fn is_package_installed( &mut self, repo: &dyn InstalledRepositoryInterface, - package: &dyn PackageInterface, + package: &PackageInterfaceHandle, ) -> Result { - // TODO(phase-b): $package instanceof AliasPackage downcast - let package_as_alias: Option<&AliasPackage> = None; - if let Some(alias) = package_as_alias { - return Ok(repo.has_package(package) - && self.is_package_installed(repo, alias.get_alias_of())?); + if let Some(alias) = package.as_alias() { + let alias_of: PackageInterfaceHandle = alias.get_alias_of().into(); + return Ok( + repo.has_package(package.as_rc().borrow().as_package_interface()) + && self.is_package_installed(repo, &alias_of)?, + ); } Ok(self - .get_installer(package.get_type())? - .is_installed(repo, package)) + .get_installer(&package.get_type())? + .is_installed(repo, package.as_rc().borrow().as_package_interface())) } /// Install binary for the given package. @@ -311,9 +312,10 @@ impl InstallationManager { let update_op: Option<&UpdateOperation> = None; if op_type == "update" { // @var UpdateOperation $operation - if let Some(u) = update_op { - package = u.get_target_package(); - initial_package = Some(u.get_initial_package()); + if let Some(_u) = update_op { + // TODO(phase-c): bridge UpdateOperation handles (target/initial) into the + // &dyn PackageInterface that the installer APIs still expect. + continue; } else { continue; } @@ -451,9 +453,10 @@ impl InstallationManager { let initial_package: Option<&dyn PackageInterface>; let update_op: Option<&UpdateOperation> = None; if op_type == "update" { - if let Some(u) = update_op { - package = u.get_target_package(); - initial_package = Some(u.get_initial_package()); + if let Some(_u) = update_op { + // TODO(phase-c): bridge UpdateOperation handles (target/initial) into the + // &dyn PackageInterface that the installer APIs still expect. + continue; } else { continue; } @@ -537,10 +540,11 @@ impl InstallationManager { repo: &mut dyn InstalledRepositoryInterface, operation: &InstallOperation, ) -> Option { - let package = operation.get_package(); - let installer = self.get_installer(package.get_type()).ok()?; - let promise = installer.install(repo, package).await.ok()?; - self.mark_for_notification(package); + let package = operation.get_package().clone(); + let package_type = package.get_type(); + let installer = self.get_installer(&package_type).ok()?; + let promise = installer.install(repo, &package).await.ok()?; + self.mark_for_notification(&package); promise } @@ -553,27 +557,27 @@ impl InstallationManager { repo: &mut dyn InstalledRepositoryInterface, operation: &UpdateOperation, ) -> Option { - let initial = operation.get_initial_package(); - let target = operation.get_target_package(); + let initial = operation.get_initial_package().clone(); + let target = operation.get_target_package().clone(); let initial_type = initial.get_type(); let target_type = target.get_type(); let promise = if initial_type == target_type { - let installer = self.get_installer(initial_type).ok()?; - let promise = installer.update(repo, initial, target).await.ok()?; - self.mark_for_notification(target); + let installer = self.get_installer(&initial_type).ok()?; + let promise = installer.update(repo, &initial, &target).await.ok()?; + self.mark_for_notification(&target); promise } else { // PHP: uninstall initial, then install target via the target-type installer. let _ = self - .get_installer(initial_type) + .get_installer(&initial_type) .ok()? - .uninstall(repo, initial) + .uninstall(repo, &initial) .await .ok()?; - let installer = self.get_installer(target_type).ok()?; - installer.install(repo, target).await.ok()? + let installer = self.get_installer(&target_type).ok()?; + installer.install(repo, &target).await.ok()? }; promise @@ -587,10 +591,11 @@ impl InstallationManager { repo: &mut dyn InstalledRepositoryInterface, operation: &UninstallOperation, ) -> Option { - let package = operation.get_package(); - let installer = self.get_installer(package.get_type()).ok()?; + let package = operation.get_package().clone(); + let package_type = package.get_type(); + let installer = self.get_installer(&package_type).ok()?; - installer.uninstall(repo, package).await.ok()? + installer.uninstall(repo, &package).await.ok()? } /// Executes markAliasInstalled operation. @@ -602,7 +607,10 @@ impl InstallationManager { let package = operation.get_package(); if !repo.has_package(package) { - repo.add_package(package.clone_package_box()); + // TODO(phase-c): MarkAliasInstalledOperation::get_package() yields a borrowed + // &AliasPackage; add_package now wants a shared PackageInterfaceHandle. + let package_handle: PackageInterfaceHandle = todo!(); + repo.add_package(package_handle); } } @@ -638,17 +646,11 @@ impl InstallationManager { // non-batch API, deprecated if str_contains(repo_url, "%package%") { for package in packages { - let url = str_replace("%package%", package.get_pretty_name(), repo_url); + let url = str_replace("%package%", &package.get_pretty_name(), repo_url); let mut params: IndexMap = IndexMap::new(); - params.insert( - "version".to_string(), - package.get_pretty_version().to_string(), - ); - params.insert( - "version_normalized".to_string(), - package.get_version().to_string(), - ); + params.insert("version".to_string(), package.get_pretty_version()); + params.insert("version_normalized".to_string(), package.get_version()); let mut opts: IndexMap = IndexMap::new(); opts.insert("retry-auth-failure".to_string(), PhpMixed::Bool(false)); let mut http: IndexMap = IndexMap::new(); @@ -693,15 +695,15 @@ impl InstallationManager { let mut package_notification: IndexMap = IndexMap::new(); package_notification.insert( "name".to_string(), - PhpMixed::String(package.get_pretty_name().to_string()), + PhpMixed::String(package.get_pretty_name()), ); package_notification.insert( "version".to_string(), - PhpMixed::String(package.get_version().to_string()), + PhpMixed::String(package.get_version()), ); if strpos(repo_url, "packagist.org/").is_some() { if let Some(metadata) = - FileDownloader::download_metadata().get(package.get_name()) + FileDownloader::download_metadata().get(&package.get_name()) { package_notification.insert("downloaded".to_string(), metadata.clone()); } else { @@ -764,12 +766,12 @@ impl InstallationManager { self.reset(); } - fn mark_for_notification(&mut self, package: &dyn PackageInterface) { + fn mark_for_notification(&mut self, package: &PackageInterfaceHandle) { if let Some(notification_url) = package.get_notification_url() { self.notifiable_packages - .entry(notification_url.to_string()) + .entry(notification_url) .or_insert_with(Vec::new) - .push(package.clone_package_box()); + .push(package.clone()); } } -- cgit v1.3.1