aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/application.rs10
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/helper/progress_bar.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/helper/question_helper.rs4
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/helper/table.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/input/input_interface.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/output/console_output.rs4
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/output/console_output_interface.rs4
-rw-r--r--crates/shirabe-external-packages/src/symfony/component/console/output/output_interface.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/table.rs2
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs5
-rw-r--r--crates/shirabe/src/command/about_command.rs6
-rw-r--r--crates/shirabe/src/command/archive_command.rs18
-rw-r--r--crates/shirabe/src/command/audit_command.rs28
-rw-r--r--crates/shirabe/src/command/base_command.rs204
-rw-r--r--crates/shirabe/src/command/base_config_command.rs54
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs31
-rw-r--r--crates/shirabe/src/command/bump_command.rs23
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs19
-rw-r--r--crates/shirabe/src/command/clear_cache_command.rs4
-rw-r--r--crates/shirabe/src/command/config_command.rs93
-rw-r--r--crates/shirabe/src/command/create_project_command.rs92
-rw-r--r--crates/shirabe/src/command/depends_command.rs4
-rw-r--r--crates/shirabe/src/command/diagnose_command.rs4
-rw-r--r--crates/shirabe/src/command/dump_autoload_command.rs63
-rw-r--r--crates/shirabe/src/command/exec_command.rs20
-rw-r--r--crates/shirabe/src/command/fund_command.rs5
-rw-r--r--crates/shirabe/src/command/global_command.rs17
-rw-r--r--crates/shirabe/src/command/home_command.rs13
-rw-r--r--crates/shirabe/src/command/init_command.rs88
-rw-r--r--crates/shirabe/src/command/install_command.rs98
-rw-r--r--crates/shirabe/src/command/licenses_command.rs32
-rw-r--r--crates/shirabe/src/command/outdated_command.rs93
-rw-r--r--crates/shirabe/src/command/package_discovery_trait.rs34
-rw-r--r--crates/shirabe/src/command/prohibits_command.rs4
-rw-r--r--crates/shirabe/src/command/reinstall_command.rs36
-rw-r--r--crates/shirabe/src/command/remove_command.rs80
-rw-r--r--crates/shirabe/src/command/repository_command.rs27
-rw-r--r--crates/shirabe/src/command/require_command.rs185
-rw-r--r--crates/shirabe/src/command/run_script_command.rs34
-rw-r--r--crates/shirabe/src/command/script_alias_command.rs14
-rw-r--r--crates/shirabe/src/command/search_command.rs39
-rw-r--r--crates/shirabe/src/command/self_update_command.rs61
-rw-r--r--crates/shirabe/src/command/show_command.rs219
-rw-r--r--crates/shirabe/src/command/status_command.rs39
-rw-r--r--crates/shirabe/src/command/suggests_command.rs35
-rw-r--r--crates/shirabe/src/command/update_command.rs140
-rw-r--r--crates/shirabe/src/command/validate_command.rs36
-rw-r--r--crates/shirabe/src/console/application.rs86
-rw-r--r--crates/shirabe/src/event_dispatcher/event_dispatcher.rs5
-rw-r--r--crates/shirabe/src/io/buffer_io.rs3
-rw-r--r--crates/shirabe/src/io/console_io.rs28
-rw-r--r--crates/shirabe/src/plugin/command_event.rs24
-rw-r--r--crates/shirabe/src/plugin/pre_command_run_event.rs18
53 files changed, 1562 insertions, 631 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/application.rs b/crates/shirabe-external-packages/src/symfony/component/console/application.rs
index 65abce4..becf1a5 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/application.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/application.rs
@@ -12,8 +12,8 @@ impl Application {
pub fn run(
&mut self,
- _input: Option<&mut dyn InputInterface>,
- _output: Option<&mut dyn OutputInterface>,
+ _input: Option<std::rc::Rc<std::cell::RefCell<dyn InputInterface>>>,
+ _output: Option<std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>>,
) -> anyhow::Result<i64> {
todo!()
}
@@ -90,7 +90,11 @@ impl Application {
todo!()
}
- pub fn render_throwable(&self, _exception: &anyhow::Error, _output: &mut dyn OutputInterface) {
+ pub fn render_throwable(
+ &self,
+ _exception: &anyhow::Error,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
todo!()
}
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/helper/progress_bar.rs b/crates/shirabe-external-packages/src/symfony/component/console/helper/progress_bar.rs
index 1b896f9..77bc4fd 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/helper/progress_bar.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/helper/progress_bar.rs
@@ -4,7 +4,7 @@ use crate::symfony::component::console::output::OutputInterface;
pub struct ProgressBar;
impl ProgressBar {
- pub fn new(_output: &dyn OutputInterface, _max: i64) -> Self {
+ pub fn new(_output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>, _max: i64) -> Self {
todo!()
}
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/helper/question_helper.rs b/crates/shirabe-external-packages/src/symfony/component/console/helper/question_helper.rs
index 5c723c2..5d452c7 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/helper/question_helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/helper/question_helper.rs
@@ -9,8 +9,8 @@ pub struct QuestionHelper;
impl QuestionHelper {
pub fn ask(
&self,
- _input: &mut dyn InputInterface,
- _output: &mut dyn OutputInterface,
+ _input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
_question: &Question,
) -> Option<PhpMixed> {
todo!()
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/helper/table.rs b/crates/shirabe-external-packages/src/symfony/component/console/helper/table.rs
index ca8b292..f580965 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/helper/table.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/helper/table.rs
@@ -5,7 +5,7 @@ use shirabe_php_shim::PhpMixed;
pub struct Table;
impl Table {
- pub fn new(_output: &dyn OutputInterface) -> Self {
+ pub fn new(_output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>) -> Self {
todo!()
}
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/input/input_interface.rs b/crates/shirabe-external-packages/src/symfony/component/console/input/input_interface.rs
index f38d524..a556198 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/input/input_interface.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/input/input_interface.rs
@@ -1,6 +1,6 @@
use shirabe_php_shim::PhpMixed;
-pub trait InputInterface {
+pub trait InputInterface: std::fmt::Debug {
fn get_first_argument(&self) -> Option<String>;
fn has_parameter_option(&self, values: &[&str], only_params: bool) -> bool;
fn get_parameter_option(
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/output/console_output.rs b/crates/shirabe-external-packages/src/symfony/component/console/output/console_output.rs
index 332cbd1..00b9324 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/output/console_output.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/output/console_output.rs
@@ -16,11 +16,11 @@ impl ConsoleOutput {
}
impl ConsoleOutputInterface for ConsoleOutput {
- fn get_error_output(&self) -> &dyn OutputInterface {
+ fn get_error_output(&self) -> std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> {
todo!()
}
- fn set_error_output(&mut self, _error: Box<dyn OutputInterface>) {
+ fn set_error_output(&mut self, _error: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>) {
todo!()
}
}
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/output/console_output_interface.rs b/crates/shirabe-external-packages/src/symfony/component/console/output/console_output_interface.rs
index 8e68396..83ec1de 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/output/console_output_interface.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/output/console_output_interface.rs
@@ -1,6 +1,6 @@
use crate::symfony::component::console::output::OutputInterface;
pub trait ConsoleOutputInterface: OutputInterface {
- fn get_error_output(&self) -> &dyn OutputInterface;
- fn set_error_output(&mut self, error: Box<dyn OutputInterface>);
+ fn get_error_output(&self) -> std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>;
+ fn set_error_output(&mut self, error: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>);
}
diff --git a/crates/shirabe-external-packages/src/symfony/component/console/output/output_interface.rs b/crates/shirabe-external-packages/src/symfony/component/console/output/output_interface.rs
index 11fb82e..9e58a3e 100644
--- a/crates/shirabe-external-packages/src/symfony/component/console/output/output_interface.rs
+++ b/crates/shirabe-external-packages/src/symfony/component/console/output/output_interface.rs
@@ -1,7 +1,7 @@
use crate::symfony::component::console::formatter::OutputFormatter;
use crate::symfony::component::console::output::ConsoleOutputInterface;
-pub trait OutputInterface {
+pub trait OutputInterface: std::fmt::Debug {
// PHP class semantics: OutputInterface methods take &self with interior mutability,
// because output objects are shared by reference across the PHP code.
fn write(&self, messages: &str, newline: bool, r#type: i64);
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/table.rs b/crates/shirabe-external-packages/src/symfony/console/helper/table.rs
index df4978c..30c008c 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/table.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/table.rs
@@ -5,7 +5,7 @@ use shirabe_php_shim::PhpMixed;
pub struct Table;
impl Table {
- pub fn new(_output: &dyn OutputInterface) -> Self {
+ pub fn new(_output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>) -> Self {
todo!()
}
diff --git a/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs b/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs
index 92e9e67..b5dfded 100644
--- a/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/style/symfony_style.rs
@@ -6,7 +6,10 @@ use shirabe_php_shim::PhpMixed;
pub struct SymfonyStyle;
impl SymfonyStyle {
- pub fn new(_input: &dyn InputInterface, _output: &dyn OutputInterface) -> Self {
+ pub fn new(
+ _input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) -> Self {
todo!()
}
diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs
index 3e74d6e..e26e41e 100644
--- a/crates/shirabe/src/command/about_command.rs
+++ b/crates/shirabe/src/command/about_command.rs
@@ -22,7 +22,11 @@ impl AboutCommand {
.set_help("<info>php composer.phar about</info>");
}
- pub fn execute(&mut self, input: &dyn InputInterface, output: &dyn OutputInterface) -> i64 {
+ pub fn execute(
+ &mut self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) -> i64 {
let composer_version = composer::get_version();
let _ = (input, output);
diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs
index 5e60ce1..bf3a0c1 100644
--- a/crates/shirabe/src/command/archive_command.rs
+++ b/crates/shirabe/src/command/archive_command.rs
@@ -61,15 +61,16 @@ impl ArchiveCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.try_composer(None, None);
let config = if let Some(ref composer) = composer {
let config = composer.borrow_partial().get_config();
// TODO(plugin): dispatch CommandEvent
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "archive", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "archive", input.clone(), output);
let event_dispatcher = composer.borrow_partial().get_event_dispatcher();
event_dispatcher
.borrow_mut()
@@ -86,6 +87,7 @@ impl ArchiveCommand {
};
let format = input
+ .borrow()
.get_option("format")
.as_string()
.map(|s| s.to_string())
@@ -99,6 +101,7 @@ impl ArchiveCommand {
});
let dir = input
+ .borrow()
.get_option("dir")
.as_string()
.map(|s| s.to_string())
@@ -117,17 +120,24 @@ impl ArchiveCommand {
io_box.clone(),
&config,
input
+ .borrow()
.get_argument("package")
.as_string()
.map(|s| s.to_string()),
input
+ .borrow()
.get_argument("version")
.as_string()
.map(|s| s.to_string()),
&format,
&dir,
- input.get_option("file").as_string().map(|s| s.to_string()),
input
+ .borrow()
+ .get_option("file")
+ .as_string()
+ .map(|s| s.to_string()),
+ input
+ .borrow()
.get_option("ignore-filters")
.as_bool()
.unwrap_or(false),
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index a28c344..f739029 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -48,11 +48,11 @@ impl AuditCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
- let packages = self.get_packages(&composer, input)?;
+ let packages = self.get_packages(&composer, input.clone())?;
if packages.is_empty() {
self.get_io().write_error("No packages - skipping audit.");
@@ -84,6 +84,7 @@ impl AuditCommand {
)?;
let abandoned = input
+ .borrow()
.get_option("abandoned")
.as_string()
.map(|s| s.to_string());
@@ -113,10 +114,11 @@ impl AuditCommand {
let abandoned = abandoned.unwrap_or_else(|| audit_config.audit_abandoned.clone());
let ignore_severities = array_merge(
- array_fill_keys(input.get_option("ignore-severity"), PhpMixed::Null),
+ array_fill_keys(input.borrow().get_option("ignore-severity"), PhpMixed::Null),
PhpMixed::from(audit_config.ignore_severity_for_audit.clone()),
);
let ignore_unreachable = input
+ .borrow()
.get_option("ignore-unreachable")
.as_bool()
.unwrap_or(false)
@@ -144,10 +146,15 @@ impl AuditCommand {
fn get_packages(
&self,
composer: &PartialComposerHandle,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<Vec<crate::package::PackageInterfaceHandle>> {
let mut composer = crate::command::composer_full_mut(composer);
- if input.get_option("locked").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("locked")
+ .as_bool()
+ .unwrap_or(false)
+ {
let locker = composer.get_locker().clone();
let mut locker = locker.borrow_mut();
if !locker.is_locked() {
@@ -156,8 +163,13 @@ impl AuditCommand {
code: 0,
}.into());
}
- let locked_repo = locker
- .get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?;
+ let locked_repo = locker.get_locked_repository(
+ !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false),
+ )?;
return locked_repo.borrow_mut().get_canonical_packages();
}
diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs
index 501915b..b6664e7 100644
--- a/crates/shirabe/src/command/base_command.rs
+++ b/crates/shirabe/src/command/base_command.rs
@@ -140,8 +140,8 @@ pub trait BaseCommand {
fn run(
&mut self,
- _input: &mut dyn InputInterface,
- _output: &mut dyn OutputInterface,
+ _input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
todo!()
}
@@ -196,14 +196,14 @@ pub trait BaseCommand {
/// @inheritDoc
fn initialize(
&mut self,
- input: &mut dyn InputInterface,
- output: &mut dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<()>;
/// Calls {@see Factory::create()} with the given arguments, taking into account flags and default states for disabling scripts and plugins
fn create_composer_instance(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
@@ -214,13 +214,13 @@ pub trait BaseCommand {
fn get_preferred_install_options(
&self,
config: &Config,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
keep_vcs_requires_prefer_source: bool,
) -> Result<(bool, bool)>;
fn get_platform_requirement_filter(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<std::rc::Rc<dyn PlatformRequirementFilterInterface>>;
/// @param array<string> $requirements
@@ -237,20 +237,28 @@ pub trait BaseCommand {
) -> Result<Vec<IndexMap<String, String>>>;
/// @param array<TableSeparator|mixed[]> $table
- fn render_table(&self, table: Vec<PhpMixed>, output: &dyn OutputInterface);
+ fn render_table(
+ &self,
+ table: Vec<PhpMixed>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ );
fn get_terminal_width(&self) -> i64;
/// @internal
/// @param 'format'|'audit-format' $optName
/// @return Auditor::FORMAT_*
- fn get_audit_format(&self, input: &dyn InputInterface, opt_name: &str) -> Result<String>;
+ fn get_audit_format(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ opt_name: &str,
+ ) -> Result<String>;
/// Creates an AuditConfig from the Config object, optionally overriding security blocking based on input options
fn create_audit_config(
&self,
config: &mut Config,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<AuditConfig>;
}
@@ -355,12 +363,16 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn initialize(
&mut self,
- input: &mut dyn InputInterface,
- output: &mut dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<()> {
// initialize a plugin-enabled Composer instance, either local or global
- let mut disable_plugins = input.has_parameter_option(&["--no-plugins"], false);
- let mut disable_scripts = input.has_parameter_option(&["--no-scripts"], false);
+ let mut disable_plugins = input
+ .borrow()
+ .has_parameter_option(&["--no-plugins"], false);
+ let mut disable_scripts = input
+ .borrow()
+ .has_parameter_option(&["--no-scripts"], false);
// TODO(phase-b): requires inner Symfony Application access for disable_plugins_by_default / disable_scripts_by_default
// TODO(phase-b): `$this instanceof SelfUpdateCommand` not representable
@@ -392,8 +404,12 @@ impl<C: HasBaseCommandData> BaseCommand for C {
let _ = pre_command_run_event.get_name();
}
- if input.has_parameter_option(&["--no-ansi"], false) && input.has_option("no-progress") {
- input.set_option("no-progress", PhpMixed::Bool(true));
+ if input.borrow().has_parameter_option(&["--no-ansi"], false)
+ && input.borrow().has_option("no-progress")
+ {
+ input
+ .borrow_mut()
+ .set_option("no-progress", PhpMixed::Bool(true));
}
let env_options: IndexMap<&str, Vec<&str>> = [
@@ -416,44 +432,55 @@ impl<C: HasBaseCommandData> BaseCommand for C {
.collect();
for (env_name, option_names) in &env_options {
for option_name in option_names {
- if true == input.has_option(option_name) {
- if false == input.get_option(option_name).as_bool().unwrap_or(false)
+ if true == input.borrow().has_option(option_name) {
+ if false
+ == input
+ .borrow()
+ .get_option(option_name)
+ .as_bool()
+ .unwrap_or(false)
&& Platform::get_env(env_name).map_or(false, |s| !s.is_empty() && s != "0")
{
- input.set_option(option_name, PhpMixed::Bool(true));
+ input
+ .borrow_mut()
+ .set_option(option_name, PhpMixed::Bool(true));
}
}
}
}
- if true == input.has_option("ignore-platform-reqs") {
+ if true == input.borrow().has_option("ignore-platform-reqs") {
if !input
+ .borrow()
.get_option("ignore-platform-reqs")
.as_bool()
.unwrap_or(false)
&& Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQS")
.map_or(false, |s| !s.is_empty() && s != "0")
{
- input.set_option("ignore-platform-reqs", PhpMixed::Bool(true));
+ input
+ .borrow_mut()
+ .set_option("ignore-platform-reqs", PhpMixed::Bool(true));
io.write_error("<warning>COMPOSER_IGNORE_PLATFORM_REQS is set. You may experience unexpected errors.</warning>");
}
}
- if true == input.has_option("ignore-platform-req")
- && (!input.has_option("ignore-platform-reqs")
+ if true == input.borrow().has_option("ignore-platform-req")
+ && (!input.borrow().has_option("ignore-platform-reqs")
|| !input
+ .borrow()
.get_option("ignore-platform-reqs")
.as_bool()
.unwrap_or(false))
{
let ignore_platform_req_env = Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQ");
let ignore_str = ignore_platform_req_env.clone().unwrap_or_default();
- if 0 == count(&input.get_option("ignore-platform-req"))
+ if 0 == count(&input.borrow().get_option("ignore-platform-req"))
&& ignore_platform_req_env.is_some()
&& "" != ignore_str
{
- input.set_option(
+ input.borrow_mut().set_option(
"ignore-platform-req",
PhpMixed::List(
explode(",", &ignore_str)
@@ -476,16 +503,20 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn create_composer_instance(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
) -> Result<PartialComposerHandle> {
- let disable_plugins =
- disable_plugins || input.has_parameter_option(&["--no-plugins"], false);
+ let disable_plugins = disable_plugins
+ || input
+ .borrow()
+ .has_parameter_option(&["--no-plugins"], false);
let disable_scripts = disable_scripts.unwrap_or(false)
- || input.has_parameter_option(&["--no-scripts"], false);
+ || input
+ .borrow()
+ .has_parameter_option(&["--no-scripts"], false);
// TODO(phase-b): requires inner Symfony Application access for disable_plugins_by_default / disable_scripts_by_default
let disable_plugins_kind = if disable_plugins {
@@ -501,7 +532,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn get_preferred_install_options(
&self,
config: &Config,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
keep_vcs_requires_prefer_source: bool,
) -> Result<(bool, bool)> {
let mut prefer_source = false;
@@ -519,12 +550,20 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
}
- if !input.has_option("prefer-dist") || !input.has_option("prefer-source") {
+ if !input.borrow().has_option("prefer-dist") || !input.borrow().has_option("prefer-source")
+ {
return Ok((prefer_source, prefer_dist));
}
- if input.has_option("prefer-install") && is_string(&input.get_option("prefer-install")) {
- if input.get_option("prefer-source").as_bool().unwrap_or(false) {
+ if input.borrow().has_option("prefer-install")
+ && is_string(&input.borrow().get_option("prefer-install"))
+ {
+ if input
+ .borrow()
+ .get_option("prefer-source")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Err(InvalidArgumentException {
message: "--prefer-source can not be used together with --prefer-install"
.to_string(),
@@ -532,7 +571,12 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
.into());
}
- if input.get_option("prefer-dist").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("prefer-dist")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Err(InvalidArgumentException {
message: "--prefer-dist can not be used together with --prefer-install"
.to_string(),
@@ -540,7 +584,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
.into());
}
- let prefer_install = input.get_option("prefer-install");
+ let prefer_install = input.borrow().get_option("prefer-install");
match prefer_install.as_string().unwrap_or("") {
"dist" => {
// TODO(phase-b): InputInterface set_option needs &mut self
@@ -566,17 +610,41 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
}
- if input.get_option("prefer-source").as_bool().unwrap_or(false)
- || input.get_option("prefer-dist").as_bool().unwrap_or(false)
+ if input
+ .borrow()
+ .get_option("prefer-source")
+ .as_bool()
+ .unwrap_or(false)
+ || input
+ .borrow()
+ .get_option("prefer-dist")
+ .as_bool()
+ .unwrap_or(false)
|| (keep_vcs_requires_prefer_source
- && input.has_option("keep-vcs")
- && input.get_option("keep-vcs").as_bool().unwrap_or(false))
+ && input.borrow().has_option("keep-vcs")
+ && input
+ .borrow()
+ .get_option("keep-vcs")
+ .as_bool()
+ .unwrap_or(false))
{
- prefer_source = input.get_option("prefer-source").as_bool().unwrap_or(false)
+ prefer_source = input
+ .borrow()
+ .get_option("prefer-source")
+ .as_bool()
+ .unwrap_or(false)
|| (keep_vcs_requires_prefer_source
- && input.has_option("keep-vcs")
- && input.get_option("keep-vcs").as_bool().unwrap_or(false));
- prefer_dist = input.get_option("prefer-dist").as_bool().unwrap_or(false);
+ && input.borrow().has_option("keep-vcs")
+ && input
+ .borrow()
+ .get_option("keep-vcs")
+ .as_bool()
+ .unwrap_or(false));
+ prefer_dist = input
+ .borrow()
+ .get_option("prefer-dist")
+ .as_bool()
+ .unwrap_or(false);
}
Ok((prefer_source, prefer_dist))
@@ -584,9 +652,11 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn get_platform_requirement_filter(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<std::rc::Rc<dyn PlatformRequirementFilterInterface>> {
- if !input.has_option("ignore-platform-reqs") || !input.has_option("ignore-platform-req") {
+ if !input.borrow().has_option("ignore-platform-reqs")
+ || !input.borrow().has_option("ignore-platform-req")
+ {
return Err(LogicException {
message:
"Calling getPlatformRequirementFilter from a command which does not define the --ignore-platform-req[s] flags is not permitted."
@@ -598,6 +668,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if true
== input
+ .borrow()
.get_option("ignore-platform-reqs")
.as_bool()
.unwrap_or(false)
@@ -605,7 +676,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
return Ok(PlatformRequirementFilterFactory::ignore_all());
}
- let ignores = input.get_option("ignore-platform-req");
+ let ignores = input.borrow().get_option("ignore-platform-req");
if count(&ignores) > 0 {
return Ok(PlatformRequirementFilterFactory::from_bool_or_list(
ignores,
@@ -648,7 +719,11 @@ impl<C: HasBaseCommandData> BaseCommand for C {
parser.parse_name_version_pairs(requirements)
}
- fn render_table(&self, table: Vec<PhpMixed>, output: &dyn OutputInterface) {
+ fn render_table(
+ &self,
+ table: Vec<PhpMixed>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
let mut renderer = Table::new(output);
renderer.set_style("compact");
renderer.set_rows(table).render();
@@ -668,8 +743,12 @@ impl<C: HasBaseCommandData> BaseCommand for C {
width
}
- fn get_audit_format(&self, input: &dyn InputInterface, opt_name: &str) -> Result<String> {
- if !input.has_option(opt_name) {
+ fn get_audit_format(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ opt_name: &str,
+ ) -> Result<String> {
+ if !input.borrow().has_option(opt_name) {
return Err(LogicException {
message: format!(
"This should not be called on a Command which has no {} option defined.",
@@ -680,7 +759,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
.into());
}
- let val = input.get_option(opt_name);
+ let val = input.borrow().get_option(opt_name);
let formats: Vec<Box<PhpMixed>> = Auditor::FORMATS
.iter()
.map(|s| Box::new(PhpMixed::String(s.to_string())))
@@ -703,17 +782,25 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn create_audit_config(
&self,
config: &mut Config,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<AuditConfig> {
// Handle both --audit and --no-audit flags
- let audit = if input.has_option("audit") {
- input.get_option("audit").as_bool().unwrap_or(false)
+ let audit = if input.borrow().has_option("audit") {
+ input
+ .borrow()
+ .get_option("audit")
+ .as_bool()
+ .unwrap_or(false)
} else {
- !(input.has_option("no-audit")
- && input.get_option("no-audit").as_bool().unwrap_or(false))
+ !(input.borrow().has_option("no-audit")
+ && input
+ .borrow()
+ .get_option("no-audit")
+ .as_bool()
+ .unwrap_or(false))
};
- let audit_format = if input.has_option("audit-format") {
- self.get_audit_format(input, "audit-format")?
+ let audit_format = if input.borrow().has_option("audit-format") {
+ self.get_audit_format(input.clone(), "audit-format")?
} else {
Auditor::FORMAT_SUMMARY.to_string()
};
@@ -722,8 +809,9 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if Platform::get_env("COMPOSER_NO_SECURITY_BLOCKING")
.map_or(false, |s| !s.is_empty() && s != "0")
- || (input.has_option("no-security-blocking")
+ || (input.borrow().has_option("no-security-blocking")
&& input
+ .borrow()
.get_option("no-security-blocking")
.as_bool()
.unwrap_or(false))
diff --git a/crates/shirabe/src/command/base_config_command.rs b/crates/shirabe/src/command/base_config_command.rs
index 1b7294e..3aed839 100644
--- a/crates/shirabe/src/command/base_config_command.rs
+++ b/crates/shirabe/src/command/base_config_command.rs
@@ -24,14 +24,18 @@ pub trait BaseConfigCommand: BaseCommand {
fn initialize(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<()> {
// TODO(phase-b): BaseCommand::initialize chained via Self::initialize would recurse;
// omitted until trait disambiguation is sorted.
- if input.get_option("global").as_bool().unwrap_or(false)
- && !input.get_option("file").is_null()
+ if input
+ .borrow()
+ .get_option("global")
+ .as_bool()
+ .unwrap_or(false)
+ && !input.borrow().get_option("file").is_null()
{
return Err(anyhow::anyhow!("--file and --global can not be combined"));
}
@@ -44,12 +48,17 @@ pub trait BaseConfigCommand: BaseCommand {
let config_rc = self.config().unwrap().clone();
// When using --global flag, set baseDir to home directory for correct absolute path resolution
- if input.get_option("global").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("global")
+ .as_bool()
+ .unwrap_or(false)
+ {
let home = config_rc.borrow_mut().get("home").to_string();
config_rc.borrow_mut().set_base_dir(Some(home));
}
- let config_file = self.get_composer_config_file(input, &*config_rc.borrow());
+ let config_file = self.get_composer_config_file(input.clone(), &*config_rc.borrow());
// Create global composer.json if invoked using `composer global [config-cmd]`
if (config_file == "composer.json" || config_file == "./composer.json")
@@ -69,7 +78,11 @@ pub trait BaseConfigCommand: BaseCommand {
self.set_config_source(None);
// Initialize the global file if it's not there, ignoring any warnings or notices
- if input.get_option("global").as_bool().unwrap_or(false)
+ if input
+ .borrow()
+ .get_option("global")
+ .as_bool()
+ .unwrap_or(false)
&& !self.config_file().as_ref().unwrap().exists()
{
let path = self.config_file().as_ref().unwrap().get_path().to_string();
@@ -102,11 +115,21 @@ pub trait BaseConfigCommand: BaseCommand {
}
/// Get the local composer.json, global config.json, or the file passed by the user
- fn get_composer_config_file(&self, input: &dyn InputInterface, config: &Config) -> String {
- if input.get_option("global").as_bool().unwrap_or(false) {
+ fn get_composer_config_file(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ config: &Config,
+ ) -> String {
+ if input
+ .borrow()
+ .get_option("global")
+ .as_bool()
+ .unwrap_or(false)
+ {
format!("{}/config.json", config.get("home"))
} else {
input
+ .borrow()
.get_option("file")
.as_string()
.map(|s| s.to_string())
@@ -116,8 +139,17 @@ pub trait BaseConfigCommand: BaseCommand {
/// Get the local auth.json or global auth.json, or if the user passed in a file to use,
/// the corresponding auth.json
- fn get_auth_config_file(&self, input: &dyn InputInterface, config: &Config) -> String {
- if input.get_option("global").as_bool().unwrap_or(false) {
+ fn get_auth_config_file(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ config: &Config,
+ ) -> String {
+ if input
+ .borrow()
+ .get_option("global")
+ .as_bool()
+ .unwrap_or(false)
+ {
format!("{}/auth.json", config.get("home"))
} else {
let composer_config = self.get_composer_config_file(input, config);
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index 4f929c8..4a5b854 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -45,8 +45,8 @@ pub trait BaseDependencyCommand: BaseCommand {
fn do_execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
inverted: bool,
) -> anyhow::Result<i64> {
let composer = self.require_composer(None, None)?;
@@ -60,7 +60,12 @@ pub trait BaseDependencyCommand: BaseCommand {
)),
)];
- if input.get_option("locked").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("locked")
+ .as_bool()
+ .unwrap_or(false)
+ {
let locker = composer.get_locker().clone();
let mut locker = locker.borrow_mut();
@@ -91,7 +96,7 @@ pub trait BaseDependencyCommand: BaseCommand {
if local_repo.get_packages()?.len() == 0
&& (root_pkg.get_requires().len() > 0 || root_pkg.get_dev_requires().len() > 0)
{
- output.writeln(
+ output.borrow().writeln(
"<warning>No dependencies installed. Try running composer install or update, or use --locked.</warning>",
shirabe_external_packages::symfony::console::output::OUTPUT_NORMAL,
);
@@ -118,12 +123,14 @@ pub trait BaseDependencyCommand: BaseCommand {
let mut installed_repo = InstalledRepository::new(repos);
let needle = input
+ .borrow()
.get_argument(Self::ARGUMENT_PACKAGE)
.as_string()
.unwrap_or_default()
.to_string();
- let text_constraint: String = if input.has_argument(Self::ARGUMENT_CONSTRAINT) {
+ let text_constraint: String = if input.borrow().has_argument(Self::ARGUMENT_CONSTRAINT) {
input
+ .borrow()
.get_argument(Self::ARGUMENT_CONSTRAINT)
.as_string()
.unwrap_or("*")
@@ -242,11 +249,13 @@ pub trait BaseDependencyCommand: BaseCommand {
};
let render_tree = input
+ .borrow()
.get_option(Self::OPTION_TREE)
.as_bool()
.unwrap_or(false);
let recursive = render_tree
|| input
+ .borrow()
.get_option(Self::OPTION_RECURSIVE)
.as_bool()
.unwrap_or(false);
@@ -294,7 +303,7 @@ pub trait BaseDependencyCommand: BaseCommand {
}
if inverted
- && input.has_argument(Self::ARGUMENT_CONSTRAINT)
+ && input.borrow().has_argument(Self::ARGUMENT_CONSTRAINT)
&& !PlatformRepository::is_platform_package(&needle)
{
let mut composer_command = "update";
@@ -322,7 +331,11 @@ pub trait BaseDependencyCommand: BaseCommand {
Ok(r#return)
}
- fn print_table(&self, output: &dyn OutputInterface, results: Vec<DependentsEntry>) {
+ fn print_table(
+ &self,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ results: Vec<DependentsEntry>,
+ ) {
let mut table: Vec<Vec<String>> = vec![];
let mut doubles: IndexMap<String, bool> = IndexMap::new();
let mut results = results;
@@ -383,7 +396,7 @@ pub trait BaseDependencyCommand: BaseCommand {
self.render_table(table_as_mixed, output);
}
- fn init_styles(&mut self, output: &dyn OutputInterface) {
+ fn init_styles(&mut self, output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>) {
*self.colors_mut() = vec![
"green".to_string(),
"yellow".to_string(),
@@ -395,7 +408,7 @@ pub trait BaseDependencyCommand: BaseCommand {
// TODO(phase-b): output.get_formatter() returns &OutputFormatter; set_style needs
// &mut. Need interior mutability or `get_formatter_mut`.
let _ = OutputFormatterStyle::new(Some(color), None, None);
- let _ = output.get_formatter();
+ let _ = output.borrow().get_formatter();
}
}
diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs
index d477747..ac207bc 100644
--- a/crates/shirabe/src/command/bump_command.rs
+++ b/crates/shirabe/src/command/bump_command.rs
@@ -57,10 +57,11 @@ impl BumpCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let packages_filter: Vec<String> = input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -70,9 +71,21 @@ impl BumpCommand {
})
.unwrap_or_default();
- let dev_only = input.get_option("dev-only").as_bool().unwrap_or(false);
- let no_dev_only = input.get_option("no-dev-only").as_bool().unwrap_or(false);
- let dry_run = input.get_option("dry-run").as_bool().unwrap_or(false);
+ let dev_only = input
+ .borrow()
+ .get_option("dev-only")
+ .as_bool()
+ .unwrap_or(false);
+ let no_dev_only = input
+ .borrow()
+ .get_option("no-dev-only")
+ .as_bool()
+ .unwrap_or(false);
+ let dry_run = input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false);
let io = self.get_io().clone();
self.do_bump(
io,
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index 05f7e9b..7b50d25 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -51,19 +51,24 @@ impl CheckPlatformReqsCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
let io = self.get_io();
- let no_dev = input.get_option("no-dev").as_bool().unwrap_or(false);
+ let no_dev = input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false);
let mut requires: IndexMap<String, Vec<Link>> = IndexMap::new();
let mut remove_packages: Vec<String> = vec![];
let installed_repo_base: crate::repository::RepositoryInterfaceHandle = if input
+ .borrow()
.get_option("lock")
.as_bool()
.unwrap_or(false)
@@ -242,6 +247,7 @@ impl CheckPlatformReqsCommand {
}
let format = input
+ .borrow()
.get_option("format")
.as_string()
.unwrap_or("text")
@@ -251,7 +257,12 @@ impl CheckPlatformReqsCommand {
Ok(exit_code)
}
- fn print_table(&mut self, output: &dyn OutputInterface, results: &[CheckResult], format: &str) {
+ fn print_table(
+ &mut self,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ results: &[CheckResult],
+ format: &str,
+ ) {
let io = self.get_io();
if format == "json" {
diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs
index 4859a46..1ceca69 100644
--- a/crates/shirabe/src/command/clear_cache_command.rs
+++ b/crates/shirabe/src/command/clear_cache_command.rs
@@ -29,8 +29,8 @@ impl ClearCacheCommand {
pub fn execute(
&mut self,
- _input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ _input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
// TODO(phase-b): port full execute logic once Config sharing model is settled
let _ = composer::VERSION;
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index 40a12e1..38b8a8d 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -120,13 +120,13 @@ impl ConfigCommand {
pub(crate) fn initialize(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<()> {
- self.initialize(input, output)?;
+ self.initialize(input.clone(), output)?;
let auth_config_file =
- self.get_auth_config_file(input, &*self.config.as_ref().unwrap().borrow());
+ self.get_auth_config_file(input.clone(), &*self.config.as_ref().unwrap().borrow());
self.auth_config_file = Some(JsonFile::new(
auth_config_file,
@@ -138,7 +138,7 @@ impl ConfigCommand {
self.auth_config_source = None;
// Initialize the global file if it's not there, ignoring any warnings or notices
- if input.get_option("global").as_bool() == Some(true)
+ if input.borrow().get_option("global").as_bool() == Some(true)
&& !self.auth_config_file.as_ref().unwrap().exists()
{
touch(self.auth_config_file.as_ref().unwrap().get_path());
@@ -177,11 +177,11 @@ impl ConfigCommand {
pub(crate) fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
// Open file in editor
- if input.get_option("editor").as_bool() == Some(true) {
+ if input.borrow().get_option("editor").as_bool() == Some(true) {
let mut editor = Platform::get_env("EDITOR");
if editor.is_none() || editor.as_deref() == Some("") {
if Platform::is_windows() {
@@ -201,7 +201,7 @@ impl ConfigCommand {
editor = Some(escapeshellcmd(&editor.unwrap()));
}
- let file = if input.get_option("auth").as_bool() == Some(true) {
+ let file = if input.borrow().get_option("auth").as_bool() == Some(true) {
self.auth_config_file
.as_ref()
.unwrap()
@@ -227,7 +227,7 @@ impl ConfigCommand {
return Ok(0);
}
- if input.get_option("global").as_bool() != Some(true) {
+ if input.borrow().get_option("global").as_bool() != Some(true) {
let config_read = self.config_file.as_mut().unwrap().read()?;
let config_map = match config_read {
PhpMixed::Array(m) => m
@@ -263,7 +263,7 @@ impl ConfigCommand {
}
// List the configuration of the file settings
- if input.get_option("list").as_bool() == Some(true) {
+ 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 to_mixed = |m: IndexMap<String, PhpMixed>| -> PhpMixed {
@@ -274,20 +274,20 @@ impl ConfigCommand {
to_mixed(raw_map),
output,
None,
- input.get_option("source").as_bool() == Some(true),
+ input.borrow().get_option("source").as_bool() == Some(true),
);
return Ok(0);
}
- let setting_key_arg = input.get_argument("setting-key");
+ let setting_key_arg = input.borrow().get_argument("setting-key");
let setting_key = match setting_key_arg.as_string() {
Some(s) => s.to_string(),
None => return Ok(0),
};
// If the user enters in a config variable, parse it and save to file
- let setting_values_raw = input.get_argument("setting-value");
+ let setting_values_raw = input.borrow().get_argument("setting-value");
let setting_values: Vec<String> = setting_values_raw
.as_list()
.map(|l| {
@@ -296,7 +296,8 @@ impl ConfigCommand {
.collect()
})
.unwrap_or_default();
- if !setting_values.is_empty() && input.get_option("unset").as_bool() == Some(true) {
+ if !setting_values.is_empty() && input.borrow().get_option("unset").as_bool() == Some(true)
+ {
return Err(RuntimeException {
message: "You can not combine a setting value with --unset".to_string(),
code: 0,
@@ -305,7 +306,7 @@ impl ConfigCommand {
}
// show the value if no value is provided
- if setting_values.is_empty() && input.get_option("unset").as_bool() != Some(true) {
+ if setting_values.is_empty() && input.borrow().get_option("unset").as_bool() != Some(true) {
let properties: Vec<&'static str> = Self::CONFIGURABLE_PACKAGE_PROPERTIES.to_vec();
let mut properties_defaults: IndexMap<String, PhpMixed> = IndexMap::new();
properties_defaults.insert("type".to_string(), PhpMixed::String("library".to_string()));
@@ -411,7 +412,7 @@ impl ConfigCommand {
{
value = self.config.as_ref().unwrap().borrow_mut().get_with_flags(
&setting_key,
- if input.get_option("absolute").as_bool() == Some(true) {
+ if input.borrow().get_option("absolute").as_bool() == Some(true) {
0
} else {
Config::RELATIVE_PATHS
@@ -488,7 +489,7 @@ impl ConfigCommand {
};
let mut source_of_config_value = String::new();
- if input.get_option("source").as_bool() == Some(true) {
+ if input.borrow().get_option("source").as_bool() == Some(true) {
source_of_config_value = format!(" ({})", source);
}
@@ -526,7 +527,7 @@ impl ConfigCommand {
let multi_config_values = build_multi_config_values();
// allow unsetting audit config entirely
- if input.get_option("unset").as_bool() == Some(true) && setting_key == "audit" {
+ if input.borrow().get_option("unset").as_bool() == Some(true) && setting_key == "audit" {
self.config_source
.as_mut()
.unwrap()
@@ -535,7 +536,7 @@ impl ConfigCommand {
return Ok(0);
}
- if input.get_option("unset").as_bool() == Some(true)
+ if input.borrow().get_option("unset").as_bool() == Some(true)
&& (unique_config_values.contains_key(&setting_key)
|| multi_config_values.contains_key(&setting_key))
{
@@ -580,7 +581,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -621,7 +622,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -652,7 +653,7 @@ impl ConfigCommand {
let unique_props = build_unique_props();
let multi_props = build_multi_props();
- if input.get_option("global").as_bool() == Some(true)
+ if input.borrow().get_option("global").as_bool() == Some(true)
&& (unique_props.contains_key(&setting_key)
|| multi_props.contains_key(&setting_key)
|| strpos(&setting_key, "extra.") == Some(0))
@@ -663,7 +664,7 @@ impl ConfigCommand {
}
.into());
}
- if input.get_option("unset").as_bool() == Some(true)
+ if input.borrow().get_option("unset").as_bool() == Some(true)
&& (unique_props.contains_key(&setting_key) || multi_props.contains_key(&setting_key))
{
self.config_source
@@ -693,7 +694,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -715,7 +716,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
PhpMixed::Array(repo),
- input.get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append").as_bool() == Some(true),
);
return Ok(0);
@@ -731,7 +732,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
PhpMixed::Bool(false),
- input.get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append").as_bool() == Some(true),
);
return Ok(0);
@@ -741,7 +742,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
value,
- input.get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append").as_bool() == Some(true),
);
return Ok(0);
@@ -758,7 +759,7 @@ impl ConfigCommand {
// handle extra
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^extra\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -768,9 +769,9 @@ impl ConfigCommand {
}
let mut value = PhpMixed::String(values[0].clone());
- if input.get_option("json").as_bool() == Some(true) {
+ if input.borrow().get_option("json").as_bool() == Some(true) {
value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?;
- if input.get_option("merge").as_bool() == Some(true) {
+ if input.borrow().get_option("merge").as_bool() == Some(true) {
let current_value_outer = self.config_file.as_mut().unwrap().read()?;
let bits = explode(".", &setting_key);
let mut current_value: PhpMixed = current_value_outer;
@@ -816,7 +817,7 @@ impl ConfigCommand {
// handle suggest
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^suggest\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -838,7 +839,7 @@ impl ConfigCommand {
setting_key.as_str().into(),
&vec!["suggest".to_string(), "extra".to_string()].into(),
true,
- ) && input.get_option("unset").as_bool() == Some(true)
+ ) && input.borrow().get_option("unset").as_bool() == Some(true)
{
self.config_source
.as_mut()
@@ -852,7 +853,7 @@ impl ConfigCommand {
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^platform\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false)
{
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -875,7 +876,7 @@ impl ConfigCommand {
}
// handle unsetting platform
- if setting_key == "platform" && input.get_option("unset").as_bool() == Some(true) {
+ if setting_key == "platform" && input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -894,7 +895,7 @@ impl ConfigCommand {
.into(),
true,
) {
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -909,7 +910,7 @@ impl ConfigCommand {
.map(|s| Box::new(PhpMixed::String(s.clone())))
.collect(),
);
- if input.get_option("json").as_bool() == Some(true) {
+ if input.borrow().get_option("json").as_bool() == Some(true) {
value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?;
if !is_array(&value) {
return Err(RuntimeException {
@@ -920,7 +921,7 @@ impl ConfigCommand {
}
}
- if input.get_option("merge").as_bool() == Some(true) {
+ if input.borrow().get_option("merge").as_bool() == Some(true) {
let current_config = self.config_file.as_mut().unwrap().read()?;
let key_suffix = str_replace("audit.", "", &setting_key);
let current_value = current_config
@@ -973,7 +974,7 @@ impl ConfigCommand {
// handle auth
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|custom-headers|bearer|forgejo-token)\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.auth_config_source.as_mut().unwrap().remove_config_setting(&format!("{}.{}", matches[1], matches[2]));
self.config_source.as_mut().unwrap().remove_config_setting(&format!("{}.{}", matches[1], matches[2]));
@@ -1079,7 +1080,7 @@ impl ConfigCommand {
// handle script
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^scripts\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -1107,7 +1108,7 @@ impl ConfigCommand {
}
// handle unsetting other top level properties
- if input.get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset").as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -1243,7 +1244,7 @@ impl ConfigCommand {
&mut self,
contents: PhpMixed,
raw_contents: PhpMixed,
- output: &dyn OutputInterface,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
k: Option<String>,
show_source: bool,
) {
@@ -1278,7 +1279,13 @@ impl ConfigCommand {
&Preg::replace("{^config\\.}", "", &format!("{}.", key)).unwrap_or_default(),
);
k = Some(new_k);
- self.list_configuration(value_inner, raw_val, output, k.clone(), show_source);
+ self.list_configuration(
+ value_inner,
+ raw_val,
+ output.clone(),
+ k.clone(),
+ show_source,
+ );
k = orig_k.clone();
continue;
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index b13a3d0..d05f27d 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -109,30 +109,35 @@ impl CreateProjectCommand {
fn execute(
&mut self,
- input: &mut dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?));
// TODO(phase-b): get_io returns &mut Self-borrow; clone_box for an owned Box to dodge.
let io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> = self.get_io().clone();
let (prefer_source, prefer_dist) =
- self.get_preferred_install_options(&config.borrow(), input, true)?;
+ self.get_preferred_install_options(&config.borrow(), input.clone(), true)?;
- if input.get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
io.write_error("<warning>You are using the deprecated option \"dev\". Dev packages are installed by default now.</warning>");
}
if input
+ .borrow()
.get_option("no-custom-installers")
.as_bool()
.unwrap_or(false)
{
io.write_error("<warning>You are using the deprecated option \"no-custom-installers\". Use \"no-plugins\" instead.</warning>");
- input.set_option("no-plugins", PhpMixed::Bool(true));
+ input
+ .borrow_mut()
+ .set_option("no-plugins", PhpMixed::Bool(true));
}
- if input.is_interactive() && input.get_option("ask").as_bool().unwrap_or(false) {
- let package = input.get_argument("package");
+ if input.borrow().is_interactive()
+ && input.borrow().get_option("ask").as_bool().unwrap_or(false)
+ {
+ let package = input.borrow().get_argument("package");
if package.is_null() {
return Err(RuntimeException {
message: "Not enough arguments (missing: \"package\").".to_string(),
@@ -146,11 +151,13 @@ impl CreateProjectCommand {
"New project directory [<comment>{}</comment>]: ",
array_pop(&mut parts).unwrap_or_default()
);
- input.set_argument("directory", io.ask(prompt, PhpMixed::Null));
+ input
+ .borrow_mut()
+ .set_argument("directory", io.ask(prompt, PhpMixed::Null));
}
- let repository_opt = input.get_option("repository");
- let repository_url_opt = input.get_option("repository-url");
+ let repository_opt = input.borrow().get_option("repository");
+ let repository_url_opt = input.borrow().get_option("repository-url");
let repositories = if repository_opt
.as_list()
.map(|l| l.len() > 0)
@@ -164,37 +171,63 @@ impl CreateProjectCommand {
self.install_project(
io,
config,
- input,
+ input.clone(),
input
+ .borrow()
.get_argument("package")
.as_string()
.map(|s| s.to_string()),
input
+ .borrow()
.get_argument("directory")
.as_string()
.map(|s| s.to_string()),
input
+ .borrow()
.get_argument("version")
.as_string()
.map(|s| s.to_string()),
input
+ .borrow()
.get_option("stability")
.as_string()
.map(|s| s.to_string()),
prefer_source,
prefer_dist,
- !input.get_option("no-dev").as_bool().unwrap_or(false),
+ !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false),
repositories,
- input.get_option("no-plugins").as_bool().unwrap_or(false),
- input.get_option("no-scripts").as_bool().unwrap_or(false),
- input.get_option("no-progress").as_bool().unwrap_or(false),
- input.get_option("no-install").as_bool().unwrap_or(false),
- Some(self.get_platform_requirement_filter(input)?),
+ input
+ .borrow()
+ .get_option("no-plugins")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("no-scripts")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("no-install")
+ .as_bool()
+ .unwrap_or(false),
+ Some(self.get_platform_requirement_filter(input.clone())?),
!input
+ .borrow()
.get_option("no-secure-http")
.as_bool()
.unwrap_or(false),
input
+ .borrow()
.get_option("add-repository")
.as_bool()
.unwrap_or(false),
@@ -209,7 +242,7 @@ impl CreateProjectCommand {
&mut self,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: std::rc::Rc<std::cell::RefCell<Config>>,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
package_name: Option<String>,
directory: Option<String>,
package_version: Option<String>,
@@ -254,7 +287,7 @@ impl CreateProjectCommand {
let installed_from_vcs = if let Some(package_name) = package_name.as_ref() {
self.install_root_package(
- input,
+ input.clone(),
io.clone(),
&config,
package_name,
@@ -280,7 +313,7 @@ impl CreateProjectCommand {
}
let mut composer_handle = self.create_composer_instance(
- input,
+ input.clone(),
io.clone(),
None,
disable_plugins,
@@ -339,7 +372,7 @@ impl CreateProjectCommand {
}
composer_handle = self.create_composer_instance(
- input,
+ input.clone(),
io.clone(),
None,
disable_plugins,
@@ -371,7 +404,8 @@ impl CreateProjectCommand {
// use the new config including the newly installed project
let config = composer.get_config();
- let (ps, pd) = self.get_preferred_install_options(&*config.borrow(), input, false)?;
+ let (ps, pd) =
+ self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?;
prefer_source = ps;
prefer_dist = pd;
@@ -413,7 +447,9 @@ impl CreateProjectCommand {
.unwrap_or(false),
None,
)
- .set_audit_config(self.create_audit_config(&mut *config.borrow_mut(), input)?);
+ .set_audit_config(
+ self.create_audit_config(&mut *config.borrow_mut(), input.clone())?,
+ );
if !composer.get_locker().borrow_mut().is_locked() {
installer.set_update(true);
@@ -444,9 +480,9 @@ impl CreateProjectCommand {
}
let mut has_vcs = installed_from_vcs;
- let remove_vcs = !input.get_option("keep-vcs").as_bool().unwrap_or(false)
+ let remove_vcs = !input.borrow().get_option("keep-vcs").as_bool().unwrap_or(false)
&& installed_from_vcs
- && (input.get_option("remove-vcs").as_bool().unwrap_or(false)
+ && (input.borrow().get_option("remove-vcs").as_bool().unwrap_or(false)
|| !io.is_interactive()
|| io.ask_confirmation(
"<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>y,n</comment>]? ".to_string(),
@@ -550,7 +586,7 @@ impl CreateProjectCommand {
#[allow(clippy::too_many_arguments)]
fn install_root_package(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: &std::rc::Rc<std::cell::RefCell<Config>>,
package_name: &str,
@@ -957,7 +993,7 @@ impl CreateProjectCommand {
// helpers reachable via $this in PHP, defined on BaseCommand here
fn create_composer_instance(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<indexmap::IndexMap<String, PhpMixed>>,
disable_plugins: bool,
@@ -969,7 +1005,7 @@ impl CreateProjectCommand {
fn create_audit_config(
&self,
config: &Config,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> Result<crate::advisory::AuditConfig> {
self.create_audit_config(config, input)
}
diff --git a/crates/shirabe/src/command/depends_command.rs b/crates/shirabe/src/command/depends_command.rs
index 78b3dbb..a53aab7 100644
--- a/crates/shirabe/src/command/depends_command.rs
+++ b/crates/shirabe/src/command/depends_command.rs
@@ -67,8 +67,8 @@ impl DependsCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
self.do_execute(input, output, false)
}
diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs
index d9ab5e2..59df4f9 100644
--- a/crates/shirabe/src/command/diagnose_command.rs
+++ b/crates/shirabe/src/command/diagnose_command.rs
@@ -75,8 +75,8 @@ impl DiagnoseCommand {
pub(crate) fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
let mut composer = self.try_composer(None, None);
let io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> = self.get_io().clone();
diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs
index 6f361da..0f229d0 100644
--- a/crates/shirabe/src/command/dump_autoload_command.rs
+++ b/crates/shirabe/src/command/dump_autoload_command.rs
@@ -44,15 +44,19 @@ impl DumpAutoloadCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
// TODO(plugin): dispatch CommandEvent
- let command_event =
- CommandEvent::new(PluginEvents::COMMAND, "dump-autoload", input, output);
+ let command_event = CommandEvent::new(
+ PluginEvents::COMMAND,
+ "dump-autoload",
+ input.clone(),
+ output,
+ );
composer
.get_event_dispatcher()
.borrow_mut()
@@ -78,13 +82,18 @@ impl DumpAutoloadCommand {
}
}
- let optimize = input.get_option("optimize").as_bool().unwrap_or(false)
+ let optimize = input
+ .borrow()
+ .get_option("optimize")
+ .as_bool()
+ .unwrap_or(false)
|| config
.borrow_mut()
.get("optimize-autoloader")
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -94,18 +103,25 @@ impl DumpAutoloadCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix = input
+ .borrow()
.get_option("apcu-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
- || input.get_option("apcu").as_bool().unwrap_or(false)
+ || input.borrow().get_option("apcu").as_bool().unwrap_or(false)
|| config
.borrow_mut()
.get("apcu-autoloader")
.as_bool()
.unwrap_or(false);
- if input.get_option("strict-psr").as_bool().unwrap_or(false) && !optimize && !authoritative
+ if input
+ .borrow()
+ .get_option("strict-psr")
+ .as_bool()
+ .unwrap_or(false)
+ && !optimize
+ && !authoritative
{
return Err(InvalidArgumentException {
message: "--strict-psr mode only works with optimized autoloader, use --optimize or --classmap-authoritative if you want a strict return value.".to_string(),
@@ -114,6 +130,7 @@ impl DumpAutoloadCommand {
.into());
}
if input
+ .borrow()
.get_option("strict-ambiguous")
.as_bool()
.unwrap_or(false)
@@ -138,21 +155,36 @@ impl DumpAutoloadCommand {
.write("<info>Generating autoload files</info>");
}
- let platform_requirement_filter = self.get_platform_requirement_filter(input)?;
- if input.get_option("dry-run").as_bool().unwrap_or(false) {
+ let platform_requirement_filter = self.get_platform_requirement_filter(input.clone())?;
+ if input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false)
+ {
composer
.get_autoload_generator()
.borrow_mut()
.set_dry_run(true);
}
- if input.get_option("no-dev").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false)
+ {
composer
.get_autoload_generator()
.borrow_mut()
.set_dev_mode(false);
}
- if input.get_option("dev").as_bool().unwrap_or(false) {
- if input.get_option("no-dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Err(InvalidArgumentException {
message:
"You can not use both --no-dev and --dev as they conflict with each other."
@@ -199,13 +231,18 @@ impl DumpAutoloadCommand {
}
if missing_dependencies
- || (input.get_option("strict-psr").as_bool().unwrap_or(false)
+ || (input
+ .borrow()
+ .get_option("strict-psr")
+ .as_bool()
+ .unwrap_or(false)
&& !class_map.get_psr_violations().is_empty())
{
return Ok(1);
}
if input
+ .borrow()
.get_option("strict-ambiguous")
.as_bool()
.unwrap_or(false)
diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs
index cfc0e89..b086937 100644
--- a/crates/shirabe/src/command/exec_command.rs
+++ b/crates/shirabe/src/command/exec_command.rs
@@ -41,16 +41,16 @@ impl ExecCommand {
pub fn interact(
&mut self,
- input: &mut dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<()> {
let binaries = self.get_binaries(false)?;
if binaries.is_empty() {
return Ok(());
}
- if input.get_argument("binary").as_string().is_some()
- || input.get_option("list").as_bool().unwrap_or(false)
+ if input.borrow().get_argument("binary").as_string().is_some()
+ || input.borrow().get_option("list").as_bool().unwrap_or(false)
{
return Ok(());
}
@@ -66,7 +66,7 @@ impl ExecCommand {
);
if let Some(idx) = binary.as_int() {
- input.set_argument(
+ input.borrow_mut().set_argument(
"binary",
shirabe_php_shim::PhpMixed::String(binaries[idx as usize].clone()),
);
@@ -77,13 +77,13 @@ impl ExecCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
- if input.get_option("list").as_bool().unwrap_or(false)
- || input.get_argument("binary").as_string().is_none()
+ if input.borrow().get_option("list").as_bool().unwrap_or(false)
+ || input.borrow().get_argument("binary").as_string().is_none()
{
let bins = self.get_binaries(true)?;
if bins.is_empty() {
@@ -114,6 +114,7 @@ impl ExecCommand {
}
let binary = input
+ .borrow()
.get_argument("binary")
.as_string()
.unwrap_or("")
@@ -139,6 +140,7 @@ impl ExecCommand {
}
let args = input
+ .borrow()
.get_argument("args")
.as_list()
.map(|l| {
diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs
index 0fab473..cb60eb0 100644
--- a/crates/shirabe/src/command/fund_command.rs
+++ b/crates/shirabe/src/command/fund_command.rs
@@ -47,8 +47,8 @@ impl FundCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let composer = crate::command::composer_full(&composer);
@@ -121,6 +121,7 @@ impl FundCommand {
let io = self.get_io();
let format = input
+ .borrow()
.get_option("format")
.as_string()
.unwrap_or("text")
diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs
index a3d5a78..e5d06b7 100644
--- a/crates/shirabe/src/command/global_command.rs
+++ b/crates/shirabe/src/command/global_command.rs
@@ -56,8 +56,12 @@ impl GlobalCommand {
);
}
- pub fn run(&mut self, input: &dyn InputInterface, output: &dyn OutputInterface) -> Result<i64> {
- let tokens = Preg::split(r"{\s+}", &input.to_input_string())?;
+ pub fn run(
+ &mut self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) -> Result<i64> {
+ let tokens = Preg::split(r"{\s+}", &input.borrow().to_input_string())?;
let mut args: Vec<String> = vec![];
for token in &tokens {
if !token.is_empty() && !token.starts_with('-') {
@@ -76,12 +80,15 @@ impl GlobalCommand {
let mut sub_input = self.prepare_subcommand_input(input, false)?;
let mut app = self.get_application()?;
let _ = output;
- Ok(app.run(Some(&mut sub_input), None)?)
+ Ok(app.run(
+ Some(std::rc::Rc::new(std::cell::RefCell::new(sub_input))),
+ None,
+ )?)
}
fn prepare_subcommand_input(
&mut self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
quiet: bool,
) -> Result<StringInput> {
if Platform::get_env("COMPOSER").is_some() {
@@ -118,7 +125,7 @@ impl GlobalCommand {
let new_input_str = Preg::replace4(
r"{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}",
"",
- &input.to_input_string(),
+ &input.borrow().to_input_string(),
1,
)?;
self.get_application()?.reset_composer();
diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs
index db6f644..86909f5 100644
--- a/crates/shirabe/src/command/home_command.rs
+++ b/crates/shirabe/src/command/home_command.rs
@@ -69,14 +69,15 @@ impl HomeCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let repos = self.initialize_repos()?;
let io = self.get_io().clone();
let mut return_code: i64 = 0;
let packages: Vec<String> = input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -95,8 +96,12 @@ impl HomeCommand {
packages
};
- let show_homepage = input.get_option("homepage").as_bool().unwrap_or(false);
- let show_only = input.get_option("show").as_bool().unwrap_or(false);
+ let show_homepage = input
+ .borrow()
+ .get_option("homepage")
+ .as_bool()
+ .unwrap_or(false);
+ let show_only = input.borrow().get_option("show").as_bool().unwrap_or(false);
for package_name in &packages {
let mut handled = false;
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs
index a46b6ca..eabe6e2 100644
--- a/crates/shirabe/src/command/init_command.rs
+++ b/crates/shirabe/src/command/init_command.rs
@@ -72,7 +72,7 @@ impl PackageDiscoveryTrait for InitCommand {
fn get_platform_requirement_filter(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> std::rc::Rc<
dyn crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface,
> {
@@ -116,8 +116,8 @@ impl InitCommand {
/// @throws \Seld\JsonLint\ParsingException
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let io = PackageDiscoveryTrait::get_io(self);
@@ -134,11 +134,13 @@ impl InitCommand {
"autoload".to_string(),
];
// TODO(phase-b): adapt PhpMixed<->Box<PhpMixed> for array_filter_map
- let filtered_input: IndexMap<String, Box<PhpMixed>> =
- array_intersect_key(&input.get_options(), &array_flip_strings(&allowlist))
- .into_iter()
- .map(|(k, v)| (k, Box::new(v)))
- .collect();
+ let filtered_input: IndexMap<String, Box<PhpMixed>> = array_intersect_key(
+ &input.borrow().get_options(),
+ &array_flip_strings(&allowlist),
+ )
+ .into_iter()
+ .map(|(k, v)| (k, Box::new(v)))
+ .collect();
let mut options = shirabe_php_shim::array_filter_map(&filtered_input, |val: &PhpMixed| {
!matches!(val, PhpMixed::Null) && !matches!(val, PhpMixed::List(l) if l.is_empty())
});
@@ -186,6 +188,7 @@ impl InitCommand {
}
let repositories: Vec<String> = input
+ .borrow()
.get_option("repository")
.as_list()
.map(|l| {
@@ -283,6 +286,7 @@ impl InitCommand {
.to_string();
autoload_path = Some(ap.clone());
let name = input
+ .borrow()
.get_option("name")
.as_string()
.unwrap_or("")
@@ -303,7 +307,7 @@ impl InitCommand {
.collect();
let json = JsonFile::encode(&PhpMixed::Array(options_for_encode.clone()));
- if input.is_interactive() {
+ if input.borrow().is_interactive() {
io.write_error3(&format!("\n{}\n", json), true, io_interface::NORMAL);
if !io.ask_confirmation(
"Do you confirm generation [<comment>yes</comment>]? ".to_string(),
@@ -358,11 +362,11 @@ impl InitCommand {
// dump-autoload only for projects without added dependencies.
if !self.has_dependencies(&options) {
- self.run_dump_autoload_command(output);
+ self.run_dump_autoload_command(output.clone());
}
}
- if input.is_interactive() && is_dir(".git") {
+ if input.borrow().is_interactive() && is_dir(".git") {
let mut ignore_file = realpath(".gitignore").unwrap_or_default();
if ignore_file.is_empty() {
@@ -380,7 +384,7 @@ impl InitCommand {
let question =
"Would you like to install dependencies now [<comment>yes</comment>]? ".to_string();
- if input.is_interactive()
+ if input.borrow().is_interactive()
&& self.has_dependencies(&options)
&& io.ask_confirmation(question, true)
{
@@ -390,6 +394,7 @@ impl InitCommand {
// --autoload - Show post-install configuration info
if autoload_path.is_some() {
let name = input
+ .borrow()
.get_option("name")
.as_string()
.unwrap_or("")
@@ -411,15 +416,19 @@ impl InitCommand {
Ok(0)
}
- pub(crate) fn initialize(&mut self, input: &dyn InputInterface, output: &dyn OutputInterface) {
- self.initialize(input, output);
+ pub(crate) fn initialize(
+ &mut self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
+ self.initialize(input.clone(), output);
- if !input.is_interactive() {
- if input.get_option("name").is_null() {
+ if !input.borrow().is_interactive() {
+ if input.borrow().get_option("name").is_null() {
// TODO(phase-b): input.set_option requires &mut; signature passes &dyn here
}
- if input.get_option("author").is_null() {
+ if input.borrow().get_option("author").is_null() {
// TODO(phase-b): input.set_option requires &mut; signature passes &dyn here
}
}
@@ -427,8 +436,8 @@ impl InitCommand {
pub(crate) fn interact(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<()> {
let io = self.get_io();
// @var FormatterHelper $formatter
@@ -439,6 +448,7 @@ impl InitCommand {
// initialize repos if configured
let repositories: Vec<String> = input
+ .borrow()
.get_option("repository")
.as_list()
.map(|l| {
@@ -527,6 +537,7 @@ impl InitCommand {
);
let mut name = input
+ .borrow()
.get_option("name")
.as_string()
.map(|s| s.to_string())
@@ -569,9 +580,12 @@ impl InitCommand {
.as_string()
.unwrap_or("")
.to_string();
- input.set_option("name", PhpMixed::String(name));
+ input
+ .borrow_mut()
+ .set_option("name", PhpMixed::String(name));
let description = input
+ .borrow()
.get_option("description")
.as_string()
.map(|s| s.to_string());
@@ -585,9 +599,10 @@ impl InitCommand {
.map(PhpMixed::String)
.unwrap_or(PhpMixed::Null),
);
- input.set_option("description", description);
+ input.borrow_mut().set_option("description", description);
let author = input
+ .borrow()
.get_option("author")
.as_string()
.map(|s| s.to_string())
@@ -623,9 +638,10 @@ impl InitCommand {
None,
PhpMixed::String(author_default),
)?;
- input.set_option("author", author_value);
+ input.borrow_mut().set_option("author", author_value);
let minimum_stability = input
+ .borrow()
.get_option("stability")
.as_string()
.map(|s| s.to_string());
@@ -669,9 +685,11 @@ impl InitCommand {
.map(PhpMixed::String)
.unwrap_or(PhpMixed::Null),
)?;
- input.set_option("stability", minimum_stability_value);
+ input
+ .borrow_mut()
+ .set_option("stability", minimum_stability_value);
- let type_val = input.get_option("type");
+ let type_val = input.borrow().get_option("type");
let type_str = type_val.as_string().unwrap_or("").to_string();
let mut type_value = io.ask(
format!(
@@ -683,9 +701,10 @@ impl InitCommand {
if type_value.as_string() == Some("") || matches!(type_value, PhpMixed::Bool(false)) {
type_value = PhpMixed::Null;
}
- input.set_option("type", type_value);
+ input.borrow_mut().set_option("type", type_value);
let mut license = input
+ .borrow()
.get_option("license")
.as_string()
.map(|s| s.to_string());
@@ -722,7 +741,7 @@ impl InitCommand {
}
.into());
}
- input.set_option("license", license);
+ input.borrow_mut().set_option("license", license);
io.write_error3("\nDefine your dependencies.\n", true, io_interface::NORMAL);
@@ -741,6 +760,7 @@ impl InitCommand {
let question = "Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ".to_string();
let require: Vec<String> = input
+ .borrow()
.get_option("require")
.as_list()
.map(|l| {
@@ -762,7 +782,7 @@ impl InitCommand {
} else {
vec![]
};
- input.set_option(
+ input.borrow_mut().set_option(
"require",
PhpMixed::List(
requirements
@@ -774,6 +794,7 @@ impl InitCommand {
let question = "Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ".to_string();
let require_dev: Vec<String> = input
+ .borrow()
.get_option("require-dev")
.as_list()
.map(|l| {
@@ -796,7 +817,7 @@ impl InitCommand {
} else {
vec![]
};
- input.set_option(
+ input.borrow_mut().set_option(
"require-dev",
PhpMixed::List(
dev_requirements
@@ -808,12 +829,14 @@ impl InitCommand {
// --autoload - input and validation
let mut autoload = input
+ .borrow()
.get_option("autoload")
.as_string()
.map(|s| s.to_string())
.filter(|s| !s.is_empty())
.unwrap_or_else(|| "src/".to_string());
let name_str = input
+ .borrow()
.get_option("name")
.as_string()
.unwrap_or("")
@@ -861,7 +884,7 @@ impl InitCommand {
None,
PhpMixed::String(autoload_default),
)?;
- input.set_option("autoload", autoload_value);
+ input.borrow_mut().set_option("autoload", autoload_value);
Ok(())
}
@@ -1035,7 +1058,7 @@ impl InitCommand {
shirabe_php_shim::filter_var(email, FILTER_VALIDATE_EMAIL)
}
- fn update_dependencies(&self, output: &dyn OutputInterface) {
+ fn update_dependencies(&self, output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>) {
// PHP try/catch: catch \Exception
let result = self.get_application().and_then(|mut app| {
let _update_command = app.find("update")?;
@@ -1054,7 +1077,10 @@ impl InitCommand {
}
}
- fn run_dump_autoload_command(&self, output: &dyn OutputInterface) {
+ fn run_dump_autoload_command(
+ &self,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
let result = self.get_application().and_then(|mut app| {
let _command = app.find("dump-autoload")?;
app.reset_composer();
diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs
index 768f75f..de68f87 100644
--- a/crates/shirabe/src/command/install_command.rs
+++ b/crates/shirabe/src/command/install_command.rs
@@ -64,19 +64,24 @@ impl InstallCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let io = self.get_io().clone();
- if input.get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
io.write_error("<warning>You are using the deprecated option \"--dev\". It has no effect and will break in Composer 3.</warning>");
}
- if input.get_option("no-suggest").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-suggest")
+ .as_bool()
+ .unwrap_or(false)
+ {
io.write_error("<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>");
}
- let args = input.get_argument("packages");
+ let args = input.borrow().get_argument("packages");
let args_vec: Vec<String> = args
.as_list()
.map(|l| {
@@ -94,7 +99,12 @@ impl InstallCommand {
return Ok(1);
}
- if input.get_option("no-install").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-install")
+ .as_bool()
+ .unwrap_or(false)
+ {
io.write_error("<error>Invalid option \"--no-install\". Use \"composer update --no-install\" instead if you are trying to update the composer.lock file.</error>");
return Ok(1);
}
@@ -107,7 +117,8 @@ impl InstallCommand {
}
// TODO(plugin): dispatch CommandEvent
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "install", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "install", input.clone(), output);
composer
.get_event_dispatcher()
.borrow_mut()
@@ -117,9 +128,10 @@ impl InstallCommand {
let config = composer.get_config();
let (prefer_source, prefer_dist) =
- self.get_preferred_install_options(&*config.borrow(), input, false)?;
+ self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?;
let optimize = input
+ .borrow()
.get_option("optimize-autoloader")
.as_bool()
.unwrap_or(false)
@@ -129,6 +141,7 @@ impl InstallCommand {
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -138,11 +151,13 @@ impl InstallCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix = input
+ .borrow()
.get_option("apcu-autoloader-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
+ .borrow()
.get_option("apcu-autoloader")
.as_bool()
.unwrap_or(false)
@@ -155,26 +170,73 @@ impl InstallCommand {
composer
.get_installation_manager()
.borrow_mut()
- .set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
+ .set_output_progress(
+ !input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false),
+ );
install
- .set_dry_run(input.get_option("dry-run").as_bool().unwrap_or(false))
- .set_download_only(input.get_option("download-only").as_bool().unwrap_or(false))
- .set_verbose(input.get_option("verbose").as_bool().unwrap_or(false))
+ .set_dry_run(
+ input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_download_only(
+ input
+ .borrow()
+ .get_option("download-only")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_verbose(
+ input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_prefer_source(prefer_source)
.set_prefer_dist(prefer_dist)
- .set_dev_mode(!input.get_option("no-dev").as_bool().unwrap_or(false))
- .set_dump_autoloader(!input.get_option("no-autoloader").as_bool().unwrap_or(false))
+ .set_dev_mode(
+ !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_dump_autoloader(
+ !input
+ .borrow()
+ .get_option("no-autoloader")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_optimize_autoloader(optimize)
.set_class_map_authoritative(authoritative)
.set_apcu_autoloader(apcu, apcu_prefix.clone())
- .set_platform_requirement_filter(self.get_platform_requirement_filter(input)?)
+ .set_platform_requirement_filter(self.get_platform_requirement_filter(input.clone())?)
.set_audit_config(
- self.create_audit_config(&mut *composer.get_config().borrow_mut(), input)?,
+ self.create_audit_config(&mut *composer.get_config().borrow_mut(), input.clone())?,
)
- .set_error_on_audit(input.get_option("audit").as_bool().unwrap_or(false));
+ .set_error_on_audit(
+ input
+ .borrow()
+ .get_option("audit")
+ .as_bool()
+ .unwrap_or(false),
+ );
- if input.get_option("no-plugins").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-plugins")
+ .as_bool()
+ .unwrap_or(false)
+ {
install.disable_plugins();
}
diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs
index d870acb..79c86d1 100644
--- a/crates/shirabe/src/command/licenses_command.rs
+++ b/crates/shirabe/src/command/licenses_command.rs
@@ -76,14 +76,19 @@ impl LicensesCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
// TODO(plugin): dispatch COMMAND event for plugin hooks
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "licenses", input, output);
+ let command_event = CommandEvent::new(
+ PluginEvents::COMMAND,
+ "licenses",
+ input.clone(),
+ output.clone(),
+ );
composer
.get_event_dispatcher()
.borrow_mut()
@@ -91,7 +96,12 @@ impl LicensesCommand {
let root = composer.get_package();
- let packages = if input.get_option("locked").as_bool().unwrap_or(false) {
+ let packages = if input
+ .borrow()
+ .get_option("locked")
+ .as_bool()
+ .unwrap_or(false)
+ {
let locker = composer.get_locker().clone();
let mut locker = locker.borrow_mut();
if !locker.is_locked() {
@@ -100,7 +110,11 @@ impl LicensesCommand {
code: 0,
}.into());
}
- let no_dev = input.get_option("no-dev").as_bool().unwrap_or(false);
+ let no_dev = input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false);
let repo = locker.get_locked_repository(!no_dev)?;
repo.borrow_mut().get_packages()?
} else {
@@ -108,7 +122,12 @@ impl LicensesCommand {
let repository_manager = repository_manager.borrow();
let repo = repository_manager.get_local_repository();
- if input.get_option("no-dev").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false)
+ {
RepositoryUtils::filter_required_packages(
&repo.get_packages()?,
composer.get_package().clone().into(),
@@ -126,6 +145,7 @@ impl LicensesCommand {
let io = self.get_io();
let format = input
+ .borrow()
.get_option("format")
.as_string()
.unwrap_or("text")
diff --git a/crates/shirabe/src/command/outdated_command.rs b/crates/shirabe/src/command/outdated_command.rs
index 89edb44..f14ebe3 100644
--- a/crates/shirabe/src/command/outdated_command.rs
+++ b/crates/shirabe/src/command/outdated_command.rs
@@ -53,73 +53,130 @@ impl OutdatedCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let mut args: IndexMap<String, PhpMixed> = IndexMap::new();
args.insert("command".to_string(), PhpMixed::String("show".to_string()));
args.insert("--latest".to_string(), PhpMixed::Bool(true));
if input
+ .borrow()
.get_option("no-interaction")
.as_bool()
.unwrap_or(false)
{
args.insert("--no-interaction".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("no-plugins").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-plugins")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--no-plugins".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("no-scripts").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-scripts")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--no-scripts".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("no-cache").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-cache")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--no-cache".to_string(), PhpMixed::Bool(true));
}
- if !input.get_option("all").as_bool().unwrap_or(false) {
+ if !input.borrow().get_option("all").as_bool().unwrap_or(false) {
args.insert("--outdated".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("direct").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("direct")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--direct".to_string(), PhpMixed::Bool(true));
}
- let package_arg = input.get_argument("package");
+ let package_arg = input.borrow().get_argument("package");
if !matches!(package_arg, PhpMixed::Null) {
args.insert("package".to_string(), package_arg);
}
- if input.get_option("strict").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("strict")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--strict".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("major-only").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("major-only")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--major-only".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("minor-only").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("minor-only")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--minor-only".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("patch-only").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("patch-only")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--patch-only".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("locked").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("locked")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--locked".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("no-dev").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--no-dev".to_string(), PhpMixed::Bool(true));
}
- if input.get_option("sort-by-age").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("sort-by-age")
+ .as_bool()
+ .unwrap_or(false)
+ {
args.insert("--sort-by-age".to_string(), PhpMixed::Bool(true));
}
args.insert(
"--ignore-platform-req".to_string(),
- input.get_option("ignore-platform-req"),
+ input.borrow().get_option("ignore-platform-req"),
);
if input
+ .borrow()
.get_option("ignore-platform-reqs")
.as_bool()
.unwrap_or(false)
{
args.insert("--ignore-platform-reqs".to_string(), PhpMixed::Bool(true));
}
- args.insert("--format".to_string(), input.get_option("format"));
- args.insert("--ignore".to_string(), input.get_option("ignore"));
+ args.insert("--format".to_string(), input.borrow().get_option("format"));
+ args.insert("--ignore".to_string(), input.borrow().get_option("ignore"));
let input = ArrayInput::new(args);
diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs
index 72b635f..9bd49c2 100644
--- a/crates/shirabe/src/command/package_discovery_trait.rs
+++ b/crates/shirabe/src/command/package_discovery_trait.rs
@@ -49,7 +49,7 @@ pub trait PackageDiscoveryTrait {
) -> PartialComposerHandle;
fn get_platform_requirement_filter(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> std::rc::Rc<
dyn crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface,
>;
@@ -81,7 +81,7 @@ pub trait PackageDiscoveryTrait {
/// @param key-of<BasePackage::STABILITIES>|null $minimumStability
fn get_repository_set(
&mut self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
minimum_stability: Option<&str>,
) -> &RepositorySet {
let key = minimum_stability.unwrap_or("default").to_string();
@@ -109,11 +109,15 @@ pub trait PackageDiscoveryTrait {
}
/// @return key-of<BasePackage::STABILITIES>
- fn get_minimum_stability(&self, input: &dyn InputInterface) -> String {
- if input.has_option("stability") {
+ fn get_minimum_stability(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ ) -> String {
+ if input.borrow().has_option("stability") {
// @phpstan-ignore-line as InitCommand does have this option but not all classes using this trait do
return VersionParser::normalize_stability(
&input
+ .borrow()
.get_option("stability")
.as_string()
.map(|s| s.to_string())
@@ -147,8 +151,8 @@ pub trait PackageDiscoveryTrait {
/// @throws \Exception
fn determine_requirements(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
mut requires: Vec<String>,
platform_repo: Option<&PlatformRepositoryHandle>,
preferred_stability: &str,
@@ -184,7 +188,7 @@ pub trait PackageDiscoveryTrait {
let (name, version): (String, String) = self
.find_best_version_and_name_for_package(
io.clone(),
- input,
+ input.clone(),
requirement.get("name").map(|s| s.as_str()).unwrap_or(""),
platform_repo,
preferred_stability,
@@ -492,27 +496,27 @@ pub trait PackageDiscoveryTrait {
fn find_best_version_and_name_for_package(
&mut self,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
name: &str,
platform_repo: Option<&PlatformRepositoryHandle>,
preferred_stability: &str,
fixed: bool,
) -> Result<(String, String)> {
// handle ignore-platform-reqs flag if present
- let platform_requirement_filter = if input.has_option("ignore-platform-reqs")
- && input.has_option("ignore-platform-req")
+ let platform_requirement_filter = if input.borrow().has_option("ignore-platform-reqs")
+ && input.borrow().has_option("ignore-platform-req")
{
- self.get_platform_requirement_filter(input)
+ self.get_platform_requirement_filter(input.clone())
} else {
PlatformRequirementFilterFactory::ignore_nothing()
};
// find the latest version allowed in this repo set
- let repo_set = self.get_repository_set(input, None);
+ let repo_set = self.get_repository_set(input.clone(), None);
// TODO(phase-b): VersionSelector::new takes owned RepositorySet; we have a shared reference
let mut version_selector: VersionSelector =
todo!("VersionSelector::new with owned repo_set");
- let effective_minimum_stability = self.get_minimum_stability(input);
+ let effective_minimum_stability = self.get_minimum_stability(input.clone());
let package = version_selector.find_best_candidate(
name,
@@ -539,7 +543,7 @@ pub trait PackageDiscoveryTrait {
)) > 0
{
let mut constraint = "*".to_string();
- if input.is_interactive() {
+ if input.borrow().is_interactive() {
let providers_count = providers.len();
let name_owned = name.to_string();
let validator: Box<dyn Fn(PhpMixed) -> anyhow::Result<PhpMixed>> =
@@ -733,7 +737,7 @@ pub trait PackageDiscoveryTrait {
.into());
}
- if input.is_interactive() {
+ if input.borrow().is_interactive() {
let result_mixed = io.select(
format!(
"<error>Could not find package {}.</error>\nPick one of these or leave empty to abort:",
diff --git a/crates/shirabe/src/command/prohibits_command.rs b/crates/shirabe/src/command/prohibits_command.rs
index ff9328c..6fca061 100644
--- a/crates/shirabe/src/command/prohibits_command.rs
+++ b/crates/shirabe/src/command/prohibits_command.rs
@@ -75,8 +75,8 @@ impl ProhibitsCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
self.do_execute(input, output, true)
}
diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs
index d183c00..6e4cd7b 100644
--- a/crates/shirabe/src/command/reinstall_command.rs
+++ b/crates/shirabe/src/command/reinstall_command.rs
@@ -61,8 +61,8 @@ impl ReinstallCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let composer = crate::command::composer_full(&composer);
@@ -74,9 +74,9 @@ impl ReinstallCommand {
let mut packages_to_reinstall: Vec<crate::package::PackageInterfaceHandle> = vec![];
let mut package_names_to_reinstall: Vec<String> = vec![];
- let type_option = input.get_option("type");
+ let type_option = input.borrow().get_option("type");
let type_count = type_option.as_list().map_or(0, |l| l.len());
- let packages_arg = input.get_argument("packages");
+ let packages_arg = input.borrow().get_argument("packages");
let packages_count = packages_arg.as_list().map_or(0, |l| l.len());
if type_count > 0 {
@@ -180,7 +180,8 @@ impl ReinstallCommand {
});
// TODO(plugin): dispatch CommandEvent
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "reinstall", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "reinstall", input.clone(), output);
let event_dispatcher = composer.get_event_dispatcher();
event_dispatcher
.borrow_mut()
@@ -188,15 +189,23 @@ impl ReinstallCommand {
let config = composer.get_config();
let (prefer_source, prefer_dist) =
- self.get_preferred_install_options(&*config.borrow(), input, false)?;
+ self.get_preferred_install_options(&*config.borrow(), input.clone(), false)?;
let installation_manager = composer.get_installation_manager().clone();
let download_manager = composer.get_download_manager();
let package = composer.get_package();
// TODO(phase-b): InstallationManager setters need &mut self; conflicts with the &installation_manager / &local_repo / &package borrows held below; needs shared-ownership refactor
- let _no_progress = !input.get_option("no-progress").as_bool().unwrap_or(false);
- let _no_plugins = input.get_option("no-plugins").as_bool().unwrap_or(false);
+ let _no_progress = !input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false);
+ let _no_plugins = input
+ .borrow()
+ .get_option("no-plugins")
+ .as_bool()
+ .unwrap_or(false);
download_manager
.borrow_mut()
@@ -225,8 +234,14 @@ impl ReinstallCommand {
// installation_manager.execute(local_repo_mut, uninstall_ops_boxed, dev_mode, true, false);
// installation_manager.execute(local_repo_mut, install_ops_boxed, dev_mode, true, false);
- if !input.get_option("no-autoloader").as_bool().unwrap_or(false) {
+ if !input
+ .borrow()
+ .get_option("no-autoloader")
+ .as_bool()
+ .unwrap_or(false)
+ {
let optimize = input
+ .borrow()
.get_option("optimize-autoloader")
.as_bool()
.unwrap_or(false)
@@ -236,6 +251,7 @@ impl ReinstallCommand {
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -245,11 +261,13 @@ impl ReinstallCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix = input
+ .borrow()
.get_option("apcu-autoloader-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
+ .borrow()
.get_option("apcu-autoloader")
.as_bool()
.unwrap_or(false)
diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs
index 225714e..2cf71e7 100644
--- a/crates/shirabe/src/command/remove_command.rs
+++ b/crates/shirabe/src/command/remove_command.rs
@@ -157,15 +157,20 @@ impl RemoveCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
if input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| l.is_empty())
.unwrap_or(true)
- && !input.get_option("unused").as_bool().unwrap_or(false)
+ && !input
+ .borrow()
+ .get_option("unused")
+ .as_bool()
+ .unwrap_or(false)
{
return Err(anyhow::anyhow!(InvalidArgumentException {
message: "Not enough arguments (missing: \"packages\").".to_string(),
@@ -174,6 +179,7 @@ impl RemoveCommand {
}
let mut packages: Vec<String> = input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -183,7 +189,12 @@ impl RemoveCommand {
})
.unwrap_or_default();
- if input.get_option("unused").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("unused")
+ .as_bool()
+ .unwrap_or(false)
+ {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
{
@@ -261,12 +272,12 @@ impl RemoveCommand {
let json_file_for_source = JsonFile::new(file.clone(), None, None)?;
let mut json = JsonConfigSource::new(json_file_for_source, false);
- let r#type = if input.get_option("dev").as_bool().unwrap_or(false) {
+ let r#type = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
};
- let alt_type = if !input.get_option("dev").as_bool().unwrap_or(false) {
+ let alt_type = if !input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
@@ -274,6 +285,7 @@ impl RemoveCommand {
let io = self.get_io();
if input
+ .borrow()
.get_option("update-with-dependencies")
.as_bool()
.unwrap_or(false)
@@ -299,7 +311,11 @@ impl RemoveCommand {
}
}
- let dry_run = input.get_option("dry-run").as_bool().unwrap_or(false);
+ let dry_run = input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false);
let mut to_remove: IndexMap<String, Vec<String>> = IndexMap::new();
for package in &packages {
let in_type = composer_data
@@ -425,7 +441,12 @@ impl RemoveCommand {
io.write_error(&format!("<info>{} has been updated</info>", file));
- if input.get_option("no-update").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-update")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Ok(0);
}
@@ -468,7 +489,7 @@ impl RemoveCommand {
let command_event = crate::plugin::CommandEvent::new(
crate::plugin::PluginEvents::COMMAND,
"remove",
- input,
+ input.clone(),
output,
);
composer
@@ -510,12 +531,23 @@ impl RemoveCommand {
composer
.get_installation_manager()
.borrow_mut()
- .set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
+ .set_output_progress(
+ !input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false),
+ );
let mut install = Installer::create(self.get_io().clone(), &composer_handle);
- let update_dev_mode = !input.get_option("update-no-dev").as_bool().unwrap_or(false);
+ let update_dev_mode = !input
+ .borrow()
+ .get_option("update-no-dev")
+ .as_bool()
+ .unwrap_or(false);
let optimize = input
+ .borrow()
.get_option("optimize-autoloader")
.as_bool()
.unwrap_or(false)
@@ -526,6 +558,7 @@ impl RemoveCommand {
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -536,11 +569,13 @@ impl RemoveCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix = input
+ .borrow()
.get_option("apcu-autoloader-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
+ .borrow()
.get_option("apcu-autoloader")
.as_bool()
.unwrap_or(false)
@@ -551,6 +586,7 @@ impl RemoveCommand {
.as_bool()
.unwrap_or(false);
let minimal_changes = input
+ .borrow()
.get_option("minimal-changes")
.as_bool()
.unwrap_or(false)
@@ -565,10 +601,12 @@ impl RemoveCommand {
Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
let mut flags = String::new();
if input
+ .borrow()
.get_option("update-with-all-dependencies")
.as_bool()
.unwrap_or(false)
|| input
+ .borrow()
.get_option("with-all-dependencies")
.as_bool()
.unwrap_or(false)
@@ -576,6 +614,7 @@ impl RemoveCommand {
update_allow_transitive_dependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
flags += " --with-all-dependencies";
} else if input
+ .borrow()
.get_option("no-update-with-dependencies")
.as_bool()
.unwrap_or(false)
@@ -590,15 +629,28 @@ impl RemoveCommand {
flags
));
- install.set_verbose(input.get_option("verbose").as_bool().unwrap_or(false));
+ install.set_verbose(
+ input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false),
+ );
install.set_dev_mode(update_dev_mode);
install.set_optimize_autoloader(optimize);
install.set_class_map_authoritative(authoritative);
install.set_apcu_autoloader(apcu, apcu_prefix);
install.set_update(true);
- install.set_install(!input.get_option("no-install").as_bool().unwrap_or(false));
+ install.set_install(
+ !input
+ .borrow()
+ .get_option("no-install")
+ .as_bool()
+ .unwrap_or(false),
+ );
install.set_update_allow_transitive_dependencies(update_allow_transitive_dependencies);
- install.set_platform_requirement_filter(self.get_platform_requirement_filter(input)?);
+ install
+ .set_platform_requirement_filter(self.get_platform_requirement_filter(input.clone())?);
install.set_dry_run(dry_run);
install.set_audit_config(
self.create_audit_config(&mut *composer.get_config().borrow_mut(), input)?,
diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs
index d57a98d..5ced013 100644
--- a/crates/shirabe/src/command/repository_command.rs
+++ b/crates/shirabe/src/command/repository_command.rs
@@ -68,25 +68,29 @@ impl RepositoryCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
let action = strtolower(
&input
+ .borrow()
.get_argument("action")
.as_string()
.unwrap_or("")
.to_string(),
);
let name = input
+ .borrow()
.get_argument("name")
.as_string()
.map(|s| s.to_string());
let arg1 = input
+ .borrow()
.get_argument("arg1")
.as_string()
.map(|s| s.to_string());
let arg2 = input
+ .borrow()
.get_argument("arg2")
.as_string()
.map(|s| s.to_string());
@@ -143,10 +147,15 @@ impl RepositoryCommand {
};
let before = input
+ .borrow()
.get_option("before")
.as_string()
.map(|s| s.to_string());
- let after = input.get_option("after").as_string().map(|s| s.to_string());
+ let after = input
+ .borrow()
+ .get_option("after")
+ .as_string()
+ .map(|s| s.to_string());
if before.is_some() && after.is_some() {
return Err(anyhow::anyhow!(RuntimeException {
message: "You can not combine --before and --after".to_string(),
@@ -173,7 +182,11 @@ impl RepositoryCommand {
return Ok(0);
}
- let append = input.get_option("append").as_bool().unwrap_or(false);
+ let append = input
+ .borrow()
+ .get_option("append")
+ .as_bool()
+ .unwrap_or(false);
self.config_source.as_mut().unwrap().add_repository(
name.as_deref().unwrap(),
repo_config.clone(),
@@ -270,7 +283,11 @@ impl RepositoryCommand {
}
let name_str = name.as_deref().unwrap();
if ["packagist", "packagist.org"].contains(&name_str) {
- let append = input.get_option("append").as_bool().unwrap_or(false);
+ let append = input
+ .borrow()
+ .get_option("append")
+ .as_bool()
+ .unwrap_or(false);
self.config_source.as_mut().unwrap().add_repository(
"packagist.org",
PhpMixed::Bool(false),
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index e5ddbe7..d1143fe 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -87,7 +87,7 @@ impl PackageDiscoveryTrait for RequireCommand {
fn get_platform_requirement_filter(
&self,
- input: &dyn InputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
) -> std::rc::Rc<
dyn crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface,
> {
@@ -154,12 +154,17 @@ impl RequireCommand {
/// @throws \Seld\JsonLint\ParsingException
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
self.file = Factory::get_composer_file()?;
- if input.get_option("no-suggest").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-suggest")
+ .as_bool()
+ .unwrap_or(false)
+ {
self.get_io().write_error3("<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>", true, io_interface::NORMAL);
}
@@ -225,7 +230,7 @@ impl RequireCommand {
return Ok(1);
}
- if input.get_option("fixed").as_bool() == Some(true) {
+ if input.borrow().get_option("fixed").as_bool() == Some(true) {
let config = self.json.as_mut().unwrap().read()?;
let package_type = if empty(&config.get("type").cloned().unwrap_or(PhpMixed::Null)) {
@@ -239,7 +244,9 @@ impl RequireCommand {
};
/// @see https://github.com/composer/composer/pull/8313#issuecomment-532637955
- if package_type != "project" && !input.get_option("dev").as_bool().unwrap_or(false) {
+ if package_type != "project"
+ && !input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ {
self.get_io().write_error3("<error>The \"--fixed\" option is only allowed for packages with a \"project\" type or for dev dependencies to prevent possible misuses.</error>", true, io_interface::NORMAL);
if config.get("type").is_none() {
@@ -278,9 +285,10 @@ impl RequireCommand {
};
let requirements_result = self.determine_requirements(
- input,
- output,
+ input.clone(),
+ output.clone(),
input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -292,8 +300,16 @@ impl RequireCommand {
Some(&platform_repo),
&preferred_stability,
// if there is no update, we need to use the best possible version constraint directly as we cannot rely on the solver to guess the best constraint
- input.get_option("no-update").as_bool().unwrap_or(false),
- input.get_option("fixed").as_bool().unwrap_or(false),
+ input
+ .borrow()
+ .get_option("no-update")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("fixed")
+ .as_bool()
+ .unwrap_or(false),
);
let requirements = match requirements_result {
@@ -318,7 +334,7 @@ impl RequireCommand {
let mut requirements = self.format_requirements(requirements)?;
- if !input.get_option("dev").as_bool().unwrap_or(false)
+ if !input.borrow().get_option("dev").as_bool().unwrap_or(false)
&& self.get_io().is_interactive()
&& !composer.is_global()
{
@@ -398,12 +414,12 @@ impl RequireCommand {
// unset($devPackages, $pkgDevTags);
}
- let mut require_key = if input.get_option("dev").as_bool().unwrap_or(false) {
+ let mut require_key = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
};
- let mut remove_key = if input.get_option("dev").as_bool().unwrap_or(false) {
+ let mut remove_key = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"require"
} else {
"require-dev"
@@ -446,7 +462,7 @@ impl RequireCommand {
PhpMixed::String(package.clone()),
PhpMixed::String(remove_key.to_string()),
PhpMixed::String(
- if input.get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"with"
} else {
"without"
@@ -475,7 +491,7 @@ impl RequireCommand {
let q2 = sprintf(
"<info>Do you want to re-run the command %s --dev?</info> [<comment>yes</comment>]? ",
&[PhpMixed::String(
- if input.get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
"without"
} else {
"with"
@@ -497,7 +513,11 @@ impl RequireCommand {
}
}
- let sort_packages = input.get_option("sort-packages").as_bool().unwrap_or(false)
+ let sort_packages = input
+ .borrow()
+ .get_option("sort-packages")
+ .as_bool()
+ .unwrap_or(false)
|| composer
.get_config()
.borrow()
@@ -523,7 +543,12 @@ impl RequireCommand {
}
}
- if !input.get_option("dry-run").as_bool().unwrap_or(false) {
+ if !input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false)
+ {
// TODO(phase-b): update_file takes &mut self, but the json argument must be borrowed
// from self.json, producing an overlapping borrow of self. Commented out until JsonFile
// is shared (Rc<RefCell> / interior mutability) so it can be passed without holding a
@@ -550,7 +575,12 @@ impl RequireCommand {
self.get_io()
.write_error3(&updated_msg, true, io_interface::NORMAL);
- if input.get_option("no-update").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-update")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Ok(0);
}
@@ -560,9 +590,19 @@ impl RequireCommand {
.deactivate_installed_plugins()?;
let io = self.get_io().clone();
- let do_update_result =
- self.do_update(input, output, io, &requirements, require_key, remove_key);
- let dry_run = input.get_option("dry-run").as_bool().unwrap_or(false);
+ let do_update_result = self.do_update(
+ input.clone(),
+ output,
+ io,
+ &requirements,
+ require_key,
+ remove_key,
+ );
+ let dry_run = input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false);
let result = match do_update_result {
Ok(result) => {
@@ -573,7 +613,11 @@ impl RequireCommand {
remove_key,
sort_packages,
dry_run,
- input.get_option("fixed").as_bool().unwrap_or(false),
+ input
+ .borrow()
+ .get_option("fixed")
+ .as_bool()
+ .unwrap_or(false),
)?
} else {
result
@@ -678,8 +722,8 @@ impl RequireCommand {
/// @throws \Exception
fn do_update(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
requirements: &IndexMap<String, String>,
require_key: &str,
@@ -699,7 +743,12 @@ impl RequireCommand {
10000,
);
- if input.get_option("dry-run").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false)
+ {
let root_package = composer.get_package();
let mut links: IndexMap<String, IndexMap<String, crate::package::Link>> =
IndexMap::new();
@@ -746,8 +795,13 @@ impl RequireCommand {
// unset($stabilityFlags, $references);
}
- let update_dev_mode = !input.get_option("update-no-dev").as_bool().unwrap_or(false);
+ let update_dev_mode = !input
+ .borrow()
+ .get_option("update-no-dev")
+ .as_bool()
+ .unwrap_or(false);
let optimize = input
+ .borrow()
.get_option("optimize-autoloader")
.as_bool()
.unwrap_or(false)
@@ -758,6 +812,7 @@ impl RequireCommand {
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -768,11 +823,13 @@ impl RequireCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix = input
+ .borrow()
.get_option("apcu-autoloader-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
+ .borrow()
.get_option("apcu-autoloader")
.as_bool()
.unwrap_or(false)
@@ -783,6 +840,7 @@ impl RequireCommand {
.as_bool()
.unwrap_or(false);
let minimal_changes = input
+ .borrow()
.get_option("minimal-changes")
.as_bool()
.unwrap_or(false)
@@ -796,10 +854,12 @@ impl RequireCommand {
let mut update_allow_transitive_dependencies = Request::UPDATE_ONLY_LISTED;
let mut flags = String::new();
if input
+ .borrow()
.get_option("update-with-all-dependencies")
.as_bool()
.unwrap_or(false)
|| input
+ .borrow()
.get_option("with-all-dependencies")
.as_bool()
.unwrap_or(false)
@@ -807,10 +867,12 @@ impl RequireCommand {
update_allow_transitive_dependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
flags += " --with-all-dependencies";
} else if input
+ .borrow()
.get_option("update-with-dependencies")
.as_bool()
.unwrap_or(false)
|| input
+ .borrow()
.get_option("with-dependencies")
.as_bool()
.unwrap_or(false)
@@ -835,7 +897,8 @@ impl RequireCommand {
io_interface::NORMAL,
);
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "require", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "require", input.clone(), output);
composer
.get_event_dispatcher()
.borrow_mut()
@@ -844,16 +907,37 @@ impl RequireCommand {
composer
.get_installation_manager()
.borrow_mut()
- .set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
+ .set_output_progress(
+ !input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false),
+ );
let mut install = Installer::create(io.clone(), &composer_handle);
- let (prefer_source, prefer_dist) =
- self.get_preferred_install_options(&*composer.get_config().borrow(), input, false)?;
+ let (prefer_source, prefer_dist) = self.get_preferred_install_options(
+ &*composer.get_config().borrow(),
+ input.clone(),
+ false,
+ )?;
install
- .set_dry_run(input.get_option("dry-run").as_bool().unwrap_or(false))
- .set_verbose(input.get_option("verbose").as_bool().unwrap_or(false))
+ .set_dry_run(
+ input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_verbose(
+ input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_prefer_source(prefer_source)
.set_prefer_dist(prefer_dist)
.set_dev_mode(update_dev_mode)
@@ -861,15 +945,34 @@ impl RequireCommand {
.set_class_map_authoritative(authoritative)
.set_apcu_autoloader(apcu, apcu_prefix.clone())
.set_update(true)
- .set_install(!input.get_option("no-install").as_bool().unwrap_or(false))
+ .set_install(
+ !input
+ .borrow()
+ .get_option("no-install")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_update_allow_transitive_dependencies(update_allow_transitive_dependencies)?
.set_platform_requirement_filter(BaseCommand::get_platform_requirement_filter(
- self, input,
+ self,
+ input.clone(),
)?)
- .set_prefer_stable(input.get_option("prefer-stable").as_bool().unwrap_or(false))
- .set_prefer_lowest(input.get_option("prefer-lowest").as_bool().unwrap_or(false))
+ .set_prefer_stable(
+ input
+ .borrow()
+ .get_option("prefer-stable")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_prefer_lowest(
+ input
+ .borrow()
+ .get_option("prefer-lowest")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_audit_config(
- self.create_audit_config(&mut *composer.get_config().borrow_mut(), input)?,
+ self.create_audit_config(&mut *composer.get_config().borrow_mut(), input.clone())?,
)
.set_minimal_update(minimal_changes);
@@ -889,6 +992,7 @@ impl RequireCommand {
for req in BaseCommand::normalize_requirements(
self,
input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -1138,7 +1242,12 @@ impl RequireCommand {
true
}
- pub(crate) fn interact(&self, _input: &dyn InputInterface, _output: &dyn OutputInterface) {}
+ pub(crate) fn interact(
+ &self,
+ _input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
+ }
fn revert_composer_file(&mut self) {
if self.newly_created {
diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs
index 9118463..cf8b8f1 100644
--- a/crates/shirabe/src/command/run_script_command.rs
+++ b/crates/shirabe/src/command/run_script_command.rs
@@ -115,16 +115,16 @@ impl RunScriptCommand {
pub fn interact(
&mut self,
- input: &mut dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<()> {
let scripts = self.get_scripts()?;
if scripts.is_empty() {
return Ok(());
}
- if input.get_argument("script").as_string().is_some()
- || input.get_option("list").as_bool().unwrap_or(false)
+ if input.borrow().get_argument("script").as_string().is_some()
+ || input.borrow().get_option("list").as_bool().unwrap_or(false)
{
return Ok(());
}
@@ -145,7 +145,7 @@ impl RunScriptCommand {
);
if let Some(selected) = script.as_string() {
- // TODO(phase-b): input is &dyn InputInterface but set_argument needs &mut.
+ // TODO(phase-b): input is std::rc::Rc<std::cell::RefCell<dyn InputInterface>> but set_argument needs &mut.
let _ = selected;
}
@@ -154,14 +154,14 @@ impl RunScriptCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
- if input.get_option("list").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("list").as_bool().unwrap_or(false) {
return self.list_scripts(output);
}
- let script = match input.get_argument("script").as_string() {
+ let script = match input.borrow().get_argument("script").as_string() {
None => {
return Err(RuntimeException {
message: "Missing required argument \"script\"".to_string(),
@@ -187,8 +187,12 @@ impl RunScriptCommand {
let dispatcher = crate::command::composer_full(&composer)
.get_event_dispatcher()
.clone();
- let dev_mode = input.get_option("dev").as_bool().unwrap_or(false)
- || !input.get_option("no-dev").as_bool().unwrap_or(false);
+ let dev_mode = input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ || !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false);
// TODO(phase-b): ScriptEvent::new takes Composer/IOInterface by value; placeholder construction.
let _ = (script.clone(), &composer, dev_mode);
let has_listeners = false;
@@ -201,6 +205,7 @@ impl RunScriptCommand {
}
let args: Vec<String> = input
+ .borrow()
.get_argument("args")
.as_list()
.map(|l| {
@@ -210,7 +215,7 @@ impl RunScriptCommand {
})
.unwrap_or_default();
- if let Some(timeout_val) = input.get_option("timeout").as_string() {
+ if let Some(timeout_val) = input.borrow().get_option("timeout").as_string() {
let timeout_str = timeout_val.to_string();
if !timeout_str.chars().all(|c| c.is_ascii_digit()) {
return Err(RuntimeException {
@@ -232,7 +237,10 @@ impl RunScriptCommand {
.dispatch_script(&script, dev_mode, args, IndexMap::new())?)
}
- fn list_scripts(&mut self, output: &dyn OutputInterface) -> Result<i64> {
+ fn list_scripts(
+ &mut self,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) -> Result<i64> {
let scripts = self.get_scripts()?;
if scripts.is_empty() {
return Ok(0);
diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs
index 6499002..7c6e9fb 100644
--- a/crates/shirabe/src/command/script_alias_command.rs
+++ b/crates/shirabe/src/command/script_alias_command.rs
@@ -93,15 +93,15 @@ impl ScriptAliasCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let dispatcher = crate::command::composer_full(&composer)
.get_event_dispatcher()
.clone();
- let args = input.get_arguments();
+ let args = input.borrow().get_arguments();
// TODO(phase-b): InputInterface has_to_string/get_class_name not modeled in Rust
// TODO remove for Symfony 6+ as it is then in the interface
@@ -113,8 +113,12 @@ impl ScriptAliasCommand {
.into());
}
- let dev_mode = input.get_option("dev").as_bool().unwrap_or(false)
- || !input.get_option("no-dev").as_bool().unwrap_or(false);
+ let dev_mode = input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ || !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false);
Platform::put_env("COMPOSER_DEV_MODE", if dev_mode { "1" } else { "0" });
diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs
index 593b927..7149db7 100644
--- a/crates/shirabe/src/command/search_command.rs
+++ b/crates/shirabe/src/command/search_command.rs
@@ -45,13 +45,14 @@ impl SearchCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let platform_repo = PlatformRepository::new4(vec![], IndexMap::new(), None, None)?;
let io = self.get_io();
let format = input
+ .borrow()
.get_option("format")
.as_string()
.map(|s| s.to_string())
@@ -76,7 +77,7 @@ impl SearchCommand {
} else {
// TODO(phase-b): clone_box to release self borrow held by get_io.
let io_box = self.get_io().clone();
- self.create_composer_instance(input, io_box, None, false, None)?
+ self.create_composer_instance(input.clone(), io_box, None, false, None)?
};
let composer_ref = crate::command::composer_full(&composer);
let local_repo = composer_ref
@@ -99,7 +100,8 @@ impl SearchCommand {
let mut repos = CompositeRepository::new(all_repos);
// TODO(plugin): dispatch CommandEvent for search command
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "search", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "search", input.clone(), output);
let dispatcher = composer_ref.get_event_dispatcher().clone();
drop(composer_ref);
dispatcher
@@ -107,8 +109,18 @@ impl SearchCommand {
.dispatch(Some(command_event.get_name()), None);
let mut mode: i64 = repository_interface::SEARCH_FULLTEXT;
- if input.get_option("only-name").as_bool().unwrap_or(false) {
- if input.get_option("only-vendor").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("only-name")
+ .as_bool()
+ .unwrap_or(false)
+ {
+ if input
+ .borrow()
+ .get_option("only-vendor")
+ .as_bool()
+ .unwrap_or(false)
+ {
return Err(InvalidArgumentException {
message: "--only-name and --only-vendor cannot be used together".to_string(),
code: 0,
@@ -116,13 +128,22 @@ impl SearchCommand {
.into());
}
mode = repository_interface::SEARCH_NAME;
- } else if input.get_option("only-vendor").as_bool().unwrap_or(false) {
+ } else if input
+ .borrow()
+ .get_option("only-vendor")
+ .as_bool()
+ .unwrap_or(false)
+ {
mode = repository_interface::SEARCH_VENDOR;
}
- let r#type = input.get_option("type").as_string().map(|s| s.to_string());
+ let r#type = input
+ .borrow()
+ .get_option("type")
+ .as_string()
+ .map(|s| s.to_string());
- let tokens_arg = input.get_argument("tokens");
+ let tokens_arg = input.borrow().get_argument("tokens");
let token_strings: Vec<String> = tokens_arg
.as_array()
.map(|arr| {
diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs
index 1dc8d87..2353d13 100644
--- a/crates/shirabe/src/command/self_update_command.rs
+++ b/crates/shirabe/src/command/self_update_command.rs
@@ -75,8 +75,8 @@ impl SelfUpdateCommand {
/// @throws FilesystemException
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
// TODO(phase-b): __FILE__ / __DIR__ have no direct Rust equivalent
let file_path: &str = "";
@@ -85,27 +85,27 @@ impl SelfUpdateCommand {
if strpos(file_path, "phar:") != Some(0) {
if str_contains(&strtr(dir_path, "\\", "/"), "vendor/composer/composer") {
let proj_dir = shirabe_php_shim::dirname_levels(dir_path, 6);
- output.writeln(
+ output.borrow().writeln(
"<error>This instance of Composer does not have the self-update command.</error>",
io_interface::NORMAL,
);
- output.writeln(
+ output.borrow().writeln(
&format!(
"<comment>You are running Composer installed as a package in your current project (\"{}\").</comment>",
proj_dir
),
io_interface::NORMAL,
);
- output.writeln(
+ output.borrow().writeln(
"<comment>To update Composer, download a composer.phar from https://getcomposer.org and then run `composer.phar update composer/composer` in your project.</comment>",
io_interface::NORMAL,
);
} else {
- output.writeln(
+ output.borrow().writeln(
"<error>This instance of Composer does not have the self-update command.</error>",
io_interface::NORMAL,
);
- output.writeln(
+ output.borrow().writeln(
"<comment>This could be due to a number of reasons, such as Composer being installed as a system package on your OS, or Composer being installed as a package in the current project.</comment>",
io_interface::NORMAL,
);
@@ -141,7 +141,12 @@ impl SelfUpdateCommand {
// switch channel if requested
let mut requested_channel: Option<String> = None;
for channel in Versions::CHANNELS {
- if input.get_option(channel).as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option(channel)
+ .as_bool()
+ .unwrap_or(false)
+ {
requested_channel = Some(channel.to_string());
versions_util.set_channel(channel.to_string(), Some(io.clone()))??;
break;
@@ -149,6 +154,7 @@ impl SelfUpdateCommand {
}
if input
+ .borrow()
.get_option("set-channel-only")
.as_bool()
.unwrap_or(false)
@@ -183,7 +189,12 @@ impl SelfUpdateCommand {
.into());
}
- if input.get_option("update-keys").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("update-keys")
+ .as_bool()
+ .unwrap_or(false)
+ {
self.fetch_keys(io.clone(), &*config.borrow())?;
return Ok(0);
}
@@ -252,12 +263,17 @@ impl SelfUpdateCommand {
}
}
- if input.get_option("rollback").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("rollback")
+ .as_bool()
+ .unwrap_or(false)
+ {
return self.rollback(output, &rollback_dir, &local_filename);
}
- if input.get_argument("command").as_string() == Some("self")
- && input.get_argument("version").as_string() == Some("update")
+ if input.borrow().get_argument("command").as_string() == Some("self")
+ && input.borrow().get_argument("version").as_string() == Some("update")
{
// TODO(phase-b): set_argument requires &mut InputInterface; input is &dyn here
}
@@ -274,6 +290,7 @@ impl SelfUpdateCommand {
.unwrap_or("")
.to_string();
let mut update_version = input
+ .borrow()
.get_argument("version")
.as_string()
.map(|s| s.to_string())
@@ -289,7 +306,9 @@ impl SelfUpdateCommand {
.unwrap_or(""),
)?;
- if versions_util.get_channel()? == "stable" && input.get_argument("version").is_null() {
+ if versions_util.get_channel()? == "stable"
+ && input.borrow().get_argument("version").is_null()
+ {
// if requesting stable channel and no specific version, avoid automatically upgrading to the next major
// simply output a warning that the next major stable is available and let users upgrade to it manually
if version_compare(&current_major_version, &update_major_version, "<") {
@@ -394,7 +413,12 @@ impl SelfUpdateCommand {
);
// remove all backups except for the most recent, if any
- if input.get_option("clean-backups").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("clean-backups")
+ .as_bool()
+ .unwrap_or(false)
+ {
let last_backup = self.get_last_backup_version(&rollback_dir);
self.clean_backups(&rollback_dir, last_backup.as_deref());
}
@@ -616,7 +640,12 @@ RGv89BPD+2DLnJysngsvVaUCAwEAAQ==\n\
}
// remove saved installations of composer
- if input.get_option("clean-backups").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("clean-backups")
+ .as_bool()
+ .unwrap_or(false)
+ {
// TODO(phase-b): self.clean_backups conflicts with earlier `self.get_io()` borrow
}
@@ -807,7 +836,7 @@ RGv89BPD+2DLnJysngsvVaUCAwEAAQ==\n\
/// @throws FilesystemException
pub(crate) fn rollback(
&mut self,
- _output: &dyn OutputInterface,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
rollback_dir: &str,
local_filename: &str,
) -> Result<i64> {
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index 299ba1e..e14ab15 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -78,41 +78,49 @@ impl ShowCommand {
pub fn execute(
&mut self,
- input: &mut dyn InputInterface,
- output: &mut dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
self.version_parser = VersionParser::new();
- if input.get_option("tree").as_bool() == Some(true) {
- self.init_styles(output);
+ if input.borrow().get_option("tree").as_bool() == Some(true) {
+ self.init_styles(output.clone());
}
let mut composer = self.try_composer(None, None);
- if input.get_option("installed").as_bool() == Some(true)
- && input.get_option("self").as_bool() != Some(true)
+ if input.borrow().get_option("installed").as_bool() == Some(true)
+ && input.borrow().get_option("self").as_bool() != Some(true)
{
self.get_io().write_error("<warning>You are using the deprecated option \"installed\". Only installed packages are shown by default now. The --all option can be used to show all packages.</warning>");
}
- if input.get_option("outdated").as_bool() == Some(true) {
- input.set_option("latest", PhpMixed::Bool(true));
- } else if input.get_option("ignore").as_list().map_or(0, |l| l.len()) > 0 {
+ if input.borrow().get_option("outdated").as_bool() == Some(true) {
+ input
+ .borrow_mut()
+ .set_option("latest", PhpMixed::Bool(true));
+ } else if input
+ .borrow()
+ .get_option("ignore")
+ .as_list()
+ .map_or(0, |l| l.len())
+ > 0
+ {
self.get_io().write_error("<warning>You are using the option \"ignore\" for action other than \"outdated\", it will be ignored.</warning>");
}
- if input.get_option("direct").as_bool() == Some(true)
- && (input.get_option("all").as_bool() == Some(true)
- || input.get_option("available").as_bool() == Some(true)
- || input.get_option("platform").as_bool() == Some(true))
+ if input.borrow().get_option("direct").as_bool() == Some(true)
+ && (input.borrow().get_option("all").as_bool() == Some(true)
+ || input.borrow().get_option("available").as_bool() == Some(true)
+ || input.borrow().get_option("platform").as_bool() == Some(true))
{
self.get_io().write_error("The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)");
return Ok(1);
}
- if input.get_option("tree").as_bool() == Some(true)
- && (input.get_option("all").as_bool() == Some(true)
- || input.get_option("available").as_bool() == Some(true))
+ if input.borrow().get_option("tree").as_bool() == Some(true)
+ && (input.borrow().get_option("all").as_bool() == Some(true)
+ || input.borrow().get_option("available").as_bool() == Some(true))
{
self.get_io().write_error("The --tree (-t) option is not usable in combination with --all or --available (-a)");
@@ -120,9 +128,9 @@ impl ShowCommand {
}
let only_count: usize = [
- input.get_option("patch-only").as_bool() == Some(true),
- input.get_option("minor-only").as_bool() == Some(true),
- input.get_option("major-only").as_bool() == Some(true),
+ input.borrow().get_option("patch-only").as_bool() == Some(true),
+ input.borrow().get_option("minor-only").as_bool() == Some(true),
+ input.borrow().get_option("major-only").as_bool() == Some(true),
]
.iter()
.filter(|b| **b)
@@ -135,8 +143,8 @@ impl ShowCommand {
return Ok(1);
}
- if input.get_option("tree").as_bool() == Some(true)
- && input.get_option("latest").as_bool() == Some(true)
+ if input.borrow().get_option("tree").as_bool() == Some(true)
+ && input.borrow().get_option("latest").as_bool() == Some(true)
{
self.get_io().write_error(
"The --tree (-t) option is not usable in combination with --latest (-l)",
@@ -145,8 +153,8 @@ impl ShowCommand {
return Ok(1);
}
- if input.get_option("tree").as_bool() == Some(true)
- && input.get_option("path").as_bool() == Some(true)
+ if input.borrow().get_option("tree").as_bool() == Some(true)
+ && input.borrow().get_option("path").as_bool() == Some(true)
{
self.get_io().write_error(
"The --tree (-t) option is not usable in combination with --path (-P)",
@@ -156,6 +164,7 @@ impl ShowCommand {
}
let format = input
+ .borrow()
.get_option("format")
.as_string()
.unwrap_or("text")
@@ -176,7 +185,7 @@ impl ShowCommand {
return Ok(1);
}
- let platform_req_filter = self.get_platform_requirement_filter(input)?;
+ let platform_req_filter = self.get_platform_requirement_filter(input.clone())?;
// init repos
let mut platform_overrides: IndexMap<String, PhpMixed> = IndexMap::new();
@@ -207,20 +216,20 @@ impl ShowCommand {
let installed_repo: RepositoryInterfaceHandle;
let repos: RepositoryInterfaceHandle;
- if input.get_option("self").as_bool() == Some(true)
- && input.get_option("installed").as_bool() != Some(true)
- && input.get_option("locked").as_bool() != Some(true)
+ if input.borrow().get_option("self").as_bool() == Some(true)
+ && input.borrow().get_option("installed").as_bool() != Some(true)
+ && input.borrow().get_option("locked").as_bool() != Some(true)
{
let composer = self.require_composer(None, None)?;
let package = crate::package::RootPackageInterfaceHandle::dup(
composer.borrow_partial().get_package(),
);
- if input.get_option("name-only").as_bool() == Some(true) {
+ if input.borrow().get_option("name-only").as_bool() == Some(true) {
self.get_io().write(&package.get_name());
return Ok(0);
}
- if input.get_argument("package").as_string().is_some() {
+ if input.borrow().get_argument("package").as_string().is_some() {
return Err(InvalidArgumentException {
message: "You cannot use --self together with a package name".to_string(),
code: 0,
@@ -234,14 +243,14 @@ impl ShowCommand {
RepositoryInterfaceHandle::new(RootPackageRepository::new(package.clone())),
]));
single_package = Some(package.clone().into());
- } else if input.get_option("platform").as_bool() == Some(true) {
+ } else if input.borrow().get_option("platform").as_bool() == Some(true) {
installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
RepositoryInterfaceHandle::new(make_platform_repo()?),
]));
repos = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
RepositoryInterfaceHandle::new(make_platform_repo()?),
]));
- } else if input.get_option("available").as_bool() == Some(true) {
+ } else if input.borrow().get_option("available").as_bool() == Some(true) {
let mut ir = InstalledRepository::new(vec![RepositoryInterfaceHandle::new(
make_platform_repo()?,
)]);
@@ -276,7 +285,7 @@ impl ShowCommand {
));
installed_repo = RepositoryInterfaceHandle::new(ir);
}
- } else if input.get_option("all").as_bool() == Some(true) && composer.is_some() {
+ } else if input.borrow().get_option("all").as_bool() == Some(true) && composer.is_some() {
let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
let local_repo = composer_ref
.get_repository_manager()
@@ -316,7 +325,7 @@ impl ShowCommand {
composite_input.push(r.clone());
}
repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
- } else if input.get_option("all").as_bool() == Some(true) {
+ } else if input.borrow().get_option("all").as_bool() == Some(true) {
let default_repos =
RepositoryFactory::default_repos_with_default_manager(self.get_io())?;
let names: Vec<String> = default_repos.keys().cloned().collect();
@@ -332,7 +341,7 @@ impl ShowCommand {
composite_input.push(v);
}
repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
- } else if input.get_option("locked").as_bool() == Some(true) {
+ } else if input.borrow().get_option("locked").as_bool() == Some(true) {
if composer.is_none()
|| !crate::command::composer_full_mut(composer.as_ref().unwrap())
.get_locker()
@@ -348,10 +357,11 @@ impl ShowCommand {
let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
let locker_rc = composer_ref.get_locker().clone();
let mut locker = locker_rc.borrow_mut();
- let lr =
- locker.get_locked_repository(input.get_option("no-dev").as_bool() != Some(true))?;
+ let lr = locker.get_locked_repository(
+ input.borrow().get_option("no-dev").as_bool() != Some(true),
+ )?;
let lr_handle: RepositoryInterfaceHandle = lr.into();
- if input.get_option("self").as_bool() == Some(true) {
+ if input.borrow().get_option("self").as_bool() == Some(true) {
// TODO(phase-b): LockArrayRepository needs add_package via WritableRepositoryInterface;
// skipping the insertion here keeps compile clean.
let _ = &lr_handle;
@@ -382,16 +392,17 @@ impl ShowCommand {
};
let root_pkg = composer_local.get_package();
- let root_repo: RepositoryInterfaceHandle = if input.get_option("self").as_bool()
- == Some(true)
- {
- RepositoryInterfaceHandle::new(RootPackageRepository::new(
- crate::package::RootPackageInterfaceHandle::dup(composer_local.get_package()),
- ))
- } else {
- RepositoryInterfaceHandle::new(InstalledArrayRepository::new()?)
- };
- if input.get_option("no-dev").as_bool() == Some(true) {
+ let root_repo: RepositoryInterfaceHandle =
+ if input.borrow().get_option("self").as_bool() == Some(true) {
+ RepositoryInterfaceHandle::new(RootPackageRepository::new(
+ crate::package::RootPackageInterfaceHandle::dup(
+ composer_local.get_package(),
+ ),
+ ))
+ } else {
+ RepositoryInterfaceHandle::new(InstalledArrayRepository::new()?)
+ };
+ if input.borrow().get_option("no-dev").as_bool() == Some(true) {
let local_packages = composer_local
.get_repository_manager()
.borrow()
@@ -452,7 +463,7 @@ impl ShowCommand {
let command_event = CommandEvent::new6(
PluginEvents::COMMAND,
"show",
- input,
+ input.clone(),
output,
vec![],
IndexMap::new(),
@@ -466,14 +477,17 @@ impl ShowCommand {
.dispatch(Some(&_event_name), None)?;
}
- if input.get_option("latest").as_bool() == Some(true) && composer.is_none() {
+ if input.borrow().get_option("latest").as_bool() == Some(true) && composer.is_none() {
self.get_io().write_error(
"No composer.json found in the current directory, disabling \"latest\" option",
);
- input.set_option("latest", PhpMixed::Bool(false));
+ input
+ .borrow_mut()
+ .set_option("latest", PhpMixed::Bool(false));
}
let package_filter: Option<String> = input
+ .borrow()
.get_argument("package")
.as_string()
.map(|s| s.to_string());
@@ -487,11 +501,11 @@ impl ShowCommand {
&*installed_repo.borrow(),
&repos,
pf,
- input.get_argument("version"),
+ input.borrow().get_argument("version"),
)?;
if let Some(ref pkg) = matched_package {
- if input.get_option("direct").as_bool() == Some(true) {
+ if input.borrow().get_option("direct").as_bool() == Some(true) {
if !in_array(
PhpMixed::String(pkg.get_name()),
&PhpMixed::List(
@@ -515,9 +529,9 @@ impl ShowCommand {
}
if matched_package.is_none() {
- let options = input.get_options();
+ let options = input.borrow().get_options();
let mut hint = String::new();
- if input.get_option("locked").as_bool() == Some(true) {
+ if input.borrow().get_option("locked").as_bool() == Some(true) {
hint.push_str(" in lock file");
}
if options.contains_key("working-dir") {
@@ -530,12 +544,12 @@ impl ShowCommand {
));
}
if PlatformRepository::is_platform_package(pf)
- && input.get_option("platform").as_bool() != Some(true)
+ && input.borrow().get_option("platform").as_bool() != Some(true)
{
hint.push_str(", try using --platform (-p) to show platform packages");
}
- if input.get_option("all").as_bool() != Some(true)
- && input.get_option("available").as_bool() != Some(true)
+ if input.borrow().get_option("all").as_bool() != Some(true)
+ && input.borrow().get_option("available").as_bool() != Some(true)
{
hint.push_str(
", try using --available (-a) to show all available packages",
@@ -557,7 +571,7 @@ impl ShowCommand {
// assert(isset($versions));
let mut exit_code: i64 = 0;
- if input.get_option("tree").as_bool() == Some(true) {
+ if input.borrow().get_option("tree").as_bool() == Some(true) {
let array_tree = self.generate_package_tree(
package.clone().into(),
&*installed_repo.borrow(),
@@ -586,19 +600,31 @@ impl ShowCommand {
}
let mut latest_package: Option<crate::package::PackageInterfaceHandle> = None;
- if input.get_option("latest").as_bool() == Some(true) {
+ if input.borrow().get_option("latest").as_bool() == Some(true) {
latest_package = self.find_latest_package(
package.clone().into(),
composer.as_ref().unwrap(),
&mut platform_repo,
- input.get_option("major-only").as_bool().unwrap_or(false),
- input.get_option("minor-only").as_bool().unwrap_or(false),
- input.get_option("patch-only").as_bool().unwrap_or(false),
+ input
+ .borrow()
+ .get_option("major-only")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("minor-only")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
+ .get_option("patch-only")
+ .as_bool()
+ .unwrap_or(false),
&*platform_req_filter,
)?;
}
- if input.get_option("outdated").as_bool() == Some(true)
- && input.get_option("strict").as_bool() == Some(true)
+ if input.borrow().get_option("outdated").as_bool() == Some(true)
+ && input.borrow().get_option("strict").as_bool() == Some(true)
&& latest_package.is_some()
&& latest_package
.as_ref()
@@ -614,7 +640,7 @@ impl ShowCommand {
{
exit_code = 1;
}
- if input.get_option("path").as_bool() == Some(true) {
+ if input.borrow().get_option("path").as_bool() == Some(true) {
self.get_io().write_no_newline(&package.get_name());
let path = {
let composer_ref = composer.as_ref().unwrap();
@@ -654,7 +680,7 @@ impl ShowCommand {
}
// show tree view if requested
- if input.get_option("tree").as_bool() == Some(true) {
+ if input.borrow().get_option("tree").as_bool() == Some(true) {
let root_requires = self.get_root_requires();
let mut packages = installed_repo.get_packages()?;
packages.sort_by(|a, b| {
@@ -716,15 +742,15 @@ impl ShowCommand {
}
let mut package_list_filter: Option<Vec<String>> = None;
- if input.get_option("direct").as_bool() == Some(true) {
+ if input.borrow().get_option("direct").as_bool() == Some(true) {
package_list_filter = Some(self.get_root_requires());
}
- if input.get_option("path").as_bool() == Some(true) && composer.is_none() {
+ if input.borrow().get_option("path").as_bool() == Some(true) && composer.is_none() {
self.get_io().write_error(
"No composer.json found in the current directory, disabling \"path\" option",
);
- input.set_option("path", PhpMixed::Bool(false));
+ input.borrow_mut().set_option("path", PhpMixed::Bool(false));
}
for repo in RepositoryUtils::flatten_repositories(repos.clone(), false) {
@@ -799,13 +825,14 @@ impl ShowCommand {
}
}
- let show_all_types = input.get_option("all").as_bool() == Some(true);
- let show_latest = input.get_option("latest").as_bool() == Some(true);
- let show_major_only = input.get_option("major-only").as_bool() == Some(true);
- let show_minor_only = input.get_option("minor-only").as_bool() == Some(true);
- let show_patch_only = input.get_option("patch-only").as_bool() == Some(true);
+ let show_all_types = input.borrow().get_option("all").as_bool() == Some(true);
+ let show_latest = input.borrow().get_option("latest").as_bool() == Some(true);
+ let show_major_only = input.borrow().get_option("major-only").as_bool() == Some(true);
+ let show_minor_only = input.borrow().get_option("minor-only").as_bool() == Some(true);
+ let show_patch_only = input.borrow().get_option("patch-only").as_bool() == Some(true);
let ignored_packages_regex = base_package::package_names_to_regexp(
&input
+ .borrow()
.get_option("ignore")
.as_list()
.map(|l| {
@@ -865,21 +892,21 @@ impl ShowCommand {
}
}
- let write_path = input.get_option("name-only").as_bool() != Some(true)
- && input.get_option("path").as_bool() == Some(true);
- write_version = input.get_option("name-only").as_bool() != Some(true)
- && input.get_option("path").as_bool() != Some(true)
+ let write_path = input.borrow().get_option("name-only").as_bool() != Some(true)
+ && input.borrow().get_option("path").as_bool() == Some(true);
+ write_version = input.borrow().get_option("name-only").as_bool() != Some(true)
+ && input.borrow().get_option("path").as_bool() != Some(true)
&& *show_version;
let write_latest = write_version && show_latest;
- write_description = input.get_option("name-only").as_bool() != Some(true)
- && input.get_option("path").as_bool() != Some(true);
+ write_description = input.borrow().get_option("name-only").as_bool() != Some(true)
+ && input.borrow().get_option("path").as_bool() != Some(true);
let write_release_date = write_latest
- && (input.get_option("sort-by-age").as_bool() == Some(true)
+ && (input.borrow().get_option("sort-by-age").as_bool() == Some(true)
|| format == "json");
let mut has_outdated_packages = false;
- if input.get_option("sort-by-age").as_bool() == Some(true) {
+ if input.borrow().get_option("sort-by-age").as_bool() == Some(true) {
type_packages.sort_by(|_ka, a, _kb, b| match (a, b) {
(PackageOrName::Pkg(a), PackageOrName::Pkg(b)) => {
a.get_release_date().cmp(&b.get_release_date())
@@ -917,14 +944,14 @@ impl ShowCommand {
package_is_up_to_date || (latest_package.is_none() && show_major_only);
let package_is_ignored =
Preg::is_match(&ignored_packages_regex, &package.get_pretty_name())?;
- if input.get_option("outdated").as_bool() == Some(true)
+ if input.borrow().get_option("outdated").as_bool() == Some(true)
&& (package_is_up_to_date || package_is_ignored)
{
continue;
}
- if input.get_option("outdated").as_bool() == Some(true)
- || input.get_option("strict").as_bool() == Some(true)
+ if input.borrow().get_option("outdated").as_bool() == Some(true)
+ || input.borrow().get_option("strict").as_bool() == Some(true)
{
has_outdated_packages = true;
}
@@ -946,7 +973,8 @@ impl ShowCommand {
true,
)),
);
- if format != "json" || input.get_option("name-only").as_bool() != Some(true)
+ if format != "json"
+ || input.borrow().get_option("name-only").as_bool() != Some(true)
{
package_view_data.insert(
"homepage".to_string(),
@@ -1122,7 +1150,9 @@ impl ShowCommand {
write_release_date,
},
);
- if input.get_option("strict").as_bool() == Some(true) && has_outdated_packages {
+ if input.borrow().get_option("strict").as_bool() == Some(true)
+ && has_outdated_packages
+ {
exit_code = 1;
break;
}
@@ -1155,7 +1185,7 @@ impl ShowCommand {
.collect(),
)));
} else {
- if input.get_option("latest").as_bool() == Some(true)
+ if input.borrow().get_option("latest").as_bool() == Some(true)
&& view_data.values().any(|v| !v.is_empty())
{
let io = self.get_io();
@@ -1163,7 +1193,7 @@ impl ShowCommand {
io.write_error("Legend:");
io.write_error("! patch or minor release available - update recommended");
io.write_error("~ major release available - update possible");
- if input.get_option("outdated").as_bool() != Some(true) {
+ if input.borrow().get_option("outdated").as_bool() != Some(true) {
io.write_error("= up to date version");
}
} else {
@@ -1172,7 +1202,7 @@ impl ShowCommand {
io.write_error(
"- <comment>major</comment> release available - update possible",
);
- if input.get_option("outdated").as_bool() != Some(true) {
+ if input.borrow().get_option("outdated").as_bool() != Some(true) {
io.write_error("- <info>up to date</info> version");
}
}
@@ -1215,7 +1245,7 @@ impl ShowCommand {
}
}
- if write_latest && input.get_option("direct").as_bool() != Some(true) {
+ if write_latest && input.borrow().get_option("direct").as_bool() != Some(true) {
let mut direct_deps: Vec<IndexMap<String, PhpMixed>> = Vec::new();
let mut transitive_deps: Vec<IndexMap<String, PhpMixed>> = Vec::new();
for pkg in packages.iter() {
@@ -2186,7 +2216,10 @@ impl ShowCommand {
}
/// Init styles for tree
- pub(crate) fn init_styles(&mut self, output: &mut dyn OutputInterface) {
+ pub(crate) fn init_styles(
+ &mut self,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
self.colors = vec![
"green".to_string(),
"yellow".to_string(),
@@ -2200,7 +2233,7 @@ impl ShowCommand {
// TODO(phase-b): OutputInterface::get_formatter returns &OutputFormatter, but
// set_style requires &mut. Resolution requires interior-mutability refactor of
// OutputFormatter wiring across symfony shim.
- let _ = (output.get_formatter(), color);
+ let _ = (output.borrow().get_formatter(), color);
}
}
diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs
index f651e59..0c9abc9 100644
--- a/crates/shirabe/src/command/status_command.rs
+++ b/crates/shirabe/src/command/status_command.rs
@@ -41,15 +41,16 @@ impl StatusCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer_rc = self.require_composer(None, None)?;
{
let composer = crate::command::composer_full(&composer_rc);
// TODO(plugin): dispatch CommandEvent
- let command_event = CommandEvent::new(PluginEvents::COMMAND, "status", input, output);
+ let command_event =
+ CommandEvent::new(PluginEvents::COMMAND, "status", input.clone(), output);
composer
.get_event_dispatcher()
.borrow_mut()
@@ -84,7 +85,10 @@ impl StatusCommand {
Ok(exit_code)
}
- fn do_execute(&mut self, input: &dyn InputInterface) -> Result<i64> {
+ fn do_execute(
+ &mut self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ ) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
let io = self.get_io().clone();
@@ -212,7 +216,12 @@ impl StatusCommand {
io.write_error("<error>You have changes in the following dependencies:</error>");
for (path, changes) in &errors {
- if input.get_option("verbose").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false)
+ {
let indented_changes = changes
.lines()
.map(|line| format!(" {}", line.trim_start()))
@@ -230,7 +239,12 @@ impl StatusCommand {
io.write_error("<warning>You have unpushed changes on the current branch in the following dependencies:</warning>");
for (path, changes) in &unpushed_changes {
- if input.get_option("verbose").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false)
+ {
let indented_changes = changes
.lines()
.map(|line| format!(" {}", line.trim_start()))
@@ -250,7 +264,12 @@ impl StatusCommand {
);
for (path, changes) in &vcs_version_changes {
- if input.get_option("verbose").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false)
+ {
let current_version = {
let v = changes["current"]
.get("version")
@@ -311,7 +330,11 @@ impl StatusCommand {
}
if (!errors.is_empty() || !unpushed_changes.is_empty() || !vcs_version_changes.is_empty())
- && !input.get_option("verbose").as_bool().unwrap_or(false)
+ && !input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false)
{
io.write_error("Use --verbose (-v) to see a list of files");
}
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index 92a4288..d050ec7 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -42,8 +42,8 @@ impl SuggestsCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ _output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
@@ -65,10 +65,13 @@ impl SuggestsCommand {
vec![],
platform_overrides,
)?));
- let locked_repo = composer
- .get_locker()
- .borrow_mut()
- .get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?;
+ let locked_repo = composer.get_locker().borrow_mut().get_locked_repository(
+ !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false),
+ )?;
installed_repos.push(locked_repo.into());
} else {
// TODO(phase-b): Config::get returns PhpMixed; need to coerce to IndexMap<String, PhpMixed>
@@ -90,7 +93,7 @@ impl SuggestsCommand {
let mut installed_repo = InstalledRepository::new(installed_repos);
let mut reporter = SuggestedPackagesReporter::new(self.get_io().clone());
- let filter = input.get_argument("packages");
+ let filter = input.borrow().get_argument("packages");
let mut packages = RepositoryInterface::get_packages(&mut installed_repo)?;
let root_pkg_as_base: crate::package::BasePackageHandle =
composer.get_package().clone().into();
@@ -104,18 +107,28 @@ impl SuggestsCommand {
let mut mode = SuggestedPackagesReporter::MODE_BY_PACKAGE;
- if input.get_option("by-suggestion").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("by-suggestion")
+ .as_bool()
+ .unwrap_or(false)
+ {
mode = SuggestedPackagesReporter::MODE_BY_SUGGESTION;
}
- if input.get_option("by-package").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("by-package")
+ .as_bool()
+ .unwrap_or(false)
+ {
mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE;
}
- if input.get_option("list").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("list").as_bool().unwrap_or(false) {
mode = SuggestedPackagesReporter::MODE_LIST;
}
let only_dependents_of: Option<crate::package::PackageInterfaceHandle> =
- if empty(&filter) && !input.get_option("all").as_bool().unwrap_or(false) {
+ if empty(&filter) && !input.borrow().get_option("all").as_bool().unwrap_or(false) {
Some(composer.get_package().clone().into())
} else {
None
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index e28d407..7731e4f 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -73,18 +73,23 @@ impl UpdateCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let io = self.get_io().clone();
- if input.get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
io.write_error3(
"<warning>You are using the deprecated option \"--dev\". It has no effect and will break in Composer 3.</warning>",
true,
io_interface::NORMAL,
);
}
- if input.get_option("no-suggest").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-suggest")
+ .as_bool()
+ .unwrap_or(false)
+ {
io.write_error3(
"<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>",
true,
@@ -104,6 +109,7 @@ impl UpdateCommand {
}
let mut packages: Vec<String> = input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -114,6 +120,7 @@ impl UpdateCommand {
.unwrap_or_default();
let mut reqs: IndexMap<String, String> = self.format_requirements(
input
+ .borrow()
.get_option("with")
.as_list()
.map(|l| {
@@ -200,7 +207,12 @@ impl UpdateCommand {
}
}
- if input.get_option("patch-only").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("patch-only")
+ .as_bool()
+ .unwrap_or(false)
+ {
if !composer.get_locker().borrow_mut().is_locked() {
return Err(InvalidArgumentException {
message: "patch-only can only be used with a lock file present".to_string(),
@@ -245,7 +257,12 @@ impl UpdateCommand {
}
}
- if input.get_option("interactive").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("interactive")
+ .as_bool()
+ .unwrap_or(false)
+ {
packages = self.get_packages_interactively(
io.clone(),
input,
@@ -255,9 +272,19 @@ impl UpdateCommand {
)?;
}
- if input.get_option("root-reqs").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("root-reqs")
+ .as_bool()
+ .unwrap_or(false)
+ {
let mut requires: Vec<String> = array_keys(&root_package.get_requires());
- if !input.get_option("no-dev").as_bool().unwrap_or(false) {
+ if !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false)
+ {
requires = array_merge(
// TODO(phase-b): array_merge for Vec<String>
todo!("requires as PhpMixed"),
@@ -292,7 +319,7 @@ impl UpdateCommand {
true,
)
});
- let update_mirrors = input.get_option("lock").as_bool().unwrap_or(false)
+ let update_mirrors = input.borrow().get_option("lock").as_bool().unwrap_or(false)
|| filtered_packages.len() != packages.len();
packages = filtered_packages;
@@ -313,7 +340,13 @@ impl UpdateCommand {
composer
.get_installation_manager()
.borrow_mut()
- .set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
+ .set_output_progress(
+ !input
+ .borrow()
+ .get_option("no-progress")
+ .as_bool()
+ .unwrap_or(false),
+ );
let mut install = Installer::create(io.clone(), &composer_handle);
@@ -322,6 +355,7 @@ impl UpdateCommand {
self.get_preferred_install_options(&*config.borrow(), input, false)?;
let optimize = input
+ .borrow()
.get_option("optimize-autoloader")
.as_bool()
.unwrap_or(false)
@@ -331,6 +365,7 @@ impl UpdateCommand {
.as_bool()
.unwrap_or(false);
let authoritative = input
+ .borrow()
.get_option("classmap-authoritative")
.as_bool()
.unwrap_or(false)
@@ -340,11 +375,13 @@ impl UpdateCommand {
.as_bool()
.unwrap_or(false);
let apcu_prefix: Option<String> = input
+ .borrow()
.get_option("apcu-autoloader-prefix")
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
+ .borrow()
.get_option("apcu-autoloader")
.as_bool()
.unwrap_or(false)
@@ -354,6 +391,7 @@ impl UpdateCommand {
.as_bool()
.unwrap_or(false);
let minimal_changes = input
+ .borrow()
.get_option("minimal-changes")
.as_bool()
.unwrap_or(false)
@@ -365,12 +403,14 @@ impl UpdateCommand {
let mut update_allow_transitive_dependencies: i64 = Request::UPDATE_ONLY_LISTED;
if input
+ .borrow()
.get_option("with-all-dependencies")
.as_bool()
.unwrap_or(false)
{
update_allow_transitive_dependencies = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
} else if input
+ .borrow()
.get_option("with-dependencies")
.as_bool()
.unwrap_or(false)
@@ -382,23 +422,65 @@ impl UpdateCommand {
let _ = UpdateAllowTransitiveDeps::UpdateOnlyListed;
install
- .set_dry_run(input.get_option("dry-run").as_bool().unwrap_or(false))
- .set_verbose(input.get_option("verbose").as_bool().unwrap_or(false))
+ .set_dry_run(
+ input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_verbose(
+ input
+ .borrow()
+ .get_option("verbose")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_prefer_source(prefer_source)
.set_prefer_dist(prefer_dist)
- .set_dev_mode(!input.get_option("no-dev").as_bool().unwrap_or(false))
- .set_dump_autoloader(!input.get_option("no-autoloader").as_bool().unwrap_or(false))
+ .set_dev_mode(
+ !input
+ .borrow()
+ .get_option("no-dev")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_dump_autoloader(
+ !input
+ .borrow()
+ .get_option("no-autoloader")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_optimize_autoloader(optimize)
.set_class_map_authoritative(authoritative)
.set_apcu_autoloader(apcu, apcu_prefix.clone())
.set_update(true)
- .set_install(!input.get_option("no-install").as_bool().unwrap_or(false))
+ .set_install(
+ !input
+ .borrow()
+ .get_option("no-install")
+ .as_bool()
+ .unwrap_or(false),
+ )
.set_update_mirrors(update_mirrors)
.set_update_allow_list(packages.clone())
.set_update_allow_transitive_dependencies(update_allow_transitive_dependencies)?
.set_platform_requirement_filter(self.get_platform_requirement_filter(input)?)
- .set_prefer_stable(input.get_option("prefer-stable").as_bool().unwrap_or(false))
- .set_prefer_lowest(input.get_option("prefer-lowest").as_bool().unwrap_or(false))
+ .set_prefer_stable(
+ input
+ .borrow()
+ .get_option("prefer-stable")
+ .as_bool()
+ .unwrap_or(false),
+ )
+ .set_prefer_lowest(
+ input
+ .borrow()
+ .get_option("prefer-lowest")
+ .as_bool()
+ .unwrap_or(false),
+ )
// TODO(phase-b): VersionParser::parse_constraints returns Arc<dyn ...> but
// Installer::set_temporary_constraints expects IndexMap<String, Box<dyn ...>>;
// bridge the constraint storage types later.
@@ -411,14 +493,19 @@ impl UpdateCommand {
)
.set_minimal_update(minimal_changes);
- if input.get_option("no-plugins").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("no-plugins")
+ .as_bool()
+ .unwrap_or(false)
+ {
install.disable_plugins();
}
let mut result = install.run()?;
- if result == 0 && !input.get_option("lock").as_bool().unwrap_or(false) {
- let mut bump_after_update = input.get_option("bump-after-update");
+ if result == 0 && !input.borrow().get_option("lock").as_bool().unwrap_or(false) {
+ let mut bump_after_update = input.borrow().get_option("bump-after-update");
// PHP: false === $bumpAfterUpdate (strict)
if matches!(bump_after_update, PhpMixed::Bool(false)) {
bump_after_update = composer.get_config().borrow().get("bump-after-update");
@@ -438,8 +525,13 @@ impl UpdateCommand {
io.clone(),
bump_after_update.as_string() == Some("dev"),
bump_after_update.as_string() == Some("no-dev"),
- input.get_option("dry-run").as_bool().unwrap_or(false),
input
+ .borrow()
+ .get_option("dry-run")
+ .as_bool()
+ .unwrap_or(false),
+ input
+ .borrow()
.get_argument("packages")
.as_list()
.map(|l| {
@@ -461,12 +553,12 @@ impl UpdateCommand {
fn get_packages_interactively(
&self,
io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
composer: &PartialComposerHandle,
packages: Vec<String>,
) -> Result<Vec<String>> {
- if !input.is_interactive() {
+ if !input.borrow().is_interactive() {
return Err(InvalidArgumentException {
message: "--interactive cannot be used in non-interactive terminals.".to_string(),
code: 0,
diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs
index b168b03..eaae2db 100644
--- a/crates/shirabe/src/command/validate_command.rs
+++ b/crates/shirabe/src/command/validate_command.rs
@@ -110,10 +110,11 @@ impl ValidateCommand {
pub fn execute(
&mut self,
- input: &dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let file = input
+ .borrow()
.get_argument("file")
.as_string()
.map(|s| s.to_string())
@@ -131,17 +132,28 @@ impl ValidateCommand {
}
let validator = ConfigValidator::new(io.clone());
- let check_all = if input.get_option("no-check-all").as_bool().unwrap_or(false) {
+ let check_all = if input
+ .borrow()
+ .get_option("no-check-all")
+ .as_bool()
+ .unwrap_or(false)
+ {
0
} else {
ValidatingArrayLoader::CHECK_ALL
};
let check_publish = !input
+ .borrow()
.get_option("no-check-publish")
.as_bool()
.unwrap_or(false);
- let check_lock = !input.get_option("no-check-lock").as_bool().unwrap_or(false);
+ let check_lock = !input
+ .borrow()
+ .get_option("no-check-lock")
+ .as_bool()
+ .unwrap_or(false);
let check_version = if input
+ .borrow()
.get_option("no-check-version")
.as_bool()
.unwrap_or(false)
@@ -150,12 +162,17 @@ impl ValidateCommand {
} else {
ConfigValidator::CHECK_VERSION
};
- let is_strict = input.get_option("strict").as_bool().unwrap_or(false);
+ let is_strict = input
+ .borrow()
+ .get_option("strict")
+ .as_bool()
+ .unwrap_or(false);
let (mut errors, mut publish_errors, mut warnings) =
validator.validate(&file, check_all, check_version);
let mut lock_errors: Vec<String> = vec![];
- let composer = self.create_composer_instance(input, io.clone(), None, false, None)?;
+ let composer =
+ self.create_composer_instance(input.clone(), io.clone(), None, false, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
let check_lock = (check_lock
&& composer
@@ -164,7 +181,11 @@ impl ValidateCommand {
.get("lock")
.as_bool()
.unwrap_or(true))
- || input.get_option("check-lock").as_bool().unwrap_or(false);
+ || input
+ .borrow()
+ .get_option("check-lock")
+ .as_bool()
+ .unwrap_or(false);
// TODO(phase-b): get_missing_requirement_info needs &package from composer while
// locker holds &mut composer; cloning lock state isn't trivial. Use todo!() for the
// package-arg subexpression below.
@@ -202,6 +223,7 @@ impl ValidateCommand {
let mut exit_code = exit_code;
if input
+ .borrow()
.get_option("with-dependencies")
.as_bool()
.unwrap_or(false)
diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs
index 8bd34ad..124cc9b 100644
--- a/crates/shirabe/src/console/application.rs
+++ b/crates/shirabe/src/console/application.rs
@@ -165,10 +165,10 @@ impl Application {
pub fn run(
&mut self,
- input: Option<&mut dyn InputInterface>,
- output: Option<&mut dyn OutputInterface>,
+ input: Option<std::rc::Rc<std::cell::RefCell<dyn InputInterface>>>,
+ output: Option<std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>>,
) -> anyhow::Result<i64> {
- // TODO(phase-b): Factory::create_output returns ConsoleOutput, not Box<dyn OutputInterface>.
+ // TODO(phase-b): Factory::create_output returns ConsoleOutput, not std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>.
// The PHP code falls back to a default output when none is supplied; for now we
// forward the caller-provided output as-is.
self.inner.run(input, output)
@@ -176,11 +176,15 @@ impl Application {
pub fn do_run(
&mut self,
- input: &mut dyn InputInterface,
- output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
- self.disable_plugins_by_default = input.has_parameter_option(&["--no-plugins"], false);
- self.disable_scripts_by_default = input.has_parameter_option(&["--no-scripts"], false);
+ self.disable_plugins_by_default = input
+ .borrow()
+ .has_parameter_option(&["--no-plugins"], false);
+ self.disable_scripts_by_default = input
+ .borrow()
+ .has_parameter_option(&["--no-scripts"], false);
// PHP: static $stdin = null;
// We use an Option here to mimic the lazy initialization.
@@ -196,7 +200,7 @@ impl Application {
|| matches!(stdin, PhpMixed::Null)
|| !Platform::is_tty(Some(stdin)))
{
- input.set_interactive(false);
+ input.borrow_mut().set_interactive(false);
}
let mut helpers: Vec<PhpMixed> = vec![];
@@ -217,7 +221,7 @@ impl Application {
// not a borrow; passing None until the IO sharing story is settled.
ErrorHandler::register(None);
- if input.has_parameter_option(&["--no-cache"], false) {
+ if input.borrow().has_parameter_option(&["--no-cache"], false) {
self.io
.write_error3("Disabling cache usage", true, io_interface::DEBUG);
Platform::put_env(
@@ -231,7 +235,7 @@ impl Application {
}
// switch working dir
- let new_work_dir = self.get_new_working_dir(input)?;
+ let new_work_dir = self.get_new_working_dir(input.clone())?;
let mut old_working_dir: Option<String> = None;
if let Some(ref nwd) = new_work_dir {
old_working_dir = Some(Platform::get_cwd(true).unwrap_or_default());
@@ -254,7 +258,7 @@ impl Application {
// determine command name to be executed without including plugin commands
let mut command_name: Option<String> = Some(String::new());
- let raw_command_name = self.get_command_name_before_binding(input);
+ let raw_command_name = self.get_command_name_before_binding(input.clone());
if let Some(ref raw) = raw_command_name {
match self.inner.find(raw) {
Ok(cmd) => {
@@ -302,10 +306,10 @@ impl Application {
&& !file_exists(&Factory::get_composer_file().unwrap_or_default())
&& use_parent_dir_if_no_json_available.as_bool() != Some(false)
&& (command_name.as_deref() != Some("config")
- || (input.has_parameter_option(&["--file"], true) == false
- && input.has_parameter_option(&["-f"], true) == false))
- && input.has_parameter_option(&["--help"], true) == false
- && input.has_parameter_option(&["-h"], true) == false
+ || (input.borrow().has_parameter_option(&["--file"], true) == false
+ && input.borrow().has_parameter_option(&["-f"], true) == false))
+ && input.borrow().has_parameter_option(&["--help"], true) == false
+ && input.borrow().has_parameter_option(&["-h"], true) == false
{
let mut dir = dirname(&Platform::get_cwd(true).unwrap_or_default());
let home_value = Platform::get_env("HOME")
@@ -386,7 +390,9 @@ impl Application {
Box::new(PhpMixed::String("list".to_string())),
Box::new(PhpMixed::String("help".to_string())),
]);
- let may_need_plugin_command = !input.has_parameter_option(&["--version", "-V"], false)
+ let may_need_plugin_command = !input
+ .borrow()
+ .has_parameter_option(&["--version", "-V"], false)
&& (command_name.is_none()
|| in_array(
command_name.as_deref().unwrap_or("").into(),
@@ -478,7 +484,7 @@ impl Application {
// determine command name to be executed incl plugin commands, and check if it's a proxy command
let is_proxy_command = false;
- if let Some(ref name) = self.get_command_name_before_binding(input) {
+ if let Some(ref name) = self.get_command_name_before_binding(input.clone()) {
if let Ok(command) = self.inner.find(name) {
// TODO(phase-b): BaseApplication::find returns PhpMixed; we cannot yet
// extract a typed command name or detect proxy commands without the
@@ -714,7 +720,7 @@ impl Application {
let mut start_time: Option<f64> = None;
let result_outcome: anyhow::Result<i64> = (|| -> anyhow::Result<i64> {
- if input.has_parameter_option(&["--profile"], false) {
+ if input.borrow().has_parameter_option(&["--profile"], false) {
start_time = Some(microtime(true));
// TODO(phase-b): enable_debugging is defined only on ConsoleIO, not
// through IOInterface. Skip until the IO concrete type is known here.
@@ -724,7 +730,10 @@ impl Application {
// TODO(phase-b): BaseApplication exposes only `run`, not `do_run`.
let result: i64 = todo!("BaseApplication::do_run");
- if input.has_parameter_option(&["--version", "-V"], true) {
+ if input
+ .borrow()
+ .has_parameter_option(&["--version", "-V"], true)
+ {
self.io.write_error(&sprintf(
"<info>PHP</info> version <comment>%s</comment> (%s)",
&[PHP_VERSION.into(), PHP_BINARY.into()],
@@ -780,20 +789,6 @@ impl Application {
self.hint_common_errors(&e, output);
- // TODO(phase-b): method_exists/as_any on the inner application and
- // output trait objects are not yet supported; replicate the catch-all
- // branch unconditionally.
- if false {
- let _ = <dyn ConsoleOutputInterface>::is_console_output_interface;
- // self.inner.render_throwable expects &mut dyn OutputInterface.
- // Skipped while output is &dyn OutputInterface here.
- let code = e
- .downcast_ref::<RuntimeException>()
- .map(|r| r.code)
- .unwrap_or(0);
- return Ok(max_i64(1, code));
- }
-
// override TransportException's code for the purpose of parent::run() using it as process exit code
// as http error codes are all beyond the 255 range of permitted exit codes
if e.downcast_ref::<TransportException>().is_some() {
@@ -814,8 +809,12 @@ impl Application {
outcome
}
- fn get_new_working_dir(&self, input: &dyn InputInterface) -> anyhow::Result<Option<String>> {
+ fn get_new_working_dir(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ ) -> anyhow::Result<Option<String>> {
let working_dir = input
+ .borrow()
.get_parameter_option(&["--working-dir", "-d"], PhpMixed::Null, true)
.as_string()
.map(|s| s.to_string());
@@ -835,10 +834,18 @@ impl Application {
Ok(working_dir)
}
- fn hint_common_errors(&mut self, exception: &anyhow::Error, output: &dyn OutputInterface) {
+ fn hint_common_errors(
+ &mut self,
+ exception: &anyhow::Error,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) {
let is_logic_or_error = exception.downcast_ref::<ShimLogicException>().is_some();
- if is_logic_or_error && output.get_verbosity() < output_interface::VERBOSITY_VERBOSE {
- output.set_verbosity(output_interface::VERBOSITY_VERBOSE);
+ if is_logic_or_error
+ && output.borrow().get_verbosity() < output_interface::VERBOSITY_VERBOSE
+ {
+ output
+ .borrow_mut()
+ .set_verbosity(output_interface::VERBOSITY_VERBOSE);
}
Silencer::suppress(None);
@@ -1051,7 +1058,10 @@ impl Application {
}
/// This ensures we can find the correct command name even if a global input option is present before it
- fn get_command_name_before_binding(&self, input: &dyn InputInterface) -> Option<String> {
+ fn get_command_name_before_binding(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ ) -> Option<String> {
let mut input = clone(&input);
// Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
// TODO(phase-b): BaseApplication::get_definition returns PhpMixed, not InputDefinition.
diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
index 7122a4b..bea2e76 100644
--- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
+++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
@@ -627,7 +627,10 @@ impl EventDispatcher {
.to_string();
let mut input = StringInput::new(&input_str);
let mut output = output;
- Ok(app.run(Some(&mut input), Some(&mut output))?)
+ Ok(app.run(
+ Some(std::rc::Rc::new(std::cell::RefCell::new(input))),
+ Some(std::rc::Rc::new(std::cell::RefCell::new(output))),
+ )?)
})();
match result {
Ok(v) => r#return = v,
diff --git a/crates/shirabe/src/io/buffer_io.rs b/crates/shirabe/src/io/buffer_io.rs
index 836fd95..0696c1c 100644
--- a/crates/shirabe/src/io/buffer_io.rs
+++ b/crates/shirabe/src/io/buffer_io.rs
@@ -44,7 +44,8 @@ impl BufferIO {
// Real fix requires unifying the two crate paths.
let _ = formatter;
let _ = StreamOutput::new(stream, verbosity, Some(decorated));
- let output: Box<dyn OutputInterface> = todo!("StreamOutput as Box<dyn OutputInterface>");
+ let output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> =
+ todo!("StreamOutput as std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>");
// TODO(phase-b): symfony console helper modules live under both `symfony::console`
// and `symfony::component::console`; QuestionHelper::new is not yet provided.
diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs
index 44e5609..edb0a97 100644
--- a/crates/shirabe/src/io/console_io.rs
+++ b/crates/shirabe/src/io/console_io.rs
@@ -34,7 +34,7 @@ pub struct ConsoleIO {
authentications: indexmap::IndexMap<String, indexmap::IndexMap<String, Option<String>>>,
pub(crate) input: Box<dyn InputInterface>,
- pub(crate) output: Box<dyn OutputInterface>,
+ pub(crate) output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
pub(crate) helper_set: HelperSet,
pub(crate) last_message: RefCell<String>,
pub(crate) last_message_err: RefCell<String>,
@@ -68,7 +68,7 @@ impl ConsoleIO {
/// @param HelperSet $helperSet The helperSet instance
pub fn new(
input: Box<dyn InputInterface>,
- output: Box<dyn OutputInterface>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
helper_set: HelperSet,
) -> Self {
let mut verbosity_map = IndexMap::new();
@@ -99,7 +99,7 @@ impl ConsoleIO {
/// @param string[]|string $messages
fn do_write(&self, messages: PhpMixed, newline: bool, stderr: bool, verbosity: i64, raw: bool) {
let mut sf_verbosity = *self.verbosity_map.get(&verbosity).unwrap_or(&0);
- if sf_verbosity > self.output.get_verbosity() {
+ if sf_verbosity > self.output.borrow().get_verbosity() {
return;
}
@@ -142,8 +142,8 @@ impl ConsoleIO {
messages
};
- if stderr && let Some(console_output) = self.output.as_console_output_interface() {
- console_output.get_error_output().write(
+ if stderr && let Some(console_output) = self.output.borrow().as_console_output_interface() {
+ console_output.get_error_output().borrow().write(
&Self::to_string_list(&messages).join(if newline { "\n" } else { "" }),
newline,
sf_verbosity,
@@ -157,7 +157,7 @@ impl ConsoleIO {
return;
}
- self.output.write(
+ self.output.borrow().write(
&Self::to_string_list(&messages).join(if newline { "\n" } else { "" }),
newline,
sf_verbosity,
@@ -256,15 +256,15 @@ impl ConsoleIO {
}
pub fn get_table(&self) -> Table {
- Table::new(&*self.output)
+ Table::new(self.output.clone())
}
- fn get_error_output(&self) -> &dyn OutputInterface {
- if let Some(console_output) = self.output.as_console_output_interface() {
+ fn get_error_output(&self) -> std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> {
+ if let Some(console_output) = self.output.borrow().as_console_output_interface() {
return console_output.get_error_output();
}
- &*self.output
+ self.output.clone()
}
/// Sanitize string to remove control characters
@@ -379,19 +379,19 @@ impl IOInterfaceImmutable for ConsoleIO {
}
fn is_verbose(&self) -> bool {
- self.output.is_verbose()
+ self.output.borrow().is_verbose()
}
fn is_very_verbose(&self) -> bool {
- self.output.is_very_verbose()
+ self.output.borrow().is_very_verbose()
}
fn is_debug(&self) -> bool {
- self.output.is_debug()
+ self.output.borrow().is_debug()
}
fn is_decorated(&self) -> bool {
- self.output.is_decorated()
+ self.output.borrow().is_decorated()
}
fn write3(&self, message: &str, newline: bool, verbosity: i64) {
diff --git a/crates/shirabe/src/plugin/command_event.rs b/crates/shirabe/src/plugin/command_event.rs
index bcfe256..838260c 100644
--- a/crates/shirabe/src/plugin/command_event.rs
+++ b/crates/shirabe/src/plugin/command_event.rs
@@ -10,25 +10,25 @@ use shirabe_php_shim::PhpMixed;
pub struct CommandEvent {
inner: Event,
command_name: String,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
}
impl CommandEvent {
- // TODO(phase-b): input/output dropped because storing &dyn references in an event would
- // require lifetime parameters; restore once Plugin API needs them.
pub fn new(
name: &str,
command_name: &str,
- _input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Self {
- Self::new6(name, command_name, _input, _output, vec![], IndexMap::new())
+ Self::new6(name, command_name, input, output, vec![], IndexMap::new())
}
pub fn new6(
name: &str,
command_name: &str,
- _input: &dyn InputInterface,
- _output: &dyn OutputInterface,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
args: Vec<String>,
flags: IndexMap<String, PhpMixed>,
) -> Self {
@@ -36,9 +36,19 @@ impl CommandEvent {
Self {
inner,
command_name: command_name.to_string(),
+ input,
+ output,
}
}
+ pub fn get_input(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>> {
+ self.input.clone()
+ }
+
+ pub fn get_output(&self) -> std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> {
+ self.output.clone()
+ }
+
pub fn get_name(&self) -> &str {
self.inner.get_name()
}
diff --git a/crates/shirabe/src/plugin/pre_command_run_event.rs b/crates/shirabe/src/plugin/pre_command_run_event.rs
index 2af2626..21eb232 100644
--- a/crates/shirabe/src/plugin/pre_command_run_event.rs
+++ b/crates/shirabe/src/plugin/pre_command_run_event.rs
@@ -7,14 +7,26 @@ use shirabe_external_packages::symfony::component::console::input::InputInterfac
#[derive(Debug)]
pub struct PreCommandRunEvent {
inner: Event,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
command: String,
}
impl PreCommandRunEvent {
- // TODO(phase-b): input dropped because storing a &dyn reference would need lifetime params.
- pub fn new(name: String, _input: &dyn InputInterface, command: String) -> Self {
+ pub fn new(
+ name: String,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ command: String,
+ ) -> Self {
let inner = Event::new(name, vec![], indexmap::IndexMap::new());
- Self { inner, command }
+ Self {
+ inner,
+ input,
+ command,
+ }
+ }
+
+ pub fn get_input(&self) -> std::rc::Rc<std::cell::RefCell<dyn InputInterface>> {
+ self.input.clone()
}
pub fn get_name(&self) -> &str {