aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/command
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-22 01:29:48 +0900
committernsfisis <nsfisis@gmail.com>2026-05-22 01:43:48 +0900
commit0b06f54103490e3ce5658e82bbc0119633e26cd8 (patch)
tree687b075131d3679725e77e0931ff7c503a6c3034 /crates/shirabe/src/command
parent2914770fba6b3cc03a68fae493f60470a41962ec (diff)
downloadphp-shirabe-0b06f54103490e3ce5658e82bbc0119633e26cd8.tar.gz
php-shirabe-0b06f54103490e3ce5658e82bbc0119633e26cd8.tar.zst
php-shirabe-0b06f54103490e3ce5658e82bbc0119633e26cd8.zip
refactor(composer): unify Composer/PartialComposer via Rc handles
Model PHP's `Composer extends PartialComposer` as a PartialOrFullComposer enum and merge partial_composer.rs into composer.rs. Introduce ComposerHandle / PartialComposerHandle (plus their Weak variants) so the graph can be shared, and build it at once with Rc::new_cyclic in the factory to resolve the back-reference cycles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/command')
-rw-r--r--crates/shirabe/src/command/about_command.rs5
-rw-r--r--crates/shirabe/src/command/archive_command.rs66
-rw-r--r--crates/shirabe/src/command/audit_command.rs19
-rw-r--r--crates/shirabe/src/command/base_command.rs42
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs12
-rw-r--r--crates/shirabe/src/command/bump_command.rs30
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs23
-rw-r--r--crates/shirabe/src/command/clear_cache_command.rs5
-rw-r--r--crates/shirabe/src/command/config_command.rs1
-rw-r--r--crates/shirabe/src/command/create_project_command.rs39
-rw-r--r--crates/shirabe/src/command/diagnose_command.rs24
-rw-r--r--crates/shirabe/src/command/dump_autoload_command.rs39
-rw-r--r--crates/shirabe/src/command/exec_command.rs22
-rw-r--r--crates/shirabe/src/command/fund_command.rs9
-rw-r--r--crates/shirabe/src/command/global_command.rs1
-rw-r--r--crates/shirabe/src/command/home_command.rs11
-rw-r--r--crates/shirabe/src/command/init_command.rs6
-rw-r--r--crates/shirabe/src/command/install_command.rs12
-rw-r--r--crates/shirabe/src/command/licenses_command.rs11
-rw-r--r--crates/shirabe/src/command/mod.rs2
-rw-r--r--crates/shirabe/src/command/outdated_command.rs1
-rw-r--r--crates/shirabe/src/command/package_discovery_trait.rs28
-rw-r--r--crates/shirabe/src/command/reinstall_command.rs10
-rw-r--r--crates/shirabe/src/command/remove_command.rs27
-rw-r--r--crates/shirabe/src/command/repository_command.rs1
-rw-r--r--crates/shirabe/src/command/require_command.rs37
-rw-r--r--crates/shirabe/src/command/run_script_command.rs12
-rw-r--r--crates/shirabe/src/command/script_alias_command.rs7
-rw-r--r--crates/shirabe/src/command/search_command.rs13
-rw-r--r--crates/shirabe/src/command/self_update_command.rs13
-rw-r--r--crates/shirabe/src/command/show_command.rs83
-rw-r--r--crates/shirabe/src/command/status_command.rs66
-rw-r--r--crates/shirabe/src/command/suggests_command.rs15
-rw-r--r--crates/shirabe/src/command/update_command.rs41
-rw-r--r--crates/shirabe/src/command/validate_command.rs11
35 files changed, 462 insertions, 282 deletions
diff --git a/crates/shirabe/src/command/about_command.rs b/crates/shirabe/src/command/about_command.rs
index bd7643d..ddb9f12 100644
--- a/crates/shirabe/src/command/about_command.rs
+++ b/crates/shirabe/src/command/about_command.rs
@@ -3,7 +3,8 @@
use crate::command::BaseCommand;
use crate::command::BaseCommandData;
use crate::command::HasBaseCommandData;
-use crate::composer::Composer;
+use crate::composer;
+use crate::composer::ComposerHandle;
use crate::io::IOInterface;
use shirabe_external_packages::symfony::component::console::input::InputInterface;
use shirabe_external_packages::symfony::component::console::output::OutputInterface;
@@ -21,7 +22,7 @@ impl AboutCommand {
}
pub fn execute(&mut self, input: &dyn InputInterface, output: &dyn OutputInterface) -> i64 {
- let composer_version = Composer::get_version();
+ let composer_version = composer::get_version();
let _ = (input, output);
self.get_io().write(&format!(
diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs
index 9c43fc6..c823860 100644
--- a/crates/shirabe/src/command/archive_command.rs
+++ b/crates/shirabe/src/command/archive_command.rs
@@ -10,7 +10,7 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{LogicException, get_debug_type};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::config::Config;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
@@ -68,13 +68,12 @@ impl ArchiveCommand {
output: &dyn OutputInterface,
) -> Result<i64> {
let composer = self.try_composer(None, None);
- let mut config: Option<std::rc::Rc<std::cell::RefCell<Config>>> = None;
- if let Some(ref composer) = composer {
- config = Some(std::rc::Rc::clone(composer.get_config()));
+ 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 event_dispatcher = composer.get_event_dispatcher();
+ let event_dispatcher = composer.borrow_partial().get_event_dispatcher();
event_dispatcher
.borrow_mut()
.dispatch(Some(command_event.get_name()), None);
@@ -84,11 +83,9 @@ impl ArchiveCommand {
vec![],
indexmap::IndexMap::new(),
);
- }
-
- let config = match config {
- Some(c) => c,
- None => std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?)),
+ config
+ } else {
+ std::rc::Rc::new(std::cell::RefCell::new(Factory::create_config(None, None)?))
};
let format = input
@@ -143,18 +140,19 @@ impl ArchiveCommand {
composer.as_ref(),
)?;
- if return_code == 0 {
- if let Some(ref composer) = composer {
- composer
- .get_event_dispatcher()
- .borrow_mut()
- .dispatch_script(
- ScriptEvents::POST_ARCHIVE_CMD,
- true,
- vec![],
- indexmap::IndexMap::new(),
- );
- }
+ if return_code == 0
+ && let Some(ref composer) = composer
+ {
+ composer
+ .borrow_partial()
+ .get_event_dispatcher()
+ .borrow_mut()
+ .dispatch_script(
+ ScriptEvents::POST_ARCHIVE_CMD,
+ true,
+ vec![],
+ indexmap::IndexMap::new(),
+ );
}
Ok(return_code)
@@ -170,11 +168,16 @@ impl ArchiveCommand {
dest: &str,
file_name: Option<String>,
ignore_filters: bool,
- composer: Option<&Composer>,
+ composer: Option<&PartialComposerHandle>,
) -> Result<i64> {
+ let composer_guard = composer.map(crate::command::composer_full);
let owned_archive_manager;
- let archive_manager: &ArchiveManager = if let Some(composer) = composer {
- composer.get_archive_manager()
+ let composer_archive_manager;
+ let composer_archive_manager_ref;
+ let archive_manager: &ArchiveManager = if let Some(composer) = &composer_guard {
+ composer_archive_manager = composer.get_archive_manager().clone();
+ composer_archive_manager_ref = composer_archive_manager.borrow();
+ &composer_archive_manager_ref
} else {
let factory = Factory;
let process = std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(())));
@@ -198,7 +201,10 @@ impl ArchiveCommand {
None => return Ok(1),
}
} else {
- self.require_composer(None, None)?.get_package().clone_box()
+ let _rc = self.require_composer(None, None)?;
+ crate::command::composer_full(&_rc)
+ .get_package()
+ .clone_box()
};
io.write_error(&format!(
@@ -244,12 +250,14 @@ impl ArchiveCommand {
let repo;
if let Some(composer) = self.try_composer(None, None) {
- let local_repo = composer.get_repository_manager().get_local_repository();
+ let composer = crate::command::composer_full(&composer);
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let local_repo = repository_manager.get_local_repository();
let mut repos: Vec<Box<dyn crate::repository::RepositoryInterface>> =
vec![local_repo.clone_box()];
repos.extend(
- composer
- .get_repository_manager()
+ repository_manager
.get_repositories()
.iter()
.map(|r| r.clone_box()),
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index c2e6c93..e814821 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -3,7 +3,7 @@
use crate::advisory::AuditConfig;
use crate::advisory::Auditor;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::package::PackageInterface;
@@ -51,14 +51,15 @@ impl AuditCommand {
input: &dyn InputInterface,
_output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
- let packages = self.get_packages(&mut composer, input)?;
+ let composer = self.require_composer(None, None)?;
+ let packages = self.get_packages(&composer, input)?;
if packages.is_empty() {
self.get_io().write_error("No packages - skipping audit.");
return Ok(0);
}
+ let composer = crate::command::composer_full(&composer);
let auditor = Auditor;
let mut repo_set = RepositorySet::new(
"stable",
@@ -68,7 +69,11 @@ impl AuditCommand {
indexmap::IndexMap::new(),
indexmap::IndexMap::new(),
);
- for repo in composer.get_repository_manager().get_repositories() {
+ for repo in composer
+ .get_repository_manager()
+ .borrow()
+ .get_repositories()
+ {
// TODO(phase-b): repositories are shared (PHP class semantics); needs Rc wrapper
repo_set.add_repository(repo.clone_box())?;
}
@@ -139,11 +144,13 @@ impl AuditCommand {
fn get_packages(
&self,
- composer: &mut Composer,
+ composer: &PartialComposerHandle,
input: &dyn InputInterface,
) -> Result<Vec<Box<dyn PackageInterface>>> {
+ let mut composer = crate::command::composer_full_mut(composer);
if input.get_option("locked").as_bool().unwrap_or(false) {
- let locker = composer.get_locker_mut();
+ let locker = composer.get_locker().clone();
+ let mut locker = locker.borrow_mut();
if !locker.is_locked() {
return Err(UnexpectedValueException {
message: "Valid composer.json and composer.lock files are required to run this command with --locked".to_string(),
diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs
index 2aebccb..9511c4d 100644
--- a/crates/shirabe/src/command/base_command.rs
+++ b/crates/shirabe/src/command/base_command.rs
@@ -17,7 +17,7 @@ use shirabe_php_shim::{
use crate::advisory::AuditConfig;
use crate::advisory::Auditor;
use crate::command::SelfUpdateCommand;
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::config::Config;
use crate::console::Application;
use crate::console::input::InputArgument;
@@ -160,23 +160,23 @@ pub trait BaseCommand {
required: bool,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Result<Option<Composer>>;
+ ) -> Result<Option<PartialComposerHandle>>;
/// Retrieves the default Composer\Composer instance or throws
fn require_composer(
&mut self,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Result<Composer>;
+ ) -> Result<PartialComposerHandle>;
/// Retrieves the default Composer\Composer instance or null
fn try_composer(
&mut self,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Option<Composer>;
+ ) -> Option<PartialComposerHandle>;
- fn set_composer(&mut self, composer: Composer);
+ fn set_composer(&mut self, composer: PartialComposerHandle);
/// Removes the cached composer instance
fn reset_composer(&mut self) -> Result<()>;
@@ -205,7 +205,7 @@ pub trait BaseCommand {
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
- ) -> Result<Composer>;
+ ) -> Result<PartialComposerHandle>;
/// Returns preferSource and preferDist values based on the configuration.
fn get_preferred_install_options(
@@ -253,7 +253,7 @@ pub trait BaseCommand {
#[derive(Debug)]
pub struct BaseCommandData {
- pub(crate) composer: Option<Composer>,
+ pub(crate) composer: Option<PartialComposerHandle>,
pub(crate) io: Option<Box<dyn IOInterface>>,
}
@@ -261,11 +261,11 @@ pub trait HasBaseCommandData {
fn base_command_data(&self) -> &BaseCommandData;
fn base_command_data_mut(&mut self) -> &mut BaseCommandData;
- fn composer(&self) -> Option<&Composer> {
- self.base_command_data().composer.as_ref()
+ fn composer(&self) -> Option<PartialComposerHandle> {
+ self.base_command_data().composer.clone()
}
- fn composer_mut(&mut self) -> &mut Option<Composer> {
+ fn composer_mut(&mut self) -> &mut Option<PartialComposerHandle> {
&mut self.base_command_data_mut().composer
}
@@ -289,7 +289,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
required: bool,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Result<Option<Composer>> {
+ ) -> Result<Option<PartialComposerHandle>> {
if required {
return Ok(Some(
self.require_composer(disable_plugins, disable_scripts)?,
@@ -303,27 +303,25 @@ impl<C: HasBaseCommandData> BaseCommand for C {
&mut self,
_disable_plugins: Option<bool>,
_disable_scripts: Option<bool>,
- ) -> Result<Composer> {
- // TODO(phase-b): Composer is a PHP class (shared by reference). Returning owned
- // `Composer` and the Application::get_composer -> &Composer mismatch require a
- // shared-ownership wrapper (Rc<RefCell<Composer>>) before this can be wired up.
+ ) -> Result<PartialComposerHandle> {
+ // TODO(phase-b): depends on Application::get_composer, which is still stubbed.
let _ = RuntimeException {
message: String::new(),
code: 0,
};
- todo!("require_composer pending Composer shared-ownership refactor")
+ todo!("require_composer pending Application::get_composer")
}
fn try_composer(
&mut self,
_disable_plugins: Option<bool>,
_disable_scripts: Option<bool>,
- ) -> Option<Composer> {
- // TODO(phase-b): same shared-ownership refactor as require_composer.
- todo!("try_composer pending Composer shared-ownership refactor")
+ ) -> Option<PartialComposerHandle> {
+ // TODO(phase-b): depends on Application::get_composer, which is still stubbed.
+ todo!("try_composer pending Application::get_composer")
}
- fn set_composer(&mut self, composer: Composer) {
+ fn set_composer(&mut self, composer: PartialComposerHandle) {
*self.composer_mut() = Some(composer);
}
@@ -389,7 +387,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
);
// TODO(phase-b): event_dispatcher.dispatch expects Option<Event>; need wrapper from
// PreCommandRunEvent.
- let _ = composer.get_event_dispatcher();
+ let _ = composer.borrow_partial().get_event_dispatcher();
let _ = pre_command_run_event.get_name();
}
@@ -482,7 +480,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
config: Option<IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
- ) -> Result<Composer> {
+ ) -> Result<PartialComposerHandle> {
let disable_plugins =
disable_plugins || input.has_parameter_option(&["--no-plugins"], false);
let disable_scripts = disable_scripts.unwrap_or(false)
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index 7ef3b15..498c589 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -47,7 +47,8 @@ pub trait BaseDependencyCommand: BaseCommand {
output: &dyn OutputInterface,
inverted: bool,
) -> anyhow::Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
// TODO(plugin): dispatch CommandEvent(PluginEvents::COMMAND, self.get_name(), input, output) via composer.get_event_dispatcher()
let mut repos: Vec<Box<dyn RepositoryInterface>> = vec![];
@@ -56,7 +57,8 @@ pub trait BaseDependencyCommand: BaseCommand {
)));
if input.get_option("locked").as_bool().unwrap_or(false) {
- let locker = composer.get_locker_mut();
+ let locker = composer.get_locker().clone();
+ let mut locker = locker.borrow_mut();
if !locker.is_locked() {
return Err(anyhow::anyhow!(UnexpectedValueException {
@@ -78,7 +80,9 @@ pub trait BaseDependencyCommand: BaseCommand {
platform_overrides,
)?));
} else {
- let local_repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let local_repo = repository_manager.get_local_repository();
let root_pkg = composer.get_package();
if local_repo.get_packages().len() == 0
@@ -142,7 +146,7 @@ pub trait BaseDependencyCommand: BaseCommand {
let default_repos = CompositeRepository::new(
RepositoryFactory::default_repos(
Some(self.get_io()),
- Some(std::rc::Rc::clone(composer.get_config())),
+ Some(composer.get_config()),
// TODO(phase-b): get_repository_manager returns &; default_repos needs &mut
Some(todo!("share repository_manager as &mut")),
)?
diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs
index 4141235..0b9727f 100644
--- a/crates/shirabe/src/command/bump_command.rs
+++ b/crates/shirabe/src/command/bump_command.rs
@@ -9,7 +9,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{PhpMixed, file_get_contents, file_put_contents, is_writable, strtolower};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::factory::Factory;
@@ -134,7 +133,8 @@ impl BumpCommand {
return Ok(Self::ERROR_GENERIC);
}
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
let has_lock_file_disabled = !composer.get_config().borrow().has("lock")
|| composer
.get_config()
@@ -143,9 +143,14 @@ impl BumpCommand {
.as_bool()
.unwrap_or(true);
let repo: Box<dyn crate::repository::RepositoryInterface> = if !has_lock_file_disabled {
- Box::new(composer.get_locker_mut().get_locked_repository(true)?)
- } else if composer.get_locker_mut().is_locked() {
- if !composer.get_locker_mut().is_fresh()? {
+ Box::new(
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?,
+ )
+ } else if composer.get_locker().borrow_mut().is_locked() {
+ if !composer.get_locker().borrow_mut().is_fresh()? {
io.write_error3(
"<error>The lock file is not up to date with the latest changes in composer.json. Run the appropriate `update` to fix that before you use the `bump` command.</error>",
true,
@@ -153,12 +158,18 @@ impl BumpCommand {
);
return Ok(Self::ERROR_LOCK_OUTDATED);
}
- Box::new(composer.get_locker_mut().get_locked_repository(true)?)
+ Box::new(
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?,
+ )
} else {
// TODO(phase-b): get_local_repository returns &dyn InstalledRepositoryInterface;
// cloning into an owned Box requires clone_box on that trait.
composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.clone_box()
};
@@ -253,7 +264,7 @@ impl BumpCommand {
}
updates
- .entry(key)
+ .entry(*key)
.or_default()
.insert(pkg_name.clone(), bumped);
}
@@ -306,7 +317,7 @@ impl BumpCommand {
}
if !dry_run
- && composer.get_locker_mut().is_locked()
+ && composer.get_locker().borrow_mut().is_locked()
&& composer
.get_config()
.borrow_mut()
@@ -316,7 +327,8 @@ impl BumpCommand {
&& change_count > 0
{
composer
- .get_locker_mut()
+ .get_locker()
+ .borrow_mut()
.update_hash(&composer_json, None::<fn(_) -> _>)?;
}
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index 40bd898..83770be 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -9,7 +9,6 @@ use shirabe_semver::constraint::Constraint;
use shirabe_semver::constraint::ConstraintInterface;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::json::JsonFile;
@@ -54,7 +53,8 @@ impl CheckPlatformReqsCommand {
input: &dyn InputInterface,
_output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ 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);
@@ -71,16 +71,27 @@ impl CheckPlatformReqsCommand {
"<info>Checking {}platform requirements using the lock file</info>",
if no_dev { "non-dev " } else { "" }
));
- Box::new(composer.get_locker_mut().get_locked_repository(!no_dev)?)
+ Box::new(
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(!no_dev)?,
+ )
} else {
- let local_repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let local_repo = repository_manager.get_local_repository();
if local_repo.get_packages().is_empty() {
io.write_error(&format!(
"<warning>No vendor dir present, checking {}platform requirements from the lock file</warning>",
if no_dev { "non-dev " } else { "" }
));
- Box::new(composer.get_locker_mut().get_locked_repository(!no_dev)?)
- as Box<dyn crate::repository::RepositoryInterface>
+ Box::new(
+ composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(!no_dev)?,
+ ) as Box<dyn crate::repository::RepositoryInterface>
} else {
if no_dev {
remove_packages = local_repo.get_dev_package_names().clone();
diff --git a/crates/shirabe/src/command/clear_cache_command.rs b/crates/shirabe/src/command/clear_cache_command.rs
index 515b0e4..4859a46 100644
--- a/crates/shirabe/src/command/clear_cache_command.rs
+++ b/crates/shirabe/src/command/clear_cache_command.rs
@@ -1,7 +1,8 @@
//! ref: composer/src/Composer/Command/ClearCacheCommand.php
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer;
+use crate::composer::ComposerHandle;
use crate::factory::Factory;
use indexmap::IndexMap;
use shirabe_external_packages::symfony::component::console::input::InputInterface;
@@ -32,7 +33,7 @@ impl ClearCacheCommand {
_output: &dyn OutputInterface,
) -> anyhow::Result<i64> {
// TODO(phase-b): port full execute logic once Config sharing model is settled
- let _ = Composer::VERSION;
+ let _ = composer::VERSION;
let _: IndexMap<String, String> = IndexMap::new();
let _ = Factory::create_config(None, None);
todo!("phase-b: ClearCacheCommand::execute requires Config sharing strategy")
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index 3b9e632..6412160 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -19,7 +19,6 @@ use shirabe_php_shim::{
use crate::advisory::Auditor;
use crate::command::BaseConfigCommand;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::config::Config;
use crate::config::ConfigSourceInterface;
use crate::config::JsonConfigSource;
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index 6a289ed..c0093e8 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -15,7 +15,7 @@ use shirabe_php_shim::{
use crate::advisory::Auditor;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::config::Config;
use crate::config::ConfigSourceInterface;
use crate::config::JsonConfigSource;
@@ -279,21 +279,21 @@ impl CreateProjectCommand {
unlink("composer.lock");
}
- let mut composer =
+ let mut composer_handle =
self.create_composer_instance(input, io, 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() {
if add_repository {
for (index, repo) in repos.iter().enumerate() {
- let repo_config = RepositoryFactory::config_from_string(
- io,
- composer.get_config(),
- repo,
- true,
- )?;
+ let config = crate::command::composer_full(&composer_handle).get_config();
+ let repo_config =
+ RepositoryFactory::config_from_string(io, &config, repo, true)?;
let composer_json_repositories_config =
- composer.get_config().borrow().get_repositories();
+ crate::command::composer_full(&composer_handle)
+ .get_config()
+ .borrow()
+ .get_repositories();
// TODO(phase-b): generate_repository_name expects existing repos as
// IndexMap<String, Box<dyn RepositoryInterface>>; pass empty placeholder.
let _ = &composer_json_repositories_config;
@@ -333,12 +333,14 @@ impl CreateProjectCommand {
);
}
- composer =
+ composer_handle =
self.create_composer_instance(input, io, None, disable_plugins, None)?;
}
}
}
+ let mut composer = crate::command::composer_full_mut(&composer_handle);
+
let process = composer
.get_loop()
.borrow()
@@ -358,7 +360,7 @@ impl CreateProjectCommand {
);
// use the new config including the newly installed project
- let config = std::rc::Rc::clone(composer.get_config());
+ let config = composer.get_config();
let (ps, pd) = self.get_preferred_install_options(&*config.borrow(), input, false)?;
prefer_source = ps;
prefer_dist = pd;
@@ -366,10 +368,11 @@ impl CreateProjectCommand {
// install dependencies of the created project
if no_install == false {
composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .borrow_mut()
.set_output_progress(!no_progress);
- let mut installer = Installer::create(io.clone_box(), &composer);
+ let mut installer = Installer::create(io.clone_box(), &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
@@ -402,7 +405,7 @@ impl CreateProjectCommand {
)
.set_audit_config(self.create_audit_config(&mut *config.borrow_mut(), input)?);
- if !composer.get_locker_mut().is_locked() {
+ if !composer.get_locker().borrow_mut().is_locked() {
installer.set_update(true);
}
@@ -700,13 +703,14 @@ impl CreateProjectCommand {
.into());
}
- let composer = self.create_composer_instance(
+ let composer_handle = self.create_composer_instance(
input,
io,
Some(config.borrow_mut().all(0)?),
disable_plugins,
Some(disable_scripts),
)?;
+ let composer = crate::command::composer_full(&composer_handle);
let config = composer.get_config();
// set the base dir here again on the new config instance, as otherwise in case the vendor dir is defined in an env var for example it would still override the value set above by $config->all()
config.borrow_mut().set_base_dir(Some(directory.clone()));
@@ -910,7 +914,8 @@ impl CreateProjectCommand {
.set_prefer_dist(prefer_dist);
let project_installer = ProjectInstaller::new(&directory, dm.clone(), fs.clone());
- let im = composer.get_installation_manager();
+ let installation_manager = composer.get_installation_manager().clone();
+ let mut im = installation_manager.borrow_mut();
im.set_output_progress(!no_progress);
im.add_installer(Box::new(project_installer));
let mut installed_repo = InstalledArrayRepository::new()?;
@@ -959,7 +964,7 @@ impl CreateProjectCommand {
config: Option<indexmap::IndexMap<String, PhpMixed>>,
disable_plugins: bool,
disable_scripts: Option<bool>,
- ) -> Result<Composer> {
+ ) -> Result<PartialComposerHandle> {
self.create_composer_instance(input, io, config, disable_plugins, disable_scripts)
}
diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs
index 1fdea40..e721e52 100644
--- a/crates/shirabe/src/command/diagnose_command.rs
+++ b/crates/shirabe/src/command/diagnose_command.rs
@@ -20,7 +20,8 @@ use shirabe_php_shim::{
use crate::advisory::Auditor;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer;
+use crate::composer::ComposerHandle;
use crate::config::Config;
use crate::downloader::TransportException;
use crate::factory::Factory;
@@ -81,6 +82,7 @@ impl DiagnoseCommand {
let config: std::rc::Rc<std::cell::RefCell<Config>>;
if let Some(ref mut c) = composer {
+ let c = crate::command::composer_full(c);
config = c.get_config().clone();
let command_event = CommandEvent::new6(
@@ -146,7 +148,7 @@ impl DiagnoseCommand {
io.write(&format!(
"Composer version: <comment>{}</comment>",
- Composer::get_version()
+ composer::get_version()
));
io.write_no_newline("Checking Composer and its dependencies for vulnerabilities: ");
@@ -244,18 +246,24 @@ impl DiagnoseCommand {
));
if let Some(ref mut c) = composer {
+ let mut c = crate::command::composer_full_mut(c);
io.write(&format!(
"Active plugins: {}",
- implode(", ", &c.get_plugin_manager().get_registered_plugins())
+ implode(
+ ", ",
+ &c.get_plugin_manager().borrow().get_registered_plugins()
+ )
));
io.write_no_newline("Checking composer.json: ");
let r = self.check_composer_schema()?;
self.output_result(r);
- if c.get_locker_mut().is_locked() {
+ if c.get_locker().borrow_mut().is_locked() {
io.write_no_newline("Checking composer.lock: ");
- let r = self.check_composer_lock_schema(c.get_locker_mut())?;
+ let locker = c.get_locker().clone();
+ let locker = locker.borrow();
+ let r = self.check_composer_lock_schema(&locker)?;
self.output_result(r);
}
}
@@ -874,11 +882,11 @@ impl DiagnoseCommand {
.and_then(|v| v.as_string())
.unwrap_or("")
.to_string();
- if Composer::VERSION != latest_version && Composer::VERSION != "@package_version@" {
+ if composer::VERSION != latest_version && composer::VERSION != "@package_version@" {
return Ok(PhpMixed::String(format!(
"<comment>You are not running the latest {} version, run `composer self-update` to update ({} => {})</comment>",
versions_util.get_channel()?,
- Composer::VERSION,
+ composer::VERSION,
latest_version
)));
}
@@ -912,7 +920,7 @@ impl DiagnoseCommand {
}
let local_repo = FilesystemRepository::new(installed_json, false, None, None)?;
- let version = Composer::get_version();
+ let version = composer::get_version();
let mut packages = local_repo.inner.get_canonical_packages();
if version != "@package_version@" {
let version_parser = VersionParser::new();
diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs
index 5e883c7..588c91e 100644
--- a/crates/shirabe/src/command/dump_autoload_command.rs
+++ b/crates/shirabe/src/command/dump_autoload_command.rs
@@ -6,7 +6,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{InvalidArgumentException, PhpMixed, file_exists};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::plugin::CommandEvent;
@@ -47,7 +46,8 @@ impl DumpAutoloadCommand {
input: &dyn InputInterface,
output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
// TODO(plugin): dispatch CommandEvent
let command_event =
@@ -58,11 +58,13 @@ impl DumpAutoloadCommand {
.dispatch(Some(command_event.get_name()), None);
// Clone the Rc<RefCell<Config>> so we can take mutable borrows of composer later
- let config = std::rc::Rc::clone(composer.get_config());
+ let config = composer.get_config();
let mut missing_dependencies = false;
{
- let local_repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let local_repo = repository_manager.get_local_repository();
for local_pkg in local_repo.get_canonical_packages() {
// TODO(phase-b): get_install_path takes &mut self on installation_manager which conflicts with the &local_repo borrow held by this loop; needs shared-ownership refactor
let install_path: Option<String> =
@@ -137,10 +139,16 @@ impl DumpAutoloadCommand {
let platform_requirement_filter = self.get_platform_requirement_filter(input)?;
if input.get_option("dry-run").as_bool().unwrap_or(false) {
- composer.get_autoload_generator_mut().set_dry_run(true);
+ composer
+ .get_autoload_generator()
+ .borrow_mut()
+ .set_dry_run(true);
}
if input.get_option("no-dev").as_bool().unwrap_or(false) {
- composer.get_autoload_generator_mut().set_dev_mode(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) {
@@ -152,17 +160,26 @@ impl DumpAutoloadCommand {
}
.into());
}
- composer.get_autoload_generator_mut().set_dev_mode(true);
+ composer
+ .get_autoload_generator()
+ .borrow_mut()
+ .set_dev_mode(true);
}
composer
- .get_autoload_generator_mut()
+ .get_autoload_generator()
+ .borrow_mut()
.set_class_map_authoritative(authoritative);
- composer.get_autoload_generator_mut().set_run_scripts(true);
composer
- .get_autoload_generator_mut()
+ .get_autoload_generator()
+ .borrow_mut()
+ .set_run_scripts(true);
+ composer
+ .get_autoload_generator()
+ .borrow_mut()
.set_apcu(apcu, apcu_prefix);
composer
- .get_autoload_generator_mut()
+ .get_autoload_generator()
+ .borrow_mut()
.set_platform_requirement_filter(platform_requirement_filter);
// TODO(phase-b): dump requires multiple borrows of composer simultaneously (autoload generator mut, repository, package, installation manager, locker); needs shared-ownership refactor
let class_map: shirabe_class_map_generator::class_map::ClassMap =
diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs
index 198bdb1..68e2d0f 100644
--- a/crates/shirabe/src/command/exec_command.rs
+++ b/crates/shirabe/src/command/exec_command.rs
@@ -6,7 +6,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{PhpMixed, RuntimeException, basename, chdir, getcwd, glob};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
@@ -80,15 +79,15 @@ impl ExecCommand {
input: &dyn InputInterface,
_output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
if input.get_option("list").as_bool().unwrap_or(false)
|| input.get_argument("binary").as_string_opt().is_none()
{
let bins = self.get_binaries(true)?;
if bins.is_empty() {
- let bin_dir = composer
- .get_config_mut()
+ let bin_dir = crate::command::composer_full_mut(&composer)
+ .get_config()
.borrow_mut()
.get("bin-dir")
.as_string()
@@ -119,9 +118,11 @@ impl ExecCommand {
.unwrap_or("")
.to_string();
- let dispatcher = composer.get_event_dispatcher();
+ let dispatcher = crate::command::composer_full(&composer)
+ .get_event_dispatcher()
+ .clone();
// TODO(phase-b): add_listener takes a Callable; wiring binary as callable not yet ported
- let _ = (dispatcher, &binary);
+ let _ = &binary;
let initial_working_directory = self.get_application()?.get_initial_working_directory();
if let Some(ref iwd) = initial_working_directory {
@@ -152,16 +153,17 @@ impl ExecCommand {
}
fn get_binaries(&mut self, for_display: bool) -> Result<Vec<String>> {
- let mut composer = self.require_composer(None, None)?;
- let bin_dir = composer
- .get_config_mut()
+ let composer = self.require_composer(None, None)?;
+ let composer_ref = crate::command::composer_full_mut(&composer);
+ let bin_dir = composer_ref
+ .get_config()
.borrow_mut()
.get("bin-dir")
.as_string()
.unwrap_or("")
.to_string();
let bins = glob(&format!("{}/*", bin_dir));
- let local_bins_raw: Vec<String> = composer.get_package().get_binaries();
+ let local_bins_raw: Vec<String> = composer_ref.get_package().get_binaries();
let local_bins: Vec<String> = if for_display {
local_bins_raw
.into_iter()
diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs
index 058e5af..233eeaa 100644
--- a/crates/shirabe/src/command/fund_command.rs
+++ b/crates/shirabe/src/command/fund_command.rs
@@ -13,7 +13,6 @@ use shirabe_semver::constraint::ConstraintInterface;
use shirabe_semver::constraint::MatchAllConstraint;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::json::JsonFile;
@@ -51,11 +50,13 @@ impl FundCommand {
_output: &dyn OutputInterface,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
+ let composer = crate::command::composer_full(&composer);
- let repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let repo = repository_manager.get_local_repository();
let remote_repos = CompositeRepository::new(
- composer
- .get_repository_manager()
+ repository_manager
.get_repositories()
.iter()
.map(|r| r.clone_box())
diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs
index 27dec6a..a8cf1d4 100644
--- a/crates/shirabe/src/command/global_command.rs
+++ b/crates/shirabe/src/command/global_command.rs
@@ -10,7 +10,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{LogicException, RuntimeException, chdir};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::factory::Factory;
use crate::io::IOInterface;
diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs
index 6f3ac5c..e7fc6b5 100644
--- a/crates/shirabe/src/command/home_command.rs
+++ b/crates/shirabe/src/command/home_command.rs
@@ -6,7 +6,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{FILTER_VALIDATE_URL, PhpMixed, filter_var};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
@@ -90,12 +89,9 @@ impl HomeCommand {
let packages = if packages.is_empty() {
io.write_error("No package specified, opening homepage for the root package");
- vec![
- self.require_composer(None, None)?
- .get_package()
- .get_name()
- .to_string(),
- ]
+ let composer_rc = self.require_composer(None, None)?;
+ let composer_ref = crate::command::composer_full(&composer_rc);
+ vec![composer_ref.get_package().get_name().to_string()]
} else {
packages
};
@@ -209,6 +205,7 @@ impl HomeCommand {
let composer = self.try_composer(None, None);
if let Some(composer) = composer {
+ let composer = crate::command::composer_full(&composer);
let mut repos: Vec<Box<dyn RepositoryInterface>> = vec![];
repos.push(Box::new(RootPackageRepository::new(
composer.get_package().clone_box(),
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs
index eb6983f..122642d 100644
--- a/crates/shirabe/src/command/init_command.rs
+++ b/crates/shirabe/src/command/init_command.rs
@@ -19,7 +19,7 @@ use shirabe_php_shim::{
use crate::command::PackageDiscoveryTrait;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::console::input::InputOption;
use crate::factory::Factory;
use crate::io::IOInterface;
@@ -56,7 +56,7 @@ impl PackageDiscoveryTrait for InitCommand {
todo!()
}
- fn try_composer(&self) -> Option<Composer> {
+ fn try_composer(&self) -> Option<PartialComposerHandle> {
todo!()
}
@@ -64,7 +64,7 @@ impl PackageDiscoveryTrait for InitCommand {
&self,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Composer {
+ ) -> PartialComposerHandle {
todo!()
}
diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs
index 666833d..632ccb1 100644
--- a/crates/shirabe/src/command/install_command.rs
+++ b/crates/shirabe/src/command/install_command.rs
@@ -100,9 +100,10 @@ impl InstallCommand {
return Ok(1);
}
- let mut composer = self.require_composer(None, None)?;
+ let composer_handle = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer_handle);
- if !composer.get_locker_mut().is_locked() && !HttpDownloader::is_curl_enabled() {
+ if !composer.get_locker().borrow_mut().is_locked() && !HttpDownloader::is_curl_enabled() {
io.write_error("<warning>Composer is operating significantly slower than normal because you do not have the PHP curl extension enabled.</warning>");
}
@@ -113,9 +114,9 @@ impl InstallCommand {
.borrow_mut()
.dispatch(Some(command_event.get_name()), None);
- let mut install = Installer::create(io.clone_box(), &composer);
+ let mut install = Installer::create(io.clone_box(), &composer_handle);
- let config = std::rc::Rc::clone(composer.get_config());
+ let config = composer.get_config();
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&*config.borrow(), input, false)?;
@@ -153,7 +154,8 @@ impl InstallCommand {
.unwrap_or(false);
composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .borrow_mut()
.set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
install
diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs
index 0c00ed6..961f70b 100644
--- a/crates/shirabe/src/command/licenses_command.rs
+++ b/crates/shirabe/src/command/licenses_command.rs
@@ -12,7 +12,6 @@ use shirabe_external_packages::symfony::console::style::SymfonyStyle;
use shirabe_php_shim::{PhpMixed, RuntimeException, UnexpectedValueException};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::json::JsonFile;
@@ -80,7 +79,8 @@ impl LicensesCommand {
input: &dyn InputInterface,
output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ 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);
@@ -95,7 +95,8 @@ impl LicensesCommand {
let root_licenses_snap = composer.get_package().get_license().clone();
let packages = if input.get_option("locked").as_bool().unwrap_or(false) {
- let locker = composer.get_locker_mut();
+ let locker = composer.get_locker().clone();
+ let mut locker = locker.borrow_mut();
if !locker.is_locked() {
return Err(UnexpectedValueException {
message: "Valid composer.json and composer.lock files are required to run this command with --locked".to_string(),
@@ -106,7 +107,9 @@ impl LicensesCommand {
let repo = locker.get_locked_repository(!no_dev)?;
<crate::repository::LockArrayRepository as crate::repository::RepositoryInterface>::get_packages(&repo)
} else {
- let repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let repo = repository_manager.get_local_repository();
if input.get_option("no-dev").as_bool().unwrap_or(false) {
RepositoryUtils::filter_required_packages(
&repo.get_packages(),
diff --git a/crates/shirabe/src/command/mod.rs b/crates/shirabe/src/command/mod.rs
index 614fff7..4452f85 100644
--- a/crates/shirabe/src/command/mod.rs
+++ b/crates/shirabe/src/command/mod.rs
@@ -37,6 +37,8 @@ pub mod suggests_command;
pub mod update_command;
pub mod validate_command;
+pub(crate) use crate::composer::{composer_full, composer_full_mut};
+
pub use about_command::*;
pub use archive_command::*;
pub use audit_command::*;
diff --git a/crates/shirabe/src/command/outdated_command.rs b/crates/shirabe/src/command/outdated_command.rs
index c4d9e89..89edb44 100644
--- a/crates/shirabe/src/command/outdated_command.rs
+++ b/crates/shirabe/src/command/outdated_command.rs
@@ -1,7 +1,6 @@
//! ref: composer/src/Composer/Command/OutdatedCommand.php
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs
index f273811..43d6ee8 100644
--- a/crates/shirabe/src/command/package_discovery_trait.rs
+++ b/crates/shirabe/src/command/package_discovery_trait.rs
@@ -15,7 +15,7 @@ use shirabe_php_shim::{
trim,
};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::factory::Factory;
use crate::filter::platform_requirement_filter::IgnoreAllPlatformRequirementFilter;
use crate::filter::platform_requirement_filter::PlatformRequirementFilterFactory;
@@ -41,12 +41,12 @@ pub trait PackageDiscoveryTrait {
// PHP: trait dependencies (provided by BaseCommand)
fn get_io(&self) -> &dyn IOInterface;
- fn try_composer(&self) -> Option<Composer>;
+ fn try_composer(&self) -> Option<PartialComposerHandle>;
fn require_composer(
&self,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Composer;
+ ) -> PartialComposerHandle;
fn get_platform_requirement_filter(
&self,
input: &dyn InputInterface,
@@ -219,10 +219,14 @@ pub trait PackageDiscoveryTrait {
// Collect existing packages
let composer = self.try_composer();
- let mut installed_repo: Option<_> = None;
- if let Some(c) = &composer {
- installed_repo = Some(c.get_repository_manager().get_local_repository());
- }
+ let composer_ref = composer.as_ref().map(|c| c.borrow_partial());
+ let repository_manager = composer_ref
+ .as_ref()
+ .map(|c| c.get_repository_manager().clone());
+ let repository_manager_ref = repository_manager.as_ref().map(|rm| rm.borrow());
+ let installed_repo = repository_manager_ref
+ .as_ref()
+ .map(|rm| rm.get_local_repository());
let mut existing_packages: Vec<String> = vec![];
if let Some(repo) = &installed_repo {
for package in repo.get_packages() {
@@ -231,6 +235,9 @@ pub trait PackageDiscoveryTrait {
}
// PHP: unset($composer, $installedRepo);
drop(installed_repo);
+ drop(repository_manager_ref);
+ drop(repository_manager);
+ drop(composer_ref);
drop(composer);
let io = self.get_io();
@@ -804,9 +811,10 @@ pub trait PackageDiscoveryTrait {
let mut similar_packages: IndexMap<String, i64> = IndexMap::new();
let composer_for_installed = self.require_composer(None, None);
- let installed_repo = composer_for_installed
- .get_repository_manager()
- .get_local_repository();
+ let composer_for_installed = composer_for_installed.borrow_partial();
+ let repository_manager = composer_for_installed.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let installed_repo = repository_manager.get_local_repository();
for result in &results {
// TODO(phase-b): installed_repo.find_package signature mismatch with FindPackageConstraint
diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs
index 3e985a4..8bb4643 100644
--- a/crates/shirabe/src/command/reinstall_command.rs
+++ b/crates/shirabe/src/command/reinstall_command.rs
@@ -9,7 +9,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::InvalidArgumentException;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputDefinitionItem;
use crate::console::input::InputOption;
@@ -68,9 +67,12 @@ impl ReinstallCommand {
output: &dyn OutputInterface,
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
+ let composer = crate::command::composer_full(&composer);
let io = self.get_io();
- let local_repo = composer.get_repository_manager().get_local_repository();
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let local_repo = repository_manager.get_local_repository();
let mut packages_to_reinstall: Vec<Box<dyn crate::package::PackageInterface>> = vec![];
let mut package_names_to_reinstall: Vec<String> = vec![];
@@ -193,11 +195,11 @@ impl ReinstallCommand {
.borrow_mut()
.dispatch(Some(command_event.get_name()), None);
- let config = std::rc::Rc::clone(composer.get_config());
+ let config = composer.get_config();
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&*config.borrow(), input, false)?;
- let installation_manager = composer.get_installation_manager();
+ let installation_manager = composer.get_installation_manager().clone();
let download_manager = composer.get_download_manager();
let package = composer.get_package();
diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs
index dbffcea..ab322f9 100644
--- a/crates/shirabe/src/command/remove_command.rs
+++ b/crates/shirabe/src/command/remove_command.rs
@@ -9,7 +9,6 @@ use shirabe_php_shim::{PhpMixed, UnexpectedValueException, array_map, strtolower
use crate::advisory::Auditor;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::config::ConfigSourceInterface;
use crate::config::JsonConfigSource;
use crate::console::input::InputArgument;
@@ -183,9 +182,11 @@ impl RemoveCommand {
.unwrap_or_default();
if input.get_option("unused").as_bool().unwrap_or(false) {
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
{
- let locker = composer.get_locker_mut();
+ let locker = composer.get_locker().clone();
+ let mut locker = locker.borrow_mut();
if !locker.is_locked() {
return Err(anyhow::anyhow!(UnexpectedValueException {
message:
@@ -197,7 +198,8 @@ impl RemoveCommand {
}
let locked_packages = composer
- .get_locker_mut()
+ .get_locker()
+ .borrow_mut()
.get_locked_repository(true)?
.get_packages();
@@ -426,14 +428,17 @@ impl RemoveCommand {
}
// TODO(plugin): deactivate installed plugins
- if let Some(mut composer_opt) = self.try_composer(None, None) {
+ if let Some(composer_opt) = self.try_composer(None, None) {
+ let mut composer_opt = crate::command::composer_full_mut(&composer_opt);
composer_opt
- .get_plugin_manager_mut()
+ .get_plugin_manager()
+ .borrow_mut()
.deactivate_installed_plugins();
}
self.reset_composer();
- let mut composer = self.require_composer(None, None)?;
+ let composer_handle = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer_handle);
if dry_run {
// TODO(phase-b): composer.get_package() returns &dyn RootPackageInterface; set_requires/set_dev_requires need &mut self; needs shared-ownership refactor
@@ -501,12 +506,13 @@ impl RemoveCommand {
}
composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .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>");
- let mut install = Installer::create(io_box, &composer);
+ let mut install = Installer::create(io_box, &composer_handle);
let update_dev_mode = !input.get_option("update-no-dev").as_bool().unwrap_or(false);
let optimize = input
@@ -601,7 +607,7 @@ impl RemoveCommand {
// if no lock is present, we do not do a partial update as
// this is not supported by the Installer
- if composer.get_locker_mut().is_locked() {
+ if composer.get_locker().borrow_mut().is_locked() {
install.set_update_allow_list(packages.clone());
}
@@ -618,6 +624,7 @@ impl RemoveCommand {
for package in &packages {
if !composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.find_packages(package, None)
.is_empty()
diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs
index dce57b5..1f6599b 100644
--- a/crates/shirabe/src/command/repository_command.rs
+++ b/crates/shirabe/src/command/repository_command.rs
@@ -10,7 +10,6 @@ use shirabe_php_shim::{
use crate::command::BaseConfigCommand;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::config::Config;
use crate::config::ConfigSourceInterface;
use crate::config::JsonConfigSource;
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index 5f4e27a..15bff24 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -17,7 +17,7 @@ use shirabe_php_shim::{
use crate::advisory::Auditor;
use crate::command::PackageDiscoveryTrait;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::dependency_resolver::Request;
@@ -74,7 +74,7 @@ impl PackageDiscoveryTrait for RequireCommand {
todo!()
}
- fn try_composer(&self) -> Option<Composer> {
+ fn try_composer(&self) -> Option<PartialComposerHandle> {
todo!()
}
@@ -82,7 +82,7 @@ impl PackageDiscoveryTrait for RequireCommand {
&self,
disable_plugins: Option<bool>,
disable_scripts: Option<bool>,
- ) -> Composer {
+ ) -> PartialComposerHandle {
todo!()
}
@@ -251,7 +251,10 @@ impl RequireCommand {
}
let composer = self.require_composer(None, None)?;
- let repos = composer.get_repository_manager().get_repositories();
+ let composer = crate::command::composer_full(&composer);
+ let repository_manager = composer.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let repos = repository_manager.get_repositories();
let platform_overrides = composer.get_config().borrow_mut().get("platform");
let platform_overrides_map: IndexMap<String, PhpMixed> = platform_overrides
@@ -545,7 +548,10 @@ impl RequireCommand {
return Ok(0);
}
- composer.get_plugin_manager().deactivate_installed_plugins();
+ composer
+ .get_plugin_manager()
+ .borrow_mut()
+ .deactivate_installed_plugins();
// try/catch/finally
// TODO(phase-b): do_update borrows io from self while also needing &mut self for state
@@ -683,7 +689,8 @@ impl RequireCommand {
) -> Result<i64> {
// Update packages
self.reset_composer()?;
- let mut composer = self.require_composer(None, None)?;
+ let composer_handle = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer_handle);
self.dependency_resolution_completed = false;
// TODO(phase-b): add_listener expects a Callable enum; PHP closure should set
@@ -837,12 +844,14 @@ impl RequireCommand {
.dispatch(Some(command_event.get_name()), None);
composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .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
// borrowed &dyn here; needs Rc<dyn IOInterface> for proper sharing.
- let mut install = Installer::create(todo!("share io as Box<dyn IOInterface>"), &composer);
+ let mut install =
+ Installer::create(todo!("share io as Box<dyn IOInterface>"), &composer_handle);
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&*composer.get_config().borrow(), input, false)?;
@@ -871,7 +880,7 @@ impl RequireCommand {
// if no lock is present, or the file is brand new, we do not do a
// partial update as this is not supported by the Installer
- if !self.first_require && composer.get_locker().is_locked() {
+ if !self.first_require && composer.get_locker().borrow_mut().is_locked() {
install.set_update_allow_list(
array_keys(requirements)
.into_iter()
@@ -920,8 +929,9 @@ impl RequireCommand {
dry_run: bool,
fixed: bool,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
- let locker_is_locked = composer.get_locker_mut().is_locked();
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
+ let locker_is_locked = composer.get_locker().borrow_mut().is_locked();
let mut requirements: IndexMap<String, String> = IndexMap::new();
let mut version_selector = VersionSelector::new(
RepositorySet::new(
@@ -939,7 +949,10 @@ impl RequireCommand {
// interface for find_package.
let locked_repo;
let repo: &dyn RepositoryInterface = if locker_is_locked {
- locked_repo = composer.get_locker_mut().get_locked_repository(true)?;
+ locked_repo = composer
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?;
&locked_repo
} else {
todo!("convert &dyn InstalledRepositoryInterface to &dyn RepositoryInterface")
diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs
index 8121feb..436d906 100644
--- a/crates/shirabe/src/command/run_script_command.rs
+++ b/crates/shirabe/src/command/run_script_command.rs
@@ -7,7 +7,6 @@ use shirabe_external_packages::symfony::component::console::output::OutputInterf
use shirabe_php_shim::{InvalidArgumentException, PhpMixed, RuntimeException};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
@@ -184,6 +183,9 @@ impl RunScriptCommand {
}
let composer = self.require_composer(None, None)?;
+ 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);
// TODO(phase-b): ScriptEvent::new takes Composer/IOInterface by value; placeholder construction.
@@ -224,8 +226,7 @@ impl RunScriptCommand {
Platform::put_env("COMPOSER_DEV_MODE", if dev_mode { "1" } else { "0" });
- Ok(composer
- .get_event_dispatcher()
+ Ok(dispatcher
.borrow_mut()
.dispatch_script(&script, dev_mode, args, IndexMap::new())?)
}
@@ -254,10 +255,11 @@ impl RunScriptCommand {
}
fn get_scripts(&mut self) -> Result<Vec<(String, String)>> {
- let scripts = self
- .require_composer(None, None)?
+ let composer = self.require_composer(None, None)?;
+ let scripts = crate::command::composer_full(&composer)
.get_package()
.get_scripts();
+ drop(composer);
if scripts.is_empty() {
return Ok(vec![]);
}
diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs
index a054631..6499002 100644
--- a/crates/shirabe/src/command/script_alias_command.rs
+++ b/crates/shirabe/src/command/script_alias_command.rs
@@ -1,7 +1,6 @@
//! ref: composer/src/Composer/Command/ScriptAliasCommand.php
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
@@ -98,6 +97,9 @@ impl ScriptAliasCommand {
_output: &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();
@@ -136,8 +138,7 @@ impl ScriptAliasCommand {
})
.unwrap_or_default();
- Ok(composer
- .get_event_dispatcher()
+ Ok(dispatcher
.borrow_mut()
.dispatch_script(&self.script, dev_mode, args_value, flags)?)
}
diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs
index 16df221..fb6b047 100644
--- a/crates/shirabe/src/command/search_command.rs
+++ b/crates/shirabe/src/command/search_command.rs
@@ -1,7 +1,6 @@
//! ref: composer/src/Composer/Command/SearchCommand.php
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::io::IOInterface;
@@ -77,21 +76,27 @@ impl SearchCommand {
let io_box = self.get_io().clone_box();
self.create_composer_instance(input, io_box.as_ref(), 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>
let local_repo: Box<dyn RepositoryInterface> =
todo!("share local_repo as RepositoryInterface");
let installed_repo = CompositeRepository::new(vec![local_repo, Box::new(platform_repo)]);
let mut all_repos: Vec<Box<dyn RepositoryInterface>> = vec![Box::new(installed_repo)];
// TODO(phase-b): get_repositories returns &Vec<Box<...>>; needs ownership reshape
- for r in composer.get_repository_manager().get_repositories() {
+ for r in composer_ref
+ .get_repository_manager()
+ .borrow()
+ .get_repositories()
+ {
all_repos.push(r.clone_box());
}
let repos = CompositeRepository::new(all_repos);
// TODO(plugin): dispatch CommandEvent for search command
let command_event = CommandEvent::new(PluginEvents::COMMAND, "search", input, output);
- composer
- .get_event_dispatcher()
+ let dispatcher = composer_ref.get_event_dispatcher().clone();
+ drop(composer_ref);
+ dispatcher
.borrow_mut()
.dispatch(Some(command_event.get_name()), None);
diff --git a/crates/shirabe/src/command/self_update_command.rs b/crates/shirabe/src/command/self_update_command.rs
index ccfbe07..8645ce1 100644
--- a/crates/shirabe/src/command/self_update_command.rs
+++ b/crates/shirabe/src/command/self_update_command.rs
@@ -20,7 +20,8 @@ use shirabe_php_shim::{
};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer;
+use crate::composer::ComposerHandle;
use crate::config::Config;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
@@ -280,7 +281,7 @@ impl SelfUpdateCommand {
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| latest_version.clone());
- let current_major_version = Preg::replace(r"{^(\d+).*}", "$1", &Composer::get_version())?;
+ let current_major_version = Preg::replace(r"{^(\d+).*}", "$1", &composer::get_version())?;
let update_major_version = Preg::replace(r"{^(\d+).*}", "$1", &update_version)?;
let preview_major_version = Preg::replace(
r"{^(\d+).*}",
@@ -382,7 +383,7 @@ impl SelfUpdateCommand {
channel_string.push_str(".x");
}
- if Composer::VERSION == update_version.as_str() {
+ if composer::VERSION == update_version.as_str() {
io.write_error3(
&sprintf(
"<info>You are already using the latest available Composer version %s (%s channel).</info>",
@@ -414,11 +415,11 @@ impl SelfUpdateCommand {
"%s/%s-%s%s",
&[
PhpMixed::String(rollback_dir.clone()),
- PhpMixed::String(strtr(Composer::RELEASE_DATE, " :", "_-")),
+ PhpMixed::String(strtr(composer::RELEASE_DATE, " :", "_-")),
PhpMixed::String(Preg::replace(
r"{^([0-9a-f]{7})[0-9a-f]{33}$}",
"$1",
- &Composer::VERSION,
+ &composer::VERSION,
)?),
PhpMixed::String(Self::OLD_INSTALL_EXT.to_string()),
],
@@ -637,7 +638,7 @@ RGv89BPD+2DLnJysngsvVaUCAwEAAQ==\n\
io.write_error3(
&sprintf(
"Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>",
- &[PhpMixed::String(Composer::VERSION.to_string())],
+ &[PhpMixed::String(composer::VERSION.to_string())],
),
true,
io_interface::NORMAL,
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index ae386ac..3eac2df 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -16,7 +16,7 @@ use shirabe_php_shim::{
use shirabe_semver::constraint::ConstraintInterface;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::console::input::InputOption;
use crate::dependency_resolver::DefaultPolicy;
use crate::dependency_resolver::PolicyInterface;
@@ -179,6 +179,7 @@ impl ShowCommand {
// init repos
let mut platform_overrides: IndexMap<String, PhpMixed> = IndexMap::new();
if let Some(ref composer) = composer {
+ let composer = crate::command::composer_full(composer);
if let Some(p) = composer
.get_config()
.borrow()
@@ -208,7 +209,10 @@ impl ShowCommand {
&& input.get_option("installed").as_bool() != Some(true)
&& input.get_option("locked").as_bool() != Some(true)
{
- let package = self.require_composer(None, None)?.get_package().clone_box();
+ let _rc = self.require_composer(None, None)?;
+ let package = crate::command::composer_full(&_rc)
+ .get_package()
+ .clone_box();
if input.get_option("name-only").as_bool() == Some(true) {
self.get_io().write(package.get_name());
@@ -239,9 +243,11 @@ impl ShowCommand {
} else if input.get_option("available").as_bool() == Some(true) {
let mut ir = InstalledRepository::new(vec![Box::new(make_platform_repo()?)]);
if let Some(ref composer) = composer {
+ let composer = crate::command::composer_full(composer);
repos = Box::new(CompositeRepository::new(
composer
.get_repository_manager()
+ .borrow()
.get_repositories()
.iter()
.map(|r| r.clone_box())
@@ -250,6 +256,7 @@ impl ShowCommand {
ir.add_repository(
composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.clone_box(),
);
@@ -268,12 +275,14 @@ impl ShowCommand {
installed_repo = Box::new(ir);
}
} else if input.get_option("all").as_bool() == Some(true) && composer.is_some() {
- let composer_ref = composer.as_mut().unwrap();
+ let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
let local_repo_cloned = composer_ref
.get_repository_manager()
+ .borrow()
.get_local_repository()
.clone_box();
- let locker = composer_ref.get_locker_mut();
+ let locker_rc = composer_ref.get_locker().clone();
+ let mut locker = locker_rc.borrow_mut();
if locker.is_locked() {
let lr = locker.get_locked_repository(true)?;
installed_repo = Box::new(InstalledRepository::new(vec![
@@ -297,7 +306,11 @@ impl ShowCommand {
m
})?,
)];
- for r in composer_ref.get_repository_manager().get_repositories() {
+ for r in composer_ref
+ .get_repository_manager()
+ .borrow()
+ .get_repositories()
+ {
composite_input.push(r.clone_box());
}
repos = Box::new(CompositeRepository::new(composite_input));
@@ -319,15 +332,21 @@ impl ShowCommand {
}
repos = Box::new(CompositeRepository::new(composite_input));
} else if input.get_option("locked").as_bool() == Some(true) {
- if composer.is_none() || !composer.as_mut().unwrap().get_locker_mut().is_locked() {
+ if composer.is_none()
+ || !crate::command::composer_full_mut(composer.as_ref().unwrap())
+ .get_locker()
+ .borrow_mut()
+ .is_locked()
+ {
return Err(UnexpectedValueException {
message: "A valid composer.json and composer.lock files is required to run this command with --locked".to_string(),
code: 0,
}
.into());
}
- let composer_ref = composer.as_mut().unwrap();
- let locker = composer_ref.get_locker_mut();
+ 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 mut lr =
locker.get_locked_repository(input.get_option("no-dev").as_bool() != Some(true))?;
if input.get_option("self").as_bool() == Some(true) {
@@ -346,11 +365,17 @@ impl ShowCommand {
// can't clone Composer, so we re-fetch via require_composer when missing
// but otherwise borrow the existing Option.
let composer_local_owned;
- let composer_local: &Composer = match composer.as_ref() {
- Some(c) => c,
+ // Borrow guards that keep the Ref alive for the duration of the block.
+ let _guard_from_existing;
+ let composer_local = match composer.as_ref() {
+ Some(c) => {
+ _guard_from_existing = crate::command::composer_full(c);
+ &*_guard_from_existing
+ }
None => {
composer_local_owned = self.require_composer(None, None)?;
- &composer_local_owned
+ _guard_from_existing = crate::command::composer_full(&composer_local_owned);
+ &*_guard_from_existing
}
};
let root_pkg = composer_local.get_package();
@@ -364,6 +389,7 @@ impl ShowCommand {
if input.get_option("no-dev").as_bool() == Some(true) {
let local_packages = composer_local
.get_repository_manager()
+ .borrow()
.get_local_repository()
.get_packages();
let packages = RepositoryUtils::filter_required_packages(
@@ -385,9 +411,9 @@ impl ShowCommand {
Box::new(InstalledArrayRepository::new_with_packages(Vec::new())?),
]));
} else {
- let lr = composer_local
- .get_repository_manager()
- .get_local_repository();
+ let repository_manager = composer_local.get_repository_manager().clone();
+ let repository_manager = repository_manager.borrow();
+ let lr = repository_manager.get_local_repository();
installed_repo = Box::new(InstalledRepository::new(vec![
root_repo.clone_box(),
lr.clone_box(),
@@ -412,6 +438,7 @@ impl ShowCommand {
}
if let Some(ref composer) = composer {
+ let composer = crate::command::composer_full(composer);
let command_event = CommandEvent::new6(
PluginEvents::COMMAND,
"show",
@@ -1418,11 +1445,12 @@ impl ShowCommand {
}
pub(crate) fn get_root_requires(&mut self) -> Vec<String> {
- let composer = self.try_composer(None, None);
- let composer = match composer {
+ let composer_rc = self.try_composer(None, None);
+ let composer_rc = match composer_rc {
None => return vec![],
Some(c) => c,
};
+ let composer = crate::command::composer_full(&composer_rc);
let root_package = composer.get_package();
@@ -2522,7 +2550,7 @@ impl ShowCommand {
fn find_latest_package(
&mut self,
package: &dyn PackageInterface,
- composer: &Composer,
+ composer: &PartialComposerHandle,
platform_repo: &PlatformRepository,
major_only: bool,
minor_only: bool,
@@ -2534,17 +2562,21 @@ impl ShowCommand {
// TODO(phase-b): VersionSelector::new wants RepositorySet by value, but get_repository_set
// returns &mut RepositorySet. Constructing a placeholder set keeps compile clean.
let _ = self.get_repository_set(composer)?;
+ let composer_ref = crate::command::composer_full(composer);
let placeholder_rs = RepositorySet::new(
- composer.get_package().get_minimum_stability(),
- composer.get_package().get_stability_flags().clone(),
+ composer_ref.get_package().get_minimum_stability(),
+ composer_ref.get_package().get_stability_flags().clone(),
Vec::new(),
IndexMap::new(),
IndexMap::new(),
IndexMap::new(),
);
let mut version_selector = VersionSelector::new(placeholder_rs, Some(platform_repo))?;
- let mut stability = composer.get_package().get_minimum_stability().to_string();
- let flags = composer.get_package().get_stability_flags();
+ let mut stability = composer_ref
+ .get_package()
+ .get_minimum_stability()
+ .to_string();
+ let flags = composer_ref.get_package().get_stability_flags();
if let Some(flag_value) = flags.get(name) {
let key_map: IndexMap<String, String> = base_package::STABILITIES
.iter()
@@ -2557,7 +2589,7 @@ impl ShowCommand {
}
let mut best_stability = stability.clone();
- if composer.get_package().get_prefer_stable() {
+ if composer_ref.get_package().get_prefer_stable() {
best_stability = package.get_stability().to_string();
}
@@ -2654,7 +2686,11 @@ impl ShowCommand {
Ok(candidate)
}
- fn get_repository_set(&mut self, composer: &Composer) -> anyhow::Result<&mut RepositorySet> {
+ fn get_repository_set(
+ &mut self,
+ composer: &PartialComposerHandle,
+ ) -> anyhow::Result<&mut RepositorySet> {
+ let composer = crate::command::composer_full(composer);
if self.repository_set.is_none() {
// TODO(phase-b): RepositorySet::with_stability_and_flags — using new() placeholder.
let mut rs = RepositorySet::new(
@@ -2668,6 +2704,7 @@ impl ShowCommand {
rs.add_repository(Box::new(CompositeRepository::new(
composer
.get_repository_manager()
+ .borrow()
.get_repositories()
.iter()
.map(|r| r.clone_box())
diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs
index 801d2c6..83a21b8 100644
--- a/crates/shirabe/src/command/status_command.rs
+++ b/crates/shirabe/src/command/status_command.rs
@@ -6,7 +6,6 @@ use shirabe_external_packages::symfony::component::console::input::InputInterfac
use shirabe_external_packages::symfony::component::console::output::OutputInterface;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputOption;
use crate::io::IOInterface;
use crate::package::dumper::ArrayDumper;
@@ -44,42 +43,49 @@ impl StatusCommand {
input: &dyn InputInterface,
output: &dyn OutputInterface,
) -> Result<i64> {
- let composer = self.require_composer(None, None)?;
+ 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);
- composer
- .get_event_dispatcher()
- .borrow_mut()
- .dispatch(Some(command_event.get_name()), None);
+ // TODO(plugin): dispatch CommandEvent
+ let command_event = CommandEvent::new(PluginEvents::COMMAND, "status", input, output);
+ composer
+ .get_event_dispatcher()
+ .borrow_mut()
+ .dispatch(Some(command_event.get_name()), None);
- composer
- .get_event_dispatcher()
- .borrow_mut()
- .dispatch_script(
- ScriptEvents::PRE_STATUS_CMD,
- true,
- vec![],
- indexmap::IndexMap::new(),
- );
+ composer
+ .get_event_dispatcher()
+ .borrow_mut()
+ .dispatch_script(
+ ScriptEvents::PRE_STATUS_CMD,
+ true,
+ vec![],
+ indexmap::IndexMap::new(),
+ );
+ }
let exit_code = self.do_execute(input)?;
- composer
- .get_event_dispatcher()
- .borrow_mut()
- .dispatch_script(
- ScriptEvents::POST_STATUS_CMD,
- true,
- vec![],
- indexmap::IndexMap::new(),
- );
+ {
+ let composer = crate::command::composer_full(&composer_rc);
+ composer
+ .get_event_dispatcher()
+ .borrow_mut()
+ .dispatch_script(
+ ScriptEvents::POST_STATUS_CMD,
+ true,
+ vec![],
+ indexmap::IndexMap::new(),
+ );
+ }
Ok(exit_code)
}
fn do_execute(&mut self, input: &dyn InputInterface) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ 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();
@@ -97,7 +103,7 @@ impl StatusCommand {
.map(std::rc::Rc::clone)
.unwrap_or_else(|| std::rc::Rc::new(std::cell::RefCell::new(ProcessExecutor::new(io))));
let mut guesser = VersionGuesser::new(
- std::rc::Rc::clone(composer.get_config()),
+ composer.get_config(),
std::rc::Rc::clone(&process_executor),
parser.clone(),
Some(io_box.clone_box()),
@@ -107,11 +113,13 @@ impl StatusCommand {
let dm = composer.get_download_manager().clone();
let packages: Vec<_> = composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.get_canonical_packages();
for package in packages {
let target_dir = composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .borrow_mut()
.get_install_path(package.as_ref());
let target_dir = match target_dir {
Some(d) => d,
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index 9d5897c..6b617b1 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -1,7 +1,6 @@
//! ref: composer/src/Composer/Command/SuggestsCommand.php
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::installer::SuggestedPackagesReporter;
@@ -45,15 +44,19 @@ impl SuggestsCommand {
input: &dyn InputInterface,
_output: &dyn OutputInterface,
) -> Result<i64> {
- let mut composer = self.require_composer(None, None)?;
+ let composer = self.require_composer(None, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
let mut installed_repos: Vec<Box<dyn RepositoryInterface>> = vec![Box::new(
RootPackageRepository::new(composer.get_package().clone_box()),
)];
- if composer.get_locker_mut().is_locked() {
+ if composer.get_locker().borrow_mut().is_locked() {
// TODO(phase-b): get_platform_overrides returns IndexMap<String, String>; PlatformRepository::new expects IndexMap<String, PhpMixed>
- let _platform_overrides = composer.get_locker_mut().get_platform_overrides()?;
+ let _platform_overrides = composer
+ .get_locker()
+ .borrow_mut()
+ .get_platform_overrides()?;
let platform_overrides: IndexMap<String, PhpMixed> =
todo!("convert IndexMap<String, String> to IndexMap<String, PhpMixed>");
installed_repos.push(Box::new(PlatformRepository::new(
@@ -61,7 +64,8 @@ impl SuggestsCommand {
platform_overrides,
)?));
let locked_repo = composer
- .get_locker_mut()
+ .get_locker()
+ .borrow_mut()
.get_locked_repository(!input.get_option("no-dev").as_bool().unwrap_or(false))?;
installed_repos.push(Box::new(locked_repo));
} else {
@@ -76,6 +80,7 @@ impl SuggestsCommand {
installed_repos.push(
composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.clone_box(),
);
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index 3595066..b96793d 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -18,7 +18,7 @@ use shirabe_semver::intervals::Intervals;
use crate::advisory::Auditor;
use crate::command::BumpCommand;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
+use crate::composer::PartialComposerHandle;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::dependency_resolver::request::{self, Request, UpdateAllowTransitiveDeps};
@@ -95,7 +95,8 @@ impl UpdateCommand {
);
}
- let composer = self.require_composer(None, None)?;
+ let composer_handle = self.require_composer(None, None)?;
+ let composer = crate::command::composer_full(&composer_handle);
if !HttpDownloader::is_curl_enabled() {
io.write_error3(
@@ -205,7 +206,7 @@ impl UpdateCommand {
}
if input.get_option("patch-only").as_bool().unwrap_or(false) {
- if !composer.get_locker().is_locked() {
+ 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(),
code: 0,
@@ -214,6 +215,7 @@ impl UpdateCommand {
}
for package in composer
.get_locker()
+ .borrow_mut()
.get_locked_repository(true)?
.get_canonical_packages()
{
@@ -249,7 +251,8 @@ impl UpdateCommand {
}
if input.get_option("interactive").as_bool().unwrap_or(false) {
- packages = self.get_packages_interactively(io, input, output, &composer, packages)?;
+ packages =
+ self.get_packages_interactively(io, input, output, &composer_handle, packages)?;
}
if input.get_option("root-reqs").as_bool().unwrap_or(false) {
@@ -309,11 +312,12 @@ impl UpdateCommand {
composer
.get_installation_manager()
+ .borrow_mut()
.set_output_progress(!input.get_option("no-progress").as_bool().unwrap_or(false));
- let mut install = Installer::create(io.clone_box(), &composer);
+ let mut install = Installer::create(io.clone_box(), &composer_handle);
- let config = std::rc::Rc::clone(composer.get_config());
+ let config = composer.get_config();
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&*config.borrow(), input, false)?;
@@ -428,7 +432,7 @@ impl UpdateCommand {
);
let mut bump_command = BumpCommand::new(None);
// TODO(phase-b): Composer is a PHP class shared by reference; calling
- // set_composer here requires Rc<RefCell<Composer>> shared-ownership.
+ // set_composer here requires a shared PartialComposer handle.
// bump_command.set_composer(composer);
result = bump_command.do_bump(
io,
@@ -459,7 +463,7 @@ impl UpdateCommand {
io: &dyn IOInterface,
input: &dyn InputInterface,
output: &dyn OutputInterface,
- composer: &Composer,
+ composer: &PartialComposerHandle,
packages: Vec<String>,
) -> Result<Vec<String>> {
if !input.is_interactive() {
@@ -470,8 +474,9 @@ impl UpdateCommand {
.into());
}
+ let composer_ref = crate::command::composer_full(composer);
let platform_req_filter = self.get_platform_requirement_filter(input);
- let stability_flags = composer.get_package().get_stability_flags();
+ let stability_flags = composer_ref.get_package().get_stability_flags();
let requires = array_merge(
// TODO(phase-b): array_merge for IndexMap<String, Link>
todo!("composer.get_package().get_requires() as PhpMixed"),
@@ -495,13 +500,17 @@ impl UpdateCommand {
// Vec<Box<dyn PackageInterface>> while RepositoryInterface::get_packages
// returns Vec<Box<dyn BasePackage>>. Use only the locker branch for now.
let installed_packages: Vec<Box<dyn crate::package::PackageInterface>> =
- if composer.get_locker().is_locked() {
+ if composer_ref.get_locker().borrow_mut().is_locked() {
CanonicalPackagesTrait::get_packages(
- &composer.get_locker().get_locked_repository(true)?,
+ &composer_ref
+ .get_locker()
+ .borrow_mut()
+ .get_locked_repository(true)?,
)
} else {
- let _ = composer
+ let _ = composer_ref
.get_repository_manager()
+ .borrow()
.get_local_repository()
.get_packages();
Vec::new()
@@ -613,7 +622,8 @@ impl UpdateCommand {
.into())
}
- fn create_version_selector(&self, composer: &Composer) -> Result<VersionSelector> {
+ fn create_version_selector(&self, composer: &PartialComposerHandle) -> Result<VersionSelector> {
+ let composer = crate::command::composer_full(composer);
let mut repository_set = RepositorySet::new(
composer.get_package().get_minimum_stability(),
composer.get_package().get_stability_flags().clone(),
@@ -625,7 +635,10 @@ impl UpdateCommand {
);
// TODO(phase-b): array_filter requires Clone on Box<dyn RepositoryInterface>
// which PHP classes must not implement. Skipping the repo filter for now.
- let _ = &composer.get_repository_manager().get_repositories();
+ let _ = &composer
+ .get_repository_manager()
+ .borrow()
+ .get_repositories();
let _ = |repository: &Box<dyn RepositoryInterface>| -> bool {
repository
.as_any()
diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs
index d6ee3aa..f57c21c 100644
--- a/crates/shirabe/src/command/validate_command.rs
+++ b/crates/shirabe/src/command/validate_command.rs
@@ -5,7 +5,6 @@ use shirabe_external_packages::symfony::component::console::input::InputInterfac
use shirabe_external_packages::symfony::component::console::output::OutputInterface;
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
-use crate::composer::Composer;
use crate::console::input::InputArgument;
use crate::console::input::InputOption;
use crate::factory::Factory;
@@ -157,7 +156,8 @@ impl ValidateCommand {
validator.validate(&file, check_all, check_version);
let mut lock_errors: Vec<String> = vec![];
- let mut composer = self.create_composer_instance(input, io, None, false, None)?;
+ let composer = self.create_composer_instance(input, io, None, false, None)?;
+ let mut composer = crate::command::composer_full_mut(&composer);
let check_lock = (check_lock
&& composer
.get_config()
@@ -169,7 +169,8 @@ impl ValidateCommand {
// 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.
- let locker = composer.get_locker_mut();
+ let locker = composer.get_locker().clone();
+ let mut locker = locker.borrow_mut();
if locker.is_locked() && !locker.is_fresh()? {
lock_errors.push("- The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update <package name>`.".to_string());
}
@@ -208,11 +209,13 @@ impl ValidateCommand {
{
let packages = composer
.get_repository_manager()
+ .borrow()
.get_local_repository()
.get_packages();
for package in packages {
let path = composer
- .get_installation_manager_mut()
+ .get_installation_manager()
+ .borrow_mut()
.get_install_path(package.as_ref());
let path = match path {
Some(p) => p,