From 0b06f54103490e3ce5658e82bbc0119633e26cd8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 22 May 2026 01:29:48 +0900 Subject: refactor(composer): unify Composer/PartialComposer via Rc handles Model PHP's `Composer extends PartialComposer` as a PartialOrFullComposer enum and merge partial_composer.rs into composer.rs. Introduce ComposerHandle / PartialComposerHandle (plus their Weak variants) so the graph can be shared, and build it at once with Rc::new_cyclic in the factory to resolve the back-reference cycles. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/shirabe/src/command/base_command.rs | 42 ++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'crates/shirabe/src/command/base_command.rs') diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs index 2aebccb..9511c4d 100644 --- a/crates/shirabe/src/command/base_command.rs +++ b/crates/shirabe/src/command/base_command.rs @@ -17,7 +17,7 @@ use shirabe_php_shim::{ use crate::advisory::AuditConfig; use crate::advisory::Auditor; use crate::command::SelfUpdateCommand; -use crate::composer::Composer; +use crate::composer::PartialComposerHandle; use crate::config::Config; use crate::console::Application; use crate::console::input::InputArgument; @@ -160,23 +160,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: Composer); + fn set_composer(&mut self, composer: PartialComposerHandle); /// Removes the cached composer instance fn reset_composer(&mut self) -> Result<()>; @@ -205,7 +205,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( @@ -253,7 +253,7 @@ pub trait BaseCommand { #[derive(Debug)] pub struct BaseCommandData { - pub(crate) composer: Option, + pub(crate) composer: Option, pub(crate) io: Option>, } @@ -261,11 +261,11 @@ pub trait HasBaseCommandData { fn base_command_data(&self) -> &BaseCommandData; fn base_command_data_mut(&mut self) -> &mut BaseCommandData; - fn composer(&self) -> Option<&Composer> { - self.base_command_data().composer.as_ref() + 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 } @@ -289,7 +289,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)?, @@ -303,27 +303,25 @@ impl BaseCommand for C { &mut self, _disable_plugins: Option, _disable_scripts: Option, - ) -> Result { - // TODO(phase-b): Composer is a PHP class (shared by reference). Returning owned - // `Composer` and the Application::get_composer -> &Composer mismatch require a - // shared-ownership wrapper (Rc>) before this can be wired up. + ) -> Result { + // TODO(phase-b): depends on Application::get_composer, which is still stubbed. let _ = RuntimeException { message: String::new(), code: 0, }; - todo!("require_composer pending Composer shared-ownership refactor") + todo!("require_composer pending Application::get_composer") } fn try_composer( &mut self, _disable_plugins: Option, _disable_scripts: Option, - ) -> Option { - // TODO(phase-b): same shared-ownership refactor as require_composer. - todo!("try_composer pending Composer shared-ownership refactor") + ) -> 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: Composer) { + fn set_composer(&mut self, composer: PartialComposerHandle) { *self.composer_mut() = Some(composer); } @@ -389,7 +387,7 @@ impl BaseCommand for C { ); // TODO(phase-b): event_dispatcher.dispatch expects Option; need wrapper from // PreCommandRunEvent. - let _ = composer.get_event_dispatcher(); + let _ = composer.borrow_partial().get_event_dispatcher(); let _ = pre_command_run_event.get_name(); } @@ -482,7 +480,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) -- cgit v1.3.1