From f1af14b1cc503ac20f56a79a96c7780d02bdfe75 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 24 Jun 2026 03:56:26 +0900 Subject: fix(console): make Command/BaseCommand methods take &self The Command trait and Composer's BaseCommand took &mut self, so dispatch held a borrow_mut on the command's RefCell for the whole call. A command re-entering itself (e.g. the help command describing itself) then panicked with "RefCell already borrowed". All Command/BaseCommand methods now take &self and the command state is interior-mutable (Cell/RefCell). Shared borrows coexist, so re-entrant describe paths no longer conflict. Getters that returned references now return Ref guards; the descriptor describe_* methods take &dyn Command; mixin accessors return Ref/RefMut. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/symfony/console/command/command.rs | 350 +++++++++++---------- .../symfony/console/command/complete_command.rs | 22 +- .../console/command/dump_completion_command.rs | 6 +- .../src/symfony/console/command/help_command.rs | 23 +- .../src/symfony/console/command/list_command.rs | 6 +- .../src/symfony/console/descriptor/descriptor.rs | 4 +- .../symfony/console/descriptor/json_descriptor.rs | 12 +- .../console/descriptor/markdown_descriptor.rs | 8 +- .../symfony/console/descriptor/text_descriptor.rs | 4 +- .../symfony/console/descriptor/xml_descriptor.rs | 10 +- crates/shirabe/src/command/about_command.rs | 16 +- crates/shirabe/src/command/archive_command.rs | 20 +- crates/shirabe/src/command/audit_command.rs | 16 +- crates/shirabe/src/command/base_command.rs | 109 +++---- crates/shirabe/src/command/base_config_command.rs | 20 +- .../shirabe/src/command/base_dependency_command.rs | 25 +- crates/shirabe/src/command/bump_command.rs | 18 +- .../src/command/check_platform_reqs_command.rs | 18 +- crates/shirabe/src/command/clear_cache_command.rs | 16 +- crates/shirabe/src/command/config_command.rs | 256 ++++++++------- .../shirabe/src/command/create_project_command.rs | 35 ++- crates/shirabe/src/command/depends_command.rs | 28 +- crates/shirabe/src/command/diagnose_command.rs | 145 +++++---- .../shirabe/src/command/dump_autoload_command.rs | 16 +- crates/shirabe/src/command/exec_command.rs | 20 +- crates/shirabe/src/command/fund_command.rs | 16 +- crates/shirabe/src/command/global_command.rs | 18 +- crates/shirabe/src/command/home_command.rs | 22 +- crates/shirabe/src/command/init_command.rs | 66 ++-- crates/shirabe/src/command/install_command.rs | 16 +- crates/shirabe/src/command/licenses_command.rs | 16 +- crates/shirabe/src/command/outdated_command.rs | 16 +- .../shirabe/src/command/package_discovery_trait.rs | 18 +- crates/shirabe/src/command/prohibits_command.rs | 28 +- crates/shirabe/src/command/reinstall_command.rs | 16 +- crates/shirabe/src/command/remove_command.rs | 16 +- crates/shirabe/src/command/repository_command.rs | 125 ++++---- crates/shirabe/src/command/require_command.rs | 193 ++++++------ crates/shirabe/src/command/run_script_command.rs | 22 +- crates/shirabe/src/command/script_alias_command.rs | 16 +- crates/shirabe/src/command/search_command.rs | 16 +- crates/shirabe/src/command/self_update_command.rs | 16 +- crates/shirabe/src/command/show_command.rs | 90 +++--- crates/shirabe/src/command/status_command.rs | 18 +- crates/shirabe/src/command/suggests_command.rs | 16 +- crates/shirabe/src/command/update_command.rs | 16 +- crates/shirabe/src/command/validate_command.rs | 16 +- crates/shirabe/src/console/application.rs | 8 +- 48 files changed, 1034 insertions(+), 969 deletions(-) diff --git a/crates/shirabe-external-packages/src/symfony/console/command/command.rs b/crates/shirabe-external-packages/src/symfony/console/command/command.rs index 59aa915..652463f 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/command.rs @@ -12,7 +12,7 @@ use crate::symfony::console::input::input_option::InputOption; use crate::symfony::console::output::output_interface::{self, OutputInterface}; use indexmap::IndexMap; use shirabe_php_shim::PhpMixed; -use std::cell::RefCell; +use std::cell::{Cell, Ref, RefCell}; use std::rc::Rc; /// The base-class state of the PHP `Command` class. @@ -22,22 +22,28 @@ use std::rc::Rc; /// which holds the base-class fields and provides their canonical behavior via /// `impl Command for CommandData`. Subclasses embed a `CommandData` (directly, or /// transitively through `BaseCommandData`) and forward the state methods to it. +/// +/// The mutable fields use interior mutability (`Cell`/`RefCell`) so that the `Command` +/// trait methods take `&self`, mirroring PHP's reference semantics: calling a method on a +/// command does not lock the object, so a command can be re-entered (e.g. the help command +/// describing itself) without the borrow conflicts a `&mut self` design would cause. pub struct CommandData { - application: Option>>, - name: Option, - process_title: Option, - aliases: Vec, - definition: Option, - hidden: bool, - help: String, - description: String, - full_definition: Option, - ignore_validation_errors: bool, + application: RefCell>>>, + name: RefCell>, + process_title: RefCell>, + aliases: RefCell>, + definition: RefCell>, + hidden: Cell, + help: RefCell, + description: RefCell, + full_definition: RefCell>, + ignore_validation_errors: Cell, // A callable(InputInterface, OutputInterface) -> i64. - code: Option PhpMixed>>, - synopsis: IndexMap, - usages: Vec, - helper_set: Option>>, + code: + RefCell PhpMixed>>>, + synopsis: RefCell>, + usages: RefCell>, + helper_set: RefCell>>>, } impl CommandData { @@ -74,23 +80,23 @@ impl CommandData { /// command's `new()` calls `configure()` after embedding the data, mirroring the /// virtual dispatch of `$this->configure()` from the parent constructor. pub fn new(name: Option) -> Self { - let mut this = CommandData { - application: None, - name: None, - process_title: None, - aliases: Vec::new(), - definition: Some( + let this = CommandData { + application: RefCell::new(None), + name: RefCell::new(None), + process_title: RefCell::new(None), + aliases: RefCell::new(Vec::new()), + definition: RefCell::new(Some( InputDefinition::new(Vec::new()).expect("an empty InputDefinition cannot fail"), - ), - hidden: false, - help: String::new(), - description: String::new(), - full_definition: None, - ignore_validation_errors: false, - code: None, - synopsis: IndexMap::new(), - usages: Vec::new(), - helper_set: None, + )), + hidden: Cell::new(false), + help: RefCell::new(String::new()), + description: RefCell::new(String::new()), + full_definition: RefCell::new(None), + ignore_validation_errors: Cell::new(false), + code: RefCell::new(None), + synopsis: RefCell::new(IndexMap::new()), + usages: RefCell::new(Vec::new()), + helper_set: RefCell::new(None), }; // PHP's __construct also derives the name from getDefaultName() when null and @@ -98,7 +104,7 @@ impl CommandData { // (get_default_name/get_default_description are todo!()), and concrete commands // always set their name in configure(), so only an explicit name is honored here. if let Some(name) = name { - this.name = Some(name); + *this.name.borrow_mut() = Some(name); } this @@ -107,7 +113,7 @@ impl CommandData { /// Applies a `$defaultName`-style name (PHP `Command::__construct` when `$name` is null and a /// `static $defaultName` exists). The string is `|`-separated; a leading empty segment marks the /// command hidden, the next segment is the name, and the rest are aliases. - pub fn apply_default_name(&mut self, default_name: &str) -> anyhow::Result<()> { + pub fn apply_default_name(&self, default_name: &str) -> anyhow::Result<()> { let mut aliases: Vec = default_name.split('|').map(|s| s.to_string()).collect(); let mut name = aliases.remove(0); if name.is_empty() { @@ -144,17 +150,22 @@ impl CommandData { /// Sets an array of argument and option instances (the Symfony-typed entry point; /// `BaseCommand::set_definition` adapts the Composer-typed arguments to this). - pub fn set_definition(&mut self, definition: SetDefinitionArg) -> &mut Self { + pub fn set_definition(&self, definition: SetDefinitionArg) -> &Self { match definition { SetDefinitionArg::Definition(definition) => { - self.definition = Some(definition); + *self.definition.borrow_mut() = Some(definition); } SetDefinitionArg::Array(definition) => { - let _ = self.definition.as_mut().unwrap().set_definition(definition); + let _ = self + .definition + .borrow_mut() + .as_mut() + .unwrap() + .set_definition(definition); } } - self.full_definition = None; + *self.full_definition.borrow_mut() = None; self } @@ -163,13 +174,14 @@ impl CommandData { /// /// Throws InvalidArgumentException when argument mode is not valid. pub fn add_argument( - &mut self, + &self, name: &str, mode: Option, description: &str, default: PhpMixed, - ) -> anyhow::Result<&mut Self> { + ) -> anyhow::Result<&Self> { self.definition + .borrow_mut() .as_mut() .unwrap() .add_argument(InputArgument::new( @@ -178,7 +190,7 @@ impl CommandData { description.to_string(), default.clone(), )?)?; - if let Some(full_definition) = self.full_definition.as_mut() { + if let Some(full_definition) = self.full_definition.borrow_mut().as_mut() { full_definition.add_argument(InputArgument::new( name.to_string(), mode, @@ -194,14 +206,15 @@ impl CommandData { /// /// Throws InvalidArgumentException if option mode is invalid or incompatible. pub fn add_option( - &mut self, + &self, name: &str, shortcut: PhpMixed, mode: Option, description: &str, default: PhpMixed, - ) -> anyhow::Result<&mut Self> { + ) -> anyhow::Result<&Self> { self.definition + .borrow_mut() .as_mut() .unwrap() .add_option(InputOption::new( @@ -211,7 +224,7 @@ impl CommandData { description.to_string(), default.clone(), )?)?; - if let Some(full_definition) = self.full_definition.as_mut() { + if let Some(full_definition) = self.full_definition.borrow_mut().as_mut() { full_definition.add_option(InputOption::new( name, shortcut, @@ -239,21 +252,22 @@ pub enum SetDefinitionArg { /// Each `Command`/`BaseCommand` implementer spells out the methods it delegates, one /// `delegate_to_inner!` per method, alongside the few methods it overrides by hand. /// The first argument names the field to forward to; the second is the method's -/// signature. Fluent setters returning `&mut Self` (optionally wrapped in -/// `anyhow::Result`) are handled specially so the returned reference is re-rooted at -/// the outer `self` rather than the inner field. +/// signature. Every method takes `&self` (the command state is interior-mutable); +/// fluent setters returning `&Self` (optionally wrapped in `anyhow::Result`) are handled +/// specially so the returned reference is re-rooted at the outer `self` rather than the +/// inner field. #[macro_export] macro_rules! delegate_to_inner { - // fluent fallible: -> anyhow::Result<&mut Self> - ($field:ident, fn $name:ident(&mut self $(, $arg:ident : $ty:ty )* $(,)?) -> anyhow::Result<&mut Self>) => { - fn $name(&mut self $(, $arg: $ty)*) -> anyhow::Result<&mut Self> { + // fluent fallible: -> anyhow::Result<&Self> + ($field:ident, fn $name:ident(&self $(, $arg:ident : $ty:ty )* $(,)?) -> anyhow::Result<&Self>) => { + fn $name(&self $(, $arg: $ty)*) -> anyhow::Result<&Self> { self.$field.$name($($arg),*)?; Ok(self) } }; - // fluent infallible: -> &mut Self - ($field:ident, fn $name:ident(&mut self $(, $arg:ident : $ty:ty )* $(,)?) -> &mut Self) => { - fn $name(&mut self $(, $arg: $ty)*) -> &mut Self { + // fluent infallible: -> &Self + ($field:ident, fn $name:ident(&self $(, $arg:ident : $ty:ty )* $(,)?) -> &Self) => { + fn $name(&self $(, $arg: $ty)*) -> &Self { self.$field.$name($($arg),*); self } @@ -270,18 +284,6 @@ macro_rules! delegate_to_inner { self.$field.$name($($arg),*) } }; - // &mut self with a return type - ($field:ident, fn $name:ident(&mut self $(, $arg:ident : $ty:ty )* $(,)?) -> $ret:ty) => { - fn $name(&mut self $(, $arg: $ty)*) -> $ret { - self.$field.$name($($arg),*) - } - }; - // &mut self without a return type - ($field:ident, fn $name:ident(&mut self $(, $arg:ident : $ty:ty )* $(,)?)) => { - fn $name(&mut self $(, $arg: $ty)*) { - self.$field.$name($($arg),*) - } - }; } /// Forwards every `Command` state method (the setters/getters whose canonical impl lives on @@ -293,33 +295,33 @@ macro_rules! delegate_to_inner { macro_rules! delegate_command_trait_impls_to_inner { ($field:ident) => { $crate::delegate_to_inner!($field, fn is_enabled(&self) -> bool); - $crate::delegate_to_inner!($field, fn set_application(&mut self, application: Option>>)); + $crate::delegate_to_inner!($field, fn set_application(&self, application: Option>>)); $crate::delegate_to_inner!($field, fn get_application(&self) -> Option>>); - $crate::delegate_to_inner!($field, fn set_helper_set(&mut self, helper_set: std::rc::Rc>)); + $crate::delegate_to_inner!($field, fn set_helper_set(&self, helper_set: std::rc::Rc>)); $crate::delegate_to_inner!($field, fn get_helper_set(&self) -> Option>>); - $crate::delegate_to_inner!($field, fn merge_application_definition(&mut self, merge_args: bool)); - $crate::delegate_to_inner!($field, fn get_definition(&self) -> &$crate::symfony::console::input::input_definition::InputDefinition); - $crate::delegate_to_inner!($field, fn get_native_definition(&self) -> &$crate::symfony::console::input::input_definition::InputDefinition); - $crate::delegate_to_inner!($field, fn set_name(&mut self, name: &str) -> anyhow::Result<()>); + $crate::delegate_to_inner!($field, fn merge_application_definition(&self, merge_args: bool)); + $crate::delegate_to_inner!($field, fn get_definition(&self) -> std::cell::Ref<'_, $crate::symfony::console::input::input_definition::InputDefinition>); + $crate::delegate_to_inner!($field, fn get_native_definition(&self) -> std::cell::Ref<'_, $crate::symfony::console::input::input_definition::InputDefinition>); + $crate::delegate_to_inner!($field, fn set_name(&self, name: &str) -> anyhow::Result<()>); $crate::delegate_to_inner!($field, fn get_name(&self) -> Option); - $crate::delegate_to_inner!($field, fn set_process_title(&mut self, title: &str)); + $crate::delegate_to_inner!($field, fn set_process_title(&self, title: &str)); $crate::delegate_to_inner!($field, fn get_process_title(&self) -> Option); - $crate::delegate_to_inner!($field, fn set_hidden(&mut self, hidden: bool)); + $crate::delegate_to_inner!($field, fn set_hidden(&self, hidden: bool)); $crate::delegate_to_inner!($field, fn is_hidden(&self) -> bool); - $crate::delegate_to_inner!($field, fn set_description(&mut self, description: &str)); + $crate::delegate_to_inner!($field, fn set_description(&self, description: &str)); $crate::delegate_to_inner!($field, fn get_description(&self) -> String); - $crate::delegate_to_inner!($field, fn set_help(&mut self, help: &str)); + $crate::delegate_to_inner!($field, fn set_help(&self, help: &str)); $crate::delegate_to_inner!($field, fn get_help(&self) -> String); $crate::delegate_to_inner!($field, fn get_processed_help(&self) -> String); - $crate::delegate_to_inner!($field, fn set_aliases(&mut self, aliases: Vec) -> anyhow::Result<()>); + $crate::delegate_to_inner!($field, fn set_aliases(&self, aliases: Vec) -> anyhow::Result<()>); $crate::delegate_to_inner!($field, fn get_aliases(&self) -> Vec); - $crate::delegate_to_inner!($field, fn get_synopsis(&mut self, short: bool) -> String); - $crate::delegate_to_inner!($field, fn add_usage(&mut self, usage: &str)); + $crate::delegate_to_inner!($field, fn get_synopsis(&self, short: bool) -> String); + $crate::delegate_to_inner!($field, fn add_usage(&self, usage: &str)); $crate::delegate_to_inner!($field, fn get_usages(&self) -> Vec); $crate::delegate_to_inner!($field, fn get_helper(&self, name: &str) -> anyhow::Result>); - $crate::delegate_to_inner!($field, fn set_code(&mut self, code: Box shirabe_php_shim::PhpMixed>)); - $crate::delegate_to_inner!($field, fn get_code(&self) -> Option<&Box shirabe_php_shim::PhpMixed>>); - $crate::delegate_to_inner!($field, fn ignore_validation_errors(&mut self)); + $crate::delegate_to_inner!($field, fn set_code(&self, code: Box shirabe_php_shim::PhpMixed>)); + $crate::delegate_to_inner!($field, fn get_code(&self) -> std::cell::Ref<'_, Option shirabe_php_shim::PhpMixed>>>); + $crate::delegate_to_inner!($field, fn ignore_validation_errors(&self)); $crate::delegate_to_inner!($field, fn get_ignore_validation_errors(&self) -> bool); }; } @@ -329,8 +331,8 @@ macro_rules! delegate_command_trait_impls_to_inner { /// /// The canonical behavior lives in `impl Command for CommandData`; subclasses forward /// the state methods there and override the behavior hooks (`configure`/`execute`/...). -/// Object-safe so `dyn Command` works; the fluent `where Self: Sized` setters are only -/// called from `configure()` on a concrete command, never through `dyn Command`. +/// Object-safe so `dyn Command` works. All methods take `&self`; the command's mutable +/// state is interior-mutable (see [`CommandData`]). pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { fn clone_box(&self) -> Box { todo!() @@ -339,7 +341,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { // --- behavior hooks (PHP-overridable; defaults match the PHP `Command` class) --- /// Configures the current command. - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { Ok(()) } @@ -348,7 +350,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { /// Concrete commands override this; reaching the default means a command class /// forgot to implement it (PHP throws LogicException — a programming error here). fn execute( - &mut self, + &self, _input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -357,7 +359,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { /// Interacts with the user before the InputDefinition is validated. fn interact( - &mut self, + &self, _input: Rc>, _output: Rc>, ) { @@ -365,7 +367,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { /// Initializes the command after the input has been bound and before it is validated. fn initialize( - &mut self, + &self, _input: Rc>, _output: Rc>, ) -> anyhow::Result<()> { @@ -390,7 +392,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { /// not be overridden (except by proxy commands like `GlobalCommand`) nor delegated, /// or that late binding breaks. fn run( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -402,7 +404,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { /// matching PHP's `parent::run($input, $output)`. It must not be overridden, or the late /// binding of `initialize`/`interact`/`execute` to the concrete command breaks. fn base_run( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -410,7 +412,7 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { self.merge_application_definition(true); // bind the input against the command specific arguments/options - match input.borrow_mut().bind(self.get_definition()) { + match input.borrow_mut().bind(&*self.get_definition()) { Ok(()) => {} Err(e) => { if !self.get_ignore_validation_errors() { @@ -463,7 +465,9 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { input.borrow_mut().validate()?; let status_code: PhpMixed; - if let Some(code) = self.get_code() { + if self.get_code().is_some() { + let code = self.get_code(); + let code = code.as_ref().unwrap(); status_code = code(&mut *input.borrow_mut(), &mut *output.borrow_mut()); } else { let executed = self.execute(input.clone(), output.clone())?; @@ -480,49 +484,49 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { fn is_enabled(&self) -> bool; - fn set_application(&mut self, application: Option>>); + fn set_application(&self, application: Option>>); fn get_application(&self) -> Option>>; - fn set_helper_set(&mut self, helper_set: Rc>); + fn set_helper_set(&self, helper_set: Rc>); fn get_helper_set(&self) -> Option>>; - fn merge_application_definition(&mut self, merge_args: bool); + fn merge_application_definition(&self, merge_args: bool); - fn get_definition(&self) -> &InputDefinition; + fn get_definition(&self) -> Ref<'_, InputDefinition>; - fn get_native_definition(&self) -> &InputDefinition; + fn get_native_definition(&self) -> Ref<'_, InputDefinition>; - fn set_name(&mut self, name: &str) -> anyhow::Result<()>; + fn set_name(&self, name: &str) -> anyhow::Result<()>; fn get_name(&self) -> Option; - fn set_process_title(&mut self, title: &str); + fn set_process_title(&self, title: &str); fn get_process_title(&self) -> Option; - fn set_hidden(&mut self, hidden: bool); + fn set_hidden(&self, hidden: bool); fn is_hidden(&self) -> bool; - fn set_description(&mut self, description: &str); + fn set_description(&self, description: &str); fn get_description(&self) -> String; - fn set_help(&mut self, help: &str); + fn set_help(&self, help: &str); fn get_help(&self) -> String; fn get_processed_help(&self) -> String; - fn set_aliases(&mut self, aliases: Vec) -> anyhow::Result<()>; + fn set_aliases(&self, aliases: Vec) -> anyhow::Result<()>; fn get_aliases(&self) -> Vec; - fn get_synopsis(&mut self, short: bool) -> String; + fn get_synopsis(&self, short: bool) -> String; - fn add_usage(&mut self, usage: &str); + fn add_usage(&self, usage: &str); fn get_usages(&self) -> Vec; @@ -534,15 +538,15 @@ pub trait Command: std::fmt::Debug + shirabe_php_shim::AsAny { >; fn set_code( - &mut self, + &self, code: Box PhpMixed>, ); fn get_code( &self, - ) -> Option<&Box PhpMixed>>; + ) -> Ref<'_, Option PhpMixed>>>; - fn ignore_validation_errors(&mut self); + fn ignore_validation_errors(&self); fn get_ignore_validation_errors(&self) -> bool; } @@ -552,32 +556,32 @@ impl Command for CommandData { true } - fn set_application(&mut self, application: Option>>) { - self.application = application.clone(); + fn set_application(&self, application: Option>>) { + *self.application.borrow_mut() = application.clone(); if let Some(application) = application { self.set_helper_set(application.borrow_mut().get_helper_set()); } else { - self.helper_set = None; + *self.helper_set.borrow_mut() = None; } - self.full_definition = None; + *self.full_definition.borrow_mut() = None; } fn get_application(&self) -> Option>> { - self.application.clone() + self.application.borrow().clone() } - fn set_helper_set(&mut self, helper_set: Rc>) { - self.helper_set = Some(helper_set); + fn set_helper_set(&self, helper_set: Rc>) { + *self.helper_set.borrow_mut() = Some(helper_set); } fn get_helper_set(&self) -> Option>> { - self.helper_set.clone() + self.helper_set.borrow().clone() } /// Merges the application definition with the command definition. - fn merge_application_definition(&mut self, merge_args: bool) { - let application = match &self.application { + fn merge_application_definition(&self, merge_args: bool) { + let application = match &*self.application.borrow() { None => return, Some(application) => application.clone(), }; @@ -591,6 +595,7 @@ impl Command for CommandData { let own_options: Vec = self .definition + .borrow() .as_ref() .unwrap() .get_options() @@ -624,6 +629,7 @@ impl Command for CommandData { let own_arguments: Vec = self .definition + .borrow() .as_ref() .unwrap() .get_arguments() @@ -636,6 +642,7 @@ impl Command for CommandData { } else { let own_arguments: Vec = self .definition + .borrow() .as_ref() .unwrap() .get_arguments() @@ -647,18 +654,22 @@ impl Command for CommandData { .expect("the command's own arguments are already valid"); } - self.full_definition = Some(full_definition); + *self.full_definition.borrow_mut() = Some(full_definition); } - fn get_definition(&self) -> &InputDefinition { - match &self.full_definition { - Some(full_definition) => full_definition, - None => self.get_native_definition(), + fn get_definition(&self) -> Ref<'_, InputDefinition> { + if self.full_definition.borrow().is_some() { + Ref::map(self.full_definition.borrow(), |full_definition| { + full_definition.as_ref().unwrap() + }) + } else { + self.get_native_definition() } } - fn get_native_definition(&self) -> &InputDefinition { - match &self.definition { + fn get_native_definition(&self) -> Ref<'_, InputDefinition> { + Ref::map(self.definition.borrow(), |definition| match definition { + Some(definition) => definition, None => { // PHP throws LogicException; `definition` is set in `new()`, so None is a // programming error (forgot to call the parent constructor). @@ -666,59 +677,58 @@ impl Command for CommandData { "Command class is not correctly initialized. You probably forgot to call the parent constructor." ); } - Some(definition) => definition, - } + }) } - fn set_name(&mut self, name: &str) -> anyhow::Result<()> { + fn set_name(&self, name: &str) -> anyhow::Result<()> { if let Err(e) = self.validate_name(name)? { return Err(e.into()); } - self.name = Some(name.to_string()); + *self.name.borrow_mut() = Some(name.to_string()); Ok(()) } fn get_name(&self) -> Option { - self.name.clone() + self.name.borrow().clone() } - fn set_process_title(&mut self, title: &str) { - self.process_title = Some(title.to_string()); + fn set_process_title(&self, title: &str) { + *self.process_title.borrow_mut() = Some(title.to_string()); } fn get_process_title(&self) -> Option { - self.process_title.clone() + self.process_title.borrow().clone() } - fn set_hidden(&mut self, hidden: bool) { - self.hidden = hidden; + fn set_hidden(&self, hidden: bool) { + self.hidden.set(hidden); } fn is_hidden(&self) -> bool { - self.hidden + self.hidden.get() } - fn set_description(&mut self, description: &str) { - self.description = description.to_string(); + fn set_description(&self, description: &str) { + *self.description.borrow_mut() = description.to_string(); } fn get_description(&self) -> String { - self.description.clone() + self.description.borrow().clone() } - fn set_help(&mut self, help: &str) { - self.help = help.to_string(); + fn set_help(&self, help: &str) { + *self.help.borrow_mut() = help.to_string(); } fn get_help(&self) -> String { - self.help.clone() + self.help.borrow().clone() } fn get_processed_help(&self) -> String { - let name = self.name.clone(); - let is_single_command = match &self.application { + let name = self.name.borrow().clone(); + let is_single_command = match &*self.application.borrow() { Some(application) => application.borrow().is_single_command(), None => false, }; @@ -747,7 +757,7 @@ impl Command for CommandData { shirabe_php_shim::str_replace_array(&placeholders, &replacements, &subject) } - fn set_aliases(&mut self, aliases: Vec) -> anyhow::Result<()> { + fn set_aliases(&self, aliases: Vec) -> anyhow::Result<()> { let mut list = Vec::new(); for alias in &aliases { @@ -759,44 +769,48 @@ impl Command for CommandData { // PHP: `\is_array($aliases) ? $aliases : $list`. Here `aliases` is always an // array (Vec), so the result is `aliases`; `list` mirrors the validation loop. - self.aliases = aliases; + *self.aliases.borrow_mut() = aliases; Ok(()) } fn get_aliases(&self) -> Vec { - self.aliases.clone() + self.aliases.borrow().clone() } - fn get_synopsis(&mut self, short: bool) -> String { + fn get_synopsis(&self, short: bool) -> String { let key = if short { "short" } else { "long" }.to_string(); - if !self.synopsis.contains_key(&key) { + if !self.synopsis.borrow().contains_key(&key) { let value = format!( "{} {}", - self.name.clone().unwrap_or_default(), - self.definition.as_ref().unwrap().get_synopsis(short) + self.name.borrow().clone().unwrap_or_default(), + self.definition + .borrow() + .as_ref() + .unwrap() + .get_synopsis(short) ) .trim() .to_string(); - self.synopsis.insert(key.clone(), value); + self.synopsis.borrow_mut().insert(key.clone(), value); } - self.synopsis[&key].clone() + self.synopsis.borrow()[&key].clone() } - fn add_usage(&mut self, usage: &str) { + fn add_usage(&self, usage: &str) { let mut usage = usage.to_string(); - let name = self.name.clone().unwrap_or_default(); + let name = self.name.borrow().clone().unwrap_or_default(); if !usage.starts_with(&name) { usage = format!("{} {}", name, usage); } - self.usages.push(usage); + self.usages.borrow_mut().push(usage); } fn get_usages(&self) -> Vec { - self.usages.clone() + self.usages.borrow().clone() } fn get_helper( @@ -805,7 +819,8 @@ impl Command for CommandData { ) -> anyhow::Result< Result, > { - let helper_set = match &self.helper_set { + let helper_set_ref = self.helper_set.borrow(); + let helper_set = match &*helper_set_ref { None => { return Ok(Err( crate::symfony::console::exception::logic_exception::LogicException( @@ -832,37 +847,38 @@ impl Command for CommandData { } fn set_code( - &mut self, + &self, code: Box PhpMixed>, ) { // TODO: PHP rebinds an unbound Closure's $this to the command instance via // ReflectionFunction/Closure::bind. Rust closures have no `$this` rebinding; // the closure is stored as-is. - self.code = Some(code); + *self.code.borrow_mut() = Some(code); } fn get_code( &self, - ) -> Option<&Box PhpMixed>> { - self.code.as_ref() + ) -> Ref<'_, Option PhpMixed>>> + { + self.code.borrow() } - fn ignore_validation_errors(&mut self) { - self.ignore_validation_errors = true; + fn ignore_validation_errors(&self) { + self.ignore_validation_errors.set(true); } fn get_ignore_validation_errors(&self) -> bool { - self.ignore_validation_errors + self.ignore_validation_errors.get() } } impl std::fmt::Debug for CommandData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CommandData") - .field("name", &self.name) - .field("aliases", &self.aliases) - .field("hidden", &self.hidden) - .field("description", &self.description) + .field("name", &self.name.borrow()) + .field("aliases", &self.aliases.borrow()) + .field("hidden", &self.hidden.get()) + .field("description", &self.description.borrow()) .finish_non_exhaustive() } } diff --git a/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs index 1bae4ad..cc700dc 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/complete_command.rs @@ -22,7 +22,7 @@ use crate::symfony::console::output::output_interface::OutputInterface; pub struct CompleteCommand { inner: CommandData, completion_outputs: IndexMap, - is_debug: bool, + is_debug: std::cell::Cell, } impl Deref for CompleteCommand { @@ -59,10 +59,10 @@ impl CompleteCommand { ) }); - let mut this = Self { + let this = Self { inner: CommandData::new(None), completion_outputs, - is_debug: false, + is_debug: std::cell::Cell::new(false), }; // PHP: static $defaultName = '|_complete' / $defaultDescription, applied by the parent // constructor before configure(). @@ -121,7 +121,7 @@ impl CompleteCommand { } fn log_many(&self, messages: Vec) { - if !self.is_debug { + if !self.is_debug.get() { return; } @@ -159,7 +159,7 @@ fn instantiate_completion_output(_class: &PhpMixed) -> Box anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { let shells = self .completion_outputs .keys() @@ -200,20 +200,20 @@ impl Command for CompleteCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { let _ = (input, output); - self.is_debug = shirabe_php_shim::filter_var_boolean( + self.is_debug.set(shirabe_php_shim::filter_var_boolean( &shirabe_php_shim::getenv("SYMFONY_COMPLETION_DEBUG").unwrap_or_default(), - ); + )); Ok(()) } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -307,8 +307,8 @@ impl Command for CompleteCommand { ); } Some(command) => { - command.borrow_mut().merge_application_definition(false); - completion_input.bind(command.borrow().get_definition())?; + command.borrow().merge_application_definition(false); + completion_input.bind(&*command.borrow().get_definition())?; if CompletionInput::TYPE_OPTION_NAME == completion_input.get_completion_type() { self.log(&format!( diff --git a/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs index cb76ff8..306bd59 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/dump_completion_command.rs @@ -45,7 +45,7 @@ impl DumpCompletionCommand { pub const DEFAULT_DESCRIPTION: &'static str = "Dump the shell completion script"; pub fn new() -> Self { - let mut command = DumpCompletionCommand { + let command = DumpCompletionCommand { inner: CommandData::new(None), }; // PHP: static $defaultName = 'completion' / $defaultDescription, applied by the parent @@ -111,7 +111,7 @@ impl DumpCompletionCommand { } impl Command for DumpCompletionCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { let full_command = shirabe_php_shim::server_php_self(); let command_name = shirabe_php_shim::basename(&full_command); // @realpath($fullCommand) ?: $fullCommand @@ -166,7 +166,7 @@ impl Command for DumpCompletionCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { diff --git a/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs index 2346258..8ef488f 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/help_command.rs @@ -22,7 +22,7 @@ use std::rc::Rc; #[derive(Debug)] pub struct HelpCommand { inner: CommandData, - command: Option>>, + command: RefCell>>>, } impl Deref for HelpCommand { @@ -47,9 +47,9 @@ impl Default for HelpCommand { impl HelpCommand { pub fn new() -> Self { - let mut command = HelpCommand { + let command = HelpCommand { inner: CommandData::new(None), - command: None, + command: RefCell::new(None), }; command .configure() @@ -57,8 +57,8 @@ impl HelpCommand { command } - pub fn set_command(&mut self, command: Rc>) { - self.command = Some(command); + pub fn set_command(&self, command: Rc>) { + *self.command.borrow_mut() = Some(command); } pub fn complete_impl(&self, input: &CompletionInput, suggestions: &mut CompletionSuggestions) { @@ -91,7 +91,7 @@ impl HelpCommand { } impl Command for HelpCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.inner.ignore_validation_errors(); self.inner.set_name("help")?; @@ -134,24 +134,25 @@ impl Command for HelpCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { - if self.command.is_none() { + if self.command.borrow().is_none() { let application = self.get_application().unwrap(); let command_name = input.borrow().get_argument("command_name")?.to_string(); - self.command = Some(application.borrow_mut().find(&command_name)?); + let found = application.borrow_mut().find(&command_name)?; + *self.command.borrow_mut() = Some(found); } let mut helper = DescriptorHelper::new(); - let object = DescribableObject::Command(self.command.clone().unwrap()); + let object = DescribableObject::Command(self.command.borrow().clone().unwrap()); let mut options = indexmap::IndexMap::new(); options.insert("format".to_string(), input.borrow().get_option("format")?); options.insert("raw_text".to_string(), input.borrow().get_option("raw")?); helper.describe2(output.clone(), object, options)?; - self.command = None; + *self.command.borrow_mut() = None; Ok(0) } diff --git a/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs b/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs index 1d467ae..4f6e923 100644 --- a/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs +++ b/crates/shirabe-external-packages/src/symfony/console/command/list_command.rs @@ -46,7 +46,7 @@ impl Default for ListCommand { impl ListCommand { pub fn new() -> Self { - let mut command = ListCommand { + let command = ListCommand { inner: CommandData::new(None), }; command @@ -85,7 +85,7 @@ impl ListCommand { } impl Command for ListCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.inner.set_name("list")?; self.inner.set_definition(SetDefinitionArg::Array(vec![ DefinitionItem::InputArgument(InputArgument::new( @@ -139,7 +139,7 @@ impl Command for ListCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { diff --git a/crates/shirabe-external-packages/src/symfony/console/descriptor/descriptor.rs b/crates/shirabe-external-packages/src/symfony/console/descriptor/descriptor.rs index 38824a6..5055b49 100644 --- a/crates/shirabe-external-packages/src/symfony/console/descriptor/descriptor.rs +++ b/crates/shirabe-external-packages/src/symfony/console/descriptor/descriptor.rs @@ -39,7 +39,7 @@ pub trait Descriptor: DescriptorInterface { self.describe_input_definition(&definition, options)?; } DescribableObject::Command(command) => { - self.describe_command(&mut *command.borrow_mut(), options)?; + self.describe_command(&*command.borrow(), options)?; } DescribableObject::Application(application) => { self.describe_application(application, options)?; @@ -86,7 +86,7 @@ pub trait Descriptor: DescriptorInterface { /// Describes a Command instance. fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()>; diff --git a/crates/shirabe-external-packages/src/symfony/console/descriptor/json_descriptor.rs b/crates/shirabe-external-packages/src/symfony/console/descriptor/json_descriptor.rs index 381ee69..6dd64f3 100644 --- a/crates/shirabe-external-packages/src/symfony/console/descriptor/json_descriptor.rs +++ b/crates/shirabe-external-packages/src/symfony/console/descriptor/json_descriptor.rs @@ -56,7 +56,7 @@ impl JsonDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { let short = matches!(options.get("short"), Some(PhpMixed::Bool(true))); @@ -83,9 +83,9 @@ impl JsonDescriptor { .values() .map(|c| c.borrow().clone_box()) .collect(); - for mut command in command_list { + for command in command_list { commands.push(PhpMixed::Array( - self.get_command_data(command.as_mut(), short)? + self.get_command_data(command.as_ref(), short)? .into_iter() .collect(), )); @@ -292,7 +292,7 @@ impl JsonDescriptor { fn get_command_data( &self, - command: &mut dyn Command, + command: &dyn Command, short: bool, ) -> anyhow::Result> { let mut data: IndexMap = IndexMap::new(); @@ -333,7 +333,7 @@ impl JsonDescriptor { data.insert( "definition".to_string(), PhpMixed::Array( - self.get_input_definition_data(command.get_definition())? + self.get_input_definition_data(&command.get_definition())? .into_iter() .collect(), ), @@ -392,7 +392,7 @@ impl Descriptor for JsonDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { JsonDescriptor::describe_command(self, command, options) diff --git a/crates/shirabe-external-packages/src/symfony/console/descriptor/markdown_descriptor.rs b/crates/shirabe-external-packages/src/symfony/console/descriptor/markdown_descriptor.rs index 49d958f..ef16fc0 100644 --- a/crates/shirabe-external-packages/src/symfony/console/descriptor/markdown_descriptor.rs +++ b/crates/shirabe-external-packages/src/symfony/console/descriptor/markdown_descriptor.rs @@ -147,7 +147,7 @@ impl MarkdownDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { if matches!(options.get("short"), Some(PhpMixed::Bool(true))) { @@ -285,10 +285,10 @@ impl MarkdownDescriptor { .values() .map(|c| c.borrow().clone_box()) .collect(); - for mut command in command_list { + for command in command_list { self.write("\n\n", true); // describeCommand returns null; the guarded write never runs. - self.describe_command(command.as_mut(), options.clone())?; + self.describe_command(command.as_ref(), options.clone())?; } Ok(()) } @@ -372,7 +372,7 @@ impl Descriptor for MarkdownDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { MarkdownDescriptor::describe_command(self, command, options) diff --git a/crates/shirabe-external-packages/src/symfony/console/descriptor/text_descriptor.rs b/crates/shirabe-external-packages/src/symfony/console/descriptor/text_descriptor.rs index 097d7f4..b0c0090 100644 --- a/crates/shirabe-external-packages/src/symfony/console/descriptor/text_descriptor.rs +++ b/crates/shirabe-external-packages/src/symfony/console/descriptor/text_descriptor.rs @@ -220,7 +220,7 @@ impl TextDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { command.merge_application_definition(false); @@ -593,7 +593,7 @@ impl Descriptor for TextDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { TextDescriptor::describe_command(self, command, options) diff --git a/crates/shirabe-external-packages/src/symfony/console/descriptor/xml_descriptor.rs b/crates/shirabe-external-packages/src/symfony/console/descriptor/xml_descriptor.rs index 25cdb12..fc2b948 100644 --- a/crates/shirabe-external-packages/src/symfony/console/descriptor/xml_descriptor.rs +++ b/crates/shirabe-external-packages/src/symfony/console/descriptor/xml_descriptor.rs @@ -42,7 +42,7 @@ impl XmlDescriptor { dom } - pub fn get_command_document(&self, command: &mut dyn Command, short: bool) -> DOMDocument { + pub fn get_command_document(&self, command: &dyn Command, short: bool) -> DOMDocument { let dom = DOMDocument::new("1.0", "UTF-8"); let command_xml = dom.append_child(dom.create_element("command")); @@ -125,8 +125,8 @@ impl XmlDescriptor { .values() .map(|c| c.borrow().clone_box()) .collect(); - for mut command in command_list { - let command_xml = self.get_command_document(command.as_mut(), short); + for command in command_list { + let command_xml = self.get_command_document(command.as_ref(), short); self.append_document(&commands_xml, &command_xml.as_node()); } @@ -186,7 +186,7 @@ impl XmlDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { let short = matches!(options.get("short"), Some(PhpMixed::Bool(true))); @@ -399,7 +399,7 @@ impl Descriptor for XmlDescriptor { fn describe_command( &mut self, - command: &mut dyn Command, + command: &dyn Command, options: IndexMap, ) -> anyhow::Result<()> { XmlDescriptor::describe_command(self, command, options) diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs index 8ca44db..5306b89 100644 --- a/crates/shirabe/src/command/about_command.rs +++ b/crates/shirabe/src/command/about_command.rs @@ -33,7 +33,7 @@ impl Default for AboutCommand { impl AboutCommand { pub fn new() -> Self { - let mut command = AboutCommand { + let command = AboutCommand { base_command_data: BaseCommandData::new(None), }; command @@ -44,7 +44,7 @@ impl AboutCommand { } impl Command for AboutCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("about")?; self.set_description("Shows a short information about Composer"); self.set_help("shirabe about"); @@ -52,7 +52,7 @@ impl Command for AboutCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -69,7 +69,7 @@ impl Command for AboutCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -80,10 +80,10 @@ impl Command for AboutCommand { } impl BaseCommand for AboutCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs index 1a043af..7355d63 100644 --- a/crates/shirabe/src/command/archive_command.rs +++ b/crates/shirabe/src/command/archive_command.rs @@ -50,7 +50,7 @@ impl ArchiveCommand { const FORMATS: &'static [&'static str] = &["tar", "tar.gz", "tar.bz2", "zip"]; pub fn new() -> Self { - let mut command = ArchiveCommand { + let command = ArchiveCommand { base_command_data: BaseCommandData::new(None), }; command @@ -61,7 +61,7 @@ impl ArchiveCommand { } impl Command for ArchiveCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_available_package(99) for `package` argument self.set_name("archive")?; self.set_description("Creates an archive of this composer package"); @@ -84,7 +84,7 @@ impl Command for ArchiveCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -186,7 +186,7 @@ impl Command for ArchiveCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -197,10 +197,10 @@ impl Command for ArchiveCommand { } impl BaseCommand for ArchiveCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -209,7 +209,7 @@ impl BaseCommand for ArchiveCommand { impl ArchiveCommand { #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] pub fn archive( - &mut self, + &self, io: std::rc::Rc>, config: &std::rc::Rc>, package_name: Option, @@ -289,7 +289,7 @@ impl ArchiveCommand { } pub fn select_package( - &mut self, + &self, io: std::rc::Rc>, package_name: &str, version: Option<&str>, diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs index 3014736..2a4f8a7 100644 --- a/crates/shirabe/src/command/audit_command.rs +++ b/crates/shirabe/src/command/audit_command.rs @@ -42,7 +42,7 @@ impl Default for AuditCommand { impl AuditCommand { pub fn new() -> Self { - let mut command = AuditCommand { + let command = AuditCommand { base_command_data: BaseCommandData::new(None), }; command @@ -53,7 +53,7 @@ impl AuditCommand { } impl Command for AuditCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("audit")?; self.set_description("Checks for security vulnerability advisories for installed packages"); self.set_definition(&[ @@ -122,7 +122,7 @@ impl Command for AuditCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -226,7 +226,7 @@ impl Command for AuditCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -237,10 +237,10 @@ impl Command for AuditCommand { } impl BaseCommand for AuditCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs index c4bfaef..8b6cc20 100644 --- a/crates/shirabe/src/command/base_command.rs +++ b/crates/shirabe/src/command/base_command.rs @@ -46,23 +46,24 @@ pub const INVALID: i64 = 2; #[derive(Debug)] pub struct BaseCommandData { inner: CommandData, - pub(crate) composer: Option, - pub(crate) io: Option>>, + pub(crate) composer: RefCell>, + pub(crate) io: RefCell>>>, } impl BaseCommandData { pub fn new(name: Option) -> Self { BaseCommandData { inner: CommandData::new(name), - composer: None, - io: None, + composer: RefCell::new(None), + io: RefCell::new(None), } } - /// Mutable access to the embedded Symfony command state, used by the Composer-typed definition - /// builders to forward to `CommandData`'s Symfony-typed entry points. - pub(crate) fn command_data_mut(&mut self) -> &mut CommandData { - &mut self.inner + /// Access to the embedded Symfony command state, used by the Composer-typed definition + /// builders to forward to `CommandData`'s Symfony-typed entry points. `CommandData` is + /// interior-mutable, so a shared reference is enough. + pub(crate) fn command_data(&self) -> &CommandData { + &self.inner } } @@ -70,13 +71,14 @@ impl BaseCommandData { /// `Command` trait. The Symfony state methods are inherited from the [`Command`] supertrait; /// only the Composer-specific behavior and the Composer-typed definition builders live here. pub trait BaseCommand: Command { - /// Mutable access to the embedded Symfony command state. Each command returns - /// `self.base_command_data.command_data_mut()`; this lets the Composer-typed definition - /// builders below forward to `CommandData`'s Symfony-typed entry points. - fn command_data_mut(&mut self) -> &mut CommandData; + /// Access to the embedded Symfony command state. Each command returns + /// `self.base_command_data.command_data()`; this lets the Composer-typed definition + /// builders below forward to `CommandData`'s Symfony-typed entry points. `CommandData` is + /// interior-mutable, so a shared reference is enough. + fn command_data(&self) -> &CommandData; /// Sets the definition from Composer-typed argument/option instances. - fn set_definition(&mut self, definition: &[InputDefinitionItem]) -> &mut Self + fn set_definition(&self, definition: &[InputDefinitionItem]) -> &Self where Self: Sized, { @@ -84,42 +86,42 @@ pub trait BaseCommand: Command { .iter() .map(|item| item.to_definition_item()) .collect(); - self.command_data_mut() + self.command_data() .set_definition(SetDefinitionArg::Array(items)); self } fn add_argument( - &mut self, + &self, name: &str, mode: Option, description: &str, default: PhpMixed, - ) -> &mut Self + ) -> &Self where Self: Sized, { - self.command_data_mut() + self.command_data() .add_argument(name, mode, description, default) .expect("command argument definitions in configure() are statically valid"); self } fn add_option( - &mut self, + &self, name: &str, shortcut: Option<&str>, mode: Option, description: &str, default: PhpMixed, - ) -> &mut Self + ) -> &Self where Self: Sized, { let shortcut = shortcut .map(|s| PhpMixed::from(s.to_string())) .unwrap_or(PhpMixed::Null); - self.command_data_mut() + self.command_data() .add_option(name, shortcut, mode, description, default) .expect("command option definitions in configure() are statically valid"); self @@ -137,26 +139,26 @@ pub trait BaseCommand: Command { /// Retrieves the default Composer\Composer instance or throws fn require_composer( - &mut self, + &self, disable_plugins: Option, disable_scripts: Option, ) -> Result; /// Retrieves the default Composer\Composer instance or null fn try_composer( - &mut self, + &self, disable_plugins: Option, disable_scripts: Option, ) -> Option; - fn set_composer(&mut self, composer: PartialComposerHandle); + fn set_composer(&self, composer: PartialComposerHandle); /// Removes the cached composer instance - fn reset_composer(&mut self) -> Result<()>; + fn reset_composer(&self) -> Result<()>; - fn get_io(&mut self) -> Rc>; + fn get_io(&self) -> Rc>; - fn set_io(&mut self, io: Rc>); + fn set_io(&self, io: Rc>); /// Calls {@see Factory::create()} with the given arguments, taking into account flags and default states for disabling scripts and plugins fn create_composer_instance( @@ -223,12 +225,12 @@ pub trait BaseCommand: Command { #[macro_export] macro_rules! delegate_base_command_trait_impls_to_inner { ($field:ident) => { - shirabe_external_packages::delegate_to_inner!($field, fn require_composer(&mut self, disable_plugins: Option, disable_scripts: Option) -> anyhow::Result<$crate::composer::PartialComposerHandle>); - shirabe_external_packages::delegate_to_inner!($field, fn try_composer(&mut self, disable_plugins: Option, disable_scripts: Option) -> Option<$crate::composer::PartialComposerHandle>); - shirabe_external_packages::delegate_to_inner!($field, fn set_composer(&mut self, composer: $crate::composer::PartialComposerHandle)); - shirabe_external_packages::delegate_to_inner!($field, fn reset_composer(&mut self) -> anyhow::Result<()>); - shirabe_external_packages::delegate_to_inner!($field, fn get_io(&mut self) -> std::rc::Rc>); - shirabe_external_packages::delegate_to_inner!($field, fn set_io(&mut self, io: std::rc::Rc>)); + shirabe_external_packages::delegate_to_inner!($field, fn require_composer(&self, disable_plugins: Option, disable_scripts: Option) -> anyhow::Result<$crate::composer::PartialComposerHandle>); + shirabe_external_packages::delegate_to_inner!($field, fn try_composer(&self, disable_plugins: Option, disable_scripts: Option) -> Option<$crate::composer::PartialComposerHandle>); + shirabe_external_packages::delegate_to_inner!($field, fn set_composer(&self, composer: $crate::composer::PartialComposerHandle)); + shirabe_external_packages::delegate_to_inner!($field, fn reset_composer(&self) -> anyhow::Result<()>); + shirabe_external_packages::delegate_to_inner!($field, fn get_io(&self) -> std::rc::Rc>); + shirabe_external_packages::delegate_to_inner!($field, fn set_io(&self, io: std::rc::Rc>)); shirabe_external_packages::delegate_to_inner!($field, fn create_composer_instance(&self, input: std::rc::Rc>, io: std::rc::Rc>, config: Option>, disable_plugins: bool, disable_scripts: Option) -> anyhow::Result<$crate::composer::PartialComposerHandle>); shirabe_external_packages::delegate_to_inner!($field, fn get_preferred_install_options(&self, config: &$crate::config::Config, input: std::rc::Rc>, keep_vcs_requires_prefer_source: bool) -> anyhow::Result<(bool, bool)>); shirabe_external_packages::delegate_to_inner!($field, fn get_platform_requirement_filter(&self, input: std::rc::Rc>) -> anyhow::Result>); @@ -246,16 +248,16 @@ impl Command for BaseCommandData { } impl BaseCommand for BaseCommandData { - fn command_data_mut(&mut self) -> &mut CommandData { - &mut self.inner + fn command_data(&self) -> &CommandData { + &self.inner } fn require_composer( - &mut self, + &self, disable_plugins: Option, disable_scripts: Option, ) -> Result { - if self.composer.is_none() { + if self.composer.borrow().is_none() { let application = self.get_application(); let Some(application) = application else { return Err(RuntimeException { @@ -273,21 +275,22 @@ impl BaseCommand for BaseCommandData { .expect("a Composer command's application is a shirabe Application"); app.get_composer(true, disable_plugins, disable_scripts)? }; - self.composer = composer; + *self.composer.borrow_mut() = composer; } Ok(self .composer + .borrow() .clone() .expect("requireComposer always yields a Composer or errors")) } fn try_composer( - &mut self, + &self, disable_plugins: Option, disable_scripts: Option, ) -> Option { - if self.composer.is_none() + if self.composer.borrow().is_none() && let Some(application) = self.get_application() { let result = { @@ -300,19 +303,19 @@ impl BaseCommand for BaseCommandData { app.get_composer(false, disable_plugins, disable_scripts) }; if let Ok(composer) = result { - self.composer = composer; + *self.composer.borrow_mut() = composer; } } - self.composer.clone() + self.composer.borrow().clone() } - fn set_composer(&mut self, composer: PartialComposerHandle) { - self.composer = Some(composer); + fn set_composer(&self, composer: PartialComposerHandle) { + *self.composer.borrow_mut() = Some(composer); } - fn reset_composer(&mut self) -> Result<()> { - self.composer = None; + fn reset_composer(&self) -> Result<()> { + *self.composer.borrow_mut() = None; if let Some(application) = self.get_application() { let mut app_ref = application.borrow_mut(); let app_dyn: &mut dyn shirabe_external_packages::symfony::console::application::Application = &mut *app_ref; @@ -325,8 +328,8 @@ impl BaseCommand for BaseCommandData { Ok(()) } - fn get_io(&mut self) -> Rc> { - if self.io.is_none() { + fn get_io(&self) -> Rc> { + if self.io.borrow().is_none() { match self.get_application() { Some(application) => { let io = { @@ -338,19 +341,19 @@ impl BaseCommand for BaseCommandData { .expect("a Composer command's application is a shirabe Application"); app.get_io() }; - self.io = Some(io); + *self.io.borrow_mut() = Some(io); } None => { - self.io = Some(Rc::new(RefCell::new(NullIO::new()))); + *self.io.borrow_mut() = Some(Rc::new(RefCell::new(NullIO::new()))); } } } - self.io.clone().unwrap() + self.io.borrow().clone().unwrap() } - fn set_io(&mut self, io: Rc>) { - self.io = Some(io); + fn set_io(&self, io: Rc>) { + *self.io.borrow_mut() = Some(io); } fn create_composer_instance( @@ -695,7 +698,7 @@ impl BaseCommand for BaseCommandData { /// `Command::initialize` forwards here so the leaf's `is_self_update_command()` override (and /// future overrides) bind correctly. pub fn base_command_initialize( - cmd: &mut dyn BaseCommand, + cmd: &dyn BaseCommand, input: Rc>, _output: Rc>, ) -> Result<()> { diff --git a/crates/shirabe/src/command/base_config_command.rs b/crates/shirabe/src/command/base_config_command.rs index 4099ea5..fa14197 100644 --- a/crates/shirabe/src/command/base_config_command.rs +++ b/crates/shirabe/src/command/base_config_command.rs @@ -13,16 +13,14 @@ use shirabe_external_packages::symfony::console::output::OutputInterface; use shirabe_php_shim::{PhpMixed, chmod, touch}; pub trait BaseConfigCommand: BaseCommand { - fn config(&self) -> Option<&std::rc::Rc>>; - fn config_mut(&mut self) -> &mut Option>>; - fn config_file(&self) -> Option<&std::rc::Rc>>; - fn set_config_file(&mut self, file: Option>>); - fn config_source(&self) -> Option<&JsonConfigSource>; - fn config_source_mut(&mut self) -> Option<&mut JsonConfigSource>; - fn set_config_source(&mut self, source: Option); + fn config(&self) -> Option>>; + fn set_config(&self, config: Option>>); + fn config_file(&self) -> Option>>; + fn set_config_file(&self, file: Option>>); + fn set_config_source(&self, source: Option); fn initialize( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, ) -> anyhow::Result<()> { @@ -40,10 +38,10 @@ pub trait BaseConfigCommand: BaseCommand { } let io = self.get_io(); - *self.config_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new( + self.set_config(Some(std::rc::Rc::new(std::cell::RefCell::new( Factory::create_config(Some(io.clone()), None)?, - ))); - let config_rc = self.config().unwrap().clone(); + )))); + let config_rc = self.config().unwrap(); // When using --global flag, set baseDir to home directory for correct absolute path resolution if input diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs index 6a892e8..7bedf7d 100644 --- a/crates/shirabe/src/command/base_dependency_command.rs +++ b/crates/shirabe/src/command/base_dependency_command.rs @@ -37,11 +37,11 @@ pub trait BaseDependencyCommand: BaseCommand { const OPTION_RECURSIVE: &'static str = OPTION_RECURSIVE; const OPTION_TREE: &'static str = OPTION_TREE; - fn colors(&self) -> &[String]; - fn colors_mut(&mut self) -> &mut Vec; + fn colors(&self) -> std::cell::Ref<'_, Vec>; + fn set_colors(&self, colors: Vec); fn do_execute( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, inverted: bool, @@ -383,15 +383,15 @@ pub trait BaseDependencyCommand: BaseCommand { self.render_table(table_as_mixed, output); } - fn init_styles(&mut self, output: std::rc::Rc>) { - *self.colors_mut() = vec![ + fn init_styles(&self, output: std::rc::Rc>) { + self.set_colors(vec![ "green".to_string(), "yellow".to_string(), "cyan".to_string(), "magenta".to_string(), "blue".to_string(), - ]; - for color in self.colors() { + ]); + for color in self.colors().iter() { let style = OutputFormatterStyle::new(Some(color), None, vec![]); output .borrow() @@ -401,14 +401,15 @@ pub trait BaseDependencyCommand: BaseCommand { } } - fn print_tree(&mut self, results: &[DependentsEntry], prefix: &str, level: i64) { + fn print_tree(&self, results: &[DependentsEntry], prefix: &str, level: i64) { let count = results.len() as i64; let mut idx: i64 = 0; - let colors_len = self.colors().len() as i64; + let colors = self.colors(); + let colors_len = colors.len() as i64; for result in results { let DependentsEntry(package, link, children) = result; - let color = &self.colors()[(level % colors_len) as usize]; - let prev_color = &self.colors()[((level - 1) % colors_len) as usize]; + let color = &colors[(level % colors_len) as usize]; + let prev_color = &colors[((level - 1) % colors_len) as usize]; idx += 1; let is_last = idx == count; let version_text = @@ -464,7 +465,7 @@ pub trait BaseDependencyCommand: BaseCommand { } } - fn write_tree_line(&mut self, line: &str) { + fn write_tree_line(&self, line: &str) { let io = self.get_io(); let line = if !io.is_decorated() { line.replace('└', "`-") diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs index 17605d6..b80e41c 100644 --- a/crates/shirabe/src/command/bump_command.rs +++ b/crates/shirabe/src/command/bump_command.rs @@ -48,7 +48,7 @@ impl BumpCommand { const ERROR_LOCK_OUTDATED: i64 = 2; pub fn new() -> Self { - let mut command = BumpCommand { + let command = BumpCommand { base_command_data: BaseCommandData::new(None), }; command @@ -58,7 +58,7 @@ impl BumpCommand { } pub fn do_bump( - &mut self, + &self, io: std::rc::Rc>, dev_only: bool, no_dev_only: bool, @@ -340,7 +340,7 @@ impl BumpCommand { } impl Command for BumpCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_root_requirement() for `packages` argument self.set_name("bump")?; self.set_description("Increases the lower limit of your composer.json requirements to the currently installed versions"); @@ -396,7 +396,7 @@ impl Command for BumpCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -438,7 +438,7 @@ impl Command for BumpCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -449,10 +449,10 @@ impl Command for BumpCommand { } impl BaseCommand for BumpCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs index 0f18557..2ab66c5 100644 --- a/crates/shirabe/src/command/check_platform_reqs_command.rs +++ b/crates/shirabe/src/command/check_platform_reqs_command.rs @@ -48,7 +48,7 @@ impl Default for CheckPlatformReqsCommand { impl CheckPlatformReqsCommand { pub fn new() -> Self { - let mut command = CheckPlatformReqsCommand { + let command = CheckPlatformReqsCommand { base_command_data: BaseCommandData::new(None), }; command @@ -58,7 +58,7 @@ impl CheckPlatformReqsCommand { } fn print_table( - &mut self, + &self, output: std::rc::Rc>, results: &[CheckResult], format: &str, @@ -154,7 +154,7 @@ impl CheckPlatformReqsCommand { } impl Command for CheckPlatformReqsCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("check-platform-reqs")?; self.set_description("Check that platform requirements are satisfied"); self.set_definition(&[ @@ -195,7 +195,7 @@ impl Command for CheckPlatformReqsCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -403,7 +403,7 @@ impl Command for CheckPlatformReqsCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -414,10 +414,10 @@ impl Command for CheckPlatformReqsCommand { } impl BaseCommand for CheckPlatformReqsCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs index ece594d..c3d1eb5 100644 --- a/crates/shirabe/src/command/clear_cache_command.rs +++ b/crates/shirabe/src/command/clear_cache_command.rs @@ -31,7 +31,7 @@ impl Default for ClearCacheCommand { impl ClearCacheCommand { pub fn new() -> Self { - let mut command = ClearCacheCommand { + let command = ClearCacheCommand { base_command_data: BaseCommandData::new(None), }; command @@ -42,7 +42,7 @@ impl ClearCacheCommand { } impl Command for ClearCacheCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("clear-cache")?; self.set_aliases(vec!["clearcache".to_string(), "cc".to_string()])?; self.set_description("Clears composer's internal package cache"); @@ -64,7 +64,7 @@ impl Command for ClearCacheCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -182,7 +182,7 @@ impl Command for ClearCacheCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -193,10 +193,10 @@ impl Command for ClearCacheCommand { } impl BaseCommand for ClearCacheCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs index aff950e..7bd65b6 100644 --- a/crates/shirabe/src/command/config_command.rs +++ b/crates/shirabe/src/command/config_command.rs @@ -44,12 +44,13 @@ use shirabe_semver::VersionParser; pub struct ConfigCommand { base_command_data: BaseCommandData, - config: Option>>, - config_file: Option>>, - config_source: Option, + config: std::cell::RefCell>>>, + config_file: std::cell::RefCell>>>, + config_source: std::cell::RefCell>, - pub(crate) auth_config_file: Option>>, - pub(crate) auth_config_source: Option, + pub(crate) auth_config_file: + std::cell::RefCell>>>, + pub(crate) auth_config_source: std::cell::RefCell>, } impl ConfigCommand { @@ -78,13 +79,13 @@ impl Default for ConfigCommand { impl ConfigCommand { pub fn new() -> Self { - let mut command = ConfigCommand { + let command = ConfigCommand { base_command_data: BaseCommandData::new(None), - config: None, - config_file: None, - config_source: None, - auth_config_file: None, - auth_config_source: None, + config: std::cell::RefCell::new(None), + config_file: std::cell::RefCell::new(None), + config_source: std::cell::RefCell::new(None), + auth_config_file: std::cell::RefCell::new(None), + auth_config_source: std::cell::RefCell::new(None), }; command .configure() @@ -94,7 +95,7 @@ impl ConfigCommand { } impl Command for ConfigCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_setting_keys() for `setting-key` argument self.set_name("config")?; self.set_description("Sets config options"); @@ -152,7 +153,7 @@ impl Command for ConfigCommand { } fn initialize( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, ) -> anyhow::Result<()> { @@ -162,22 +163,24 @@ impl Command for ConfigCommand { output, )?; - let auth_config_file = - self.get_auth_config_file(input.clone(), &self.config.as_ref().unwrap().borrow())?; + let config = self.config.borrow().as_ref().unwrap().clone(); + let auth_config_file = self.get_auth_config_file(input.clone(), &config.borrow())?; let auth_config_file_jf = std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( auth_config_file, None, Some(self.get_io().clone()), )?)); - self.auth_config_file = Some(auth_config_file_jf.clone()); - self.auth_config_source = Some(JsonConfigSource::new(auth_config_file_jf, true)); + *self.auth_config_file.borrow_mut() = Some(auth_config_file_jf.clone()); + *self.auth_config_source.borrow_mut() = + Some(JsonConfigSource::new(auth_config_file_jf, true)); // Initialize the global file if it's not there, ignoring any warnings or notices + let auth_config_file = self.auth_config_file.borrow().as_ref().unwrap().clone(); if input.borrow().get_option("global")?.as_bool() == Some(true) - && !self.auth_config_file.as_ref().unwrap().borrow().exists() + && !auth_config_file.borrow().exists() { - touch(self.auth_config_file.as_ref().unwrap().borrow().get_path()); + touch(auth_config_file.borrow().get_path()); let mut empty_objs: IndexMap = IndexMap::new(); for k in &[ "bitbucket-oauth", @@ -190,18 +193,10 @@ impl Command for ConfigCommand { ] { empty_objs.insert(k.to_string(), PhpMixed::Object(IndexMap::new())); } - self.auth_config_file - .as_ref() - .unwrap() + auth_config_file .borrow() .write(PhpMixed::Array(empty_objs))?; - let path_clone = self - .auth_config_file - .as_ref() - .unwrap() - .borrow() - .get_path() - .to_string(); + let path_clone = auth_config_file.borrow().get_path().to_string(); Silencer::call(|| { shirabe_php_shim::chmod(&path_clone, 0o600); Ok(()) @@ -211,7 +206,7 @@ impl Command for ConfigCommand { } fn execute( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, ) -> anyhow::Result { @@ -238,6 +233,7 @@ impl Command for ConfigCommand { let file = if input.borrow().get_option("auth")?.as_bool() == Some(true) { self.auth_config_file + .borrow() .as_ref() .unwrap() .borrow() @@ -245,6 +241,7 @@ impl Command for ConfigCommand { .to_string() } else { self.config_file + .borrow() .as_ref() .unwrap() .borrow() @@ -268,35 +265,30 @@ impl Command for ConfigCommand { return Ok(0); } + let config = self.config.borrow().as_ref().unwrap().clone(); + let config_file = self.config_file.borrow().as_ref().unwrap().clone(); + let auth_config_file = self.auth_config_file.borrow().as_ref().unwrap().clone(); if input.borrow().get_option("global")?.as_bool() != Some(true) { - let config_read = self.config_file.as_ref().unwrap().borrow_mut().read()?; + let config_read = config_file.borrow_mut().read()?; let config_map = match config_read { PhpMixed::Array(m) => m, _ => IndexMap::new(), }; - self.config.as_mut().unwrap().borrow_mut().merge( - &config_map, - self.config_file.as_ref().unwrap().borrow().get_path(), - ); - let auth_data: PhpMixed = if self.auth_config_file.as_ref().unwrap().borrow().exists() { - self.auth_config_file - .as_ref() - .unwrap() - .borrow_mut() - .read()? + let config_file_path = config_file.borrow().get_path().to_string(); + config.borrow_mut().merge(&config_map, &config_file_path); + let auth_data: PhpMixed = if auth_config_file.borrow().exists() { + auth_config_file.borrow_mut().read()? } else { PhpMixed::Array(IndexMap::new()) }; let mut wrap: IndexMap = IndexMap::new(); wrap.insert("config".to_string(), auth_data); - self.config.as_mut().unwrap().borrow_mut().merge( - &wrap, - self.auth_config_file.as_ref().unwrap().borrow().get_path(), - ); + let auth_config_file_path = auth_config_file.borrow().get_path().to_string(); + config.borrow_mut().merge(&wrap, &auth_config_file_path); } { - let config_rc = self.config.as_ref().unwrap().clone(); + let config_rc = config.clone(); self.get_io() .borrow_mut() .load_configuration(&mut config_rc.borrow_mut())?; @@ -304,8 +296,8 @@ impl Command for ConfigCommand { // List the configuration of the file settings if input.borrow().get_option("list")?.as_bool() == Some(true) { - let all_map = self.config.as_ref().unwrap().borrow_mut().all(0)?; - let raw_map = self.config.as_ref().unwrap().borrow().raw(); + let all_map = config.borrow_mut().all(0)?; + let raw_map = config.borrow().raw(); let to_mixed = |m: IndexMap| -> PhpMixed { PhpMixed::Array(m.into_iter().collect()) }; @@ -362,14 +354,9 @@ impl Command for ConfigCommand { properties_defaults.insert("license".to_string(), PhpMixed::List(vec![])); properties_defaults.insert("suggest".to_string(), PhpMixed::List(vec![])); properties_defaults.insert("extra".to_string(), PhpMixed::List(vec![])); - let raw_data = self.config_file.as_ref().unwrap().borrow_mut().read()?; - let mut data = self.config.as_ref().unwrap().borrow_mut().all(0)?; - let mut source = self - .config - .as_ref() - .unwrap() - .borrow_mut() - .get_source_of_value(&setting_key); + let raw_data = config_file.borrow_mut().read()?; + let mut data = config.borrow_mut().all(0)?; + let mut source = config.borrow_mut().get_source_of_value(&setting_key); let mut value: PhpMixed; let mut matches: IndexMap = IndexMap::new(); @@ -444,7 +431,7 @@ impl Command for ConfigCommand { .map(|c| c.contains_key(&setting_key)) .unwrap_or(false) { - value = self.config.as_ref().unwrap().borrow_mut().get_with_flags( + value = config.borrow_mut().get_with_flags( &setting_key, if input.borrow().get_option("absolute")?.as_bool() == Some(true) { 0 @@ -503,13 +490,7 @@ impl Command for ConfigCommand { .get(&setting_key) .unwrap() .clone(); - source = self - .config_file - .as_ref() - .unwrap() - .borrow() - .get_path() - .to_string(); + source = config_file.borrow().get_path().to_string(); } else if let Some(v) = properties_defaults.get(&setting_key) { value = v.clone(); source = "defaults".to_string(); @@ -574,6 +555,7 @@ impl Command for ConfigCommand { // allow unsetting audit config entirely if input.borrow().get_option("unset")?.as_bool() == Some(true) && setting_key == "audit" { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -586,10 +568,7 @@ impl Command for ConfigCommand { || multi_config_values.contains_key(&setting_key)) { if setting_key == "disable-tls" - && self - .config - .as_ref() - .unwrap() + && config .borrow() .get("disable-tls") .as_bool() @@ -601,6 +580,7 @@ impl Command for ConfigCommand { } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -626,6 +606,7 @@ impl Command for ConfigCommand { ) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -649,6 +630,7 @@ impl Command for ConfigCommand { } self.config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&setting_key, PhpMixed::String(values[0].clone())); @@ -665,6 +647,7 @@ impl Command for ConfigCommand { ) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -683,6 +666,7 @@ impl Command for ConfigCommand { let normalized_value = boolean_normalizer(&PhpMixed::String(values[0].clone())); self.config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&setting_key, normalized_value); @@ -709,6 +693,7 @@ impl Command for ConfigCommand { && (unique_props.contains_key(&setting_key) || multi_props.contains_key(&setting_key)) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -735,6 +720,7 @@ impl Command for ConfigCommand { ) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_repository(&matches[1]); @@ -746,11 +732,15 @@ impl Command for ConfigCommand { let mut repo: IndexMap = IndexMap::new(); repo.insert("type".to_string(), PhpMixed::String(values[0].clone())); repo.insert("url".to_string(), PhpMixed::String(values[1].clone())); - self.config_source.as_mut().unwrap().add_repository( - &matches[1], - PhpMixed::Array(repo), - input.borrow().get_option("append")?.as_bool() == Some(true), - ); + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository( + &matches[1], + PhpMixed::Array(repo), + input.borrow().get_option("append")?.as_bool() == Some(true), + ); return Ok(0); } @@ -762,21 +752,29 @@ impl Command for ConfigCommand { .as_bool() .unwrap_or(false) { - self.config_source.as_mut().unwrap().add_repository( - &matches[1], - PhpMixed::Bool(false), - input.borrow().get_option("append")?.as_bool() == Some(true), - ); + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository( + &matches[1], + PhpMixed::Bool(false), + input.borrow().get_option("append")?.as_bool() == Some(true), + ); return Ok(0); } } else { let value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?; - self.config_source.as_mut().unwrap().add_repository( - &matches[1], - value, - input.borrow().get_option("append")?.as_bool() == Some(true), - ); + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository( + &matches[1], + value, + input.borrow().get_option("append")?.as_bool() == Some(true), + ); return Ok(0); } @@ -794,6 +792,7 @@ impl Command for ConfigCommand { if Preg::is_match3("/^extra\\.(.+)/", &setting_key, Some(&mut matches)) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -805,8 +804,7 @@ impl Command for ConfigCommand { if input.borrow().get_option("json")?.as_bool() == Some(true) { value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?; if input.borrow().get_option("merge")?.as_bool() == Some(true) { - let current_value_outer = - self.config_file.as_ref().unwrap().borrow_mut().read()?; + let current_value_outer = config_file.borrow_mut().read()?; let bits = explode(".", &setting_key); let mut current_value: PhpMixed = current_value_outer; for bit in &bits { @@ -841,6 +839,7 @@ impl Command for ConfigCommand { } } self.config_source + .borrow_mut() .as_mut() .unwrap() .add_property(&setting_key, value); @@ -853,6 +852,7 @@ impl Command for ConfigCommand { if Preg::is_match3("/^suggest\\.(.+)/", &setting_key, Some(&mut matches)) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -861,6 +861,7 @@ impl Command for ConfigCommand { } self.config_source + .borrow_mut() .as_mut() .unwrap() .add_property(&setting_key, PhpMixed::String(implode(" ", &values))); @@ -876,6 +877,7 @@ impl Command for ConfigCommand { ) && input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -888,6 +890,7 @@ impl Command for ConfigCommand { if Preg::is_match3("/^platform\\.(.+)/", &setting_key, Some(&mut matches)) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -901,6 +904,7 @@ impl Command for ConfigCommand { PhpMixed::String(values[0].clone()) }; self.config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&setting_key, value); @@ -912,6 +916,7 @@ impl Command for ConfigCommand { if setting_key == "platform" && input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -931,6 +936,7 @@ impl Command for ConfigCommand { ) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&setting_key); @@ -952,7 +958,7 @@ impl Command for ConfigCommand { } if input.borrow().get_option("merge")?.as_bool() == Some(true) { - let current_config = self.config_file.as_ref().unwrap().borrow_mut().read()?; + let current_config = config_file.borrow_mut().read()?; let key_suffix = str_replace("audit.", "", &setting_key); let current_value = current_config .as_array() @@ -994,6 +1000,7 @@ impl Command for ConfigCommand { } self.config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&setting_key, value); @@ -1010,10 +1017,12 @@ impl Command for ConfigCommand { ) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&format!("{}.{}", matches[1], matches[2])); self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&format!("{}.{}", matches[1], matches[2])); @@ -1034,6 +1043,7 @@ impl Command for ConfigCommand { .into()); } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); @@ -1047,11 +1057,13 @@ impl Command for ConfigCommand { PhpMixed::String(values[1].clone()), ); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); } else if matches[1] == "gitlab-token" && 2 == values.len() { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); @@ -1059,6 +1071,7 @@ impl Command for ConfigCommand { obj.insert("username".to_string(), PhpMixed::String(values[0].clone())); obj.insert("token".to_string(), PhpMixed::String(values[1].clone())); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); @@ -1081,10 +1094,12 @@ impl Command for ConfigCommand { .into()); } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::String(values[0].clone())); @@ -1100,6 +1115,7 @@ impl Command for ConfigCommand { .into()); } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); @@ -1107,6 +1123,7 @@ impl Command for ConfigCommand { obj.insert("username".to_string(), PhpMixed::String(values[0].clone())); obj.insert("password".to_string(), PhpMixed::String(values[1].clone())); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); @@ -1149,10 +1166,12 @@ impl Command for ConfigCommand { } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::List(formatted_headers)); @@ -1168,6 +1187,7 @@ impl Command for ConfigCommand { .into()); } self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_config_setting(&key); @@ -1175,6 +1195,7 @@ impl Command for ConfigCommand { obj.insert("username".to_string(), PhpMixed::String(values[0].clone())); obj.insert("token".to_string(), PhpMixed::String(values[1].clone())); self.auth_config_source + .borrow_mut() .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); @@ -1188,6 +1209,7 @@ impl Command for ConfigCommand { if Preg::is_match3("/^scripts\\.(.+)/", &setting_key, Some(&mut matches)) { if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -1201,6 +1223,7 @@ impl Command for ConfigCommand { PhpMixed::String(values[0].clone()) }; self.config_source + .borrow_mut() .as_mut() .unwrap() .add_property(&setting_key, value); @@ -1211,6 +1234,7 @@ impl Command for ConfigCommand { // handle unsetting other top level properties if input.borrow().get_option("unset")?.as_bool() == Some(true) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_property(&setting_key); @@ -1232,10 +1256,10 @@ impl Command for ConfigCommand { } impl BaseCommand for ConfigCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -1243,7 +1267,7 @@ impl BaseCommand for ConfigCommand { impl ConfigCommand { pub(crate) fn handle_single_value( - &mut self, + &self, key: &str, callbacks: &(ValidatorFn, NormalizerFn), values: &[String], @@ -1276,11 +1300,9 @@ impl ConfigCommand { let normalized_value = normalizer(&PhpMixed::String(values[0].clone())); if key == "disable-tls" { + let config = self.config.borrow().as_ref().unwrap().clone(); if !normalized_value.as_bool().unwrap_or(false) - && self - .config - .as_ref() - .unwrap() + && config .borrow() .get("disable-tls") .as_bool() @@ -1290,10 +1312,7 @@ impl ConfigCommand { "You are now running Composer with SSL/TLS protection enabled.", ); } else if normalized_value.as_bool().unwrap_or(false) - && !self - .config - .as_ref() - .unwrap() + && !config .borrow() .get("disable-tls") .as_bool() @@ -1303,7 +1322,8 @@ impl ConfigCommand { } } - let config_source = self.config_source.as_mut().unwrap(); + let mut config_source = self.config_source.borrow_mut(); + let config_source = config_source.as_mut().unwrap(); match method { "addConfigSetting" => config_source.add_config_setting(key, normalized_value)?, "addProperty" => config_source.add_property(key, normalized_value)?, @@ -1313,7 +1333,7 @@ impl ConfigCommand { } pub(crate) fn handle_multi_value( - &mut self, + &self, key: &str, callbacks: &(ValidatorFn, NormalizerFn), values: &[String], @@ -1340,7 +1360,8 @@ impl ConfigCommand { .into()); } - let config_source = self.config_source.as_mut().unwrap(); + let mut config_source = self.config_source.borrow_mut(); + let config_source = config_source.as_mut().unwrap(); match method { "addConfigSetting" => { config_source.add_config_setting(key, normalizer(&values_mixed))? @@ -1353,7 +1374,7 @@ impl ConfigCommand { /// Display the contents of the file in a pretty formatted way pub(crate) fn list_configuration( - &mut self, + &self, contents: PhpMixed, raw_contents: PhpMixed, output: std::rc::Rc>, @@ -1424,6 +1445,7 @@ impl ConfigCommand { format!( " ({})", self.config + .borrow() .as_ref() .unwrap() .borrow_mut() @@ -2166,31 +2188,23 @@ fn key_first_key(value: &PhpMixed) -> Option { } impl BaseConfigCommand for ConfigCommand { - fn config(&self) -> Option<&std::rc::Rc>> { - self.config.as_ref() - } - - fn config_mut(&mut self) -> &mut Option>> { - &mut self.config - } - - fn config_file(&self) -> Option<&std::rc::Rc>> { - self.config_file.as_ref() + fn config(&self) -> Option>> { + self.config.borrow().clone() } - fn set_config_file(&mut self, file: Option>>) { - self.config_file = file; + fn set_config(&self, config: Option>>) { + *self.config.borrow_mut() = config; } - fn config_source(&self) -> Option<&JsonConfigSource> { - self.config_source.as_ref() + fn config_file(&self) -> Option>> { + self.config_file.borrow().clone() } - fn config_source_mut(&mut self) -> Option<&mut JsonConfigSource> { - self.config_source.as_mut() + fn set_config_file(&self, file: Option>>) { + *self.config_file.borrow_mut() = file; } - fn set_config_source(&mut self, source: Option) { - self.config_source = source; + fn set_config_source(&self, source: Option) { + *self.config_source.borrow_mut() = source; } } diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index 8432040..9969cf5 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -59,7 +59,7 @@ pub struct CreateProjectCommand { /// @var SuggestedPackagesReporter pub(crate) suggested_packages_reporter: - Option>>, + std::cell::RefCell>>>, } impl Default for CreateProjectCommand { @@ -70,9 +70,9 @@ impl Default for CreateProjectCommand { impl CreateProjectCommand { pub fn new() -> Self { - let mut command = CreateProjectCommand { + let command = CreateProjectCommand { base_command_data: BaseCommandData::new(None), - suggested_packages_reporter: None, + suggested_packages_reporter: std::cell::RefCell::new(None), }; command .configure() @@ -82,7 +82,7 @@ impl CreateProjectCommand { } impl Command for CreateProjectCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_prefer_install / suggest_available_package self.set_name("create-project")?; self.set_description("Creates new project from a package into given directory"); @@ -134,7 +134,7 @@ impl Command for CreateProjectCommand { } fn execute( - &mut self, + &self, input: std::rc::Rc>, _output: std::rc::Rc>, ) -> anyhow::Result { @@ -260,7 +260,7 @@ impl Command for CreateProjectCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -271,10 +271,10 @@ impl Command for CreateProjectCommand { } impl BaseCommand for CreateProjectCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -286,7 +286,7 @@ impl CreateProjectCommand { /// @throws \Exception #[allow(clippy::too_many_arguments)] pub fn install_project( - &mut self, + &self, io: std::rc::Rc>, config: std::rc::Rc>, input: std::rc::Rc>, @@ -330,9 +330,9 @@ impl CreateProjectCommand { io.borrow_mut() .load_configuration(&mut config.borrow_mut())?; - self.suggested_packages_reporter = Some(std::rc::Rc::new(std::cell::RefCell::new( - SuggestedPackagesReporter::new(io.clone()), - ))); + *self.suggested_packages_reporter.borrow_mut() = Some(std::rc::Rc::new( + std::cell::RefCell::new(SuggestedPackagesReporter::new(io.clone())), + )); let installed_from_vcs = if let Some(package_name) = package_name.as_ref() { self.install_root_package( @@ -469,7 +469,11 @@ impl CreateProjectCommand { .set_dev_mode(install_dev_packages) .set_platform_requirement_filter(platform_requirement_filter.clone()) .set_suggested_packages_reporter( - self.suggested_packages_reporter.as_ref().unwrap().clone(), + self.suggested_packages_reporter + .borrow() + .as_ref() + .unwrap() + .clone(), ) .set_optimize_autoloader( config @@ -1014,6 +1018,7 @@ impl CreateProjectCommand { // collect suggestions self.suggested_packages_reporter + .borrow() .as_ref() .unwrap() .borrow_mut() diff --git a/crates/shirabe/src/command/depends_command.rs b/crates/shirabe/src/command/depends_command.rs index 133f8b2..f7d57db 100644 --- a/crates/shirabe/src/command/depends_command.rs +++ b/crates/shirabe/src/command/depends_command.rs @@ -25,7 +25,7 @@ use crate::io::IOInterface; pub struct DependsCommand { base_command_data: BaseCommandData, - colors: Vec, + colors: std::cell::RefCell>, } impl Default for DependsCommand { @@ -36,9 +36,9 @@ impl Default for DependsCommand { impl DependsCommand { pub fn new() -> Self { - let mut command = DependsCommand { + let command = DependsCommand { base_command_data: BaseCommandData::new(None), - colors: Vec::new(), + colors: std::cell::RefCell::new(Vec::new()), }; command .configure() @@ -48,17 +48,17 @@ impl DependsCommand { } impl BaseDependencyCommand for DependsCommand { - fn colors(&self) -> &[String] { - &self.colors + fn colors(&self) -> std::cell::Ref<'_, Vec> { + self.colors.borrow() } - fn colors_mut(&mut self) -> &mut Vec { - &mut self.colors + fn set_colors(&self, colors: Vec) { + *self.colors.borrow_mut() = colors; } } impl Command for DependsCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_installed_package(true, true) for `package` argument self.set_name("depends")?; self.set_aliases(vec!["why".to_string()])?; @@ -109,7 +109,7 @@ impl Command for DependsCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -117,7 +117,7 @@ impl Command for DependsCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -128,10 +128,10 @@ impl Command for DependsCommand { } impl BaseCommand for DependsCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index aff63bd..6757d94 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -63,9 +63,11 @@ use crate::util::http::RequestProxy; pub struct DiagnoseCommand { base_command_data: BaseCommandData, - pub(crate) http_downloader: Option>>, - pub(crate) process: Option>>, - pub(crate) exit_code: i64, + pub(crate) http_downloader: + std::cell::RefCell>>>, + pub(crate) process: + std::cell::RefCell>>>, + pub(crate) exit_code: std::cell::Cell, } impl Default for DiagnoseCommand { @@ -76,11 +78,11 @@ impl Default for DiagnoseCommand { impl DiagnoseCommand { pub fn new() -> Self { - let mut command = DiagnoseCommand { + let command = DiagnoseCommand { base_command_data: BaseCommandData::new(None), - http_downloader: None, - process: None, - exit_code: 0, + http_downloader: std::cell::RefCell::new(None), + process: std::cell::RefCell::new(None), + exit_code: std::cell::Cell::new(0), }; command .configure() @@ -90,7 +92,7 @@ impl DiagnoseCommand { } impl Command for DiagnoseCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("diagnose")?; self.set_description("Diagnoses the system to identify common errors"); self.set_help( @@ -102,7 +104,7 @@ impl Command for DiagnoseCommand { } fn execute( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, ) -> anyhow::Result { @@ -125,7 +127,7 @@ impl Command for DiagnoseCommand { c.get_event_dispatcher() .borrow_mut() .dispatch(Some(command_event.get_name()), None); - self.process = Some( + *self.process.borrow_mut() = Some( c.get_loop() .borrow() .get_process_executor() @@ -139,7 +141,7 @@ impl Command for DiagnoseCommand { } else { config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?)); - self.process = Some(std::rc::Rc::new(std::cell::RefCell::new( + *self.process.borrow_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new( ProcessExecutor::new(Some(io.clone())), ))); } @@ -157,7 +159,7 @@ impl Command for DiagnoseCommand { &IndexMap::new(), ); - self.http_downloader = Some(std::rc::Rc::new(std::cell::RefCell::new( + *self.http_downloader.borrow_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new( Factory::create_http_downloader(io.clone(), &config, indexmap::IndexMap::new())?, ))); @@ -321,7 +323,7 @@ impl Command for DiagnoseCommand { repo_arr_unboxed, self.get_io().clone(), &config.borrow(), - self.http_downloader.clone().unwrap(), + self.http_downloader.borrow().clone().unwrap(), None, ) .unwrap(); @@ -443,11 +445,11 @@ impl Command for DiagnoseCommand { let r = self.check_disk_space(&config.borrow()); self.output_result(r); - Ok(self.exit_code) + Ok(self.exit_code.get()) } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -458,17 +460,17 @@ impl Command for DiagnoseCommand { } impl BaseCommand for DiagnoseCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); } impl DiagnoseCommand { - fn check_composer_schema(&mut self) -> anyhow::Result { + fn check_composer_schema(&self) -> anyhow::Result { let validator = ConfigValidator::new(self.get_io().clone()); let (errors, _, warnings) = validator.validate(&Factory::get_composer_file()?, 0, 0); @@ -511,26 +513,33 @@ impl DiagnoseCommand { Ok(PhpMixed::Bool(true)) } - fn check_git(&mut self) -> String { + fn check_git(&self) -> String { if !function_exists("proc_open") { return "proc_open is not available, git cannot be used".to_string(); } let mut output = String::new(); - let _ = self.process.as_mut().unwrap().borrow_mut().execute( - vec![ - "git".to_string(), - "config".to_string(), - "color.ui".to_string(), - ], - &mut output, - (), - ); + let _ = self + .process + .borrow() + .as_ref() + .unwrap() + .borrow_mut() + .execute( + vec![ + "git".to_string(), + "config".to_string(), + "color.ui".to_string(), + ], + &mut output, + (), + ); if strtolower(&trim(&output, Some(" \t\n\r\0\u{0B}"))) == "always" { return "Your git color.ui setting is set to always, this is known to create issues. Use \"git config --global color.ui true\" to set it correctly.".to_string(); } - let git_version = Git::get_version(self.process.as_ref().unwrap()); + let process = self.process.borrow(); + let git_version = Git::get_version(process.as_ref().unwrap()); let git_version = match git_version { Some(v) => v, None => return "No git process found".to_string(), @@ -546,7 +555,7 @@ impl DiagnoseCommand { format!("OK git version {}", git_version) } - fn check_http(&mut self, proto: &str, config: &Config) -> anyhow::Result { + fn check_http(&self, proto: &str, config: &Config) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -558,10 +567,16 @@ impl DiagnoseCommand { tls_warning = Some("Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.".to_string()); } - match self.http_downloader.as_ref().unwrap().borrow_mut().get( - &format!("{}://repo.packagist.org/packages.json", proto), - IndexMap::new(), - ) { + match self + .http_downloader + .borrow() + .as_ref() + .unwrap() + .borrow_mut() + .get( + &format!("{}://repo.packagist.org/packages.json", proto), + IndexMap::new(), + ) { Ok(_) => {} Err(e) => { if let Some(te) = e.downcast_ref::() { @@ -594,7 +609,7 @@ impl DiagnoseCommand { Ok(PhpMixed::Bool(true)) } - fn check_composer_repo(&mut self, url: &str, config: &Config) -> anyhow::Result { + fn check_composer_repo(&self, url: &str, config: &Config) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -608,6 +623,7 @@ impl DiagnoseCommand { match self .http_downloader + .borrow() .as_ref() .unwrap() .borrow_mut() @@ -645,11 +661,7 @@ impl DiagnoseCommand { Ok(PhpMixed::Bool(true)) } - fn check_http_proxy( - &mut self, - proxy: &RequestProxy, - protocol: &str, - ) -> anyhow::Result { + fn check_http_proxy(&self, proxy: &RequestProxy, protocol: &str) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -666,6 +678,7 @@ impl DiagnoseCommand { let json = self .http_downloader + .borrow() .as_ref() .unwrap() .borrow_mut() @@ -694,10 +707,16 @@ impl DiagnoseCommand { .and_then(|a| a.keys().next().cloned()) .unwrap_or_default(), ); - let response = self.http_downloader.as_ref().unwrap().borrow_mut().get( - &format!("{}://repo.packagist.org/{}", protocol, path), - IndexMap::new(), - )?; + let response = self + .http_downloader + .borrow() + .as_ref() + .unwrap() + .borrow_mut() + .get( + &format!("{}://repo.packagist.org/{}", protocol, path), + IndexMap::new(), + )?; let provider = response.get_body().unwrap_or_default().to_string(); if hash("sha256", &provider) != hash_val.as_string().unwrap_or("") { @@ -714,7 +733,7 @@ impl DiagnoseCommand { ))) } - fn check_github_oauth(&mut self, domain: &str, token: &str) -> anyhow::Result { + fn check_github_oauth(&self, domain: &str, token: &str) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -736,6 +755,7 @@ impl DiagnoseCommand { match self .http_downloader + .borrow() .as_ref() .unwrap() .borrow_mut() @@ -773,11 +793,7 @@ impl DiagnoseCommand { } } - fn get_github_rate_limit( - &mut self, - domain: &str, - token: Option<&str>, - ) -> anyhow::Result { + fn get_github_rate_limit(&self, domain: &str, token: Option<&str>) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -800,6 +816,7 @@ impl DiagnoseCommand { opts.insert("retry-auth-failure".to_string(), PhpMixed::Bool(false)); let data = self .http_downloader + .borrow() .as_ref() .unwrap() .borrow_mut() @@ -841,7 +858,7 @@ impl DiagnoseCommand { PhpMixed::Bool(true) } - fn check_pub_keys(&mut self, config: &Config) -> anyhow::Result { + fn check_pub_keys(&self, config: &Config) -> anyhow::Result { let home = config.get("home").as_string().unwrap_or("").to_string(); let mut errors: Vec = vec![]; let io = self.get_io(); @@ -888,7 +905,7 @@ impl DiagnoseCommand { } fn check_version( - &mut self, + &self, config: &std::rc::Rc>, ) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); @@ -896,8 +913,10 @@ impl DiagnoseCommand { return Ok(result); } - let mut versions_util = - Versions::new(config.clone(), self.http_downloader.clone().unwrap()); + let mut versions_util = Versions::new( + config.clone(), + self.http_downloader.borrow().clone().unwrap(), + ); let latest = match versions_util.get_latest(None) { Ok(Ok(l)) => l, Ok(Err(e)) => { @@ -932,7 +951,7 @@ impl DiagnoseCommand { Ok(PhpMixed::Bool(true)) } - fn check_composer_audit(&mut self, config: &Config) -> anyhow::Result { + fn check_composer_audit(&self, config: &Config) -> anyhow::Result { let result = self.check_connectivity_and_composer_network_http_enablement(); if result.as_bool() != Some(true) { return Ok(result); @@ -981,7 +1000,7 @@ impl DiagnoseCommand { repo_config, std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())), config, - self.http_downloader.clone().unwrap(), + self.http_downloader.borrow().clone().unwrap(), None, )?); repo_set.add_repository(composer_repo_as_repo)?; @@ -1086,8 +1105,8 @@ impl DiagnoseCommand { "missing, using php streams fallback, which reduces performance".to_string() } - fn output_result(&mut self, result: PhpMixed) { - let prev_exit_code = self.exit_code; + fn output_result(&self, result: PhpMixed) { + let prev_exit_code = self.exit_code.get(); let io = self.get_io(); if result.as_bool() == Some(true) { io.write("OK"); @@ -1138,13 +1157,13 @@ impl DiagnoseCommand { } // Apply exit code updates after io borrow ends if had_error { - self.exit_code = prev_exit_code.max(2); + self.exit_code.set(prev_exit_code.max(2)); } else if had_warning { - self.exit_code = prev_exit_code.max(1); + self.exit_code.set(prev_exit_code.max(1)); } } - fn check_platform(&mut self) -> anyhow::Result { + fn check_platform(&self) -> anyhow::Result { let mut output = String::new(); let mut display_ini_message = false; diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs index 9369267..200ada2 100644 --- a/crates/shirabe/src/command/dump_autoload_command.rs +++ b/crates/shirabe/src/command/dump_autoload_command.rs @@ -35,7 +35,7 @@ impl Default for DumpAutoloadCommand { impl DumpAutoloadCommand { pub fn new() -> Self { - let mut command = DumpAutoloadCommand { + let command = DumpAutoloadCommand { base_command_data: BaseCommandData::new(None), }; command @@ -46,7 +46,7 @@ impl DumpAutoloadCommand { } impl Command for DumpAutoloadCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("dump-autoload")?; self.set_aliases(vec!["dumpautoload".to_string()])?; self.set_description("Dumps the autoloader"); @@ -71,7 +71,7 @@ impl Command for DumpAutoloadCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -320,7 +320,7 @@ impl Command for DumpAutoloadCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -331,10 +331,10 @@ impl Command for DumpAutoloadCommand { } impl BaseCommand for DumpAutoloadCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs index c4a1e94..caa9808 100644 --- a/crates/shirabe/src/command/exec_command.rs +++ b/crates/shirabe/src/command/exec_command.rs @@ -34,7 +34,7 @@ impl Default for ExecCommand { impl ExecCommand { pub fn new() -> Self { - let mut command = ExecCommand { + let command = ExecCommand { base_command_data: BaseCommandData::new(None), }; command @@ -43,7 +43,7 @@ impl ExecCommand { command } - fn get_binaries(&mut self, for_display: bool) -> Result> { + fn get_binaries(&self, for_display: bool) -> Result> { let composer = self.require_composer(None, None)?; let composer_ref = crate::command::composer_full_mut(&composer); let bin_dir = composer_ref @@ -81,7 +81,7 @@ impl ExecCommand { } impl Command for ExecCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("exec")?; self.set_description("Executes a vendored binary/script"); self.set_definition(&[ @@ -104,7 +104,7 @@ impl Command for ExecCommand { } fn interact( - &mut self, + &self, input: Rc>, _output: Rc>, ) { @@ -146,7 +146,7 @@ impl Command for ExecCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -236,7 +236,7 @@ impl Command for ExecCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -247,10 +247,10 @@ impl Command for ExecCommand { } impl BaseCommand for ExecCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs index 4b58a7a..5b4987f 100644 --- a/crates/shirabe/src/command/fund_command.rs +++ b/crates/shirabe/src/command/fund_command.rs @@ -46,7 +46,7 @@ impl Default for FundCommand { impl FundCommand { pub fn new() -> Self { - let mut command = FundCommand { + let command = FundCommand { base_command_data: BaseCommandData::new(None), }; command @@ -93,7 +93,7 @@ impl FundCommand { } impl Command for FundCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("fund")?; self.set_description("Discover how to help fund the maintenance of your dependencies"); self.set_definition(&[InputOption::new( @@ -109,7 +109,7 @@ impl Command for FundCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -229,7 +229,7 @@ impl Command for FundCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -240,10 +240,10 @@ impl Command for FundCommand { } impl BaseCommand for FundCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs index 0645b3a..aed142c 100644 --- a/crates/shirabe/src/command/global_command.rs +++ b/crates/shirabe/src/command/global_command.rs @@ -43,7 +43,7 @@ impl Default for GlobalCommand { impl GlobalCommand { pub fn new() -> Self { - let mut command = GlobalCommand { + let command = GlobalCommand { base_command_data: BaseCommandData::new(None), }; command @@ -78,7 +78,7 @@ impl GlobalCommand { } fn prepare_subcommand_input( - &mut self, + &self, input: Rc>, quiet: bool, ) -> Result { @@ -127,7 +127,7 @@ impl GlobalCommand { } impl Command for GlobalCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("global")?; self.set_description("Allows running commands in the global composer dir ($COMPOSER_HOME)"); self.set_definition(&[ @@ -164,7 +164,7 @@ impl Command for GlobalCommand { } fn run( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -191,7 +191,7 @@ impl Command for GlobalCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -202,10 +202,10 @@ impl Command for GlobalCommand { } impl BaseCommand for GlobalCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs index 5b05815..b3bb3ff 100644 --- a/crates/shirabe/src/command/home_command.rs +++ b/crates/shirabe/src/command/home_command.rs @@ -43,7 +43,7 @@ impl Default for HomeCommand { impl HomeCommand { pub fn new() -> Self { - let mut command = HomeCommand { + let command = HomeCommand { base_command_data: BaseCommandData::new(None), }; command @@ -53,7 +53,7 @@ impl HomeCommand { } fn handle_package( - &mut self, + &self, package: CompletePackageInterfaceHandle, show_homepage: bool, show_only: bool, @@ -86,7 +86,7 @@ impl HomeCommand { true } - fn open_browser(&mut self, url: &str) { + fn open_browser(&self, url: &str) { let mut process = ProcessExecutor::new(Some(self.get_io().clone())); if Platform::is_windows() { let _ = process.execute( @@ -116,7 +116,7 @@ impl HomeCommand { } } - fn initialize_repos(&mut self) -> Result> { + fn initialize_repos(&self) -> Result> { let composer = self.try_composer(None, None); if let Some(composer) = composer { @@ -142,7 +142,7 @@ impl HomeCommand { } impl Command for HomeCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_installed_package() for `packages` argument self.set_name("browse")?; self.set_aliases(vec!["home".to_string()])?; @@ -186,7 +186,7 @@ impl Command for HomeCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -264,7 +264,7 @@ impl Command for HomeCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -275,10 +275,10 @@ impl Command for HomeCommand { } impl BaseCommand for HomeCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 71be193..ec9ede4 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -47,22 +47,27 @@ pub struct InitCommand { base_command_data: BaseCommandData, /// @var array - git_config: Option>, - repos: Option, - repository_sets: + git_config: std::cell::RefCell>>, + repos: std::cell::RefCell>, + repository_sets: std::cell::RefCell< IndexMap>>, + >, } impl PackageDiscoveryTrait for InitCommand { - fn get_repos_mut(&mut self) -> &mut Option { - &mut self.repos + fn get_repos_mut( + &self, + ) -> std::cell::RefMut<'_, Option> { + self.repos.borrow_mut() } fn get_repository_sets_mut( - &mut self, - ) -> &mut IndexMap>> - { - &mut self.repository_sets + &self, + ) -> std::cell::RefMut< + '_, + IndexMap>>, + > { + self.repository_sets.borrow_mut() } } @@ -74,11 +79,11 @@ impl Default for InitCommand { impl InitCommand { pub fn new() -> Self { - let mut command = InitCommand { + let command = InitCommand { base_command_data: BaseCommandData::new(None), - git_config: None, - repos: None, - repository_sets: IndexMap::new(), + git_config: std::cell::RefCell::new(None), + repos: std::cell::RefCell::new(None), + repository_sets: std::cell::RefCell::new(IndexMap::new()), }; command .configure() @@ -88,7 +93,7 @@ impl InitCommand { } impl Command for InitCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_available_package_incl_platform() for `require` / `require-dev` self.set_name("init")?; self.set_description("Creates a basic composer.json file in current directory"); @@ -118,7 +123,7 @@ impl Command for InitCommand { /// @throws \Seld\JsonLint\ParsingException fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -404,7 +409,7 @@ impl Command for InitCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -432,7 +437,7 @@ impl Command for InitCommand { } fn interact( - &mut self, + &self, input: Rc>, output: Rc>, ) { @@ -905,10 +910,10 @@ impl Command for InitCommand { } impl BaseCommand for InitCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -994,9 +999,9 @@ impl InitCommand { } /// @return array - pub(crate) fn get_git_config(&mut self) -> IndexMap { - if self.git_config.is_some() { - return self.git_config.clone().unwrap_or_default(); + pub(crate) fn get_git_config(&self) -> IndexMap { + if self.git_config.borrow().is_some() { + return self.git_config.borrow().clone().unwrap_or_default(); } let mut process = ProcessExecutor::new(Some(self.get_io().clone())); @@ -1008,7 +1013,7 @@ impl InitCommand { (), ) == 0 { - self.git_config = Some(IndexMap::new()); + *self.git_config.borrow_mut() = Some(IndexMap::new()); let mut m: IndexMap> = IndexMap::new(); if Preg::is_match_all3(r"{^([^=]+)=(.*)$}m", &output, Some(&mut m)) { let keys: Vec = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); @@ -1016,16 +1021,17 @@ impl InitCommand { m.get(&CaptureKey::ByIndex(2)).cloned().unwrap_or_default(); for (key, value) in keys.iter().zip(values.iter()) { self.git_config + .borrow_mut() .as_mut() .unwrap() .insert(key.clone(), value.clone()); } } - return self.git_config.clone().unwrap_or_default(); + return self.git_config.borrow().clone().unwrap_or_default(); } - self.git_config = Some(IndexMap::new()); + *self.git_config.borrow_mut() = Some(IndexMap::new()); IndexMap::new() } @@ -1082,7 +1088,7 @@ impl InitCommand { } /// For testing only: invoke the crate-private `get_git_config`. - pub fn __get_git_config(&mut self) -> IndexMap { + pub fn __get_git_config(&self) -> IndexMap { self.get_git_config() } @@ -1153,7 +1159,7 @@ impl InitCommand { Preg::replace(r"{([_.-]){2,}}u", "$1", &name) } - fn get_default_package_name(&mut self) -> String { + fn get_default_package_name(&self) -> String { let git = self.get_git_config(); let cwd = realpath(".").unwrap_or_default(); let name = basename(&cwd); @@ -1193,7 +1199,7 @@ impl InitCommand { format!("{}/{}", vendor, name) } - fn get_default_author(&mut self) -> Option { + fn get_default_author(&self) -> Option { let git = self.get_git_config(); let mut author_name: Option = None; diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs index 1605015..53e3a6c 100644 --- a/crates/shirabe/src/command/install_command.rs +++ b/crates/shirabe/src/command/install_command.rs @@ -39,7 +39,7 @@ impl Default for InstallCommand { impl InstallCommand { pub fn new() -> Self { - let mut command = InstallCommand { + let command = InstallCommand { base_command_data: BaseCommandData::new(None), }; command @@ -50,7 +50,7 @@ impl InstallCommand { } impl Command for InstallCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_prefer_install() for `prefer-install` option self.set_name("install")?; self.set_aliases(vec!["i".to_string()])?; @@ -91,7 +91,7 @@ impl Command for InstallCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -272,7 +272,7 @@ impl Command for InstallCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -283,10 +283,10 @@ impl Command for InstallCommand { } impl BaseCommand for InstallCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs index 46cbd02..3c1745a 100644 --- a/crates/shirabe/src/command/licenses_command.rs +++ b/crates/shirabe/src/command/licenses_command.rs @@ -49,7 +49,7 @@ impl Default for LicensesCommand { impl LicensesCommand { pub fn new() -> Self { - let mut command = LicensesCommand { + let command = LicensesCommand { base_command_data: BaseCommandData::new(None), }; command @@ -60,7 +60,7 @@ impl LicensesCommand { } impl Command for LicensesCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("licenses")?; self.set_description("Shows information about licenses of dependencies"); self.set_definition(&[ @@ -103,7 +103,7 @@ impl Command for LicensesCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -341,7 +341,7 @@ impl Command for LicensesCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -352,10 +352,10 @@ impl Command for LicensesCommand { } impl BaseCommand for LicensesCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/outdated_command.rs b/crates/shirabe/src/command/outdated_command.rs index 3281723..6a3c3e2 100644 --- a/crates/shirabe/src/command/outdated_command.rs +++ b/crates/shirabe/src/command/outdated_command.rs @@ -34,7 +34,7 @@ impl Default for OutdatedCommand { impl OutdatedCommand { pub fn new() -> Self { - let mut command = OutdatedCommand { + let command = OutdatedCommand { base_command_data: BaseCommandData::new(None), }; command @@ -45,7 +45,7 @@ impl OutdatedCommand { } impl Command for OutdatedCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_installed_package(false, false) for `package` argument and `--ignore` option self.set_name("outdated")?; self.set_description("Shows a list of installed packages that have updates available, including their latest version"); @@ -80,7 +80,7 @@ impl Command for OutdatedCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -231,7 +231,7 @@ impl Command for OutdatedCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -242,10 +242,10 @@ impl Command for OutdatedCommand { } impl BaseCommand for OutdatedCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } fn is_proxy_command(&self) -> bool { diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index 9be30f5..943eeaf 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -37,12 +37,14 @@ use crate::util::Filesystem; pub trait PackageDiscoveryTrait: BaseCommand { // PHP: private $repos; private $repositorySets; // TODO(phase-b): trait fields require an associated state struct in Rust; expose via accessors - fn get_repos_mut(&mut self) -> &mut Option; + fn get_repos_mut( + &self, + ) -> std::cell::RefMut<'_, Option>; fn get_repository_sets_mut( - &mut self, - ) -> &mut IndexMap>>; + &self, + ) -> std::cell::RefMut<'_, IndexMap>>>; - fn get_repos(&mut self) -> crate::repository::RepositoryInterfaceHandle { + fn get_repos(&self) -> crate::repository::RepositoryInterfaceHandle { if self.get_repos_mut().is_none() { // PHP: array_merge([new PlatformRepository], RepositoryFactory::defaultReposWithDefaultManager($this->getIO())) let mut repos: Vec = @@ -67,7 +69,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { /// @param key-of|null $minimumStability fn get_repository_set( - &mut self, + &self, input: std::rc::Rc>, minimum_stability: Option<&str>, ) -> std::rc::Rc> { @@ -134,7 +136,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn determine_requirements( - &mut self, + &self, input: std::rc::Rc>, _output: std::rc::Rc>, mut requires: Vec, @@ -463,7 +465,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { /// @throws \InvalidArgumentException /// @return array{string, string} name version fn find_best_version_and_name_for_package( - &mut self, + &self, io: std::rc::Rc>, input: std::rc::Rc>, name: &str, @@ -759,7 +761,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { } /// @return array - fn find_similar(&mut self, package: &str) -> Result> { + fn find_similar(&self, package: &str) -> Result> { let results: Vec = match (|| -> Result> { if self.get_repos_mut().is_none() { return Err(LogicException { diff --git a/crates/shirabe/src/command/prohibits_command.rs b/crates/shirabe/src/command/prohibits_command.rs index ddbf02a..f35990a 100644 --- a/crates/shirabe/src/command/prohibits_command.rs +++ b/crates/shirabe/src/command/prohibits_command.rs @@ -24,7 +24,7 @@ use crate::io::IOInterface; pub struct ProhibitsCommand { base_command_data: BaseCommandData, - colors: Vec, + colors: std::cell::RefCell>, } impl Default for ProhibitsCommand { @@ -35,9 +35,9 @@ impl Default for ProhibitsCommand { impl ProhibitsCommand { pub fn new() -> Self { - let mut command = ProhibitsCommand { + let command = ProhibitsCommand { base_command_data: BaseCommandData::new(None), - colors: Vec::new(), + colors: std::cell::RefCell::new(Vec::new()), }; command .configure() @@ -47,17 +47,17 @@ impl ProhibitsCommand { } impl BaseDependencyCommand for ProhibitsCommand { - fn colors(&self) -> &[String] { - &self.colors + fn colors(&self) -> std::cell::Ref<'_, Vec> { + self.colors.borrow() } - fn colors_mut(&mut self) -> &mut Vec { - &mut self.colors + fn set_colors(&self, colors: Vec) { + *self.colors.borrow_mut() = colors; } } impl Command for ProhibitsCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_available_package() for `package` argument self.set_name("prohibits")?; self.set_aliases(vec!["why-not".to_string()])?; @@ -116,7 +116,7 @@ impl Command for ProhibitsCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -124,7 +124,7 @@ impl Command for ProhibitsCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -135,10 +135,10 @@ impl Command for ProhibitsCommand { } impl BaseCommand for ProhibitsCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs index 8f48243..6e728e6 100644 --- a/crates/shirabe/src/command/reinstall_command.rs +++ b/crates/shirabe/src/command/reinstall_command.rs @@ -47,7 +47,7 @@ impl Default for ReinstallCommand { impl ReinstallCommand { pub fn new() -> Self { - let mut command = ReinstallCommand { + let command = ReinstallCommand { base_command_data: BaseCommandData::new(None), }; command @@ -58,7 +58,7 @@ impl ReinstallCommand { } impl Command for ReinstallCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_prefer_install / suggest_installed_package_types / suggest_installed_package self.set_name("reinstall")?; self.set_description("Uninstalls and reinstalls the given package names"); @@ -89,7 +89,7 @@ impl Command for ReinstallCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -349,7 +349,7 @@ impl Command for ReinstallCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -360,10 +360,10 @@ impl Command for ReinstallCommand { } impl BaseCommand for ReinstallCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs index 4260369..0cac581 100644 --- a/crates/shirabe/src/command/remove_command.rs +++ b/crates/shirabe/src/command/remove_command.rs @@ -47,7 +47,7 @@ impl Default for RemoveCommand { impl RemoveCommand { pub fn new() -> Self { - let mut command = RemoveCommand { + let command = RemoveCommand { base_command_data: BaseCommandData::new(None), }; command @@ -58,7 +58,7 @@ impl RemoveCommand { } impl Command for RemoveCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_root_requirement() for `packages` argument self.set_name("remove")?; self.set_aliases(vec!["rm".to_string(), "uninstall".to_string()])?; @@ -184,7 +184,7 @@ impl Command for RemoveCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -722,7 +722,7 @@ impl Command for RemoveCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -733,10 +733,10 @@ impl Command for RemoveCommand { } impl BaseCommand for RemoveCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs index caca808..4cbe08c 100644 --- a/crates/shirabe/src/command/repository_command.rs +++ b/crates/shirabe/src/command/repository_command.rs @@ -31,9 +31,9 @@ use crate::json::JsonFile; pub struct RepositoryCommand { base_command_data: BaseCommandData, - config: Option>>, - config_file: Option>>, - config_source: Option, + config: std::cell::RefCell>>>, + config_file: std::cell::RefCell>>>, + config_source: std::cell::RefCell>, } impl Default for RepositoryCommand { @@ -44,11 +44,11 @@ impl Default for RepositoryCommand { impl RepositoryCommand { pub fn new() -> Self { - let mut command = RepositoryCommand { + let command = RepositoryCommand { base_command_data: BaseCommandData::new(None), - config: None, - config_file: None, - config_source: None, + config: std::cell::RefCell::new(None), + config_file: std::cell::RefCell::new(None), + config_source: std::cell::RefCell::new(None), }; command .configure() @@ -56,7 +56,7 @@ impl RepositoryCommand { command } - fn list_repositories(&mut self, mut repos: IndexMap) { + fn list_repositories(&self, mut repos: IndexMap) { let io = self.get_io(); let mut packagist_present = false; @@ -132,7 +132,7 @@ impl RepositoryCommand { } impl Command for RepositoryCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_repo_names() / suggest_type_for_add() self.set_name("repository")?; self.set_aliases(vec!["repo".to_string()])?; @@ -237,7 +237,7 @@ impl Command for RepositoryCommand { } fn execute( - &mut self, + &self, input: std::rc::Rc>, _output: std::rc::Rc>, ) -> anyhow::Result { @@ -264,24 +264,18 @@ impl Command for RepositoryCommand { .as_string() .map(|s| s.to_string()); - let config_data = self.config_file.as_ref().unwrap().borrow_mut().read()?; - let config_file_path = self - .config_file - .as_ref() - .unwrap() - .borrow() - .get_path() - .to_string(); + let config_file = self.config_file.borrow().as_ref().unwrap().clone(); + let config_data = config_file.borrow_mut().read()?; + let config_file_path = config_file.borrow().get_path().to_string(); let config_data_map: IndexMap = match config_data { PhpMixed::Array(m) => m.into_iter().collect(), _ => IndexMap::new(), }; - self.config - .as_mut() - .unwrap() + let config = self.config.borrow().as_ref().unwrap().clone(); + config .borrow_mut() .merge(&config_data_map, &config_file_path); - let repos = self.config.as_ref().unwrap().borrow().get_repositories(); + let repos = config.borrow().get_repositories(); match action.as_str() { "list" | "ls" | "show" => { @@ -344,12 +338,16 @@ impl Command for RepositoryCommand { } let reference_name = before.as_deref().or(after.as_deref()).unwrap(); let offset: i64 = if after.is_some() { 1 } else { 0 }; - self.config_source.as_mut().unwrap().insert_repository( - name.as_deref().unwrap(), - repo_config.clone(), - reference_name, - offset, - )?; + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .insert_repository( + name.as_deref().unwrap(), + repo_config.clone(), + reference_name, + offset, + )?; return Ok(0); } @@ -358,11 +356,11 @@ impl Command for RepositoryCommand { .get_option("append")? .as_bool() .unwrap_or(false); - self.config_source.as_mut().unwrap().add_repository( - name.as_deref().unwrap(), - repo_config.clone(), - append, - )?; + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository(name.as_deref().unwrap(), repo_config.clone(), append)?; Ok(0) } "remove" | "rm" | "delete" => { @@ -374,15 +372,16 @@ impl Command for RepositoryCommand { } let name_str = name.as_deref().unwrap(); self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_repository(name_str)?; if ["packagist", "packagist.org"].contains(&name_str) { - self.config_source.as_mut().unwrap().add_repository( - "packagist.org", - PhpMixed::Null, - false, - )?; + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository("packagist.org", PhpMixed::Null, false)?; } Ok(0) } @@ -394,6 +393,7 @@ impl Command for RepositoryCommand { })); } self.config_source + .borrow_mut() .as_mut() .unwrap() .set_repository_url(name.as_deref().unwrap(), arg1.as_deref().unwrap()); @@ -455,11 +455,11 @@ impl Command for RepositoryCommand { .get_option("append")? .as_bool() .unwrap_or(false); - self.config_source.as_mut().unwrap().add_repository( - "packagist.org", - PhpMixed::Bool(false), - append, - ); + self.config_source + .borrow_mut() + .as_mut() + .unwrap() + .add_repository("packagist.org", PhpMixed::Bool(false), append); return Ok(0); } Err(anyhow::anyhow!(RuntimeException { @@ -477,6 +477,7 @@ impl Command for RepositoryCommand { let name_str = name.as_deref().unwrap(); if ["packagist", "packagist.org"].contains(&name_str) { self.config_source + .borrow_mut() .as_mut() .unwrap() .remove_repository("packagist.org"); @@ -499,7 +500,7 @@ impl Command for RepositoryCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -512,41 +513,33 @@ impl Command for RepositoryCommand { } impl BaseCommand for RepositoryCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); } impl BaseConfigCommand for RepositoryCommand { - fn config(&self) -> Option<&std::rc::Rc>> { - self.config.as_ref() - } - - fn config_mut(&mut self) -> &mut Option>> { - &mut self.config - } - - fn config_file(&self) -> Option<&std::rc::Rc>> { - self.config_file.as_ref() + fn config(&self) -> Option>> { + self.config.borrow().clone() } - fn config_source(&self) -> Option<&JsonConfigSource> { - self.config_source.as_ref() + fn set_config(&self, config: Option>>) { + *self.config.borrow_mut() = config; } - fn config_source_mut(&mut self) -> Option<&mut JsonConfigSource> { - self.config_source.as_mut() + fn config_file(&self) -> Option>> { + self.config_file.borrow().clone() } - fn set_config_file(&mut self, file: Option>>) { - self.config_file = file; + fn set_config_file(&self, file: Option>>) { + *self.config_file.borrow_mut() = file; } - fn set_config_source(&mut self, source: Option) { - self.config_source = source; + fn set_config_source(&self, source: Option) { + *self.config_source.borrow_mut() = source; } } diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs index f965350..b1dfd4a 100644 --- a/crates/shirabe/src/command/require_command.rs +++ b/crates/shirabe/src/command/require_command.rs @@ -55,18 +55,19 @@ use crate::util::Silencer; pub struct RequireCommand { base_command_data: BaseCommandData, - newly_created: bool, - first_require: bool, - json: Option>>, - file: String, - composer_backup: String, + newly_created: std::cell::Cell, + first_require: std::cell::Cell, + json: std::cell::RefCell>>>, + file: std::cell::RefCell, + composer_backup: std::cell::RefCell, /// file name - lock: String, + lock: std::cell::RefCell, /// contents before modification if the lock file exists - lock_backup: Option, - dependency_resolution_completed: bool, - repos: Option, - repository_sets: IndexMap>>, + lock_backup: std::cell::RefCell>, + dependency_resolution_completed: std::cell::Cell, + repos: std::cell::RefCell>, + repository_sets: + std::cell::RefCell>>>, } impl Default for RequireCommand { @@ -77,18 +78,18 @@ impl Default for RequireCommand { impl RequireCommand { pub fn new() -> Self { - let mut command = RequireCommand { + let command = RequireCommand { base_command_data: BaseCommandData::new(None), - newly_created: false, - first_require: false, - json: None, - file: String::new(), - composer_backup: String::new(), - lock: String::new(), - lock_backup: None, - dependency_resolution_completed: false, - repos: None, - repository_sets: IndexMap::new(), + newly_created: std::cell::Cell::new(false), + first_require: std::cell::Cell::new(false), + json: std::cell::RefCell::new(None), + file: std::cell::RefCell::new(String::new()), + composer_backup: std::cell::RefCell::new(String::new()), + lock: std::cell::RefCell::new(String::new()), + lock_backup: std::cell::RefCell::new(None), + dependency_resolution_completed: std::cell::Cell::new(false), + repos: std::cell::RefCell::new(None), + repository_sets: std::cell::RefCell::new(IndexMap::new()), }; command .configure() @@ -98,19 +99,22 @@ impl RequireCommand { } impl PackageDiscoveryTrait for RequireCommand { - fn get_repos_mut(&mut self) -> &mut Option { - &mut self.repos + fn get_repos_mut( + &self, + ) -> std::cell::RefMut<'_, Option> { + self.repos.borrow_mut() } fn get_repository_sets_mut( - &mut self, - ) -> &mut IndexMap>> { - &mut self.repository_sets + &self, + ) -> std::cell::RefMut<'_, IndexMap>>> + { + self.repository_sets.borrow_mut() } } impl Command for RequireCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_available_package_incl_platform / suggest_prefer_install self.set_name("require")?; self.set_aliases(vec!["r".to_string()])?; @@ -163,11 +167,11 @@ impl Command for RequireCommand { /// @throws \Seld\JsonLint\ParsingException fn execute( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, ) -> Result { - self.file = Factory::get_composer_file()?; + *self.file.borrow_mut() = Factory::get_composer_file()?; if input .borrow() @@ -178,34 +182,38 @@ impl Command for RequireCommand { self.get_io().write_error3("You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.", true, io_interface::NORMAL); } - self.newly_created = !file_exists(&self.file); - let write_failed = self.newly_created && file_put_contents(&self.file, b"{\n}\n").is_none(); + let file = self.file.borrow().clone(); + self.newly_created.set(!file_exists(&file)); + let write_failed = + self.newly_created.get() && file_put_contents(&file, b"{\n}\n").is_none(); if write_failed { - let msg = format!("{} could not be created.", self.file); + let msg = format!("{} could not be created.", file); self.get_io().write_error3(&msg, true, io_interface::NORMAL); return Ok(1); } - if !Filesystem::is_readable(&self.file) { - let msg = format!("{} is not readable.", self.file); + if !Filesystem::is_readable(&file) { + let msg = format!("{} is not readable.", file); self.get_io().write_error3(&msg, true, io_interface::NORMAL); return Ok(1); } - if filesize(&self.file) == Some(0) { - file_put_contents(&self.file, b"{\n}\n"); + if filesize(&file) == Some(0) { + file_put_contents(&file, b"{\n}\n"); } - self.json = Some(std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( - self.file.clone(), + *self.json.borrow_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new( + file.clone(), None, None, )?))); - self.lock = Factory::get_lock_file(&self.file); - self.composer_backup = - file_get_contents(self.json.as_ref().unwrap().borrow().get_path()).unwrap_or_default(); - self.lock_backup = if file_exists(&self.lock) { - file_get_contents(&self.lock) + *self.lock.borrow_mut() = Factory::get_lock_file(&file); + let json = self.json.borrow().as_ref().unwrap().clone(); + *self.composer_backup.borrow_mut() = + file_get_contents(json.borrow().get_path()).unwrap_or_default(); + let lock = self.lock.borrow().clone(); + *self.lock_backup.borrow_mut() = if file_exists(&lock) { + file_get_contents(&lock) } else { None }; @@ -232,9 +240,9 @@ impl Command for RequireCommand { // check for writability by writing to the file as is_writable can not be trusted on network-mounts // see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 - let file_path = self.file.clone(); - let backup_contents = self.composer_backup.clone(); - if !is_writable(&self.file) + let file_path = file.clone(); + let backup_contents = self.composer_backup.borrow().clone(); + if !is_writable(&file) && Silencer::call(|| { shirabe_php_shim::file_put_contents(&file_path, backup_contents.as_bytes()); Ok::(false) @@ -242,14 +250,14 @@ impl Command for RequireCommand { .ok() == Some(false) { - let msg = format!("{} is not writable.", self.file); + let msg = format!("{} is not writable.", file); self.get_io().write_error3(&msg, true, io_interface::NORMAL); return Ok(1); } if input.borrow().get_option("fixed")?.as_bool() == Some(true) { - let config = self.json.as_ref().unwrap().borrow_mut().read()?; + let config = json.borrow_mut().read()?; let package_type = if empty(&config.get("type").cloned().unwrap_or(PhpMixed::Null)) { "library".to_string() @@ -335,13 +343,13 @@ impl Command for RequireCommand { let requirements = match requirements_result { Ok(r) => r, Err(e) => { - if self.newly_created { + if self.newly_created.get() { self.revert_composer_file(); return Err(RuntimeException { message: format!( "No composer.json present in the current directory ({}), this may be the cause of the following exception.", - self.file + self.file.borrow() ), code: 0, } @@ -534,9 +542,9 @@ impl Command for RequireCommand { .as_bool() .unwrap_or(false); - self.first_require = self.newly_created; - if !self.first_require { - let composer_definition = self.json.as_ref().unwrap().borrow_mut().read()?; + self.first_require.set(self.newly_created.get()); + if !self.first_require.get() { + let composer_definition = json.borrow_mut().read()?; let require_count = composer_definition .get("require") .and_then(|v| v.as_array()) @@ -548,7 +556,7 @@ impl Command for RequireCommand { .map(|m| m.len() as i64) .unwrap_or(0); if require_count == 0 && require_dev_count == 0 { - self.first_require = true; + self.first_require.set(true); } } @@ -558,14 +566,13 @@ impl Command for RequireCommand { .as_bool() .unwrap_or(false) { - let json = self.json.as_ref().unwrap().clone(); self.update_file(&json, &requirements, require_key, remove_key, sort_packages); } let updated_msg = format!( "{} has been {}", - self.file, - if self.newly_created { + file, + if self.newly_created.get() { "created" } else { "updated" @@ -624,7 +631,7 @@ impl Command for RequireCommand { Ok(final_result) } Err(e) => { - if !self.dependency_resolution_completed { + if !self.dependency_resolution_completed.get() { self.revert_composer_file(); } Err(e) @@ -632,9 +639,9 @@ impl Command for RequireCommand { }; // finally - if dry_run && self.newly_created { + if dry_run && self.newly_created.get() { // @unlink($this->json->getPath()); - unlink(self.json.as_ref().unwrap().borrow().get_path()); + unlink(json.borrow().get_path()); } signal_handler.unregister(); @@ -642,14 +649,14 @@ impl Command for RequireCommand { } fn interact( - &mut self, + &self, _input: Rc>, _output: Rc>, ) { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -660,10 +667,10 @@ impl Command for RequireCommand { } impl BaseCommand for RequireCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -673,7 +680,7 @@ impl RequireCommand { /// @param array $newRequirements /// @return string[] fn get_inconsistent_require_keys( - &mut self, + &self, new_requirements: &IndexMap, require_key: &str, ) -> Vec { @@ -692,14 +699,9 @@ impl RequireCommand { } /// @return array - fn get_packages_by_require_key(&mut self) -> IndexMap { - let composer_definition = self - .json - .as_ref() - .unwrap() - .borrow_mut() - .read() - .unwrap_or_default(); + fn get_packages_by_require_key(&self) -> IndexMap { + let json = self.json.borrow().as_ref().unwrap().clone(); + let composer_definition = json.borrow_mut().read().unwrap_or_default(); let mut require: IndexMap = IndexMap::new(); let mut require_dev: IndexMap = IndexMap::new(); @@ -755,7 +757,7 @@ impl RequireCommand { /// @param 'require'|'require-dev' $removeKey /// @throws \Exception fn do_update( - &mut self, + &self, input: std::rc::Rc>, output: std::rc::Rc>, io: std::rc::Rc>, @@ -768,7 +770,7 @@ impl RequireCommand { let composer_handle = self.require_composer(None, None)?; let mut composer = crate::command::composer_full_mut(&composer_handle); - self.dependency_resolution_completed = false; + self.dependency_resolution_completed.set(false); // PHP: $composer->getEventDispatcher()->addListener(InstallerEvents::PRE_OPERATIONS_EXEC, // function () use (&$dependencyResolutionCompleted) { $dependencyResolutionCompleted = true; }, 10000); // TODO(phase-c): the event dispatcher's Callable::Closure is a placeholder variant that @@ -1018,7 +1020,7 @@ impl RequireCommand { // if no lock is present, or the file is brand new, we do not do a // partial update as this is not supported by the Installer - if !self.first_require && composer.get_locker().borrow_mut().is_locked() { + if !self.first_require.get() && composer.get_locker().borrow_mut().is_locked() { install.set_update_allow_list( array_keys(requirements) .into_iter() @@ -1060,7 +1062,7 @@ impl RequireCommand { /// @param list $requirementsToUpdate fn update_requirements_after_resolution( - &mut self, + &self, requirements_to_update: &[String], require_key: &str, remove_key: &str, @@ -1156,7 +1158,7 @@ impl RequireCommand { } if !dry_run { - let json = self.json.as_ref().unwrap().clone(); + let json = self.json.borrow().as_ref().unwrap().clone(); self.update_file(&json, &requirements, require_key, remove_key, sort_packages); if locker_is_locked && composer @@ -1184,7 +1186,7 @@ impl RequireCommand { /// @param array $new fn update_file( - &mut self, + &self, json: &std::rc::Rc>, new: &IndexMap, require_key: &str, @@ -1266,34 +1268,37 @@ impl RequireCommand { true } - fn revert_composer_file(&mut self) { - if self.newly_created { + fn revert_composer_file(&self) { + let json = self.json.borrow().as_ref().unwrap().clone(); + let lock = self.lock.borrow().clone(); + if self.newly_created.get() { let msg = format!( "\nInstallation failed, deleting {}.", - self.file + self.file.borrow() ); self.get_io().write_error3(&msg, true, io_interface::NORMAL); - unlink(self.json.as_ref().unwrap().borrow().get_path()); - if file_exists(&self.lock) { - unlink(&self.lock); + unlink(json.borrow().get_path()); + if file_exists(&lock) { + unlink(&lock); } } else { - let extra = if self.lock_backup.is_some() { - format!(" and {} to their ", self.lock) + let extra = if self.lock_backup.borrow().is_some() { + format!(" and {} to their ", lock) } else { " to its ".to_string() }; let msg = format!( "\nInstallation failed, reverting {}{}original content.", - self.file, extra + self.file.borrow(), + extra ); self.get_io().write_error3(&msg, true, io_interface::NORMAL); file_put_contents( - self.json.as_ref().unwrap().borrow().get_path(), - self.composer_backup.as_bytes(), + json.borrow().get_path(), + self.composer_backup.borrow().as_bytes(), ); - if let Some(ref lock_backup) = self.lock_backup { - file_put_contents(&self.lock, lock_backup.as_bytes()); + if let Some(ref lock_backup) = *self.lock_backup.borrow() { + file_put_contents(&lock, lock_backup.as_bytes()); } } } diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs index 5a8f628..383c5bb 100644 --- a/crates/shirabe/src/command/run_script_command.rs +++ b/crates/shirabe/src/command/run_script_command.rs @@ -41,7 +41,7 @@ impl Default for RunScriptCommand { impl RunScriptCommand { pub fn new() -> Self { - let mut command = RunScriptCommand { + let command = RunScriptCommand { base_command_data: BaseCommandData::new(None), script_events: vec![ ScriptEvents::PRE_INSTALL_CMD, @@ -64,7 +64,7 @@ impl RunScriptCommand { command } - fn list_scripts(&mut self, output: Rc>) -> Result { + fn list_scripts(&self, output: Rc>) -> Result { let scripts = self.get_scripts()?; if scripts.is_empty() { return Ok(0); @@ -87,7 +87,7 @@ impl RunScriptCommand { Ok(0) } - fn get_scripts(&mut self) -> Result> { + fn get_scripts(&self) -> Result> { let composer = self.require_composer(None, None)?; let scripts = crate::command::composer_full(&composer) .get_package() @@ -116,7 +116,7 @@ impl RunScriptCommand { } impl Command for RunScriptCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("run-script")?; self.set_aliases(vec!["run".to_string()])?; self.set_description("Runs the scripts defined in composer.json"); @@ -184,7 +184,7 @@ impl Command for RunScriptCommand { } fn interact( - &mut self, + &self, input: Rc>, _output: Rc>, ) { @@ -226,7 +226,7 @@ impl Command for RunScriptCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -326,7 +326,7 @@ impl Command for RunScriptCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -337,10 +337,10 @@ impl Command for RunScriptCommand { } impl BaseCommand for RunScriptCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs index 1d94f09..0fb5ce0 100644 --- a/crates/shirabe/src/command/script_alias_command.rs +++ b/crates/shirabe/src/command/script_alias_command.rs @@ -54,7 +54,7 @@ impl ScriptAliasCommand { // the command's name/definition/application state and ignoreValidationErrors() flips a flag // on it. Composer's BaseCommand carries no such Symfony Command state yet (the Symfony // Command base is an intentional todo!() stub), so there is nothing to initialize here. - let mut command = Self { + let command = Self { base_command_data: BaseCommandData::new(None), script, description, @@ -68,7 +68,7 @@ impl ScriptAliasCommand { } impl Command for ScriptAliasCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { let name = self.script.clone(); self.set_name(&name)?; let description = self.description.clone(); @@ -111,7 +111,7 @@ impl Command for ScriptAliasCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -167,7 +167,7 @@ impl Command for ScriptAliasCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -178,10 +178,10 @@ impl Command for ScriptAliasCommand { } impl BaseCommand for ScriptAliasCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs index c7070dd..bcd74c3 100644 --- a/crates/shirabe/src/command/search_command.rs +++ b/crates/shirabe/src/command/search_command.rs @@ -41,7 +41,7 @@ impl Default for SearchCommand { impl SearchCommand { pub fn new() -> Self { - let mut command = SearchCommand { + let command = SearchCommand { base_command_data: BaseCommandData::new(None), }; command @@ -52,7 +52,7 @@ impl SearchCommand { } impl Command for SearchCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("search")?; self.set_description("Searches for packages"); self.set_definition(&[ @@ -110,7 +110,7 @@ impl Command for SearchCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -277,7 +277,7 @@ impl Command for SearchCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -288,10 +288,10 @@ impl Command for SearchCommand { } impl BaseCommand for SearchCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs index 2f319ff..aaee993 100644 --- a/crates/shirabe/src/command/self_update_command.rs +++ b/crates/shirabe/src/command/self_update_command.rs @@ -35,7 +35,7 @@ impl Default for SelfUpdateCommand { impl SelfUpdateCommand { pub fn new() -> Self { - let mut command = SelfUpdateCommand { + let command = SelfUpdateCommand { base_command_data: BaseCommandData::new(None), }; command @@ -46,7 +46,7 @@ impl SelfUpdateCommand { } impl Command for SelfUpdateCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("self-update")?; self.set_aliases(vec!["selfupdate".to_string()])?; self.set_description("Updates composer.phar to the latest version"); @@ -79,7 +79,7 @@ impl Command for SelfUpdateCommand { /// differs fundamentally from the PHP phar-based one, and no release has /// been published yet. The command is therefore disabled. fn execute( - &mut self, + &self, _input: Rc>, _output: Rc>, ) -> anyhow::Result { @@ -94,7 +94,7 @@ impl Command for SelfUpdateCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -105,10 +105,10 @@ impl Command for SelfUpdateCommand { } impl BaseCommand for SelfUpdateCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs index ff348c5..3e0797a 100644 --- a/crates/shirabe/src/command/show_command.rs +++ b/crates/shirabe/src/command/show_command.rs @@ -64,9 +64,9 @@ const _INPUT_OPTION_REF: i64 = InputOption::VALUE_NONE; pub struct ShowCommand { base_command_data: BaseCommandData, - pub(crate) version_parser: VersionParser, - pub(crate) colors: Vec, - repository_set: Option>>, + pub(crate) version_parser: std::cell::RefCell, + pub(crate) colors: std::cell::RefCell>, + repository_set: std::cell::RefCell>>>, } impl Default for ShowCommand { @@ -77,11 +77,11 @@ impl Default for ShowCommand { impl ShowCommand { pub fn new() -> Self { - let mut command = ShowCommand { + let command = ShowCommand { base_command_data: BaseCommandData::new(None), - version_parser: VersionParser::new(), - colors: Vec::new(), - repository_set: None, + version_parser: std::cell::RefCell::new(VersionParser::new()), + colors: std::cell::RefCell::new(Vec::new()), + repository_set: std::cell::RefCell::new(None), }; command .configure() @@ -91,7 +91,7 @@ impl ShowCommand { } impl Command for ShowCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("show")?; self.set_aliases(vec!["info".to_string()])?; self.set_description("Shows information about packages"); @@ -107,11 +107,11 @@ impl Command for ShowCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { - self.version_parser = VersionParser::new(); + *self.version_parser.borrow_mut() = VersionParser::new(); if input.borrow().get_option("tree")?.as_bool() == Some(true) { self.init_styles(output.clone()); } @@ -1341,7 +1341,7 @@ impl Command for ShowCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -1352,10 +1352,10 @@ impl Command for ShowCommand { } impl BaseCommand for ShowCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); @@ -1366,7 +1366,7 @@ impl ShowCommand { #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn print_packages( - &mut self, + &self, packages: &[IndexMap], indent: &str, write_version: bool, @@ -1519,7 +1519,7 @@ impl ShowCommand { } } - pub(crate) fn get_root_requires(&mut self) -> Vec { + pub(crate) fn get_root_requires(&self) -> Vec { let composer_rc = self.try_composer(None, None); let composer_rc = match composer_rc { None => return vec![], @@ -1556,7 +1556,7 @@ impl ShowCommand { /// finds a package by name and version if provided pub(crate) fn get_package( - &mut self, + &self, installed_repo: &dyn RepositoryInterface, repos: &RepositoryInterfaceHandle, name: &str, @@ -1567,7 +1567,7 @@ impl ShowCommand { )> { let name = strtolower(name); let constraint: Option = match &version { - PhpMixed::String(s) => Some(self.version_parser.parse_constraints(s)?), + PhpMixed::String(s) => Some(self.version_parser.borrow().parse_constraints(s)?), PhpMixed::Null => None, _ => None, // already a ConstraintInterface }; @@ -1636,7 +1636,7 @@ impl ShowCommand { /// Prints package info. pub(crate) fn print_package_info( - &mut self, + &self, package: CompletePackageInterfaceHandle, versions: &IndexMap, installed_repo: &mut dyn RepositoryInterface, @@ -1666,7 +1666,7 @@ impl ShowCommand { /// Prints package metadata. pub(crate) fn print_meta( - &mut self, + &self, package: CompletePackageInterfaceHandle, versions: &IndexMap, installed_repo: &mut dyn RepositoryInterface, @@ -1829,7 +1829,7 @@ impl ShowCommand { /// Prints all available versions of this package and highlights the installed one if any. pub(crate) fn print_versions( - &mut self, + &self, package: CompletePackageInterfaceHandle, versions: &IndexMap, installed_repo: &mut dyn RepositoryInterface, @@ -1864,7 +1864,7 @@ impl ShowCommand { /// print link objects pub(crate) fn print_links( - &mut self, + &self, package: CompletePackageInterfaceHandle, link_type: &str, title: Option<&str>, @@ -1886,7 +1886,7 @@ impl ShowCommand { } /// Prints the licenses of a package with metadata - pub(crate) fn print_licenses(&mut self, package: CompletePackageInterfaceHandle) { + pub(crate) fn print_licenses(&self, package: CompletePackageInterfaceHandle) { let spdx_licenses = SpdxLicenses::new(); let licenses = package.get_license(); @@ -1926,7 +1926,7 @@ impl ShowCommand { /// Prints package info in JSON format. pub(crate) fn print_package_info_as_json( - &mut self, + &self, package: CompletePackageInterfaceHandle, versions: &IndexMap, installed_repo: &dyn RepositoryInterface, @@ -2261,11 +2261,8 @@ impl ShowCommand { } /// Init styles for tree - pub(crate) fn init_styles( - &mut self, - output: std::rc::Rc>, - ) { - self.colors = vec![ + pub(crate) fn init_styles(&self, output: std::rc::Rc>) { + *self.colors.borrow_mut() = vec![ "green".to_string(), "yellow".to_string(), "cyan".to_string(), @@ -2273,7 +2270,7 @@ impl ShowCommand { "blue".to_string(), ]; - for color in self.colors.iter() { + for color in self.colors.borrow().iter() { let style = OutputFormatterStyle::new(Some(color.as_str()), None, vec![]); output .borrow() @@ -2284,7 +2281,7 @@ impl ShowCommand { } /// Display the tree - pub(crate) fn display_package_tree(&mut self, array_tree: Vec>) { + pub(crate) fn display_package_tree(&self, array_tree: Vec>) { for package in array_tree.iter() { let name = package .get("name") @@ -2326,7 +2323,7 @@ impl ShowCommand { tree_bar = "└".to_string(); } let level: usize = 1; - let color = self.colors.get(level).cloned().unwrap_or_default(); + let color = self.colors.borrow().get(level).cloned().unwrap_or_default(); let info = format!( "{}──<{}>{} {}", tree_bar, @@ -2364,7 +2361,7 @@ impl ShowCommand { /// Generate the package tree pub(crate) fn generate_package_tree( - &mut self, + &self, package: PackageInterfaceHandle, installed_repo: &dyn RepositoryInterface, remote_repos: &RepositoryInterfaceHandle, @@ -2440,7 +2437,7 @@ impl ShowCommand { /// Display a package tree pub(crate) fn display_tree( - &mut self, + &self, package: &PhpMixed, packages_in_tree: &[PhpMixed], previous_tree_bar: &str, @@ -2464,8 +2461,13 @@ impl ShowCommand { if i == total { tree_bar = format!("{} └", previous_tree_bar); } - let color_ident = level % self.colors.len(); - let color = self.colors.get(color_ident).cloned().unwrap_or_default(); + let color_ident = level % self.colors.borrow().len(); + let color = self + .colors + .borrow() + .get(color_ident) + .cloned() + .unwrap_or_default(); let require = match require_mixed.as_array() { Some(a) => a, @@ -2508,7 +2510,7 @@ impl ShowCommand { /// Display a package tree pub(crate) fn add_tree( - &mut self, + &self, name: &str, link: &Link, installed_repo: &dyn RepositoryInterface, @@ -2606,7 +2608,7 @@ impl ShowCommand { Ok("update-possible".to_string()) } - fn write_tree_line(&mut self, line: &str) { + fn write_tree_line(&self, line: &str) { let io = self.get_io(); let mut line = line.to_string(); if !io.is_decorated() { @@ -2623,7 +2625,7 @@ impl ShowCommand { /// Given a package, this finds the latest package matching it #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn find_latest_package( - &mut self, + &self, package: PackageInterfaceHandle, composer: &PartialComposerHandle, platform_repo: &PlatformRepositoryHandle, @@ -2753,11 +2755,11 @@ impl ShowCommand { } fn get_repository_set( - &mut self, + &self, composer: &PartialComposerHandle, ) -> anyhow::Result>> { let composer = crate::command::composer_full(composer); - if self.repository_set.is_none() { + if self.repository_set.borrow().is_none() { let mut rs = RepositorySet::new( &composer.get_package().get_minimum_stability(), composer.get_package().get_stability_flags().clone(), @@ -2773,10 +2775,10 @@ impl ShowCommand { .get_repositories() .to_vec(), )))?; - self.repository_set = Some(std::rc::Rc::new(std::cell::RefCell::new(rs))); + *self.repository_set.borrow_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new(rs))); } - Ok(self.repository_set.as_ref().unwrap().clone()) + Ok(self.repository_set.borrow().as_ref().unwrap().clone()) } fn get_relative_time(&self, release_date: &chrono::DateTime) -> String { diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs index 06f19e0..db93e66 100644 --- a/crates/shirabe/src/command/status_command.rs +++ b/crates/shirabe/src/command/status_command.rs @@ -44,7 +44,7 @@ impl StatusCommand { const EXIT_CODE_VERSION_CHANGES: i64 = 4; pub fn new() -> Self { - let mut command = StatusCommand { + let command = StatusCommand { base_command_data: BaseCommandData::new(None), }; command @@ -54,7 +54,7 @@ impl StatusCommand { } fn do_execute( - &mut self, + &self, input: std::rc::Rc>, ) -> Result { let composer = self.require_composer(None, None)?; @@ -323,7 +323,7 @@ impl StatusCommand { } impl Command for StatusCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("status")?; self.set_description("Shows a list of locally modified packages"); self.set_definition(&[InputOption::new( @@ -342,7 +342,7 @@ impl Command for StatusCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -388,7 +388,7 @@ impl Command for StatusCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -399,10 +399,10 @@ impl Command for StatusCommand { } impl BaseCommand for StatusCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs index eb4e05d..4bd0758 100644 --- a/crates/shirabe/src/command/suggests_command.rs +++ b/crates/shirabe/src/command/suggests_command.rs @@ -37,7 +37,7 @@ impl Default for SuggestsCommand { impl SuggestsCommand { pub fn new() -> Self { - let mut command = SuggestsCommand { + let command = SuggestsCommand { base_command_data: BaseCommandData::new(None), }; command @@ -48,7 +48,7 @@ impl SuggestsCommand { } impl Command for SuggestsCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_installed_package() for `packages` argument self.set_name("suggests")?; self.set_description("Shows package suggestions"); @@ -114,7 +114,7 @@ impl Command for SuggestsCommand { } fn execute( - &mut self, + &self, input: Rc>, _output: Rc>, ) -> Result { @@ -220,7 +220,7 @@ impl Command for SuggestsCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -231,10 +231,10 @@ impl Command for SuggestsCommand { } impl BaseCommand for SuggestsCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index 4d8c90a..9073658 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -57,7 +57,7 @@ impl Default for UpdateCommand { impl UpdateCommand { pub fn new() -> Self { - let mut command = UpdateCommand { + let command = UpdateCommand { base_command_data: BaseCommandData::new(None), }; command @@ -68,7 +68,7 @@ impl UpdateCommand { } impl Command for UpdateCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { // TODO(cli-completion): suggest_installed_package(false, true) / suggest_prefer_install self.set_name("update")?; self.set_aliases(vec!["u".to_string(), "upgrade".to_string()])?; @@ -98,7 +98,7 @@ impl Command for UpdateCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -546,7 +546,7 @@ impl Command for UpdateCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -557,10 +557,10 @@ impl Command for UpdateCommand { } impl BaseCommand for UpdateCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs index a32a10c..b378393 100644 --- a/crates/shirabe/src/command/validate_command.rs +++ b/crates/shirabe/src/command/validate_command.rs @@ -40,7 +40,7 @@ impl Default for ValidateCommand { impl ValidateCommand { pub fn new() -> Self { - let mut command = ValidateCommand { + let command = ValidateCommand { base_command_data: BaseCommandData::new(None), }; command @@ -51,7 +51,7 @@ impl ValidateCommand { } impl Command for ValidateCommand { - fn configure(&mut self) -> anyhow::Result<()> { + fn configure(&self) -> anyhow::Result<()> { self.set_name("validate")?; self.set_description("Validates a composer.json and composer.lock"); self.set_definition(&[ @@ -139,7 +139,7 @@ impl Command for ValidateCommand { } fn execute( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result { @@ -310,7 +310,7 @@ impl Command for ValidateCommand { } fn initialize( - &mut self, + &self, input: Rc>, output: Rc>, ) -> anyhow::Result<()> { @@ -321,10 +321,10 @@ impl Command for ValidateCommand { } impl BaseCommand for ValidateCommand { - fn command_data_mut( - &mut self, - ) -> &mut shirabe_external_packages::symfony::console::command::command::CommandData { - self.base_command_data.command_data_mut() + fn command_data( + &self, + ) -> &shirabe_external_packages::symfony::console::command::command::CommandData { + self.base_command_data.command_data() } crate::delegate_base_command_trait_impls_to_inner!(base_command_data); diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs index 1a661df..7f22a65 100644 --- a/crates/shirabe/src/console/application.rs +++ b/crates/shirabe/src/console/application.rs @@ -1263,7 +1263,7 @@ impl Application { // PHP: sprintf('%s', OutputFormatter::escape(sprintf($synopsis, $this->getName()))) // A command synopsis carries no printf conversion specifier, so the inner sprintf is an // identity over the synopsis and the application-name argument is never substituted. - let synopsis = running_command.borrow_mut().get_synopsis(false); + let synopsis = running_command.borrow().get_synopsis(false); output.borrow().writeln( &[format!( "{}", @@ -1868,12 +1868,12 @@ impl ApplicationHandle { command: std::rc::Rc>, ) -> anyhow::Result>>> { let application = &self.0; - command.borrow_mut().set_application(Some( + command.borrow().set_application(Some( application.clone() as std::rc::Rc> )); if !command.borrow().is_enabled() { - command.borrow_mut().set_application(None); + command.borrow().set_application(None); return Ok(None); } @@ -2903,7 +2903,7 @@ impl ApplicationHandle { } command - .borrow_mut() + .borrow() .run(input.clone(), output.clone()) .map(|c| c as i32) } -- cgit v1.3.1