From c7f53c5d7d581ebf76803650c63ec615b1558dc8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 28 May 2026 03:31:41 +0900 Subject: refactor(composer): represent composer via trait-based handles Replace the PartialComposer/Composer structs and the single Rc> enum with PartialComposer and Composer traits (Composer: PartialComposer), InnerPartialComposer / InnerFullComposer data structs, and the handle types FullComposerHandle (impl Composer) and AnyComposerHandle (polymorphic enum, impl PartialComposer), plus their weak variants. Factory builds the full and partial graphs via separate Rc::new_cyclic branches that share a build_composer_base helper. Call sites now use trait methods that encapsulate borrowing instead of borrow_partial() / composer_full*(). Co-Authored-By: Claude Opus 4.7 --- crates/shirabe/src/command/about_command.rs | 1 - crates/shirabe/src/command/archive_command.rs | 9 +- crates/shirabe/src/command/audit_command.rs | 6 +- crates/shirabe/src/command/base_command.rs | 30 +- .../shirabe/src/command/base_dependency_command.rs | 3 +- crates/shirabe/src/command/bump_command.rs | 3 +- .../src/command/check_platform_reqs_command.rs | 3 +- crates/shirabe/src/command/clear_cache_command.rs | 1 - .../shirabe/src/command/create_project_command.rs | 6 +- crates/shirabe/src/command/diagnose_command.rs | 4 +- .../shirabe/src/command/dump_autoload_command.rs | 3 +- crates/shirabe/src/command/exec_command.rs | 5 +- crates/shirabe/src/command/fund_command.rs | 1 + crates/shirabe/src/command/home_command.rs | 1 + crates/shirabe/src/command/init_command.rs | 6 +- crates/shirabe/src/command/install_command.rs | 3 +- crates/shirabe/src/command/licenses_command.rs | 3 +- crates/shirabe/src/command/mod.rs | 2 +- .../shirabe/src/command/package_discovery_trait.rs | 15 +- crates/shirabe/src/command/reinstall_command.rs | 1 + crates/shirabe/src/command/remove_command.rs | 7 +- crates/shirabe/src/command/require_command.rs | 10 +- crates/shirabe/src/command/run_script_command.rs | 1 + crates/shirabe/src/command/script_alias_command.rs | 1 + crates/shirabe/src/command/search_command.rs | 1 + crates/shirabe/src/command/self_update_command.rs | 1 - crates/shirabe/src/command/show_command.rs | 26 +- crates/shirabe/src/command/status_command.rs | 3 +- crates/shirabe/src/command/suggests_command.rs | 3 +- crates/shirabe/src/command/update_command.rs | 6 +- crates/shirabe/src/command/validate_command.rs | 3 +- crates/shirabe/src/composer.rs | 727 ++++++++++----------- crates/shirabe/src/console/application.rs | 8 +- .../src/event_dispatcher/event_dispatcher.rs | 14 +- crates/shirabe/src/factory.rs | 434 ++++++------ crates/shirabe/src/installer.rs | 4 +- crates/shirabe/src/installer/installer_event.rs | 8 +- crates/shirabe/src/installer/library_installer.rs | 16 +- crates/shirabe/src/installer/package_event.rs | 8 +- crates/shirabe/src/installer/plugin_installer.rs | 4 +- crates/shirabe/src/plugin/plugin_interface.rs | 8 +- crates/shirabe/src/plugin/plugin_manager.rs | 39 +- .../shirabe/src/repository/platform_repository.rs | 1 - crates/shirabe/src/script/event.rs | 8 +- crates/shirabe/src/util/http_downloader.rs | 1 - crates/shirabe/src/util/stream_context_factory.rs | 1 - 46 files changed, 722 insertions(+), 727 deletions(-) (limited to 'crates') diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs index 3e74d6e..e3c3614 100644 --- a/crates/shirabe/src/command/about_command.rs +++ b/crates/shirabe/src/command/about_command.rs @@ -4,7 +4,6 @@ use crate::command::BaseCommand; use crate::command::BaseCommandData; use crate::command::HasBaseCommandData; use crate::composer; -use crate::composer::ComposerHandle; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; use shirabe_external_packages::symfony::component::console::input::InputInterface; diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs index aab7b51..c777f54 100644 --- a/crates/shirabe/src/command/archive_command.rs +++ b/crates/shirabe/src/command/archive_command.rs @@ -8,7 +8,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{LogicException, get_debug_type}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::config::Config; use crate::console::input::InputArgument; use crate::console::input::InputOption; @@ -67,10 +67,10 @@ impl ArchiveCommand { let composer = self.try_composer(None, None); let config = if let Some(ref composer) = composer { - let config = composer.borrow_partial().get_config(); + let config = composer.get_config(); // TODO(plugin): dispatch CommandEvent let command_event = CommandEvent::new(PluginEvents::COMMAND, "archive", input, output); - let event_dispatcher = composer.borrow_partial().get_event_dispatcher(); + let event_dispatcher = composer.get_event_dispatcher(); event_dispatcher .borrow_mut() .dispatch(Some(command_event.get_name()), None); @@ -138,7 +138,6 @@ impl ArchiveCommand { && let Some(ref composer) = composer { composer - .borrow_partial() .get_event_dispatcher() .borrow_mut() .dispatch_script( @@ -162,7 +161,7 @@ impl ArchiveCommand { dest: &str, file_name: Option, ignore_filters: bool, - composer: Option<&PartialComposerHandle>, + composer: Option<&AnyComposerHandle>, ) -> Result { let composer_guard = composer.map(crate::command::composer_full); let owned_archive_manager; diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs index ec8b495..5868b15 100644 --- a/crates/shirabe/src/command/audit_command.rs +++ b/crates/shirabe/src/command/audit_command.rs @@ -3,7 +3,7 @@ use crate::advisory::AuditConfig; use crate::advisory::Auditor; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; @@ -144,10 +144,10 @@ impl AuditCommand { fn get_packages( &self, - composer: &PartialComposerHandle, + composer: &AnyComposerHandle, input: &dyn InputInterface, ) -> Result> { - let mut composer = crate::command::composer_full_mut(composer); + let composer = crate::command::composer_full(composer); if input.get_option("locked").as_bool().unwrap_or(false) { let locker = composer.get_locker().clone(); let mut locker = locker.borrow_mut(); diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs index 6b673ed..cf121dc 100644 --- a/crates/shirabe/src/command/base_command.rs +++ b/crates/shirabe/src/command/base_command.rs @@ -19,7 +19,7 @@ use std::rc::Rc; use crate::advisory::AuditConfig; use crate::advisory::Auditor; use crate::command::SelfUpdateCommand; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, PartialComposer}; use crate::config::Config; use crate::console::Application; use crate::console::input::InputArgument; @@ -163,23 +163,23 @@ pub trait BaseCommand { required: bool, disable_plugins: Option, disable_scripts: Option, - ) -> Result>; + ) -> Result>; /// Retrieves the default Composer\Composer instance or throws fn require_composer( &mut self, disable_plugins: Option, disable_scripts: Option, - ) -> Result; + ) -> Result; /// Retrieves the default Composer\Composer instance or null fn try_composer( &mut self, disable_plugins: Option, disable_scripts: Option, - ) -> Option; + ) -> Option; - fn set_composer(&mut self, composer: PartialComposerHandle); + fn set_composer(&mut self, composer: AnyComposerHandle); /// Removes the cached composer instance fn reset_composer(&mut self) -> Result<()>; @@ -208,7 +208,7 @@ pub trait BaseCommand { config: Option>, disable_plugins: bool, disable_scripts: Option, - ) -> Result; + ) -> Result; /// Returns preferSource and preferDist values based on the configuration. fn get_preferred_install_options( @@ -256,7 +256,7 @@ pub trait BaseCommand { #[derive(Debug)] pub struct BaseCommandData { - pub(crate) composer: Option, + pub(crate) composer: Option, pub(crate) io: Option>>, } @@ -264,11 +264,11 @@ pub trait HasBaseCommandData { fn base_command_data(&self) -> &BaseCommandData; fn base_command_data_mut(&mut self) -> &mut BaseCommandData; - fn composer(&self) -> Option { + fn composer(&self) -> Option { self.base_command_data().composer.clone() } - fn composer_mut(&mut self) -> &mut Option { + fn composer_mut(&mut self) -> &mut Option { &mut self.base_command_data_mut().composer } @@ -292,7 +292,7 @@ impl BaseCommand for C { required: bool, disable_plugins: Option, disable_scripts: Option, - ) -> Result> { + ) -> Result> { if required { return Ok(Some( self.require_composer(disable_plugins, disable_scripts)?, @@ -306,7 +306,7 @@ impl BaseCommand for C { &mut self, _disable_plugins: Option, _disable_scripts: Option, - ) -> Result { + ) -> Result { // TODO(phase-b): depends on Application::get_composer, which is still stubbed. let _ = RuntimeException { message: String::new(), @@ -319,12 +319,12 @@ impl BaseCommand for C { &mut self, _disable_plugins: Option, _disable_scripts: Option, - ) -> Option { + ) -> Option { // TODO(phase-b): depends on Application::get_composer, which is still stubbed. todo!("try_composer pending Application::get_composer") } - fn set_composer(&mut self, composer: PartialComposerHandle) { + fn set_composer(&mut self, composer: AnyComposerHandle) { *self.composer_mut() = Some(composer); } @@ -388,7 +388,7 @@ impl BaseCommand for C { ); // TODO(phase-b): event_dispatcher.dispatch expects Option; need wrapper from // PreCommandRunEvent. - let _ = composer.borrow_partial().get_event_dispatcher(); + let _ = composer.get_event_dispatcher(); let _ = pre_command_run_event.get_name(); } @@ -481,7 +481,7 @@ impl BaseCommand for C { config: Option>, disable_plugins: bool, disable_scripts: Option, - ) -> Result { + ) -> Result { let disable_plugins = disable_plugins || input.has_parameter_option(&["--no-plugins"], false); let disable_scripts = disable_scripts.unwrap_or(false) diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs index 7a5300a..8634fa4 100644 --- a/crates/shirabe/src/command/base_dependency_command.rs +++ b/crates/shirabe/src/command/base_dependency_command.rs @@ -10,6 +10,7 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::Bound; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; use crate::package::CompletePackageInterface; @@ -50,7 +51,7 @@ pub trait BaseDependencyCommand: BaseCommand { inverted: bool, ) -> anyhow::Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); // TODO(plugin): dispatch CommandEvent(PluginEvents::COMMAND, self.get_name(), input, output) via composer.get_event_dispatcher() let mut repos: Vec> = vec![]; diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs index a1e5f35..784f570 100644 --- a/crates/shirabe/src/command/bump_command.rs +++ b/crates/shirabe/src/command/bump_command.rs @@ -9,6 +9,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{PhpMixed, file_get_contents, file_put_contents, is_writable, strtolower}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::factory::Factory; @@ -134,7 +135,7 @@ impl BumpCommand { } let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); let has_lock_file_disabled = !composer.get_config().borrow().has("lock") || composer .get_config() diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs index fd5edd9..a89ce15 100644 --- a/crates/shirabe/src/command/check_platform_reqs_command.rs +++ b/crates/shirabe/src/command/check_platform_reqs_command.rs @@ -9,6 +9,7 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::SimpleConstraint; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; @@ -55,7 +56,7 @@ impl CheckPlatformReqsCommand { _output: &dyn OutputInterface, ) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); let io = self.get_io(); let no_dev = input.get_option("no-dev").as_bool().unwrap_or(false); diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs index 4859a46..152b7a1 100644 --- a/crates/shirabe/src/command/clear_cache_command.rs +++ b/crates/shirabe/src/command/clear_cache_command.rs @@ -2,7 +2,6 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; use crate::composer; -use crate::composer::ComposerHandle; use crate::factory::Factory; use indexmap::IndexMap; use shirabe_external_packages::symfony::component::console::input::InputInterface; diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index d5a8a0c..14cf1f5 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -15,7 +15,7 @@ use shirabe_php_shim::{ use crate::advisory::Auditor; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::config::Config; use crate::config::ConfigSourceInterface; use crate::config::JsonConfigSource; @@ -349,7 +349,7 @@ impl CreateProjectCommand { } } - let mut composer = crate::command::composer_full_mut(&composer_handle); + let composer = crate::command::composer_full(&composer_handle); let process = composer .get_loop() @@ -962,7 +962,7 @@ impl CreateProjectCommand { config: Option>, disable_plugins: bool, disable_scripts: Option, - ) -> Result { + ) -> Result { self.create_composer_instance(input, io, config, disable_plugins, disable_scripts) } diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index c64fc39..a75e8c0 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -21,7 +21,7 @@ use shirabe_php_shim::{ use crate::advisory::Auditor; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; use crate::composer; -use crate::composer::ComposerHandle; +use crate::composer::{Composer, PartialComposer}; use crate::config::Config; use crate::downloader::TransportException; use crate::factory::Factory; @@ -248,7 +248,7 @@ impl DiagnoseCommand { )); if let Some(ref mut c) = composer { - let mut c = crate::command::composer_full_mut(c); + let c = crate::command::composer_full(c); io.write(&format!( "Active plugins: {}", implode( diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs index 6f361da..bdab00a 100644 --- a/crates/shirabe/src/command/dump_autoload_command.rs +++ b/crates/shirabe/src/command/dump_autoload_command.rs @@ -6,6 +6,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{InvalidArgumentException, PhpMixed, file_exists}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; @@ -48,7 +49,7 @@ impl DumpAutoloadCommand { output: &dyn OutputInterface, ) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); // TODO(plugin): dispatch CommandEvent let command_event = diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs index 3f70cf8..824f09e 100644 --- a/crates/shirabe/src/command/exec_command.rs +++ b/crates/shirabe/src/command/exec_command.rs @@ -6,6 +6,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{PhpMixed, RuntimeException, basename, chdir, getcwd, glob}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::io::IOInterface; @@ -87,7 +88,7 @@ impl ExecCommand { { let bins = self.get_binaries(true)?; if bins.is_empty() { - let bin_dir = crate::command::composer_full_mut(&composer) + let bin_dir = crate::command::composer_full(&composer) .get_config() .borrow_mut() .get("bin-dir") @@ -155,7 +156,7 @@ impl ExecCommand { fn get_binaries(&mut self, for_display: bool) -> Result> { let composer = self.require_composer(None, None)?; - let composer_ref = crate::command::composer_full_mut(&composer); + let composer_ref = crate::command::composer_full(&composer); let bin_dir = composer_ref .get_config() .borrow_mut() diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs index 340424f..3a671bd 100644 --- a/crates/shirabe/src/command/fund_command.rs +++ b/crates/shirabe/src/command/fund_command.rs @@ -13,6 +13,7 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::MatchAllConstraint; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs index c048bfd..bd0e3aa 100644 --- a/crates/shirabe/src/command/home_command.rs +++ b/crates/shirabe/src/command/home_command.rs @@ -6,6 +6,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{FILTER_VALIDATE_URL, PhpMixed, filter_var}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::io::IOInterface; diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 730658c..6fc34f2 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -19,7 +19,7 @@ use shirabe_php_shim::{ use crate::command::PackageDiscoveryTrait; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::input::InputOption; use crate::factory::Factory; use crate::io::IOInterface; @@ -57,7 +57,7 @@ impl PackageDiscoveryTrait for InitCommand { todo!() } - fn try_composer(&self) -> Option { + fn try_composer(&self) -> Option { todo!() } @@ -65,7 +65,7 @@ impl PackageDiscoveryTrait for InitCommand { &self, disable_plugins: Option, disable_scripts: Option, - ) -> PartialComposerHandle { + ) -> AnyComposerHandle { todo!() } diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs index 4c869f4..29c8aa1 100644 --- a/crates/shirabe/src/command/install_command.rs +++ b/crates/shirabe/src/command/install_command.rs @@ -7,6 +7,7 @@ use shirabe_php_shim::PhpMixed; use crate::advisory::Auditor; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::installer::Installer; @@ -102,7 +103,7 @@ impl InstallCommand { } let composer_handle = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer_handle); + let composer = crate::command::composer_full(&composer_handle); if !composer.get_locker().borrow_mut().is_locked() && !HttpDownloader::is_curl_enabled() { io.write_error("Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled."); diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs index add5b0b..9dbc3b5 100644 --- a/crates/shirabe/src/command/licenses_command.rs +++ b/crates/shirabe/src/command/licenses_command.rs @@ -12,6 +12,7 @@ use shirabe_external_packages::symfony::console::style::SymfonyStyle; use shirabe_php_shim::{PhpMixed, RuntimeException, UnexpectedValueException}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; @@ -81,7 +82,7 @@ impl LicensesCommand { output: &dyn OutputInterface, ) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); // TODO(plugin): dispatch COMMAND event for plugin hooks let command_event = CommandEvent::new(PluginEvents::COMMAND, "licenses", input, output); diff --git a/crates/shirabe/src/command/mod.rs b/crates/shirabe/src/command/mod.rs index 4452f85..5e1b437 100644 --- a/crates/shirabe/src/command/mod.rs +++ b/crates/shirabe/src/command/mod.rs @@ -37,7 +37,7 @@ pub mod suggests_command; pub mod update_command; pub mod validate_command; -pub(crate) use crate::composer::{composer_full, composer_full_mut}; +pub(crate) use crate::composer::composer_full; pub use about_command::*; pub use archive_command::*; diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index d0574c6..e43f401 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -15,7 +15,7 @@ use shirabe_php_shim::{ trim, }; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, PartialComposer}; use crate::factory::Factory; use crate::filter::platform_requirement_filter::IgnoreAllPlatformRequirementFilter; use crate::filter::platform_requirement_filter::PlatformRequirementFilterFactory; @@ -40,12 +40,12 @@ pub trait PackageDiscoveryTrait { // PHP: trait dependencies (provided by BaseCommand) fn get_io(&self) -> std::rc::Rc>; - fn try_composer(&self) -> Option; + fn try_composer(&self) -> Option; fn require_composer( &self, disable_plugins: Option, disable_scripts: Option, - ) -> PartialComposerHandle; + ) -> AnyComposerHandle; fn get_platform_requirement_filter( &self, input: &dyn InputInterface, @@ -218,10 +218,7 @@ pub trait PackageDiscoveryTrait { // Collect existing packages let composer = self.try_composer(); - let composer_ref = composer.as_ref().map(|c| c.borrow_partial()); - let repository_manager = composer_ref - .as_ref() - .map(|c| c.get_repository_manager().clone()); + let repository_manager = composer.as_ref().map(|c| c.get_repository_manager()); let repository_manager_ref = repository_manager.as_ref().map(|rm| rm.borrow()); let installed_repo = repository_manager_ref .as_ref() @@ -236,7 +233,6 @@ pub trait PackageDiscoveryTrait { drop(installed_repo); drop(repository_manager_ref); drop(repository_manager); - drop(composer_ref); drop(composer); let io = self.get_io(); @@ -816,8 +812,7 @@ pub trait PackageDiscoveryTrait { let mut similar_packages: IndexMap = IndexMap::new(); let composer_for_installed = self.require_composer(None, None); - let composer_for_installed = composer_for_installed.borrow_partial(); - let repository_manager = composer_for_installed.get_repository_manager().clone(); + let repository_manager = composer_for_installed.get_repository_manager(); let repository_manager = repository_manager.borrow(); let installed_repo = repository_manager.get_local_repository(); diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs index ad4739b..49f842a 100644 --- a/crates/shirabe/src/command/reinstall_command.rs +++ b/crates/shirabe/src/command/reinstall_command.rs @@ -9,6 +9,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::InvalidArgumentException; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputDefinitionItem; use crate::console::input::InputOption; diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs index 9ea7329..2b90f80 100644 --- a/crates/shirabe/src/command/remove_command.rs +++ b/crates/shirabe/src/command/remove_command.rs @@ -9,6 +9,7 @@ use shirabe_php_shim::{PhpMixed, UnexpectedValueException, array_map, strtolower use crate::advisory::Auditor; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::config::ConfigSourceInterface; use crate::config::JsonConfigSource; use crate::console::input::InputArgument; @@ -184,7 +185,7 @@ impl RemoveCommand { if input.get_option("unused").as_bool().unwrap_or(false) { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); { let locker = composer.get_locker().clone(); let mut locker = locker.borrow_mut(); @@ -430,7 +431,7 @@ impl RemoveCommand { // TODO(plugin): deactivate installed plugins if let Some(composer_opt) = self.try_composer(None, None) { - let mut composer_opt = crate::command::composer_full_mut(&composer_opt); + let composer_opt = crate::command::composer_full(&composer_opt); composer_opt .get_plugin_manager() .borrow_mut() @@ -439,7 +440,7 @@ impl RemoveCommand { self.reset_composer(); let composer_handle = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer_handle); + let composer = crate::command::composer_full(&composer_handle); if dry_run { // TODO(phase-b): composer.get_package() returns &dyn RootPackageInterface; set_requires/set_dev_requires need &mut self; needs shared-ownership refactor diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs index bf5f159..27626e7 100644 --- a/crates/shirabe/src/command/require_command.rs +++ b/crates/shirabe/src/command/require_command.rs @@ -17,7 +17,7 @@ use shirabe_php_shim::{ use crate::advisory::Auditor; use crate::command::PackageDiscoveryTrait; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::dependency_resolver::Request; @@ -72,7 +72,7 @@ impl PackageDiscoveryTrait for RequireCommand { todo!() } - fn try_composer(&self) -> Option { + fn try_composer(&self) -> Option { todo!() } @@ -80,7 +80,7 @@ impl PackageDiscoveryTrait for RequireCommand { &self, disable_plugins: Option, disable_scripts: Option, - ) -> PartialComposerHandle { + ) -> AnyComposerHandle { todo!() } @@ -688,7 +688,7 @@ impl RequireCommand { // Update packages self.reset_composer()?; let composer_handle = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer_handle); + let composer = crate::command::composer_full(&composer_handle); self.dependency_resolution_completed = false; // TODO(phase-b): add_listener expects a Callable enum; PHP closure should set @@ -930,7 +930,7 @@ impl RequireCommand { fixed: bool, ) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); let locker_is_locked = composer.get_locker().borrow_mut().is_locked(); let mut requirements: IndexMap = IndexMap::new(); let mut version_selector = VersionSelector::new( diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs index 9118463..8eb6cf2 100644 --- a/crates/shirabe/src/command/run_script_command.rs +++ b/crates/shirabe/src/command/run_script_command.rs @@ -7,6 +7,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf use shirabe_php_shim::{InvalidArgumentException, PhpMixed, RuntimeException}; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::io::IOInterface; diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs index 6499002..4306605 100644 --- a/crates/shirabe/src/command/script_alias_command.rs +++ b/crates/shirabe/src/command/script_alias_command.rs @@ -1,6 +1,7 @@ //! ref: composer/src/Composer/Command/ScriptAliasCommand.php use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::io::IOInterface; diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs index 2033cfc..313f8b2 100644 --- a/crates/shirabe/src/command/search_command.rs +++ b/crates/shirabe/src/command/search_command.rs @@ -1,6 +1,7 @@ //! ref: composer/src/Composer/Command/SearchCommand.php use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::io::IOInterface; diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs index fc22ab7..4f0fcf6 100644 --- a/crates/shirabe/src/command/self_update_command.rs +++ b/crates/shirabe/src/command/self_update_command.rs @@ -21,7 +21,6 @@ use shirabe_php_shim::{ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; use crate::composer; -use crate::composer::ComposerHandle; use crate::config::Config; use crate::console::input::InputArgument; use crate::console::input::InputOption; diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs index b72a986..3b50add 100644 --- a/crates/shirabe/src/command/show_command.rs +++ b/crates/shirabe/src/command/show_command.rs @@ -16,7 +16,7 @@ use shirabe_php_shim::{ use shirabe_semver::constraint::AnyConstraint; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::input::InputOption; use crate::dependency_resolver::DefaultPolicy; use crate::dependency_resolver::PolicyInterface; @@ -277,7 +277,7 @@ impl ShowCommand { installed_repo = Box::new(ir); } } else if input.get_option("all").as_bool() == Some(true) && composer.is_some() { - let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap()); + let composer_ref = crate::command::composer_full(composer.as_ref().unwrap()); let local_repo_cloned = composer_ref .get_repository_manager() .borrow() @@ -335,7 +335,7 @@ impl ShowCommand { repos = Box::new(CompositeRepository::new(composite_input)); } else if input.get_option("locked").as_bool() == Some(true) { if composer.is_none() - || !crate::command::composer_full_mut(composer.as_ref().unwrap()) + || !crate::command::composer_full(composer.as_ref().unwrap()) .get_locker() .borrow_mut() .is_locked() @@ -346,7 +346,7 @@ impl ShowCommand { } .into()); } - let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap()); + let composer_ref = crate::command::composer_full(composer.as_ref().unwrap()); let locker_rc = composer_ref.get_locker().clone(); let mut locker = locker_rc.borrow_mut(); let mut lr = @@ -366,19 +366,9 @@ impl ShowCommand { // TODO(phase-b): PHP shares the Composer object by reference. Phase B // can't clone Composer, so we re-fetch via require_composer when missing // but otherwise borrow the existing Option. - let composer_local_owned; - // Borrow guards that keep the Ref alive for the duration of the block. - let _guard_from_existing; let composer_local = match composer.as_ref() { - Some(c) => { - _guard_from_existing = crate::command::composer_full(c); - &*_guard_from_existing - } - None => { - composer_local_owned = self.require_composer(None, None)?; - _guard_from_existing = crate::command::composer_full(&composer_local_owned); - &*_guard_from_existing - } + Some(c) => crate::command::composer_full(c), + None => crate::command::composer_full(&self.require_composer(None, None)?), }; let root_pkg = composer_local.get_package(); @@ -2542,7 +2532,7 @@ impl ShowCommand { fn find_latest_package( &mut self, package: PackageInterfaceHandle, - composer: &PartialComposerHandle, + composer: &AnyComposerHandle, platform_repo: &PlatformRepository, major_only: bool, minor_only: bool, @@ -2680,7 +2670,7 @@ impl ShowCommand { fn get_repository_set( &mut self, - composer: &PartialComposerHandle, + composer: &AnyComposerHandle, ) -> anyhow::Result<&mut RepositorySet> { let composer = crate::command::composer_full(composer); if self.repository_set.is_none() { diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs index 9f66adf..87ab320 100644 --- a/crates/shirabe/src/command/status_command.rs +++ b/crates/shirabe/src/command/status_command.rs @@ -6,6 +6,7 @@ use shirabe_external_packages::symfony::component::console::input::InputInterfac use shirabe_external_packages::symfony::component::console::output::OutputInterface; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputOption; use crate::io::IOInterface; use crate::package::dumper::ArrayDumper; @@ -85,7 +86,7 @@ impl StatusCommand { fn do_execute(&mut self, input: &dyn InputInterface) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); // TODO(phase-b): release the &mut self borrow held by get_io via clone_box. let io_box = self.get_io().clone(); let io_ref = io_box.borrow(); diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs index aa1ae15..cab1ec8 100644 --- a/crates/shirabe/src/command/suggests_command.rs +++ b/crates/shirabe/src/command/suggests_command.rs @@ -1,6 +1,7 @@ //! ref: composer/src/Composer/Command/SuggestsCommand.php use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::installer::SuggestedPackagesReporter; @@ -45,7 +46,7 @@ impl SuggestsCommand { _output: &dyn OutputInterface, ) -> Result { let composer = self.require_composer(None, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); let root_package_handle: crate::package::RootPackageInterfaceHandle = composer.get_package().clone(); diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index f879283..c61e28a 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -18,7 +18,7 @@ use shirabe_semver::intervals::Intervals; use crate::advisory::Auditor; use crate::command::BumpCommand; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::dependency_resolver::request::{self, Request, UpdateAllowTransitiveDeps}; @@ -460,7 +460,7 @@ impl UpdateCommand { io: &dyn IOInterface, input: &dyn InputInterface, output: &dyn OutputInterface, - composer: &PartialComposerHandle, + composer: &AnyComposerHandle, packages: Vec, ) -> Result> { if !input.is_interactive() { @@ -618,7 +618,7 @@ impl UpdateCommand { .into()) } - fn create_version_selector(&self, composer: &PartialComposerHandle) -> Result { + fn create_version_selector(&self, composer: &AnyComposerHandle) -> Result { let composer = crate::command::composer_full(composer); let mut repository_set = RepositorySet::new( &composer.get_package().get_minimum_stability(), diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs index 12eadd7..3e8fbf1 100644 --- a/crates/shirabe/src/command/validate_command.rs +++ b/crates/shirabe/src/command/validate_command.rs @@ -5,6 +5,7 @@ use shirabe_external_packages::symfony::component::console::input::InputInterfac use shirabe_external_packages::symfony::component::console::output::OutputInterface; use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData}; +use crate::composer::{Composer, PartialComposer}; use crate::console::input::InputArgument; use crate::console::input::InputOption; use crate::factory::Factory; @@ -158,7 +159,7 @@ impl ValidateCommand { let mut lock_errors: Vec = vec![]; let composer = self.create_composer_instance(input, io_box.clone(), None, false, None)?; - let mut composer = crate::command::composer_full_mut(&composer); + let composer = crate::command::composer_full(&composer); let check_lock = (check_lock && composer .get_config() diff --git a/crates/shirabe/src/composer.rs b/crates/shirabe/src/composer.rs index fe700cf..6a2337a 100644 --- a/crates/shirabe/src/composer.rs +++ b/crates/shirabe/src/composer.rs @@ -31,255 +31,315 @@ pub fn get_version() -> String { VERSION.to_string() } +/// Interface for \Composer\PartialComposer. Implemented by every composer handle, since both a +/// partial and a full composer expose these common members. +pub trait PartialComposer { + fn set_package(&self, package: RootPackageInterfaceHandle); + fn get_package(&self) -> RootPackageInterfaceHandle; + fn set_config(&self, config: std::rc::Rc>); + fn get_config(&self) -> std::rc::Rc>; + fn set_loop(&self, r#loop: std::rc::Rc>); + fn get_loop(&self) -> std::rc::Rc>; + fn set_repository_manager(&self, manager: std::rc::Rc>); + fn get_repository_manager(&self) -> std::rc::Rc>; + fn set_installation_manager( + &self, + manager: std::rc::Rc>, + ); + fn get_installation_manager(&self) -> std::rc::Rc>; + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc>, + ); + fn get_event_dispatcher(&self) -> std::rc::Rc>; + fn is_global(&self) -> bool; + fn set_global(&self); +} + +/// Interface for \Composer\Composer (`extends PartialComposer`). Implemented only by fully-loaded +/// composer handles, which additionally expose the full-only members below. +pub trait Composer: PartialComposer { + fn set_locker(&self, locker: std::rc::Rc>); + fn get_locker(&self) -> std::rc::Rc>; + fn set_download_manager(&self, manager: std::rc::Rc>); + fn get_download_manager(&self) -> std::rc::Rc>; + // TODO(plugin): set_plugin_manager is part of the plugin API + fn set_plugin_manager(&self, manager: std::rc::Rc>); + // TODO(plugin): get_plugin_manager is part of the plugin API + fn get_plugin_manager(&self) -> std::rc::Rc>; + fn set_autoload_generator( + &self, + autoload_generator: std::rc::Rc>, + ); + fn get_autoload_generator(&self) -> std::rc::Rc>; + fn set_archive_manager(&self, manager: std::rc::Rc>); + fn get_archive_manager(&self) -> std::rc::Rc>; +} + /// Internal data type corresponding to \Composer\PartialComposer. #[derive(Debug, Default)] -pub struct PartialComposer { - global: bool, - package: Option, - r#loop: Option>>, - repository_manager: Option>>, - installation_manager: Option>>, - config: Option>>, - event_dispatcher: Option>>, +pub(crate) struct InnerPartialComposer { + pub(crate) global: bool, + pub(crate) package: Option, + pub(crate) r#loop: Option>>, + pub(crate) repository_manager: Option>>, + pub(crate) installation_manager: Option>>, + pub(crate) config: Option>>, + pub(crate) event_dispatcher: Option>>, } -impl PartialComposer { - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { - self.package = Some(package); - } +/// Internal data type corresponding to \Composer\Composer. +#[derive(Debug, Default)] +pub(crate) struct InnerFullComposer { + pub(crate) partial: InnerPartialComposer, + pub(crate) locker: Option>>, + pub(crate) download_manager: Option>>, + // TODO(plugin): plugin_manager is part of the plugin API + pub(crate) plugin_manager: Option>>, + pub(crate) autoload_generator: Option>>, + pub(crate) archive_manager: Option>>, +} - pub fn get_package(&self) -> &RootPackageInterfaceHandle { - self.package.as_ref().unwrap() - } +/// Shared reference to a fully-loaded \Composer\Composer. +/// Use this for parameters or fields typed as \Composer\Composer in PHP. +#[derive(Debug, Clone)] +pub struct FullComposerHandle(std::rc::Rc>); - pub fn set_config(&mut self, config: std::rc::Rc>) { - self.config = Some(config); +impl FullComposerHandle { + pub(crate) fn from_rc(rc: std::rc::Rc>) -> Self { + Self(rc) } - pub fn get_config(&self) -> std::rc::Rc> { - self.config.as_ref().unwrap().clone() + pub(crate) fn as_rc(&self) -> &std::rc::Rc> { + &self.0 } - pub fn set_loop(&mut self, r#loop: std::rc::Rc>) { - self.r#loop = Some(r#loop); + pub fn downgrade(&self) -> FullComposerWeakHandle { + FullComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) } +} - pub fn get_loop(&self) -> std::rc::Rc> { - self.r#loop.as_ref().unwrap().clone() +impl PartialComposer for FullComposerHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.0.borrow_mut().partial.package = Some(package); } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc>, - ) { - self.repository_manager = Some(manager); + fn get_package(&self) -> RootPackageInterfaceHandle { + self.0.borrow().partial.package.as_ref().unwrap().clone() } - - pub fn get_repository_manager(&self) -> std::rc::Rc> { - self.repository_manager.as_ref().unwrap().clone() + fn set_config(&self, config: std::rc::Rc>) { + self.0.borrow_mut().partial.config = Some(config); } - - pub fn set_installation_manager( - &mut self, - manager: std::rc::Rc>, - ) { - self.installation_manager = Some(manager); + fn get_config(&self) -> std::rc::Rc> { + self.0.borrow().partial.config.as_ref().unwrap().clone() } - - pub fn get_installation_manager(&self) -> std::rc::Rc> { - self.installation_manager.as_ref().unwrap().clone() + fn set_loop(&self, r#loop: std::rc::Rc>) { + self.0.borrow_mut().partial.r#loop = Some(r#loop); } - - pub fn set_event_dispatcher( - &mut self, + fn get_loop(&self) -> std::rc::Rc> { + self.0.borrow().partial.r#loop.as_ref().unwrap().clone() + } + fn set_repository_manager(&self, manager: std::rc::Rc>) { + self.0.borrow_mut().partial.repository_manager = Some(manager); + } + fn get_repository_manager(&self) -> std::rc::Rc> { + self.0 + .borrow() + .partial + .repository_manager + .as_ref() + .unwrap() + .clone() + } + fn set_installation_manager( + &self, + manager: std::rc::Rc>, + ) { + self.0.borrow_mut().partial.installation_manager = Some(manager); + } + fn get_installation_manager(&self) -> std::rc::Rc> { + self.0 + .borrow() + .partial + .installation_manager + .as_ref() + .unwrap() + .clone() + } + fn set_event_dispatcher( + &self, event_dispatcher: std::rc::Rc>, ) { - self.event_dispatcher = Some(event_dispatcher); + self.0.borrow_mut().partial.event_dispatcher = Some(event_dispatcher); } - - pub fn get_event_dispatcher(&self) -> std::rc::Rc> { - self.event_dispatcher.as_ref().unwrap().clone() + fn get_event_dispatcher(&self) -> std::rc::Rc> { + self.0 + .borrow() + .partial + .event_dispatcher + .as_ref() + .unwrap() + .clone() } - - pub fn is_global(&self) -> bool { - self.global + fn is_global(&self) -> bool { + self.0.borrow().partial.global } - - pub fn set_global(&mut self) { - self.global = true; + fn set_global(&self) { + self.0.borrow_mut().partial.global = true; } } -/// Internal data type corresponding to \Composer\Composer. -#[derive(Debug)] -pub struct Composer { - partial: PartialComposer, - locker: Option>>, - download_manager: Option>>, - // TODO(plugin): plugin_manager is part of the plugin API - plugin_manager: Option>>, - autoload_generator: Option>>, - archive_manager: Option>>, -} - -impl Composer { - pub fn new() -> Self { - Self { - partial: PartialComposer::default(), - locker: None, - download_manager: None, - plugin_manager: None, - autoload_generator: None, - archive_manager: None, - } +impl Composer for FullComposerHandle { + fn set_locker(&self, locker: std::rc::Rc>) { + self.0.borrow_mut().locker = Some(locker); } - - pub fn set_locker(&mut self, locker: std::rc::Rc>) { - self.locker = Some(locker); + fn get_locker(&self) -> std::rc::Rc> { + self.0.borrow().locker.as_ref().unwrap().clone() } - - pub fn get_locker(&self) -> std::rc::Rc> { - self.locker.as_ref().unwrap().clone() + fn set_download_manager(&self, manager: std::rc::Rc>) { + self.0.borrow_mut().download_manager = Some(manager); } - - pub fn set_download_manager( - &mut self, - manager: std::rc::Rc>, - ) { - self.download_manager = Some(manager); + fn get_download_manager(&self) -> std::rc::Rc> { + self.0.borrow().download_manager.as_ref().unwrap().clone() } - - pub fn get_download_manager(&self) -> std::rc::Rc> { - self.download_manager.as_ref().unwrap().clone() + fn set_plugin_manager(&self, manager: std::rc::Rc>) { + self.0.borrow_mut().plugin_manager = Some(manager); } - - pub fn set_archive_manager( - &mut self, - manager: std::rc::Rc>, + fn get_plugin_manager(&self) -> std::rc::Rc> { + self.0.borrow().plugin_manager.as_ref().unwrap().clone() + } + fn set_autoload_generator( + &self, + autoload_generator: std::rc::Rc>, ) { - self.archive_manager = Some(manager); + self.0.borrow_mut().autoload_generator = Some(autoload_generator); } - - pub fn get_archive_manager(&self) -> std::rc::Rc> { - self.archive_manager.as_ref().unwrap().clone() + fn get_autoload_generator(&self) -> std::rc::Rc> { + self.0.borrow().autoload_generator.as_ref().unwrap().clone() } - - // TODO(plugin): set_plugin_manager is part of the plugin API - pub fn set_plugin_manager(&mut self, manager: std::rc::Rc>) { - self.plugin_manager = Some(manager); + fn set_archive_manager(&self, manager: std::rc::Rc>) { + self.0.borrow_mut().archive_manager = Some(manager); } - - // TODO(plugin): get_plugin_manager is part of the plugin API - pub fn get_plugin_manager(&self) -> std::rc::Rc> { - self.plugin_manager.as_ref().unwrap().clone() + fn get_archive_manager(&self) -> std::rc::Rc> { + self.0.borrow().archive_manager.as_ref().unwrap().clone() } +} - pub fn set_autoload_generator( - &mut self, - autoload_generator: std::rc::Rc>, - ) { - self.autoload_generator = Some(autoload_generator); - } +/// Shared weak reference to a fully-loaded \Composer\Composer. +#[derive(Debug, Clone)] +pub struct FullComposerWeakHandle(std::rc::Weak>); - pub fn get_autoload_generator(&self) -> std::rc::Rc> { - self.autoload_generator.as_ref().unwrap().clone() +impl FullComposerWeakHandle { + pub(crate) fn from_weak(weak: std::rc::Weak>) -> Self { + Self(weak) } - pub fn as_partial(&self) -> &PartialComposer { - &self.partial + pub fn upgrade(&self) -> Option { + self.0.upgrade().map(FullComposerHandle) } - pub fn as_partial_mut(&mut self) -> &mut PartialComposer { - &mut self.partial + fn upgraded(&self) -> FullComposerHandle { + self.upgrade() + .expect("Composer has been dropped before its weak reference") } +} - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { - self.partial.set_package(package); +impl PartialComposer for FullComposerWeakHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.upgraded().set_package(package); } - - pub fn get_package(&self) -> &RootPackageInterfaceHandle { - self.partial.get_package() + fn get_package(&self) -> RootPackageInterfaceHandle { + self.upgraded().get_package() } - - pub fn set_config(&mut self, config: std::rc::Rc>) { - self.partial.set_config(config); + fn set_config(&self, config: std::rc::Rc>) { + self.upgraded().set_config(config); } - - pub fn get_config(&self) -> std::rc::Rc> { - self.partial.get_config() + fn get_config(&self) -> std::rc::Rc> { + self.upgraded().get_config() } - - pub fn set_loop(&mut self, r#loop: std::rc::Rc>) { - self.partial.set_loop(r#loop); + fn set_loop(&self, r#loop: std::rc::Rc>) { + self.upgraded().set_loop(r#loop); } - - pub fn get_loop(&self) -> std::rc::Rc> { - self.partial.get_loop() + fn get_loop(&self) -> std::rc::Rc> { + self.upgraded().get_loop() } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc>, - ) { - self.partial.set_repository_manager(manager); + fn set_repository_manager(&self, manager: std::rc::Rc>) { + self.upgraded().set_repository_manager(manager); } - - pub fn get_repository_manager( - &self, - ) -> std::rc::Rc> { - self.partial.get_repository_manager() + fn get_repository_manager(&self) -> std::rc::Rc> { + self.upgraded().get_repository_manager() } - - pub fn set_installation_manager( - &mut self, - manager: std::rc::Rc>, + fn set_installation_manager( + &self, + manager: std::rc::Rc>, ) { - self.partial.set_installation_manager(manager); + self.upgraded().set_installation_manager(manager); } - - pub fn get_installation_manager( - &self, - ) -> std::rc::Rc> { - self.partial.get_installation_manager() + fn get_installation_manager(&self) -> std::rc::Rc> { + self.upgraded().get_installation_manager() } - - pub fn set_event_dispatcher( - &mut self, - dispatcher: std::rc::Rc>, + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc>, ) { - self.partial.set_event_dispatcher(dispatcher); + self.upgraded().set_event_dispatcher(event_dispatcher); + } + fn get_event_dispatcher(&self) -> std::rc::Rc> { + self.upgraded().get_event_dispatcher() + } + fn is_global(&self) -> bool { + self.upgraded().is_global() } + fn set_global(&self) { + self.upgraded().set_global(); + } +} - pub fn get_event_dispatcher( +impl Composer for FullComposerWeakHandle { + fn set_locker(&self, locker: std::rc::Rc>) { + self.upgraded().set_locker(locker); + } + fn get_locker(&self) -> std::rc::Rc> { + self.upgraded().get_locker() + } + fn set_download_manager(&self, manager: std::rc::Rc>) { + self.upgraded().set_download_manager(manager); + } + fn get_download_manager(&self) -> std::rc::Rc> { + self.upgraded().get_download_manager() + } + fn set_plugin_manager(&self, manager: std::rc::Rc>) { + self.upgraded().set_plugin_manager(manager); + } + fn get_plugin_manager(&self) -> std::rc::Rc> { + self.upgraded().get_plugin_manager() + } + fn set_autoload_generator( &self, - ) -> std::rc::Rc> { - self.partial.get_event_dispatcher() + autoload_generator: std::rc::Rc>, + ) { + self.upgraded().set_autoload_generator(autoload_generator); } - - pub fn is_global(&self) -> bool { - self.partial.is_global() + fn get_autoload_generator(&self) -> std::rc::Rc> { + self.upgraded().get_autoload_generator() } - - pub fn set_global(&mut self) { - self.partial.set_global(); + fn set_archive_manager(&self, manager: std::rc::Rc>) { + self.upgraded().set_archive_manager(manager); + } + fn get_archive_manager(&self) -> std::rc::Rc> { + self.upgraded().get_archive_manager() } } -#[derive(Debug)] -pub enum PartialOrFullComposer { - Full(Composer), - Partial(PartialComposer), +/// Shared reference to a \Composer\PartialComposer that may at runtime be either a partial composer +/// or a full \Composer\Composer. Use this for parameters or fields typed as \Composer\PartialComposer +/// in PHP; downcast with [`AnyComposerHandle::as_full`] (`$composer instanceof Composer`). +#[derive(Debug, Clone)] +pub enum AnyComposerHandle { + Partial(std::rc::Rc>), + Full(FullComposerHandle), } -impl PartialOrFullComposer { - pub fn new_full() -> Self { - Self::Full(Composer::new()) - } - - pub fn new_partial() -> Self { - Self::Partial(PartialComposer::default()) - } - +impl AnyComposerHandle { pub fn is_full(&self) -> bool { matches!(self, Self::Full(_)) } @@ -288,274 +348,199 @@ impl PartialOrFullComposer { matches!(self, Self::Partial(_)) } - pub fn as_full(&self) -> Option<&Composer> { + /// Downcast to a full Composer handle. PHP `$composer instanceof Composer`. + pub fn as_full(&self) -> Option { match self { - Self::Full(full) => Some(full), + Self::Full(full) => Some(full.clone()), Self::Partial(_) => None, } } - pub fn as_full_mut(&mut self) -> Option<&mut Composer> { + pub fn downgrade(&self) -> AnyComposerWeakHandle { match self { - Self::Full(full) => Some(full), - Self::Partial(_) => None, + Self::Partial(rc) => AnyComposerWeakHandle::Partial(std::rc::Rc::downgrade(rc)), + Self::Full(full) => AnyComposerWeakHandle::Full(full.downgrade()), } } +} - pub fn as_partial(&self) -> &PartialComposer { - match self { - Self::Full(full) => full.as_partial(), - Self::Partial(partial) => partial, - } +impl From for AnyComposerHandle { + fn from(h: FullComposerHandle) -> Self { + Self::Full(h) } +} - pub fn as_partial_mut(&mut self) -> &mut PartialComposer { +impl PartialComposer for AnyComposerHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { match self { - Self::Full(full) => full.as_partial_mut(), - Self::Partial(partial) => partial, + Self::Partial(rc) => rc.borrow_mut().package = Some(package), + Self::Full(f) => f.set_package(package), } } - - pub fn set_package(&mut self, package: RootPackageInterfaceHandle) { + fn get_package(&self) -> RootPackageInterfaceHandle { match self { - Self::Full(full) => full.set_package(package), - Self::Partial(partial) => partial.set_package(package), + Self::Partial(rc) => rc.borrow().package.as_ref().unwrap().clone(), + Self::Full(f) => f.get_package(), } } - - pub fn get_package(&self) -> &RootPackageInterfaceHandle { + fn set_config(&self, config: std::rc::Rc>) { match self { - Self::Full(full) => full.get_package(), - Self::Partial(partial) => partial.get_package(), + Self::Partial(rc) => rc.borrow_mut().config = Some(config), + Self::Full(f) => f.set_config(config), } } - - pub fn set_config(&mut self, config: std::rc::Rc>) { + fn get_config(&self) -> std::rc::Rc> { match self { - Self::Full(full) => full.set_config(config), - Self::Partial(partial) => partial.set_config(config), + Self::Partial(rc) => rc.borrow().config.as_ref().unwrap().clone(), + Self::Full(f) => f.get_config(), } } - - pub fn get_config(&self) -> std::rc::Rc> { + fn set_loop(&self, r#loop: std::rc::Rc>) { match self { - Self::Full(full) => full.get_config(), - Self::Partial(partial) => partial.get_config(), + Self::Partial(rc) => rc.borrow_mut().r#loop = Some(r#loop), + Self::Full(f) => f.set_loop(r#loop), } } - - pub fn set_loop(&mut self, r#loop: std::rc::Rc>) { + fn get_loop(&self) -> std::rc::Rc> { match self { - Self::Full(full) => full.set_loop(r#loop), - Self::Partial(partial) => partial.set_loop(r#loop), + Self::Partial(rc) => rc.borrow().r#loop.as_ref().unwrap().clone(), + Self::Full(f) => f.get_loop(), } } - - pub fn get_loop(&self) -> std::rc::Rc> { + fn set_repository_manager(&self, manager: std::rc::Rc>) { match self { - Self::Full(full) => full.get_loop(), - Self::Partial(partial) => partial.get_loop(), + Self::Partial(rc) => rc.borrow_mut().repository_manager = Some(manager), + Self::Full(f) => f.set_repository_manager(manager), } } - - pub fn set_repository_manager( - &mut self, - manager: std::rc::Rc>, - ) { + fn get_repository_manager(&self) -> std::rc::Rc> { match self { - Self::Full(full) => full.set_repository_manager(manager), - Self::Partial(partial) => partial.set_repository_manager(manager), + Self::Partial(rc) => rc.borrow().repository_manager.as_ref().unwrap().clone(), + Self::Full(f) => f.get_repository_manager(), } } - - pub fn get_repository_manager( + fn set_installation_manager( &self, - ) -> std::rc::Rc> { - match self { - Self::Full(full) => full.get_repository_manager(), - Self::Partial(partial) => partial.get_repository_manager(), - } - } - - pub fn set_installation_manager( - &mut self, - manager: std::rc::Rc>, + manager: std::rc::Rc>, ) { match self { - Self::Full(full) => full.set_installation_manager(manager), - Self::Partial(partial) => partial.set_installation_manager(manager), + Self::Partial(rc) => rc.borrow_mut().installation_manager = Some(manager), + Self::Full(f) => f.set_installation_manager(manager), } } - - pub fn get_installation_manager( - &self, - ) -> std::rc::Rc> { + fn get_installation_manager(&self) -> std::rc::Rc> { match self { - Self::Full(full) => full.get_installation_manager(), - Self::Partial(partial) => partial.get_installation_manager(), + Self::Partial(rc) => rc.borrow().installation_manager.as_ref().unwrap().clone(), + Self::Full(f) => f.get_installation_manager(), } } - - pub fn set_event_dispatcher( - &mut self, - dispatcher: std::rc::Rc>, + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc>, ) { match self { - Self::Full(full) => full.set_event_dispatcher(dispatcher), - Self::Partial(partial) => partial.set_event_dispatcher(dispatcher), + Self::Partial(rc) => rc.borrow_mut().event_dispatcher = Some(event_dispatcher), + Self::Full(f) => f.set_event_dispatcher(event_dispatcher), } } - - pub fn get_event_dispatcher( - &self, - ) -> std::rc::Rc> { + fn get_event_dispatcher(&self) -> std::rc::Rc> { match self { - Self::Full(full) => full.get_event_dispatcher(), - Self::Partial(partial) => partial.get_event_dispatcher(), + Self::Partial(rc) => rc.borrow().event_dispatcher.as_ref().unwrap().clone(), + Self::Full(f) => f.get_event_dispatcher(), } } - - pub fn is_global(&self) -> bool { + fn is_global(&self) -> bool { match self { - Self::Full(full) => full.is_global(), - Self::Partial(partial) => partial.is_global(), + Self::Partial(rc) => rc.borrow().global, + Self::Full(f) => f.is_global(), } } - - pub fn set_global(&mut self) { + fn set_global(&self) { match self { - Self::Full(full) => full.set_global(), - Self::Partial(partial) => partial.set_global(), + Self::Partial(rc) => rc.borrow_mut().global = true, + Self::Full(f) => f.set_global(), } } } -/// Shared reference to \Composer\PartialComposer or \Composer\Composer. -/// Use this for parameters or fields typed as \Composer\PartialComposer in PHP. +/// Shared weak reference to a \Composer\PartialComposer that may at runtime be either partial or full. #[derive(Debug, Clone)] -pub struct PartialComposerHandle(std::rc::Rc>); - -impl PartialComposerHandle { - pub fn borrow_partial(&self) -> std::cell::Ref<'_, PartialComposer> { - std::cell::Ref::map(self.0.borrow(), |c| c.as_partial()) - } - - pub fn borrow_partial_mut(&self) -> std::cell::RefMut<'_, PartialComposer> { - std::cell::RefMut::map(self.0.borrow_mut(), |c| c.as_partial_mut()) - } - - pub fn is_full(&self) -> bool { - self.0.borrow().is_full() - } +pub enum AnyComposerWeakHandle { + Partial(std::rc::Weak>), + Full(FullComposerWeakHandle), +} - /// Downcast to a full Composer handle. PHP `$composer instanceof Composer`. - pub fn as_full(&self) -> Option { - if self.0.borrow().is_full() { - Some(ComposerHandle::from_rc_unchecked(self.0.clone())) - } else { - None +impl AnyComposerWeakHandle { + pub fn upgrade(&self) -> Option { + match self { + Self::Partial(p) => p.upgrade().map(AnyComposerHandle::Partial), + Self::Full(f) => f.upgrade().map(AnyComposerHandle::Full), } } - pub fn downgrade(&self) -> PartialComposerWeakHandle { - PartialComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) + fn upgraded(&self) -> AnyComposerHandle { + self.upgrade() + .expect("PartialComposer has been dropped before its weak reference") } +} - pub fn from_rc(rc: std::rc::Rc>) -> Self { - Self(rc) +impl PartialComposer for AnyComposerWeakHandle { + fn set_package(&self, package: RootPackageInterfaceHandle) { + self.upgraded().set_package(package); } - - pub fn as_rc(&self) -> &std::rc::Rc> { - &self.0 + fn get_package(&self) -> RootPackageInterfaceHandle { + self.upgraded().get_package() } -} - -/// Shared weak reference to \Composer\PartialComposer or \Composer\Composer. -#[derive(Debug, Clone)] -pub struct PartialComposerWeakHandle(std::rc::Weak>); - -impl PartialComposerWeakHandle { - pub fn upgrade(&self) -> Option { - self.0.upgrade().map(PartialComposerHandle) + fn set_config(&self, config: std::rc::Rc>) { + self.upgraded().set_config(config); } - - pub fn from_weak(weak: std::rc::Weak>) -> Self { - Self(weak) + fn get_config(&self) -> std::rc::Rc> { + self.upgraded().get_config() } -} - -/// Shared reference to \Composer\Composer. -/// Use this for parameters or fields typed as \Composer\Composer in PHP. -#[derive(Debug, Clone)] -pub struct ComposerHandle(std::rc::Rc>); - -impl ComposerHandle { - pub fn borrow(&self) -> std::cell::Ref<'_, Composer> { - std::cell::Ref::map(self.0.borrow(), |c| { - c.as_full() - .expect("Composer handle invariant: inner is Full") - }) + fn set_loop(&self, r#loop: std::rc::Rc>) { + self.upgraded().set_loop(r#loop); } - - pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Composer> { - std::cell::RefMut::map(self.0.borrow_mut(), |c| { - c.as_full_mut() - .expect("Composer handle invariant: inner is Full") - }) + fn get_loop(&self) -> std::rc::Rc> { + self.upgraded().get_loop() } - - pub fn upcast(&self) -> PartialComposerHandle { - PartialComposerHandle::from_rc(self.0.clone()) + fn set_repository_manager(&self, manager: std::rc::Rc>) { + self.upgraded().set_repository_manager(manager); } - - pub fn downgrade(&self) -> ComposerWeakHandle { - ComposerWeakHandle(std::rc::Rc::downgrade(&self.0)) + fn get_repository_manager(&self) -> std::rc::Rc> { + self.upgraded().get_repository_manager() } - - pub fn from_rc_unchecked(rc: std::rc::Rc>) -> Self { - Self(rc) + fn set_installation_manager( + &self, + manager: std::rc::Rc>, + ) { + self.upgraded().set_installation_manager(manager); } - - pub fn as_rc(&self) -> &std::rc::Rc> { - &self.0 + fn get_installation_manager(&self) -> std::rc::Rc> { + self.upgraded().get_installation_manager() } -} - -impl From for PartialComposerHandle { - fn from(c: ComposerHandle) -> Self { - c.upcast() + fn set_event_dispatcher( + &self, + event_dispatcher: std::rc::Rc>, + ) { + self.upgraded().set_event_dispatcher(event_dispatcher); } -} - -/// Shared weak reference to \Composer\Composer. -#[derive(Debug, Clone)] -pub struct ComposerWeakHandle(std::rc::Weak>); - -impl ComposerWeakHandle { - pub fn upgrade(&self) -> Option { - self.0.upgrade().map(ComposerHandle) + fn get_event_dispatcher(&self) -> std::rc::Rc> { + self.upgraded().get_event_dispatcher() } - - pub fn from_weak(weak: std::rc::Weak>) -> Self { - Self(weak) + fn is_global(&self) -> bool { + self.upgraded().is_global() + } + fn set_global(&self) { + self.upgraded().set_global(); } } -/// Borrows a polymorphic `PartialComposer` as a fully-loaded `Composer`. +/// Downcasts a polymorphic composer handle to a fully-loaded \Composer\Composer. /// /// Commands obtain their Composer through `require_composer` / `create_composer_instance`, /// which always yield a fully-loaded instance, so the downcast is infallible here. -pub fn composer_full(composer: &PartialComposerHandle) -> std::cell::Ref<'_, Composer> { - std::cell::Ref::map(composer.as_rc().borrow(), |c| { - c.as_full() - .expect("a fully loaded Composer is required here") - }) -} - -/// Mutably borrows a polymorphic `PartialComposer` as a fully-loaded `Composer`. See [`composer_full`]. -pub fn composer_full_mut(composer: &PartialComposerHandle) -> std::cell::RefMut<'_, Composer> { - std::cell::RefMut::map(composer.as_rc().borrow_mut(), |c| { - c.as_full_mut() - .expect("a fully loaded Composer is required here") - }) +pub fn composer_full(composer: &AnyComposerHandle) -> FullComposerHandle { + composer + .as_full() + .expect("a fully loaded Composer is required here") } diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs index f27ed79..c8f8e43 100644 --- a/crates/shirabe/src/console/application.rs +++ b/crates/shirabe/src/console/application.rs @@ -67,8 +67,7 @@ use crate::command::SuggestsCommand; use crate::command::UpdateCommand; use crate::command::ValidateCommand; use crate::composer; -use crate::composer::ComposerHandle; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::console::GithubActionError; use crate::downloader::TransportException; use crate::event_dispatcher::ScriptExecutionException; @@ -89,7 +88,7 @@ use crate::util::Silencer; #[derive(Debug)] pub struct Application { inner: BaseApplication, - pub(crate) composer: Option, + pub(crate) composer: Option, pub(crate) io: std::rc::Rc>, has_plugin_commands: bool, disable_plugins_by_default: bool, @@ -854,7 +853,6 @@ impl Application { let composer = self.get_composer(false, Some(true), None)?; if composer.is_some() && function_exists("disk_free_space") { let composer = composer.unwrap(); - let composer = composer.borrow_partial(); let config = composer.get_config(); let min_space_free: f64 = 100.0 * 1024.0 * 1024.0; @@ -986,7 +984,7 @@ impl Application { required: bool, disable_plugins: Option, disable_scripts: Option, - ) -> anyhow::Result> { + ) -> anyhow::Result> { let disable_plugins = disable_plugins.unwrap_or(self.disable_plugins_by_default); let disable_scripts = disable_scripts.unwrap_or(self.disable_scripts_by_default); diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs index ef02660..49775d1 100644 --- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs +++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs @@ -19,8 +19,7 @@ use shirabe_php_shim::{ }; use crate::autoload::ClassLoader; -use crate::composer::PartialComposerHandle; -use crate::composer::PartialComposerWeakHandle; +use crate::composer::{AnyComposerHandle, AnyComposerWeakHandle, Composer, PartialComposer}; use crate::dependency_resolver::Transaction; use crate::dependency_resolver::operation::OperationInterface; use crate::event_dispatcher::Event; @@ -62,7 +61,7 @@ pub enum Callable { /// `$dispatcher->dispatch(ScriptEvents::POST_INSTALL_CMD);` #[derive(Debug)] pub struct EventDispatcher { - pub(crate) composer: PartialComposerWeakHandle, + pub(crate) composer: AnyComposerWeakHandle, pub(crate) io: std::rc::Rc>, pub(crate) loader: Option, pub(crate) process: std::rc::Rc>, @@ -76,7 +75,7 @@ pub struct EventDispatcher { impl EventDispatcher { pub fn new( - composer: PartialComposerWeakHandle, + composer: AnyComposerWeakHandle, io: std::rc::Rc>, process: Option>>, ) -> Self { @@ -704,7 +703,6 @@ impl EventDispatcher { .composer .upgrade() .expect("Composer was dropped before EventDispatcher use") - .borrow_partial() .get_package() .get_binaries(); if !possible_local_binaries.is_empty() { @@ -1081,7 +1079,6 @@ impl EventDispatcher { /// Finds all listeners defined as scripts in the package fn get_script_listeners(&self, event: &Event) -> Vec { let composer = self.composer(); - let composer = composer.borrow_partial(); let package = composer.get_package(); let scripts = package.get_scripts(); @@ -1163,7 +1160,6 @@ impl EventDispatcher { // add the bin dir to the PATH to make local binaries of deps usable in scripts let bin_dir = self .composer() - .borrow_partial() .get_config() .borrow_mut() .get("bin-dir") @@ -1234,8 +1230,6 @@ impl EventDispatcher { let Some(composer) = composer.as_full() else { return; }; - let composer = composer.borrow_mut(); - let callable_key = match callable { Callable::ArrayCallable(first, method) => { let prefix = if let PhpMixed::String(s) = first.as_ref() { @@ -1316,7 +1310,7 @@ impl EventDispatcher { todo!("clone std::rc::Rc>") } - fn composer(&self) -> PartialComposerHandle { + fn composer(&self) -> AnyComposerHandle { self.composer .upgrade() .expect("EventDispatcher must lives longer than Composer") diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs index 80f1548..73197ce 100644 --- a/crates/shirabe/src/factory.rs +++ b/crates/shirabe/src/factory.rs @@ -15,8 +15,10 @@ use shirabe_php_shim::{ use crate::autoload::AutoloadGenerator; use crate::cache::Cache; -use crate::composer::{ComposerWeakHandle, PartialOrFullComposer}; -use crate::composer::{PartialComposerHandle, PartialComposerWeakHandle}; +use crate::composer::{ + AnyComposerHandle, AnyComposerWeakHandle, Composer, FullComposerHandle, FullComposerWeakHandle, + InnerFullComposer, InnerPartialComposer, PartialComposer, +}; use crate::config::Config; use crate::config::JsonConfigSource; use crate::downloader::DownloadManager; @@ -90,6 +92,16 @@ impl DisablePlugins { } } +/// Shared managers produced while building the common (partial) part of a Composer, reused by the +/// full-load branch to wire the full-only managers (download/autoload/archive/locker). +struct ComposerBuildArtifacts { + http_downloader: std::rc::Rc>, + process: std::rc::Rc>, + r#loop: std::rc::Rc>, + dispatcher: std::rc::Rc>, + im: std::rc::Rc>, +} + /// Creates a configured instance of composer. pub struct Factory; @@ -436,7 +448,7 @@ impl Factory { cwd: Option<&str>, full_load: bool, disable_scripts: bool, - ) -> anyhow::Result { + ) -> anyhow::Result { // if a custom composer.json path is given, we change the default cwd to be that file's directory let mut local_config = local_config; let mut cwd = cwd.map(|s| s.to_string()); @@ -577,161 +589,50 @@ impl Factory { // PartialComposerWeak (Weak>). The closure cannot return a // Result, so construction errors are surfaced through `build_error`. let mut build_error: Option = None; - let composer = std::rc::Rc::new_cyclic( - |composer_weak: &std::rc::Weak>| { - let mut build = || -> anyhow::Result { - let mut composer: PartialOrFullComposer = if full_load { - PartialOrFullComposer::new_full() - } else { - PartialOrFullComposer::new_partial() - }; - composer.set_config(config.clone()); - if is_global { - composer.set_global(); - } - - if full_load { - // load auth configs into the IO instance - // TODO(phase-b): load_configuration requires &mut IOInterface; create_composer takes &dyn IOInterface - // io.load_configuration(&mut *config.borrow_mut())?; - - // load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it - // we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once - let installed_versions_path = format!( - "{}/composer/installed.php", - config.borrow_mut().get_str("vendor-dir")? - ); - if !disable_plugins.is_disabled_at_all() - && !disable_scripts - && !class_exists("Composer\\InstalledVersions") - && file_exists(&installed_versions_path) - { - // force loading the class at this point so it is loaded from the composer phar and not from the vendor dir - // as we cannot guarantee integrity of that file - if class_exists("Composer\\InstalledVersions") { - FilesystemRepository::safely_load_installed_versions( - &installed_versions_path, - ); - } - } - } - - let http_downloader = std::rc::Rc::new(std::cell::RefCell::new( - Self::create_http_downloader(io.clone(), &config, IndexMap::new())?, + let composer: AnyComposerHandle = if full_load { + let inner = std::rc::Rc::new_cyclic( + |composer_weak: &std::rc::Weak>| { + let weak = AnyComposerWeakHandle::Full(FullComposerWeakHandle::from_weak( + composer_weak.clone(), )); - let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new( - Some(io.clone()), - ))); - let r#loop = std::rc::Rc::new(std::cell::RefCell::new(Loop::new( - http_downloader.clone(), - Some(process.clone()), - ))); - composer.set_loop(r#loop.clone()); - - // initialize event dispatcher with the Composer back-reference - let dispatcher = { - let mut d = EventDispatcher::new( - PartialComposerWeakHandle::from_weak(composer_weak.clone()), + let mut full = InnerFullComposer::default(); + let mut build = || -> anyhow::Result<()> { + let artifacts = self.build_composer_base( + &mut full.partial, + weak, io.clone(), - Some(process.clone()), - ); - d.set_run_scripts(!disable_scripts); - std::rc::Rc::new(std::cell::RefCell::new(d)) - }; - composer.set_event_dispatcher(dispatcher.clone()); - - // initialize repository manager - let rm = std::rc::Rc::new(std::cell::RefCell::new(RepositoryFactory::manager( - io.clone(), - &config, - Some(http_downloader.clone()), - Some(dispatcher.clone()), - Some(process.clone()), - )?)); - - // force-set the version of the global package if not defined as - // guessing it adds no value and only takes time - if !full_load && !local_config_data.contains_key("version") { - local_config_data - .insert("version".to_string(), PhpMixed::String("1.0.0".to_string())); - } - - // load package - let parser = VersionParser::new(); - let guesser = VersionGuesser::new( - config.clone(), - process.clone(), - parser.clone(), - Some(io.clone()), - ); - let mut loader = self.load_root_package( - rm.clone(), - config.clone(), - parser, - guesser, - io.clone(), - ); - let package = loader.load( - local_config_data - .iter() - .map(|(k, v)| (k.clone(), Box::new(v.clone()))) - .collect(), - "Composer\\Package\\RootPackage", - Some(&cwd), - )?; - // TODO(phase-b): set_package expects RootPackageInterface; loader returns BasePackage - // composer.set_package(package); - let _ = package; - - // load local repository - self.add_local_repository( - io.clone(), - &mut rm.borrow_mut(), - &vendor_dir, - composer.get_package().clone(), - Some(&process), - ); - composer.set_repository_manager(rm.clone()); - - // initialize installation manager - let im = std::rc::Rc::new(std::cell::RefCell::new( - self.create_installation_manager( - r#loop.clone(), - io.clone(), - Some(dispatcher.clone()), - ), - )); - composer.set_installation_manager(im.clone()); + &config, + full_load, + is_global, + disable_plugins, + disable_scripts, + &mut local_config_data, + &cwd, + &vendor_dir, + )?; - if let PartialOrFullComposer::Full(ref mut composer_full) = composer { // initialize download manager let dm = self.create_download_manager( io.clone(), &config, - &http_downloader, - &process, - Some(&dispatcher), + &artifacts.http_downloader, + &artifacts.process, + Some(&artifacts.dispatcher), )?; - composer_full.set_download_manager(dm.clone()); + full.download_manager = Some(dm.clone()); // initialize autoload generator let generator = - AutoloadGenerator::new(dispatcher.clone(), Some(io.clone())); - composer_full.set_autoload_generator(std::rc::Rc::new( - std::cell::RefCell::new(generator), - )); + AutoloadGenerator::new(artifacts.dispatcher.clone(), Some(io.clone())); + full.autoload_generator = + Some(std::rc::Rc::new(std::cell::RefCell::new(generator))); // initialize archive manager - let am = self.create_archive_manager(&*config.borrow(), &dm, &r#loop)?; - composer_full - .set_archive_manager(std::rc::Rc::new(std::cell::RefCell::new(am))); - } + let am = + self.create_archive_manager(&*config.borrow(), &dm, &artifacts.r#loop)?; + full.archive_manager = Some(std::rc::Rc::new(std::cell::RefCell::new(am))); - // add installers to the manager (must happen after download manager is created since they read it out of $composer) - self.create_default_installers(&im, &composer, io.clone(), Some(&process)); - - // init locker if possible - if let PartialOrFullComposer::Full(ref mut composer_full) = composer { + // init locker if possible if let Some(ref composer_file_path) = composer_file { let lock_file = Self::get_lock_file(composer_file_path); let lock_enabled = config @@ -741,13 +642,13 @@ impl Factory { .unwrap_or(true); if !lock_enabled && file_exists(&lock_file) { io.write_error3( - &format!( - "{} is present but ignored as the \"lock\" config option is disabled.", - lock_file - ), - true, - crate::io::NORMAL, - ); + &format!( + "{} is present but ignored as the \"lock\" config option is disabled.", + lock_file + ), + true, + crate::io::NORMAL, + ); } let locker = Locker::new( @@ -761,12 +662,11 @@ impl Factory { None, Some(io.clone()), )?, - im.clone(), + artifacts.im.clone(), &file_get_contents(composer_file_path).unwrap_or_default(), - process.clone(), + artifacts.process.clone(), ); - composer_full - .set_locker(std::rc::Rc::new(std::cell::RefCell::new(locker))); + full.locker = Some(std::rc::Rc::new(std::cell::RefCell::new(locker))); } else { let lock_contents = JsonFile::encode( &PhpMixed::Array( @@ -780,26 +680,46 @@ impl Factory { let locker = Locker::new( io.clone(), JsonFile::new(Platform::get_dev_null(), None, Some(io.clone()))?, - im.clone(), + artifacts.im.clone(), &lock_contents, - process.clone(), + artifacts.process.clone(), ); - composer_full - .set_locker(std::rc::Rc::new(std::cell::RefCell::new(locker))); + full.locker = Some(std::rc::Rc::new(std::cell::RefCell::new(locker))); } + Ok(()) + }; + if let Err(e) = build() { + build_error = Some(e); } - - Ok(composer) - }; - match build() { - Ok(composer) => std::cell::RefCell::new(composer), - Err(e) => { + std::cell::RefCell::new(full) + }, + ); + AnyComposerHandle::Full(FullComposerHandle::from_rc(inner)) + } else { + let inner = std::rc::Rc::new_cyclic( + |composer_weak: &std::rc::Weak>| { + let weak = AnyComposerWeakHandle::Partial(composer_weak.clone()); + let mut partial = InnerPartialComposer::default(); + if let Err(e) = self.build_composer_base( + &mut partial, + weak, + io.clone(), + &config, + full_load, + is_global, + disable_plugins, + disable_scripts, + &mut local_config_data, + &cwd, + &vendor_dir, + ) { build_error = Some(e); - std::cell::RefCell::new(PartialOrFullComposer::new_partial()) } - } - }, - ); + std::cell::RefCell::new(partial) + }, + ); + AnyComposerHandle::Partial(inner) + }; if let Some(e) = build_error { return Err(e); } @@ -809,11 +729,8 @@ impl Factory { // PluginManager::new upgrades the Composer back-reference to read its config and locker, so // it must be built after Rc::new_cyclic returns; inside the closure the Rc is not yet // constructed and the weak handle cannot upgrade. - let (is_full, is_global) = { - let c = composer.borrow(); - (c.is_full(), c.is_global()) - }; - if is_full { + let is_global = composer.is_global(); + if let Some(full) = composer.as_full() { let global_composer = if !is_global { self.create_global_composer( io.clone(), @@ -828,16 +745,12 @@ impl Factory { let pm = self.create_plugin_manager( io.clone(), - ComposerWeakHandle::from_weak(std::rc::Rc::downgrade(&composer)), + full.downgrade(), global_composer, disable_plugins, ); let pm = std::rc::Rc::new(std::cell::RefCell::new(pm)); - composer - .borrow_mut() - .as_full_mut() - .unwrap() - .set_plugin_manager(pm.clone()); + full.set_plugin_manager(pm.clone()); if is_global { pm.borrow_mut().set_running_in_global_dir(true); @@ -850,7 +763,7 @@ impl Factory { // the Composer through the dispatcher) is safe only after the Rc has been constructed. let init_event = Event::from_name(PluginEvents::INIT.to_string()); let init_event_name = init_event.get_name().to_string(); - let dispatcher = composer.borrow().get_event_dispatcher(); + let dispatcher = composer.get_event_dispatcher(); dispatcher .borrow_mut() .dispatch(Some(&init_event_name), Some(init_event))?; @@ -861,14 +774,14 @@ impl Factory { // self.purge_packages(rm.get_local_repository(), &mut im)?; } - Ok(PartialComposerHandle::from_rc(composer)) + Ok(composer) } pub fn create_global( io: std::rc::Rc>, disable_plugins: DisablePlugins, disable_scripts: bool, - ) -> Option { + ) -> Option { let factory = Self; let config = Self::create_config(Some(io.clone()), None).ok()?; @@ -909,7 +822,7 @@ impl Factory { disable_plugins: DisablePlugins, disable_scripts: bool, full_load: bool, - ) -> Option { + ) -> Option { // make sure if disable plugins was 'local' it is now turned off let disable_plugins = if matches!( disable_plugins, @@ -1176,8 +1089,8 @@ impl Factory { fn create_plugin_manager( &self, io: std::rc::Rc>, - composer: ComposerWeakHandle, - global_composer: Option, + composer: FullComposerWeakHandle, + global_composer: Option, disable_plugins: DisablePlugins, ) -> PluginManager { PluginManager::new(io, composer, global_composer, disable_plugins) @@ -1192,10 +1105,143 @@ impl Factory { InstallationManager::new(r#loop, io, event_dispatcher) } + /// Builds the common (partial) part of a Composer into `composer`, returning the shared managers + /// the full-load branch needs to wire its full-only managers. PHP's PartialComposer constructor + /// flow lives here so both the partial and full `Rc::new_cyclic` branches can share it. + fn build_composer_base( + &self, + composer: &mut InnerPartialComposer, + composer_weak: AnyComposerWeakHandle, + io: std::rc::Rc>, + config: &std::rc::Rc>, + full_load: bool, + is_global: bool, + disable_plugins: DisablePlugins, + disable_scripts: bool, + local_config_data: &mut IndexMap, + cwd: &str, + vendor_dir: &str, + ) -> anyhow::Result { + composer.config = Some(config.clone()); + if is_global { + composer.global = true; + } + + if full_load { + // load auth configs into the IO instance + // TODO(phase-b): load_configuration requires &mut IOInterface; create_composer takes &dyn IOInterface + // io.load_configuration(&mut *config.borrow_mut())?; + + // load existing Composer\InstalledVersions instance if available and scripts/plugins are allowed, as they might need it + // we only load if the InstalledVersions class wasn't defined yet so that this is only loaded once + let installed_versions_path = format!( + "{}/composer/installed.php", + config.borrow_mut().get_str("vendor-dir")? + ); + if !disable_plugins.is_disabled_at_all() + && !disable_scripts + && !class_exists("Composer\\InstalledVersions") + && file_exists(&installed_versions_path) + { + // force loading the class at this point so it is loaded from the composer phar and not from the vendor dir + // as we cannot guarantee integrity of that file + if class_exists("Composer\\InstalledVersions") { + FilesystemRepository::safely_load_installed_versions(&installed_versions_path); + } + } + } + + let http_downloader = std::rc::Rc::new(std::cell::RefCell::new( + Self::create_http_downloader(io.clone(), config, IndexMap::new())?, + )); + let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some( + io.clone(), + )))); + let r#loop = std::rc::Rc::new(std::cell::RefCell::new(Loop::new( + http_downloader.clone(), + Some(process.clone()), + ))); + composer.r#loop = Some(r#loop.clone()); + + // initialize event dispatcher with the Composer back-reference + let dispatcher = { + let mut d = EventDispatcher::new(composer_weak, io.clone(), Some(process.clone())); + d.set_run_scripts(!disable_scripts); + std::rc::Rc::new(std::cell::RefCell::new(d)) + }; + composer.event_dispatcher = Some(dispatcher.clone()); + + // initialize repository manager + let rm = std::rc::Rc::new(std::cell::RefCell::new(RepositoryFactory::manager( + io.clone(), + config, + Some(http_downloader.clone()), + Some(dispatcher.clone()), + Some(process.clone()), + )?)); + + // force-set the version of the global package if not defined as + // guessing it adds no value and only takes time + if !full_load && !local_config_data.contains_key("version") { + local_config_data.insert("version".to_string(), PhpMixed::String("1.0.0".to_string())); + } + + // load package + let parser = VersionParser::new(); + let guesser = VersionGuesser::new( + config.clone(), + process.clone(), + parser.clone(), + Some(io.clone()), + ); + let mut loader = + self.load_root_package(rm.clone(), config.clone(), parser, guesser, io.clone()); + let package = loader.load( + local_config_data + .iter() + .map(|(k, v)| (k.clone(), Box::new(v.clone()))) + .collect(), + "Composer\\Package\\RootPackage", + Some(cwd), + )?; + // TODO(phase-b): set_package expects RootPackageInterface; loader returns BasePackage + // composer.package = Some(package); + let _ = package; + + // load local repository + self.add_local_repository( + io.clone(), + &mut rm.borrow_mut(), + vendor_dir, + composer.package.as_ref().unwrap().clone(), + Some(&process), + ); + composer.repository_manager = Some(rm.clone()); + + // initialize installation manager + let im = std::rc::Rc::new(std::cell::RefCell::new(self.create_installation_manager( + r#loop.clone(), + io.clone(), + Some(dispatcher.clone()), + ))); + composer.installation_manager = Some(im.clone()); + + // add installers to the manager (must happen after download manager is created since they read it out of $composer) + self.create_default_installers(&im, config, io.clone(), Some(&process)); + + Ok(ComposerBuildArtifacts { + http_downloader, + process, + r#loop, + dispatcher, + im, + }) + } + fn create_default_installers( &self, im: &std::rc::Rc>, - composer: &PartialOrFullComposer, + config: &std::rc::Rc>, io: std::rc::Rc>, process: Option<&std::rc::Rc>>, ) { @@ -1203,21 +1249,15 @@ impl Factory { process.map(std::rc::Rc::clone), ))); let bin_dir = trim( - &composer - .get_config() - .borrow_mut() - .get_str("bin-dir") - .unwrap_or_default(), + &config.borrow_mut().get_str("bin-dir").unwrap_or_default(), Some("/"), ); - let bin_compat = composer - .get_config() + let bin_compat = config .borrow_mut() .get_str("bin-compat") .unwrap_or_default(); let vendor_dir = trim( - &composer - .get_config() + &config .borrow_mut() .get_str("vendor-dir") .unwrap_or_default(), @@ -1266,7 +1306,7 @@ impl Factory { config: Option, disable_plugins: DisablePlugins, disable_scripts: bool, - ) -> anyhow::Result { + ) -> anyhow::Result { let factory = Self; // for BC reasons, if a config is passed in either as array or a path that is not the default composer.json path diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs index 14e75c0..30de843 100644 --- a/crates/shirabe/src/installer.rs +++ b/crates/shirabe/src/installer.rs @@ -45,7 +45,7 @@ use shirabe_semver; use crate::advisory::AuditConfig; use crate::advisory::Auditor; use crate::autoload::AutoloadGenerator; -use crate::composer::PartialComposerHandle; +use crate::composer::{AnyComposerHandle, Composer, PartialComposer}; use crate::config::Config; use crate::console::GithubActionError; use crate::dependency_resolver::DefaultPolicy; @@ -1646,7 +1646,7 @@ impl Installer { /// Create Installer pub fn create( io: std::rc::Rc>, - composer: &PartialComposerHandle, + composer: &AnyComposerHandle, ) -> Self { let composer = crate::composer::composer_full(composer); Self::new( diff --git a/crates/shirabe/src/installer/installer_event.rs b/crates/shirabe/src/installer/installer_event.rs index 5adde1c..00a0096 100644 --- a/crates/shirabe/src/installer/installer_event.rs +++ b/crates/shirabe/src/installer/installer_event.rs @@ -1,6 +1,6 @@ //! ref: composer/src/Composer/Installer/InstallerEvent.php -use crate::composer::ComposerWeakHandle; +use crate::composer::FullComposerWeakHandle; use crate::dependency_resolver::Transaction; use crate::event_dispatcher::Event; use crate::io::IOInterface; @@ -8,7 +8,7 @@ use crate::io::IOInterface; #[derive(Debug)] pub struct InstallerEvent { inner: Event, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, execute_operations: bool, @@ -18,7 +18,7 @@ pub struct InstallerEvent { impl InstallerEvent { pub fn new( event_name: String, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, execute_operations: bool, @@ -35,7 +35,7 @@ impl InstallerEvent { } } - pub fn get_composer(&self) -> &ComposerWeakHandle { + pub fn get_composer(&self) -> &FullComposerWeakHandle { &self.composer } diff --git a/crates/shirabe/src/installer/library_installer.rs b/crates/shirabe/src/installer/library_installer.rs index c1fedef..b50dbff 100644 --- a/crates/shirabe/src/installer/library_installer.rs +++ b/crates/shirabe/src/installer/library_installer.rs @@ -9,7 +9,7 @@ use shirabe_php_shim::{ realpath, rmdir, rtrim, strpos, }; -use crate::composer::PartialComposerWeakHandle; +use crate::composer::{AnyComposerWeakHandle, Composer, PartialComposer}; use crate::downloader::DownloadManager; use crate::installer::BinaryInstaller; use crate::installer::BinaryPresenceInterface; @@ -24,7 +24,7 @@ use crate::util::Silencer; /// Package installation manager. #[derive(Debug)] pub struct LibraryInstaller { - pub(crate) composer: PartialComposerWeakHandle, + pub(crate) composer: AnyComposerWeakHandle, pub(crate) vendor_dir: String, pub(crate) download_manager: Option>>, pub(crate) io: std::rc::Rc>, @@ -37,7 +37,7 @@ impl LibraryInstaller { /// Initializes library installer. pub fn new( io: std::rc::Rc>, - composer: PartialComposerWeakHandle, + composer: AnyComposerWeakHandle, r#type: Option, filesystem: Option>>, binary_installer: Option, @@ -48,15 +48,13 @@ impl LibraryInstaller { let download_manager = composer_rc .as_full() - .map(|full| full.borrow().get_download_manager()); - - let composer_ref = composer_rc.borrow_partial(); + .map(|full| full.get_download_manager()); let filesystem = filesystem .unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(None)))); let vendor_dir = rtrim( // TODO(phase-b): Config::get returns PhpMixed; coerce to String via get_str. - &composer_ref + &composer_rc .get_config() .borrow_mut() .get_str("vendor-dir") @@ -68,7 +66,7 @@ impl LibraryInstaller { // TODO(phase-b): pass io by reference/clone todo!("io reference"), rtrim( - &composer_ref + &composer_rc .get_config() .borrow_mut() .get_str("bin-dir") @@ -76,7 +74,7 @@ impl LibraryInstaller { Some("/"), ), // TODO(phase-b): Config::get returns PhpMixed; coerce to String via get_str. - composer_ref + composer_rc .get_config() .borrow_mut() .get_str("bin-compat") diff --git a/crates/shirabe/src/installer/package_event.rs b/crates/shirabe/src/installer/package_event.rs index 342732d..62bc395 100644 --- a/crates/shirabe/src/installer/package_event.rs +++ b/crates/shirabe/src/installer/package_event.rs @@ -1,6 +1,6 @@ //! ref: composer/src/Composer/Installer/PackageEvent.php -use crate::composer::ComposerWeakHandle; +use crate::composer::FullComposerWeakHandle; use crate::dependency_resolver::operation::OperationInterface; use crate::event_dispatcher::Event; use crate::io::IOInterface; @@ -10,7 +10,7 @@ use indexmap::IndexMap; #[derive(Debug)] pub struct PackageEvent { inner: Event, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, local_repo: Box, @@ -21,7 +21,7 @@ pub struct PackageEvent { impl PackageEvent { pub fn new( event_name: String, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, local_repo: Box, @@ -43,7 +43,7 @@ impl PackageEvent { self.inner.get_name() } - pub fn get_composer(&self) -> &ComposerWeakHandle { + pub fn get_composer(&self) -> &FullComposerWeakHandle { &self.composer } diff --git a/crates/shirabe/src/installer/plugin_installer.rs b/crates/shirabe/src/installer/plugin_installer.rs index 38fcb0d..8776103 100644 --- a/crates/shirabe/src/installer/plugin_installer.rs +++ b/crates/shirabe/src/installer/plugin_installer.rs @@ -1,6 +1,6 @@ //! ref: composer/src/Composer/Installer/PluginInstaller.php -use crate::composer::PartialComposerWeakHandle; +use crate::composer::AnyComposerWeakHandle; use crate::installer::BinaryInstaller; use crate::installer::InstallerInterface; use crate::installer::LibraryInstaller; @@ -22,7 +22,7 @@ pub struct PluginInstaller { impl PluginInstaller { pub fn new( io: std::rc::Rc>, - composer: PartialComposerWeakHandle, + composer: AnyComposerWeakHandle, fs: Option>>, binary_installer: Option, ) -> Self { diff --git a/crates/shirabe/src/plugin/plugin_interface.rs b/crates/shirabe/src/plugin/plugin_interface.rs index ae5e3b6..852c69b 100644 --- a/crates/shirabe/src/plugin/plugin_interface.rs +++ b/crates/shirabe/src/plugin/plugin_interface.rs @@ -1,17 +1,17 @@ //! ref: composer/src/Composer/Plugin/PluginInterface.php -use crate::composer::ComposerHandle; +use crate::composer::FullComposerHandle; use crate::io::IOInterface; use crate::plugin::Capable; pub const PLUGIN_API_VERSION: &'static str = "2.9.0"; pub trait PluginInterface: std::fmt::Debug { - fn activate(&mut self, composer: &ComposerHandle, io: &dyn IOInterface); + fn activate(&mut self, composer: &FullComposerHandle, io: &dyn IOInterface); - fn deactivate(&mut self, composer: &ComposerHandle, io: &dyn IOInterface); + fn deactivate(&mut self, composer: &FullComposerHandle, io: &dyn IOInterface); - fn uninstall(&mut self, composer: &ComposerHandle, io: &dyn IOInterface); + fn uninstall(&mut self, composer: &FullComposerHandle, io: &dyn IOInterface); fn clone_box(&self) -> Box { todo!() diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs index e2528ff..5f62047 100644 --- a/crates/shirabe/src/plugin/plugin_manager.rs +++ b/crates/shirabe/src/plugin/plugin_manager.rs @@ -16,8 +16,9 @@ use shirabe_php_shim::{ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::SimpleConstraint; -use crate::composer::PartialComposerHandle; -use crate::composer::{ComposerHandle, ComposerWeakHandle}; +use crate::composer::{ + AnyComposerHandle, Composer, FullComposerHandle, FullComposerWeakHandle, PartialComposer, +}; use crate::event_dispatcher::EventSubscriberInterface; use crate::factory::DisablePlugins; use crate::installer::InstallerInterface; @@ -42,9 +43,9 @@ use crate::util::PackageSorter; #[derive(Debug)] pub struct PluginManager { - pub(crate) composer: ComposerWeakHandle, + pub(crate) composer: FullComposerWeakHandle, pub(crate) io: std::rc::Rc>, - pub(crate) global_composer: Option, + pub(crate) global_composer: Option, pub(crate) version_parser: VersionParser, pub(crate) disable_plugins: DisablePlugins, pub(crate) plugins: Vec>, @@ -65,20 +66,19 @@ static mut CLASS_COUNTER: i64 = 0; impl PluginManager { pub fn new( io: std::rc::Rc>, - composer: ComposerWeakHandle, - global_composer: Option, + composer: FullComposerWeakHandle, + global_composer: Option, disable_plugins: DisablePlugins, ) -> Self { let composer_rc = composer .upgrade() .expect("PluginManager must not outlive Composer"); let allow_plugins_config = composer_rc - .borrow() .get_config() .borrow() .get("allow-plugins") .clone(); - let locker = composer_rc.borrow().get_locker().clone(); + let locker = composer_rc.get_locker().clone(); let mut locker = locker.borrow_mut(); let allow_plugin_rules = Self::parse_allowed_plugins(allow_plugins_config, Some(&mut *locker)); @@ -86,13 +86,7 @@ impl PluginManager { let allow_global_plugin_rules = Self::parse_allowed_plugins( global_composer .as_ref() - .map(|gc| { - gc.borrow_partial() - .get_config() - .borrow_mut() - .get("allow-plugins") - .clone() - }) + .map(|gc| gc.get_config().borrow_mut().get("allow-plugins").clone()) .unwrap_or(PhpMixed::Bool(false)), None, ); @@ -116,7 +110,7 @@ impl PluginManager { /// Upgrades the weak Composer back-reference to a full handle. PHP holds a strong /// `Composer`; the Rust port keeps it weak to break the Composer/PluginManager cycle. - fn composer_full(&self) -> ComposerHandle { + fn composer_full(&self) -> FullComposerHandle { self.composer .upgrade() .expect("PluginManager must not outlive Composer") @@ -131,14 +125,13 @@ impl PluginManager { // `&mut self`. The Rust port should eventually share via Rc>. let repo: Box = self .composer_full() - .borrow() .get_repository_manager() .borrow() .get_local_repository() .clone_box(); // The root package borrow is also tied to `self.composer`; clone the package handle // (shared Rc) for the same reason as above. - let root_package = self.composer_full().borrow().get_package().clone(); + let root_package = self.composer_full().get_package().clone(); self.load_repository(&*repo, false, Some(root_package))?; } @@ -147,7 +140,6 @@ impl PluginManager { .global_composer .as_ref() .unwrap() - .borrow_partial() .get_repository_manager() .borrow() .get_local_repository() @@ -163,7 +155,6 @@ impl PluginManager { if !self.are_plugins_disabled("local") { let repo: Box = self .composer_full() - .borrow() .get_repository_manager() .borrow() .get_local_repository() @@ -176,7 +167,6 @@ impl PluginManager { .global_composer .as_ref() .unwrap() - .borrow_partial() .get_repository_manager() .borrow() .get_local_repository() @@ -198,7 +188,7 @@ impl PluginManager { } /// Gets global composer or null when main composer is not fully loaded - pub fn get_global_composer(&self) -> Option<&PartialComposerHandle> { + pub fn get_global_composer(&self) -> Option<&AnyComposerHandle> { self.global_composer.as_ref() } @@ -357,7 +347,6 @@ impl PluginManager { match plugin { PluginOrInstaller::Installer(inst) => { self.composer_full() - .borrow() .get_installation_manager() .borrow_mut() .remove_installer(&*inst); @@ -384,7 +373,6 @@ impl PluginManager { match plugin { PluginOrInstaller::Installer(inst) => { self.composer_full() - .borrow() .get_installation_manager() .borrow_mut() .remove_installer(&*inst); @@ -635,7 +623,6 @@ impl PluginManager { if !global { return self .composer_full() - .borrow() .get_installation_manager() .borrow_mut() .get_install_path(package); @@ -645,7 +632,6 @@ impl PluginManager { self.global_composer .as_ref() .unwrap() - .borrow_partial() .get_installation_manager() .borrow_mut() .get_install_path(package) @@ -862,7 +848,6 @@ impl PluginManager { .composer .upgrade() .expect("PluginManager must not outlive Composer") - .borrow() .get_config() .clone(); diff --git a/crates/shirabe/src/repository/platform_repository.rs b/crates/shirabe/src/repository/platform_repository.rs index 1b95ff7..4290f15 100644 --- a/crates/shirabe/src/repository/platform_repository.rs +++ b/crates/shirabe/src/repository/platform_repository.rs @@ -15,7 +15,6 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::SimpleConstraint; use crate::composer; -use crate::composer::ComposerHandle; use crate::package::CompletePackage; use crate::package::CompletePackageHandle; use crate::package::CompletePackageInterface; diff --git a/crates/shirabe/src/script/event.rs b/crates/shirabe/src/script/event.rs index 60557b0..26f85ca 100644 --- a/crates/shirabe/src/script/event.rs +++ b/crates/shirabe/src/script/event.rs @@ -1,6 +1,6 @@ //! ref: composer/src/Composer/Script/Event.php -use crate::composer::ComposerWeakHandle; +use crate::composer::FullComposerWeakHandle; use crate::event_dispatcher::Event as BaseEvent; use crate::io::IOInterface; use indexmap::IndexMap; @@ -9,7 +9,7 @@ use shirabe_php_shim::PhpMixed; #[derive(Debug)] pub struct Event { inner: BaseEvent, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, originating_event: Option>, @@ -18,7 +18,7 @@ pub struct Event { impl Event { pub fn new( name: String, - composer: ComposerWeakHandle, + composer: FullComposerWeakHandle, io: std::rc::Rc>, dev_mode: bool, args: Vec, @@ -33,7 +33,7 @@ impl Event { } } - pub fn get_composer(&self) -> &ComposerWeakHandle { + pub fn get_composer(&self) -> &FullComposerWeakHandle { &self.composer } diff --git a/crates/shirabe/src/util/http_downloader.rs b/crates/shirabe/src/util/http_downloader.rs index 610bd3a..2a9f491 100644 --- a/crates/shirabe/src/util/http_downloader.rs +++ b/crates/shirabe/src/util/http_downloader.rs @@ -14,7 +14,6 @@ use shirabe_semver::constraint::AnyConstraint; use shirabe_semver::constraint::SimpleConstraint; use crate::composer; -use crate::composer::ComposerHandle; use crate::config::Config; use crate::downloader::TransportException; use crate::io::IOInterface; diff --git a/crates/shirabe/src/util/stream_context_factory.rs b/crates/shirabe/src/util/stream_context_factory.rs index 488d807..d1c281b 100644 --- a/crates/shirabe/src/util/stream_context_factory.rs +++ b/crates/shirabe/src/util/stream_context_factory.rs @@ -9,7 +9,6 @@ use shirabe_php_shim::{ }; use crate::composer; -use crate::composer::ComposerHandle; use crate::downloader::TransportException; use crate::repository::PlatformRepository; use crate::util::Filesystem; -- cgit v1.3.1