aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/command
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-26 20:04:02 +0900
committernsfisis <nsfisis@gmail.com>2026-05-26 20:04:02 +0900
commitf411daceacad66e0bd774fda7d3c5ef8533cc55c (patch)
treeeefb065e4d676a3f7031ca49bab21c773b00b134 /crates/shirabe/src/command
parent1921f173ea219cb4b25847294d2d3fa465550fbb (diff)
downloadphp-shirabe-f411daceacad66e0bd774fda7d3c5ef8533cc55c.tar.gz
php-shirabe-f411daceacad66e0bd774fda7d3c5ef8533cc55c.tar.zst
php-shirabe-f411daceacad66e0bd774fda7d3c5ef8533cc55c.zip
refactor(io): share IOInterface via Rc<RefCell<dyn _>> handle
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/command')
-rw-r--r--crates/shirabe/src/command/about_command.rs1
-rw-r--r--crates/shirabe/src/command/archive_command.rs26
-rw-r--r--crates/shirabe/src/command/audit_command.rs3
-rw-r--r--crates/shirabe/src/command/base_command.rs33
-rw-r--r--crates/shirabe/src/command/base_config_command.rs6
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs2
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs1
-rw-r--r--crates/shirabe/src/command/config_command.rs4
-rw-r--r--crates/shirabe/src/command/create_project_command.rs57
-rw-r--r--crates/shirabe/src/command/diagnose_command.rs24
-rw-r--r--crates/shirabe/src/command/dump_autoload_command.rs1
-rw-r--r--crates/shirabe/src/command/exec_command.rs1
-rw-r--r--crates/shirabe/src/command/fund_command.rs1
-rw-r--r--crates/shirabe/src/command/global_command.rs1
-rw-r--r--crates/shirabe/src/command/home_command.rs8
-rw-r--r--crates/shirabe/src/command/init_command.rs25
-rw-r--r--crates/shirabe/src/command/install_command.rs7
-rw-r--r--crates/shirabe/src/command/licenses_command.rs1
-rw-r--r--crates/shirabe/src/command/package_discovery_trait.rs7
-rw-r--r--crates/shirabe/src/command/reinstall_command.rs1
-rw-r--r--crates/shirabe/src/command/remove_command.rs6
-rw-r--r--crates/shirabe/src/command/repository_command.rs1
-rw-r--r--crates/shirabe/src/command/require_command.rs11
-rw-r--r--crates/shirabe/src/command/run_script_command.rs1
-rw-r--r--crates/shirabe/src/command/search_command.rs5
-rw-r--r--crates/shirabe/src/command/self_update_command.rs5
-rw-r--r--crates/shirabe/src/command/show_command.rs9
-rw-r--r--crates/shirabe/src/command/status_command.rs13
-rw-r--r--crates/shirabe/src/command/suggests_command.rs5
-rw-r--r--crates/shirabe/src/command/update_command.rs7
-rw-r--r--crates/shirabe/src/command/validate_command.rs9
31 files changed, 171 insertions, 111 deletions
diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs
index ddb9f12..3e74d6e 100644
--- a/crates/shirabe/src/command/about_command.rs
+++ b/crates/shirabe/src/command/about_command.rs
@@ -6,6 +6,7 @@ use crate::command::HasBaseCommandData;
use crate::composer;
use crate::composer::ComposerHandle;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use shirabe_external_packages::symfony::component::console::input::InputInterface;
use shirabe_external_packages::symfony::component::console::output::OutputInterface;
diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs
index 1b21242..225b092 100644
--- a/crates/shirabe/src/command/archive_command.rs
+++ b/crates/shirabe/src/command/archive_command.rs
@@ -14,6 +14,7 @@ use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::package::archiver::ArchiveManager;
use crate::package::version::VersionParser;
use crate::package::version::VersionSelector;
@@ -111,9 +112,9 @@ impl ArchiveCommand {
});
// TODO(phase-b): clone_box to release self borrow held by get_io.
- let mut io_box = self.get_io().clone_box();
+ let io_box = self.get_io().clone();
let return_code = self.archive(
- io_box.as_mut(),
+ io_box.clone(),
&config,
input
.get_argument("package")
@@ -153,7 +154,7 @@ impl ArchiveCommand {
pub fn archive(
&mut self,
- io: &mut dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: &std::rc::Rc<std::cell::RefCell<Config>>,
package_name: Option<String>,
version: Option<String>,
@@ -173,12 +174,17 @@ impl ArchiveCommand {
&composer_archive_manager_ref
} else {
let factory = Factory;
- let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(())));
+ let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(None)));
let http_downloader = std::rc::Rc::new(std::cell::RefCell::new(
- Factory::create_http_downloader(io, config, indexmap::IndexMap::new())?,
+ Factory::create_http_downloader(io.clone(), config, indexmap::IndexMap::new())?,
));
- let download_manager =
- factory.create_download_manager(io, config, &http_downloader, &process, None)?;
+ let download_manager = factory.create_download_manager(
+ io.clone(),
+ config,
+ &http_downloader,
+ &process,
+ None,
+ )?;
let loop_ = std::rc::Rc::new(std::cell::RefCell::new(Loop::new(
http_downloader.clone(),
Some(process),
@@ -190,7 +196,7 @@ impl ArchiveCommand {
let package: crate::package::CompletePackageInterfaceHandle =
if let Some(name) = package_name {
- match self.select_package(io, &name, version.as_deref())? {
+ match self.select_package(io.clone(), &name, version.as_deref())? {
Some(p) => p,
None => return Ok(1),
}
@@ -227,7 +233,7 @@ impl ArchiveCommand {
pub fn select_package(
&mut self,
- io: &mut dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
package_name: &str,
version: Option<&str>,
) -> Result<Option<crate::package::CompletePackageInterfaceHandle>> {
@@ -253,7 +259,7 @@ impl ArchiveCommand {
repo = CompositeRepository::new(repos);
min_stability = composer.get_package().get_minimum_stability().to_string();
} else {
- let default_repos = RepositoryFactory::default_repos_with_default_manager(io)?;
+ let default_repos = RepositoryFactory::default_repos_with_default_manager(io.clone())?;
let repo_names: Vec<String> = default_repos.keys().cloned().collect();
io.write_error(&format!(
"No composer.json found in the current directory, searching packages from {}",
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index d3dadbd..ec8b495 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -6,6 +6,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::composer::PartialComposerHandle;
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::repository::CanonicalPackagesTrait;
use crate::repository::InstalledRepository;
use crate::repository::RepositoryInterface;
@@ -127,7 +128,7 @@ impl AuditCommand {
let _ = ignore_severities;
Ok(auditor
.audit(
- self.get_io(),
+ &mut *self.get_io().borrow_mut(),
&repo_set,
packages,
&audit_format,
diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs
index 9511c4d..6b673ed 100644
--- a/crates/shirabe/src/command/base_command.rs
+++ b/crates/shirabe/src/command/base_command.rs
@@ -13,6 +13,8 @@ use shirabe_php_shim::{
InvalidArgumentException, LogicException, PhpMixed, RuntimeException, UnexpectedValueException,
count, explode, in_array, is_string, max,
};
+use std::cell::RefCell;
+use std::rc::Rc;
use crate::advisory::AuditConfig;
use crate::advisory::Auditor;
@@ -27,6 +29,7 @@ use crate::factory::Factory;
use crate::filter::platform_requirement_filter::PlatformRequirementFilterFactory;
use crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::io::NullIO;
use crate::package::version::VersionParser;
use crate::plugin::PluginEvents;
@@ -184,9 +187,9 @@ pub trait BaseCommand {
/// Whether or not this command is meant to call another command.
fn is_proxy_command(&self) -> bool;
- fn get_io(&mut self) -> &mut dyn IOInterface;
+ fn get_io(&mut self) -> Rc<RefCell<dyn IOInterface>>;
- fn set_io(&mut self, io: Box<dyn IOInterface>);
+ fn set_io(&mut self, io: Rc<RefCell<dyn IOInterface>>);
// TODO(cli-completion): fn complete(&self, input: &CompletionInput, suggestions: &mut CompletionSuggestions);
@@ -201,7 +204,7 @@ pub trait BaseCommand {
fn create_composer_instance(
&self,
input: &dyn InputInterface,
- io: &dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
@@ -254,7 +257,7 @@ pub trait BaseCommand {
#[derive(Debug)]
pub struct BaseCommandData {
pub(crate) composer: Option<PartialComposerHandle>,
- pub(crate) io: Option<Box<dyn IOInterface>>,
+ pub(crate) io: Option<Rc<RefCell<dyn IOInterface>>>,
}
pub trait HasBaseCommandData {
@@ -269,11 +272,11 @@ pub trait HasBaseCommandData {
&mut self.base_command_data_mut().composer
}
- fn io(&self) -> Option<&dyn IOInterface> {
- self.base_command_data().io.as_deref()
+ fn io(&self) -> Option<Rc<RefCell<dyn IOInterface>>> {
+ self.base_command_data().io.clone()
}
- fn io_mut(&mut self) -> &mut Option<Box<dyn IOInterface>> {
+ fn io_mut(&mut self) -> &mut Option<Rc<RefCell<dyn IOInterface>>> {
&mut self.base_command_data_mut().io
}
}
@@ -335,16 +338,16 @@ impl<C: HasBaseCommandData> BaseCommand for C {
false
}
- fn get_io(&mut self) -> &mut dyn IOInterface {
+ fn get_io(&mut self) -> Rc<RefCell<dyn IOInterface>> {
if self.io().is_none() {
// TODO(phase-b): requires inner Symfony Application access
- *self.io_mut() = Some(Box::new(NullIO::new()));
+ *self.io_mut() = Some(Rc::new(RefCell::new(NullIO::new())));
}
- &mut **self.io_mut().as_mut().unwrap()
+ self.io().unwrap()
}
- fn set_io(&mut self, io: Box<dyn IOInterface>) {
+ fn set_io(&mut self, io: Rc<RefCell<dyn IOInterface>>) {
*self.io_mut() = Some(io);
}
@@ -363,9 +366,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
// TODO(phase-b): `$this instanceof SelfUpdateCommand` not representable
let composer = self.try_composer(Some(disable_plugins), Some(disable_scripts));
- // TODO(phase-b): re-borrow self for get_io after try_composer move
- let io_ptr: *const dyn IOInterface = self.get_io();
- let io = unsafe { &*io_ptr };
+ let io = self.get_io();
let disable_plugins_kind = if disable_plugins {
crate::factory::DisablePlugins::All
@@ -373,7 +374,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
crate::factory::DisablePlugins::None
};
let composer = if composer.is_none() {
- Factory::create_global(io, disable_plugins_kind, disable_scripts)
+ Factory::create_global(io.clone(), disable_plugins_kind, disable_scripts)
} else {
composer
};
@@ -476,7 +477,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
fn create_composer_instance(
&self,
input: &dyn InputInterface,
- io: &dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
diff --git a/crates/shirabe/src/command/base_config_command.rs b/crates/shirabe/src/command/base_config_command.rs
index 85e68b3..1b7294e 100644
--- a/crates/shirabe/src/command/base_config_command.rs
+++ b/crates/shirabe/src/command/base_config_command.rs
@@ -37,9 +37,9 @@ pub trait BaseConfigCommand: BaseCommand {
}
// TODO(phase-b): clone_box to release the &mut self borrow held by get_io.
- let io = self.get_io().clone_box();
+ let io = self.get_io().clone();
*self.config_mut() = Some(std::rc::Rc::new(std::cell::RefCell::new(
- Factory::create_config(Some(io.as_ref()), None)?,
+ Factory::create_config(Some(io.clone()), None)?,
)));
let config_rc = self.config().unwrap().clone();
@@ -62,7 +62,7 @@ pub trait BaseConfigCommand: BaseCommand {
self.set_config_file(Some(JsonFile::new(
config_file.clone(),
None,
- Some(io.clone_box()),
+ Some(io.clone()),
)?));
// TODO(phase-b): JsonConfigSource::new takes owned JsonFile, but PHP shares the same
// instance with $this->configFile. Needs Rc<RefCell<JsonFile>> refactor on both sides.
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index 8ea10b5..f449629 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -10,6 +10,8 @@ use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::Bound;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
+use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::package::CompletePackageInterface;
use crate::package::Link;
use crate::package::Package;
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index 5d886e7..fd5edd9 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -11,6 +11,7 @@ use shirabe_semver::constraint::SimpleConstraint;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::Link;
use crate::repository::InstalledRepository;
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index 6412160..476be75 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -25,6 +25,7 @@ use crate::config::JsonConfigSource;
use crate::console::input::InputArgument;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::base_package::{self, BasePackage};
use crate::util::Filesystem;
@@ -130,7 +131,7 @@ impl ConfigCommand {
self.auth_config_file = Some(JsonFile::new(
auth_config_file,
None,
- Some(self.get_io().clone_box()),
+ Some(self.get_io().clone()),
)?);
// TODO(phase-b): JsonConfigSource::new takes owned JsonFile (PHP sharing semantics).
// Skipping auth_config_source assignment until Rc<RefCell<JsonFile>> refactor lands.
@@ -257,6 +258,7 @@ impl ConfigCommand {
{
let config_rc = self.config.as_ref().unwrap().clone();
self.get_io()
+ .borrow_mut()
.load_configuration(&mut *config_rc.borrow_mut())?;
}
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index e0cb3d4..d5a8a0c 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -30,6 +30,7 @@ use crate::installer::Installer;
use crate::installer::ProjectInstaller;
use crate::installer::SuggestedPackagesReporter;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::version::VersionParser;
use crate::package::version::VersionSelector;
@@ -113,7 +114,7 @@ impl CreateProjectCommand {
) -> 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: Box<dyn IOInterface> = self.get_io().clone_box();
+ 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)?;
@@ -160,9 +161,8 @@ impl CreateProjectCommand {
Some(repository_url_opt)
};
- let mut io = io;
self.install_project(
- &mut *io,
+ io,
config,
input,
input
@@ -207,7 +207,7 @@ impl CreateProjectCommand {
#[allow(clippy::too_many_arguments)]
pub fn install_project(
&mut self,
- io: &mut dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: std::rc::Rc<std::cell::RefCell<Config>>,
input: &dyn InputInterface,
package_name: Option<String>,
@@ -247,14 +247,15 @@ impl CreateProjectCommand {
.unwrap_or_else(PlatformRequirementFilterFactory::ignore_nothing);
// we need to manually load the configuration to pass the auth credentials to the io interface!
- io.load_configuration(&mut *config.borrow_mut())?;
+ io.borrow_mut()
+ .load_configuration(&mut *config.borrow_mut())?;
- self.suggested_packages_reporter = Some(SuggestedPackagesReporter::new(io.clone_box()));
+ self.suggested_packages_reporter = Some(SuggestedPackagesReporter::new(io.clone()));
let installed_from_vcs = if let Some(package_name) = package_name.as_ref() {
self.install_root_package(
input,
- io,
+ io.clone(),
&config,
package_name,
&*platform_requirement_filter,
@@ -278,8 +279,13 @@ impl CreateProjectCommand {
unlink("composer.lock");
}
- let mut composer_handle =
- self.create_composer_instance(input, io, None, disable_plugins, Some(disable_scripts))?;
+ let mut composer_handle = self.create_composer_instance(
+ input,
+ io.clone(),
+ None,
+ disable_plugins,
+ Some(disable_scripts),
+ )?;
// add the repository to the composer.json and use it for the install run later
if let Some(repos) = repositories.as_ref() {
@@ -287,7 +293,7 @@ impl CreateProjectCommand {
for (index, repo) in repos.iter().enumerate() {
let config = crate::command::composer_full(&composer_handle).get_config();
let repo_config =
- RepositoryFactory::config_from_string(io, &config, repo, true)?;
+ RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?;
let composer_json_repositories_config =
crate::command::composer_full(&composer_handle)
.get_config()
@@ -332,8 +338,13 @@ impl CreateProjectCommand {
);
}
- composer_handle =
- self.create_composer_instance(input, io, None, disable_plugins, None)?;
+ composer_handle = self.create_composer_instance(
+ input,
+ io.clone(),
+ None,
+ disable_plugins,
+ None,
+ )?;
}
}
}
@@ -371,7 +382,7 @@ impl CreateProjectCommand {
.borrow_mut()
.set_output_progress(!no_progress);
- let mut installer = Installer::create(io.clone_box(), &composer_handle);
+ let mut installer = Installer::create(io.clone(), &composer_handle);
// TODO(phase-b): set_suggested_packages_reporter takes by value but PHP class
// means shared ownership; needs Rc<SuggestedPackagesReporter> for proper sharing.
installer
@@ -379,7 +390,7 @@ impl CreateProjectCommand {
.set_prefer_dist(prefer_dist)
.set_dev_mode(install_dev_packages)
.set_platform_requirement_filter(platform_requirement_filter.clone_box())
- .set_suggested_packages_reporter(SuggestedPackagesReporter::new(io.clone_box()))
+ .set_suggested_packages_reporter(SuggestedPackagesReporter::new(io.clone()))
.set_optimize_autoloader(
config
.borrow_mut()
@@ -540,7 +551,7 @@ impl CreateProjectCommand {
fn install_root_package(
&self,
input: &dyn InputInterface,
- io: &dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: &std::rc::Rc<std::cell::RefCell<Config>>,
package_name: &str,
platform_requirement_filter: &dyn PlatformRequirementFilterInterface,
@@ -584,7 +595,7 @@ impl CreateProjectCommand {
directory = rtrim(&directory, Some("/\\"));
let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some(
- io.clone_box(),
+ io.clone(),
))));
let fs = std::rc::Rc::new(std::cell::RefCell::new(Filesystem::new(Some(process))));
if !fs.borrow().is_absolute_path(&directory) {
@@ -704,7 +715,7 @@ impl CreateProjectCommand {
let composer_handle = self.create_composer_instance(
input,
- io,
+ io.clone(),
Some(config.borrow_mut().all(0)?),
disable_plugins,
Some(disable_scripts),
@@ -727,7 +738,7 @@ impl CreateProjectCommand {
// TODO(phase-b): default_repos needs &mut RepositoryManager but we hold &RepositoryManager.
let _ = rm;
repository_set.add_repository(Box::new(CompositeRepository::new(
- RepositoryFactory::default_repos(Some(io), Some(config.clone()), None)?
+ RepositoryFactory::default_repos(Some(io.clone()), Some(config.clone()), None)?
.into_iter()
.map(|(_, v)| v)
.collect(),
@@ -735,7 +746,7 @@ impl CreateProjectCommand {
} else {
for repo in repositories.unwrap() {
let mut repo_config =
- RepositoryFactory::config_from_string(io, &config, repo, true)?;
+ RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?;
let is_packagist_disabled = (repo_config.contains_key("packagist")
&& repo_config.len() == 1
&& repo_config.get("packagist").and_then(|v| v.as_bool()) == Some(false))
@@ -767,7 +778,7 @@ impl CreateProjectCommand {
}
repository_set.add_repository(RepositoryFactory::create_repo(
- io,
+ io.clone(),
&config,
repo_config.clone(),
None,
@@ -803,7 +814,7 @@ impl CreateProjectCommand {
&stability,
None,
0,
- Some(io),
+ Some(&*io.borrow()),
PhpMixed::Bool(true),
)?;
@@ -913,7 +924,7 @@ impl CreateProjectCommand {
true,
false,
)?;
- im.notify_installs(io);
+ im.notify_installs(&*io.borrow());
// collect suggestions
// TODO(phase-b): self.suggested_packages_reporter is on the outer scope via &self
@@ -947,7 +958,7 @@ impl CreateProjectCommand {
fn create_composer_instance(
&self,
input: &dyn InputInterface,
- io: &dyn IOInterface,
+ io: std::rc::Rc<std::cell::RefCell<dyn IOInterface>>,
config: Option<indexmap::IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs
index fe57e5c..c64fc39 100644
--- a/crates/shirabe/src/command/diagnose_command.rs
+++ b/crates/shirabe/src/command/diagnose_command.rs
@@ -27,6 +27,7 @@ use crate::downloader::TransportException;
use crate::factory::Factory;
use crate::io::BufferIO;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::io::NullIO;
use crate::json::JsonFile;
use crate::json::JsonValidationException;
@@ -78,7 +79,7 @@ impl DiagnoseCommand {
output: &dyn OutputInterface,
) -> anyhow::Result<i64> {
let mut composer = self.try_composer(None, None);
- let io_boxed: Box<dyn IOInterface> = self.get_io().clone_box();
+ let io_boxed: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> = self.get_io().clone();
let config: std::rc::Rc<std::cell::RefCell<Config>>;
if let Some(ref mut c) = composer {
@@ -103,7 +104,7 @@ impl DiagnoseCommand {
.map(std::rc::Rc::clone)
.unwrap_or_else(|| {
std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some(
- io_boxed.clone_box(),
+ io_boxed.clone(),
))))
}),
);
@@ -111,12 +112,13 @@ impl DiagnoseCommand {
config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?));
self.process = Some(std::rc::Rc::new(std::cell::RefCell::new(
- ProcessExecutor::new(Some(io_boxed.clone_box())),
+ ProcessExecutor::new(Some(io_boxed.clone())),
)));
}
// TODO(phase-b): clone_box to release self borrow held by get_io.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = io_box.as_ref();
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
let mut config_inner: IndexMap<String, Box<PhpMixed>> = IndexMap::new();
config_inner.insert("secure-http".to_string(), Box::new(PhpMixed::Bool(false)));
@@ -133,7 +135,7 @@ impl DiagnoseCommand {
);
self.http_downloader = Some(std::rc::Rc::new(std::cell::RefCell::new(
- Factory::create_http_downloader(io, &config, indexmap::IndexMap::new())?,
+ Factory::create_http_downloader(io_box.clone(), &config, indexmap::IndexMap::new())?,
)));
if strpos(file!(), "phar:") == Some(0) {
@@ -295,7 +297,7 @@ impl DiagnoseCommand {
.collect();
let composer_repo = ComposerRepository::new(
repo_arr_unboxed,
- self.get_io().clone_box(),
+ self.get_io().clone(),
&*config.borrow(),
self.http_downloader.clone().unwrap(),
None,
@@ -427,7 +429,7 @@ impl DiagnoseCommand {
}
fn check_composer_schema(&mut self) -> anyhow::Result<PhpMixed> {
- let validator = ConfigValidator::new(self.get_io().clone_box());
+ let validator = ConfigValidator::new(self.get_io().clone());
let (errors, _, warnings) = validator.validate(&Factory::get_composer_file()?, 0, 0);
if !errors.is_empty() || !warnings.is_empty() {
@@ -680,7 +682,7 @@ impl DiagnoseCommand {
return Ok(result);
}
- self.get_io().set_authentication(
+ self.get_io().borrow_mut().set_authentication(
domain.to_string(),
token.to_string(),
Some("x-oauth-basic".to_string()),
@@ -744,7 +746,7 @@ impl DiagnoseCommand {
}
if let Some(t) = token {
- self.get_io().set_authentication(
+ self.get_io().borrow_mut().set_authentication(
domain.to_string(),
t.to_string(),
Some("x-oauth-basic".to_string()),
@@ -939,7 +941,7 @@ impl DiagnoseCommand {
// TODO(phase-b): ComposerRepository does not implement RepositoryInterface yet
let _composer_repo = ComposerRepository::new(
repo_config,
- Box::new(NullIO::new()),
+ std::rc::Rc::new(std::cell::RefCell::new(NullIO::new())),
config,
self.http_downloader.clone().unwrap(),
None,
diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs
index 275e635..6f361da 100644
--- a/crates/shirabe/src/command/dump_autoload_command.rs
+++ b/crates/shirabe/src/command/dump_autoload_command.rs
@@ -8,6 +8,7 @@ use shirabe_php_shim::{InvalidArgumentException, PhpMixed, file_exists};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::plugin::CommandEvent;
use crate::plugin::PluginEvents;
diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs
index 23aa103..3f70cf8 100644
--- a/crates/shirabe/src/command/exec_command.rs
+++ b/crates/shirabe/src/command/exec_command.rs
@@ -9,6 +9,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
#[derive(Debug)]
pub struct ExecCommand {
diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs
index f829342..340424f 100644
--- a/crates/shirabe/src/command/fund_command.rs
+++ b/crates/shirabe/src/command/fund_command.rs
@@ -15,6 +15,7 @@ use shirabe_semver::constraint::MatchAllConstraint;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::AliasPackage;
use crate::package::CompletePackage;
diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs
index a8cf1d4..a3d5a78 100644
--- a/crates/shirabe/src/command/global_command.rs
+++ b/crates/shirabe/src/command/global_command.rs
@@ -13,6 +13,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::util::Filesystem;
use crate::util::Platform;
diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs
index 673039a..c048bfd 100644
--- a/crates/shirabe/src/command/home_command.rs
+++ b/crates/shirabe/src/command/home_command.rs
@@ -9,6 +9,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::package::CompletePackageInterfaceHandle;
use crate::package::PackageInterface;
use crate::package::RootPackageInterface;
@@ -73,8 +74,9 @@ impl HomeCommand {
) -> Result<i64> {
let repos = self.initialize_repos()?;
// TODO(phase-b): clone_box to release self borrow held by get_io.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = io_box.as_ref();
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
let mut return_code: i64 = 0;
let packages: Vec<String> = input
@@ -172,7 +174,7 @@ impl HomeCommand {
}
fn open_browser(&mut self, url: &str) {
- let mut process = ProcessExecutor::new(Some(self.get_io().clone_box()));
+ let mut process = ProcessExecutor::new(Some(self.get_io().clone()));
if Platform::is_windows() {
let _ = process.execute(
PhpMixed::from(vec!["start", "\"web\"", "explorer", url]),
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs
index 122642d..730658c 100644
--- a/crates/shirabe/src/command/init_command.rs
+++ b/crates/shirabe/src/command/init_command.rs
@@ -23,6 +23,7 @@ use crate::composer::PartialComposerHandle;
use crate::console::input::InputOption;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::json::JsonValidationException;
use crate::package::base_package::{self, BasePackage};
@@ -52,7 +53,7 @@ impl PackageDiscoveryTrait for InitCommand {
todo!()
}
- fn get_io(&self) -> &dyn IOInterface {
+ fn get_io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
todo!()
}
@@ -193,11 +194,12 @@ impl InitCommand {
.unwrap_or_default();
if (repositories.len() as i64) > 0 {
let config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(
- Some(io),
+ Some(io.clone()),
None,
)?));
for repo in &repositories {
- let repo_config = RepositoryFactory::config_from_string(io, &config, repo, true)?;
+ let repo_config =
+ RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?;
let entry = options
.entry("repositories".to_string())
.or_insert_with(|| PhpMixed::List(vec![]));
@@ -445,17 +447,20 @@ impl InitCommand {
.unwrap_or_default();
if (repositories.len() as i64) > 0 {
let config = std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(
- Some(io),
+ Some(io.clone()),
None,
)?));
- io.load_configuration(&mut *config.borrow_mut())?;
- let mut repo_manager = RepositoryFactory::manager(io, &config, None, None, None)?;
+ io.borrow_mut()
+ .load_configuration(&mut *config.borrow_mut())?;
+ let mut repo_manager =
+ RepositoryFactory::manager(io.clone(), &config, None, None, None)?;
let mut repos: Vec<Box<dyn crate::repository::RepositoryInterface>> =
vec![Box::new(PlatformRepository::new(vec![], IndexMap::new())?)];
let mut create_default_packagist_repo = true;
for repo in &repositories {
- let repo_config = RepositoryFactory::config_from_string(io, &config, repo, true)?;
+ let repo_config =
+ RepositoryFactory::config_from_string(io.clone(), &config, repo, true)?;
let is_packagist_false = repo_config
.get("packagist")
.map(|v| v.as_bool() == Some(false))
@@ -471,7 +476,7 @@ impl InitCommand {
continue;
}
repos.push(RepositoryFactory::create_repo(
- io,
+ io.clone(),
&config,
repo_config,
Some(&mut repo_manager),
@@ -486,7 +491,7 @@ impl InitCommand {
PhpMixed::String("https://repo.packagist.org".to_string()),
);
repos.push(RepositoryFactory::create_repo(
- io,
+ io.clone(),
&config,
default_config,
Some(&mut repo_manager),
@@ -943,7 +948,7 @@ impl InitCommand {
return self.git_config.clone().unwrap_or_default();
}
- let mut process = ProcessExecutor::new(Some(self.get_io().clone_box()));
+ let mut process = ProcessExecutor::new(Some(self.get_io().clone()));
let mut output = String::new();
if process.execute_args(
diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs
index a0710dc..4c869f4 100644
--- a/crates/shirabe/src/command/install_command.rs
+++ b/crates/shirabe/src/command/install_command.rs
@@ -67,8 +67,9 @@ impl InstallCommand {
output: &dyn OutputInterface,
) -> Result<i64> {
// TODO(phase-b): clone_box to release self borrow held by get_io.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = io_box.as_ref();
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
if input.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>");
@@ -114,7 +115,7 @@ impl InstallCommand {
.borrow_mut()
.dispatch(Some(command_event.get_name()), None);
- let mut install = Installer::create(io.clone_box(), &composer_handle);
+ let mut install = Installer::create(io_box.clone(), &composer_handle);
let config = composer.get_config();
let (prefer_source, prefer_dist) =
diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs
index 2bcecd5..6c7ea73 100644
--- a/crates/shirabe/src/command/licenses_command.rs
+++ b/crates/shirabe/src/command/licenses_command.rs
@@ -14,6 +14,7 @@ use shirabe_php_shim::{PhpMixed, RuntimeException, UnexpectedValueException};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::BasePackage;
use crate::package::CompletePackage;
diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs
index a268469..e8a56a9 100644
--- a/crates/shirabe/src/command/package_discovery_trait.rs
+++ b/crates/shirabe/src/command/package_discovery_trait.rs
@@ -20,6 +20,7 @@ use crate::factory::Factory;
use crate::filter::platform_requirement_filter::IgnoreAllPlatformRequirementFilter;
use crate::filter::platform_requirement_filter::PlatformRequirementFilterFactory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::package::BasePackage;
use crate::package::CompletePackageInterface;
use crate::package::PackageInterface;
@@ -40,7 +41,7 @@ pub trait PackageDiscoveryTrait {
fn get_repository_sets_mut(&mut self) -> &mut IndexMap<String, RepositorySet>;
// PHP: trait dependencies (provided by BaseCommand)
- fn get_io(&self) -> &dyn IOInterface;
+ fn get_io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>>;
fn try_composer(&self) -> Option<PartialComposerHandle>;
fn require_composer(
&self,
@@ -61,8 +62,8 @@ pub trait PackageDiscoveryTrait {
// TODO(phase-b): PlatformRepository::new() signature
Box::new(todo!("PlatformRepository::new()") as PlatformRepository),
];
- let mut io_owned: Box<dyn IOInterface> = todo!("clone self.get_io() into a Box");
- for (_, repo) in RepositoryFactory::default_repos_with_default_manager(&mut *io_owned)
+ let io_owned: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> = self.get_io();
+ for (_, repo) in RepositoryFactory::default_repos_with_default_manager(io_owned)
.unwrap()
.into_iter()
{
diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs
index 1e3114b..ad4739b 100644
--- a/crates/shirabe/src/command/reinstall_command.rs
+++ b/crates/shirabe/src/command/reinstall_command.rs
@@ -16,6 +16,7 @@ use crate::dependency_resolver::Transaction;
use crate::dependency_resolver::operation::InstallOperation;
use crate::dependency_resolver::operation::UninstallOperation;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::package::base_package;
use crate::plugin::CommandEvent;
use crate::plugin::PluginEvents;
diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs
index 49b21dc..9ea7329 100644
--- a/crates/shirabe/src/command/remove_command.rs
+++ b/crates/shirabe/src/command/remove_command.rs
@@ -17,6 +17,7 @@ use crate::dependency_resolver::Request;
use crate::factory::Factory;
use crate::installer::Installer;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::BasePackage;
use crate::package::base_package;
@@ -510,8 +511,9 @@ impl RemoveCommand {
.borrow_mut()
.set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
- // TODO(phase-b): Installer::create expects Box<dyn IOInterface>; io here is &mut dyn IOInterface
- let io_box: Box<dyn IOInterface> = todo!("share IOInterface as Box<dyn IOInterface>");
+ // TODO(phase-b): Installer::create expects std::rc::Rc<std::cell::RefCell<dyn IOInterface>>; io here is &mut dyn IOInterface
+ let io_box: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> =
+ todo!("share IOInterface as Box<dyn IOInterface>");
let mut install = Installer::create(io_box, &composer_handle);
let update_dev_mode = !input.get_option("update-no-dev").as_bool().unwrap_or(false);
diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs
index 1f6599b..bf000e4 100644
--- a/crates/shirabe/src/command/repository_command.rs
+++ b/crates/shirabe/src/command/repository_command.rs
@@ -17,6 +17,7 @@ use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
#[derive(Debug)]
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index f0dce6b..66e1134 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -25,6 +25,7 @@ use crate::factory::Factory;
use crate::installer::Installer;
use crate::installer::InstallerEvents;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::json::JsonManipulator;
use crate::package::base_package;
@@ -67,7 +68,7 @@ impl PackageDiscoveryTrait for RequireCommand {
todo!()
}
- fn get_io(&self) -> &dyn IOInterface {
+ fn get_io(&self) -> std::rc::Rc<std::cell::RefCell<dyn IOInterface>> {
todo!()
}
@@ -845,10 +846,12 @@ impl RequireCommand {
.borrow_mut()
.set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
- // TODO(phase-b): Installer::create takes Box<dyn IOInterface> for ownership but io is a
+ // TODO(phase-b): Installer::create takes std::rc::Rc<std::cell::RefCell<dyn IOInterface>> for ownership but io is a
// borrowed &dyn here; needs Rc<dyn IOInterface> for proper sharing.
- let mut install =
- Installer::create(todo!("share io as Box<dyn IOInterface>"), &composer_handle);
+ let mut install = Installer::create(
+ todo!("share io as std::rc::Rc<std::cell::RefCell<dyn IOInterface>>"),
+ &composer_handle,
+ );
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&*composer.get_config().borrow(), input, false)?;
diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs
index e58ad24..9118463 100644
--- a/crates/shirabe/src/command/run_script_command.rs
+++ b/crates/shirabe/src/command/run_script_command.rs
@@ -10,6 +10,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::script::Event as ScriptEvent;
use crate::script::ScriptEvents;
use crate::util::Platform;
diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs
index 9375ec7..2033cfc 100644
--- a/crates/shirabe/src/command/search_command.rs
+++ b/crates/shirabe/src/command/search_command.rs
@@ -4,6 +4,7 @@ use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::plugin::CommandEvent;
use crate::plugin::PluginEvents;
@@ -73,8 +74,8 @@ impl SearchCommand {
c
} else {
// TODO(phase-b): clone_box to release self borrow held by get_io.
- let io_box = self.get_io().clone_box();
- self.create_composer_instance(input, io_box.as_ref(), None, false, None)?
+ let io_box = self.get_io().clone();
+ self.create_composer_instance(input, io_box, None, false, None)?
};
let composer_ref = crate::command::composer_full(&composer);
// TODO(phase-b): get_local_repository returns &dyn InstalledRepositoryInterface but we need Box<dyn RepositoryInterface>
diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs
index 80d8b01..fc22ab7 100644
--- a/crates/shirabe/src/command/self_update_command.rs
+++ b/crates/shirabe/src/command/self_update_command.rs
@@ -28,6 +28,7 @@ use crate::console::input::InputOption;
use crate::downloader::FilesystemException;
use crate::factory::Factory;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::self_update::Keys;
use crate::self_update::Versions;
use crate::util::Filesystem;
@@ -132,7 +133,7 @@ impl SelfUpdateCommand {
let io = self.get_io();
let http_downloader = std::rc::Rc::new(std::cell::RefCell::new(
- Factory::create_http_downloader(io, &config, indexmap::IndexMap::new())?,
+ Factory::create_http_downloader(io.clone(), &config, indexmap::IndexMap::new())?,
));
let mut versions_util = Versions::new(config.clone(), http_downloader.clone());
@@ -142,7 +143,7 @@ impl SelfUpdateCommand {
for channel in Versions::CHANNELS {
if input.get_option(channel).as_bool().unwrap_or(false) {
requested_channel = Some(channel.to_string());
- versions_util.set_channel(channel.to_string(), Some(io))??;
+ versions_util.set_channel(channel.to_string(), Some(&*io.borrow()))??;
break;
}
}
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index c7c2f9d..f3c1b3d 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -22,6 +22,7 @@ use crate::dependency_resolver::DefaultPolicy;
use crate::dependency_resolver::PolicyInterface;
use crate::filter::platform_requirement_filter::PlatformRequirementFilterInterface;
use crate::io::IOInterface;
+use crate::io::IOInterfaceImmutable;
use crate::json::JsonFile;
use crate::package::CompletePackageInterface;
use crate::package::Link;
@@ -1144,7 +1145,7 @@ impl ShowCommand {
),
);
}
- let io: &mut dyn IOInterface = self.get_io();
+ let io = self.get_io();
io.write(&JsonFile::encode(
&PhpMixed::Array(
json_map
@@ -1158,7 +1159,7 @@ impl ShowCommand {
if input.get_option("latest").as_bool() == Some(true)
&& view_data.values().any(|v| !v.is_empty())
{
- let io: &mut dyn IOInterface = self.get_io();
+ let io = self.get_io();
if !io.is_decorated() {
io.write_error("Legend:");
io.write_error("! patch or minor release available - update recommended");
@@ -1315,7 +1316,7 @@ impl ShowCommand {
write_release_date: bool,
release_date_length: usize,
) {
- let io: &mut dyn IOInterface = self.get_io();
+ let io = self.get_io();
let pad_name = write_version || write_latest || write_release_date || write_description;
let pad_version = write_latest || write_release_date || write_description;
let pad_latest = write_description || write_release_date;
@@ -2681,7 +2682,7 @@ impl ShowCommand {
&best_stability,
None,
0,
- Some(self.get_io()),
+ Some(&*self.get_io().borrow()),
PhpMixed::Bool(true),
)?;
while let Some(ref c) = candidate {
diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs
index 69c36a1..182dec8 100644
--- a/crates/shirabe/src/command/status_command.rs
+++ b/crates/shirabe/src/command/status_command.rs
@@ -87,8 +87,9 @@ impl StatusCommand {
let composer = self.require_composer(None, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
// TODO(phase-b): release the &mut self borrow held by get_io via clone_box.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = io_box.as_ref();
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
let mut errors: IndexMap<String, String> = IndexMap::new();
let mut unpushed_changes: IndexMap<String, String> = IndexMap::new();
@@ -101,12 +102,16 @@ impl StatusCommand {
.borrow()
.get_process_executor()
.map(std::rc::Rc::clone)
- .unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(io))));
+ .unwrap_or_else(|| {
+ std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(Some(
+ io_box.clone(),
+ ))))
+ });
let mut guesser = VersionGuesser::new(
composer.get_config(),
process_executor.clone(),
parser.clone(),
- Some(io_box.clone_box()),
+ Some(io_box.clone()),
);
let dumper = ArrayDumper::new();
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index 8166c1e..b4693a2 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -90,8 +90,9 @@ impl SuggestsCommand {
}
let installed_repo = InstalledRepository::new(installed_repos);
- // TODO(phase-b): SuggestedPackagesReporter::new expects Box<dyn IOInterface>; self.get_io() returns &mut dyn IOInterface
- let io_box: Box<dyn IOInterface> = todo!("share IOInterface as Box<dyn IOInterface>");
+ // TODO(phase-b): SuggestedPackagesReporter::new expects std::rc::Rc<std::cell::RefCell<dyn IOInterface>>; self.get_io() returns &mut dyn IOInterface
+ let io_box: std::rc::Rc<std::cell::RefCell<dyn IOInterface>> =
+ todo!("share IOInterface as Box<dyn IOInterface>");
let mut reporter = SuggestedPackagesReporter::new(io_box);
let filter = input.get_argument("packages");
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index 06984e2..f879283 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -77,8 +77,9 @@ impl UpdateCommand {
) -> Result<i64> {
// TODO(phase-b): clone_box avoids the &mut self conflict with require_composer
// below; revisit when get_io can return an Rc/Arc owned handle.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = &*io_box;
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
if input.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>",
@@ -311,7 +312,7 @@ impl UpdateCommand {
.borrow_mut()
.set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
- let mut install = Installer::create(io.clone_box(), &composer_handle);
+ let mut install = Installer::create(io_box.clone(), &composer_handle);
let config = composer.get_config();
let (prefer_source, prefer_dist) =
diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs
index 814f09f..cb8fa89 100644
--- a/crates/shirabe/src/command/validate_command.rs
+++ b/crates/shirabe/src/command/validate_command.rs
@@ -119,8 +119,9 @@ impl ValidateCommand {
.map(Ok)
.unwrap_or_else(Factory::get_composer_file)?;
// TODO(phase-b): get_io() takes &mut self via BaseCommand; clone_box to release the borrow.
- let io_box = self.get_io().clone_box();
- let io: &dyn IOInterface = io_box.as_ref();
+ let io_box = self.get_io().clone();
+ let io_ref = io_box.borrow();
+ let io: &dyn IOInterface = &*io_ref;
if !std::path::Path::new(&file).exists() {
io.write_error(&format!("<error>{} not found.</error>", file));
@@ -131,7 +132,7 @@ impl ValidateCommand {
return Ok(3);
}
- let validator = ConfigValidator::new(io.clone_box());
+ let validator = ConfigValidator::new(io_box.clone());
let check_all = if input.get_option("no-check-all").as_bool().unwrap_or(false) {
0
} else {
@@ -156,7 +157,7 @@ impl ValidateCommand {
validator.validate(&file, check_all, check_version);
let mut lock_errors: Vec<String> = vec![];
- let composer = self.create_composer_instance(input, io, None, false, None)?;
+ let composer = self.create_composer_instance(input, io_box.clone(), None, false, None)?;
let mut composer = crate::command::composer_full_mut(&composer);
let check_lock = (check_lock
&& composer