aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/command/require_command.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-19 21:46:01 +0900
committernsfisis <nsfisis@gmail.com>2026-05-19 21:46:08 +0900
commit5e31fa33c3b5cf726a57a063b8e7a070869250fe (patch)
tree98522466966fa7df483cad174ab5fc03db39bc09 /crates/shirabe/src/command/require_command.rs
parentc839244d8d09f3036ebfee8eef7eb6b147e593ab (diff)
downloadphp-shirabe-5e31fa33c3b5cf726a57a063b8e7a070869250fe.tar.gz
php-shirabe-5e31fa33c3b5cf726a57a063b8e7a070869250fe.tar.zst
php-shirabe-5e31fa33c3b5cf726a57a063b8e7a070869250fe.zip
fix(compile): fix more random compile errors
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/command/require_command.rs')
-rw-r--r--crates/shirabe/src/command/require_command.rs204
1 files changed, 94 insertions, 110 deletions
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index 63efa92..a49428d 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -28,7 +28,7 @@ use crate::io::io_interface::IOInterface;
use crate::json::json_file::JsonFile;
use crate::json::json_manipulator::JsonManipulator;
use crate::package::alias_package::AliasPackage;
-use crate::package::base_package::BasePackage;
+use crate::package::base_package::{self, BasePackage};
use crate::package::complete_package_interface::CompletePackageInterface;
use crate::package::loader::array_loader::ArrayLoader;
use crate::package::loader::root_package_loader::RootPackageLoader;
@@ -104,36 +104,36 @@ impl RequireCommand {
.set_name("require")
.set_aliases(&["r".to_string()])
.set_description("Adds required packages to your composer.json and installs them")
- .set_definition(vec![
- InputArgument::new("packages", Some(InputArgument::IS_ARRAY | InputArgument::OPTIONAL), "Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or \"foo/bar 1.0.0\"", None),
- InputOption::new("dev", None, Some(InputOption::VALUE_NONE), "Add requirement to require-dev.", None),
- InputOption::new("dry-run", None, Some(InputOption::VALUE_NONE), "Outputs the operations but will not execute anything (implicitly enables --verbose).", None),
- InputOption::new("prefer-source", None, Some(InputOption::VALUE_NONE), "Forces installation from package sources when possible, including VCS information.", None),
- InputOption::new("prefer-dist", None, Some(InputOption::VALUE_NONE), "Forces installation from package dist (default behavior).", None),
- InputOption::new("prefer-install", None, Some(InputOption::VALUE_REQUIRED), "Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).", None),
- InputOption::new("fixed", None, Some(InputOption::VALUE_NONE), "Write fixed version to the composer.json.", None),
- InputOption::new("no-suggest", None, Some(InputOption::VALUE_NONE), "DEPRECATED: This flag does not exist anymore.", None),
- InputOption::new("no-progress", None, Some(InputOption::VALUE_NONE), "Do not output download progress.", None),
- InputOption::new("no-update", None, Some(InputOption::VALUE_NONE), "Disables the automatic update of the dependencies (implies --no-install).", None),
- InputOption::new("no-install", None, Some(InputOption::VALUE_NONE), "Skip the install step after updating the composer.lock file.", None),
- InputOption::new("no-audit", None, Some(InputOption::VALUE_NONE), "Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).", None),
- InputOption::new("audit-format", None, Some(InputOption::VALUE_REQUIRED), "Audit output format. Must be \"table\", \"plain\", \"json\", or \"summary\".", Some(PhpMixed::String(Auditor::FORMAT_SUMMARY.to_string()))),
- InputOption::new("no-security-blocking", None, Some(InputOption::VALUE_NONE), "Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).", None),
- InputOption::new("update-no-dev", None, Some(InputOption::VALUE_NONE), "Run the dependency update with the --no-dev option.", None),
- InputOption::new("update-with-dependencies", Some(PhpMixed::String("w".to_string())), Some(InputOption::VALUE_NONE), "Allows inherited dependencies to be updated, except those that are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).", None),
- InputOption::new("update-with-all-dependencies", Some(PhpMixed::String("W".to_string())), Some(InputOption::VALUE_NONE), "Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).", None),
- InputOption::new("with-dependencies", None, Some(InputOption::VALUE_NONE), "Alias for --update-with-dependencies", None),
- InputOption::new("with-all-dependencies", None, Some(InputOption::VALUE_NONE), "Alias for --update-with-all-dependencies", None),
- InputOption::new("ignore-platform-req", None, Some(InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY), "Ignore a specific platform requirement (php & ext- packages).", None),
- InputOption::new("ignore-platform-reqs", None, Some(InputOption::VALUE_NONE), "Ignore all platform requirements (php & ext- packages).", None),
- InputOption::new("prefer-stable", None, Some(InputOption::VALUE_NONE), "Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).", None),
- InputOption::new("prefer-lowest", None, Some(InputOption::VALUE_NONE), "Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).", None),
- InputOption::new("minimal-changes", Some(PhpMixed::String("m".to_string())), Some(InputOption::VALUE_NONE), "During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).", None),
- InputOption::new("sort-packages", None, Some(InputOption::VALUE_NONE), "Sorts packages when adding/updating a new dependency", None),
- InputOption::new("optimize-autoloader", Some(PhpMixed::String("o".to_string())), Some(InputOption::VALUE_NONE), "Optimize autoloader during autoloader dump", None),
- InputOption::new("classmap-authoritative", Some(PhpMixed::String("a".to_string())), Some(InputOption::VALUE_NONE), "Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.", None),
- InputOption::new("apcu-autoloader", None, Some(InputOption::VALUE_NONE), "Use APCu to cache found/not-found classes.", None),
- InputOption::new("apcu-autoloader-prefix", None, Some(InputOption::VALUE_REQUIRED), "Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader", None),
+ .set_definition(&[
+ InputArgument::new("packages", Some(InputArgument::IS_ARRAY | InputArgument::OPTIONAL), "Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or \"foo/bar 1.0.0\"", None).unwrap().into(),
+ InputOption::new("dev", None, Some(InputOption::VALUE_NONE), "Add requirement to require-dev.", None).unwrap().into(),
+ InputOption::new("dry-run", None, Some(InputOption::VALUE_NONE), "Outputs the operations but will not execute anything (implicitly enables --verbose).", None).unwrap().into(),
+ InputOption::new("prefer-source", None, Some(InputOption::VALUE_NONE), "Forces installation from package sources when possible, including VCS information.", None).unwrap().into(),
+ InputOption::new("prefer-dist", None, Some(InputOption::VALUE_NONE), "Forces installation from package dist (default behavior).", None).unwrap().into(),
+ InputOption::new("prefer-install", None, Some(InputOption::VALUE_REQUIRED), "Forces installation from package dist|source|auto (auto chooses source for dev versions, dist for the rest).", None).unwrap().into(),
+ InputOption::new("fixed", None, Some(InputOption::VALUE_NONE), "Write fixed version to the composer.json.", None).unwrap().into(),
+ InputOption::new("no-suggest", None, Some(InputOption::VALUE_NONE), "DEPRECATED: This flag does not exist anymore.", None).unwrap().into(),
+ InputOption::new("no-progress", None, Some(InputOption::VALUE_NONE), "Do not output download progress.", None).unwrap().into(),
+ InputOption::new("no-update", None, Some(InputOption::VALUE_NONE), "Disables the automatic update of the dependencies (implies --no-install).", None).unwrap().into(),
+ InputOption::new("no-install", None, Some(InputOption::VALUE_NONE), "Skip the install step after updating the composer.lock file.", None).unwrap().into(),
+ InputOption::new("no-audit", None, Some(InputOption::VALUE_NONE), "Skip the audit step after updating the composer.lock file (can also be set via the COMPOSER_NO_AUDIT=1 env var).", None).unwrap().into(),
+ InputOption::new("audit-format", None, Some(InputOption::VALUE_REQUIRED), "Audit output format. Must be \"table\", \"plain\", \"json\", or \"summary\".", Some(PhpMixed::String(Auditor::FORMAT_SUMMARY.to_string()))).unwrap().into(),
+ InputOption::new("no-security-blocking", None, Some(InputOption::VALUE_NONE), "Allows installing packages with security advisories or that are abandoned (can also be set via the COMPOSER_NO_SECURITY_BLOCKING=1 env var).", None).unwrap().into(),
+ InputOption::new("update-no-dev", None, Some(InputOption::VALUE_NONE), "Run the dependency update with the --no-dev option.", None).unwrap().into(),
+ InputOption::new("update-with-dependencies", Some(PhpMixed::String("w".to_string())), Some(InputOption::VALUE_NONE), "Allows inherited dependencies to be updated, except those that are root requirements (can also be set via the COMPOSER_WITH_DEPENDENCIES=1 env var).", None).unwrap().into(),
+ InputOption::new("update-with-all-dependencies", Some(PhpMixed::String("W".to_string())), Some(InputOption::VALUE_NONE), "Allows all inherited dependencies to be updated, including those that are root requirements (can also be set via the COMPOSER_WITH_ALL_DEPENDENCIES=1 env var).", None).unwrap().into(),
+ InputOption::new("with-dependencies", None, Some(InputOption::VALUE_NONE), "Alias for --update-with-dependencies", None).unwrap().into(),
+ InputOption::new("with-all-dependencies", None, Some(InputOption::VALUE_NONE), "Alias for --update-with-all-dependencies", None).unwrap().into(),
+ InputOption::new("ignore-platform-req", None, Some(InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY), "Ignore a specific platform requirement (php & ext- packages).", None).unwrap().into(),
+ InputOption::new("ignore-platform-reqs", None, Some(InputOption::VALUE_NONE), "Ignore all platform requirements (php & ext- packages).", None).unwrap().into(),
+ InputOption::new("prefer-stable", None, Some(InputOption::VALUE_NONE), "Prefer stable versions of dependencies (can also be set via the COMPOSER_PREFER_STABLE=1 env var).", None).unwrap().into(),
+ InputOption::new("prefer-lowest", None, Some(InputOption::VALUE_NONE), "Prefer lowest versions of dependencies (can also be set via the COMPOSER_PREFER_LOWEST=1 env var).", None).unwrap().into(),
+ InputOption::new("minimal-changes", Some(PhpMixed::String("m".to_string())), Some(InputOption::VALUE_NONE), "During an update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).", None).unwrap().into(),
+ InputOption::new("sort-packages", None, Some(InputOption::VALUE_NONE), "Sorts packages when adding/updating a new dependency", None).unwrap().into(),
+ InputOption::new("optimize-autoloader", Some(PhpMixed::String("o".to_string())), Some(InputOption::VALUE_NONE), "Optimize autoloader during autoloader dump", None).unwrap().into(),
+ InputOption::new("classmap-authoritative", Some(PhpMixed::String("a".to_string())), Some(InputOption::VALUE_NONE), "Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.", None).unwrap().into(),
+ InputOption::new("apcu-autoloader", None, Some(InputOption::VALUE_NONE), "Use APCu to cache found/not-found classes.", None).unwrap().into(),
+ InputOption::new("apcu-autoloader-prefix", None, Some(InputOption::VALUE_REQUIRED), "Use a custom prefix for the APCu autoloader cache. Implicitly enables --apcu-autoloader", None).unwrap().into(),
])
.set_help(
"The require command adds required packages to your composer.json and installs them.\n\
@@ -159,23 +159,13 @@ impl RequireCommand {
let io = self.get_io();
if input.get_option("no-suggest").as_bool().unwrap_or(false) {
- io.write_error(
- PhpMixed::String(
- "<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>"
- .to_string(),
- ),
- true,
- io_interface::NORMAL,
- );
+ io.write_error3("<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>", true, io_interface::NORMAL);
}
self.newly_created = !file_exists(&self.file);
- if self.newly_created && !file_put_contents(&self.file, "{\n}\n") {
- io.write_error(
- PhpMixed::String(format!(
- "<error>{} could not be created.</error>",
- self.file
- )),
+ if self.newly_created && file_put_contents(&self.file, b"{\n}\n").is_none() {
+ io.write_error3(
+ &format!("<error>{} could not be created.</error>", self.file),
true,
io_interface::NORMAL,
);
@@ -183,8 +173,8 @@ impl RequireCommand {
return Ok(1);
}
if !Filesystem::is_readable(&self.file) {
- io.write_error(
- PhpMixed::String(format!("<error>{} is not readable.</error>", self.file)),
+ io.write_error3(
+ &format!("<error>{} is not readable.</error>", self.file),
true,
io_interface::NORMAL,
);
@@ -234,8 +224,8 @@ impl RequireCommand {
.ok()
== Some(false)
{
- io.write_error(
- PhpMixed::String(format!("<error>{} is not writable.</error>", self.file)),
+ io.write_error3(
+ &format!("<error>{} is not writable.</error>", self.file),
true,
io_interface::NORMAL,
);
@@ -258,24 +248,10 @@ impl RequireCommand {
/// @see https://github.com/composer/composer/pull/8313#issuecomment-532637955
if package_type != "project" && !input.get_option("dev").as_bool().unwrap_or(false) {
- io.write_error(
- PhpMixed::String(
- "<error>The \"--fixed\" option is only allowed for packages with a \"project\" type or for dev dependencies to prevent possible misuses.</error>"
- .to_string(),
- ),
- true,
- io_interface::NORMAL,
- );
+ io.write_error3("<error>The \"--fixed\" option is only allowed for packages with a \"project\" type or for dev dependencies to prevent possible misuses.</error>", true, io_interface::NORMAL);
- if !config.contains_key("type") {
- io.write_error(
- PhpMixed::String(
- "<error>If your package is not a library, you can explicitly specify the \"type\" by using \"composer config type project\".</error>"
- .to_string(),
- ),
- true,
- io_interface::NORMAL,
- );
+ if config.get("type").is_none() {
+ io.write_error3("<error>If your package is not a library, you can explicitly specify the \"type\" by using \"composer config type project\".</error>", true, io_interface::NORMAL);
}
return Ok(1);
@@ -285,7 +261,7 @@ impl RequireCommand {
let composer = self.require_composer(None, None)?;
let repos = composer.get_repository_manager().get_repositories();
- let platform_overrides = composer.get_config().get("platform");
+ let platform_overrides = composer.get_config().borrow_mut().get("platform");
// initialize self.repos as it is used by the PackageDiscoveryTrait
let platform_repo = PlatformRepository::new(vec![], platform_overrides);
let mut combined: Vec<
@@ -447,14 +423,10 @@ impl RequireCommand {
let version_parser = VersionParser::new();
for (package, constraint) in &requirements {
if strtolower(package) == composer.get_package().get_name() {
- io.write_error(
- PhpMixed::String(sprintf(
- "<error>Root package '%s' cannot require itself in its composer.json</error>",
- &[PhpMixed::String(package.clone())],
- )),
- true,
- io_interface::NORMAL,
- );
+ io.write_error3(&sprintf(
+ "<error>Root package '%s' cannot require itself in its composer.json</error>",
+ &[PhpMixed::String(package.clone())],
+ ), true, io_interface::NORMAL);
return Ok(1);
}
@@ -529,6 +501,7 @@ impl RequireCommand {
let sort_packages = input.get_option("sort-packages").as_bool().unwrap_or(false)
|| composer
.get_config()
+ .borrow()
.get("sort-packages")
.as_bool()
.unwrap_or(false);
@@ -561,8 +534,8 @@ impl RequireCommand {
);
}
- io.write_error(
- PhpMixed::String(format!(
+ io.write_error3(
+ &format!(
"<info>{} has been {}</info>",
self.file,
if self.newly_created {
@@ -570,7 +543,7 @@ impl RequireCommand {
} else {
"updated"
}
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -730,9 +703,9 @@ impl RequireCommand {
let new_links = loader.parse_links(
root_package.get_name(),
root_package.get_pretty_version(),
- BasePackage::supported_link_types(require_key)
- .get("method")
- .cloned()
+ base_package::SUPPORTED_LINK_TYPES
+ .get(require_key)
+ .map(|t| t.method)
.unwrap_or_default(),
requirements,
);
@@ -770,6 +743,7 @@ impl RequireCommand {
.unwrap_or(false)
|| composer
.get_config()
+ .borrow()
.get("optimize-autoloader")
.as_bool()
.unwrap_or(false);
@@ -779,6 +753,7 @@ impl RequireCommand {
.unwrap_or(false)
|| composer
.get_config()
+ .borrow()
.get("classmap-authoritative")
.as_bool()
.unwrap_or(false);
@@ -793,6 +768,7 @@ impl RequireCommand {
.unwrap_or(false)
|| composer
.get_config()
+ .borrow()
.get("apcu-autoloader")
.as_bool()
.unwrap_or(false);
@@ -802,6 +778,7 @@ impl RequireCommand {
.unwrap_or(false)
|| composer
.get_config()
+ .borrow()
.get("update-with-minimal-changes")
.as_bool()
.unwrap_or(false);
@@ -833,8 +810,8 @@ impl RequireCommand {
flags += " --with-dependencies";
}
- io.write_error(
- PhpMixed::String(format!(
+ io.write_error3(
+ &format!(
"<info>Running composer update {}{}</info>",
implode(
" ",
@@ -843,7 +820,7 @@ impl RequireCommand {
.collect::<Vec<String>>()
),
flags,
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -859,9 +836,8 @@ impl RequireCommand {
let install = Installer::create(io, &composer);
- let (prefer_source, prefer_dist) = self
- .inner
- .get_preferred_install_options(composer.get_config(), input)?;
+ let (prefer_source, prefer_dist) =
+ self.get_preferred_install_options(&*composer.get_config().borrow(), input)?;
install
.set_dry_run(input.get_option("dry-run").as_bool().unwrap_or(false))
@@ -875,10 +851,14 @@ impl RequireCommand {
.set_update(true)
.set_install(!input.get_option("no-install").as_bool().unwrap_or(false))
.set_update_allow_transitive_dependencies(update_allow_transitive_dependencies)
- .set_platform_requirement_filter(self.get_platform_requirement_filter(input)?)
+ .set_platform_requirement_filter(BaseCommand::get_platform_requirement_filter(
+ self, input,
+ )?)
.set_prefer_stable(input.get_option("prefer-stable").as_bool().unwrap_or(false))
.set_prefer_lowest(input.get_option("prefer-lowest").as_bool().unwrap_or(false))
- .set_audit_config(self.create_audit_config(composer.get_config(), input)?)
+ .set_audit_config(
+ self.create_audit_config(&mut *composer.get_config().borrow_mut(), input)?,
+ )
.set_minimal_update(minimal_changes);
// if no lock is present, or the file is brand new, we do not do a
@@ -894,7 +874,8 @@ impl RequireCommand {
let status = install.run()?;
if status != 0 && status != Installer::ERROR_AUDIT_FAILED {
if status == Installer::ERROR_DEPENDENCY_RESOLUTION_FAILED {
- for req in self.normalize_requirements(
+ for req in BaseCommand::normalize_requirements(
+ self,
input
.get_argument("packages")
.as_list()
@@ -906,15 +887,11 @@ impl RequireCommand {
.unwrap_or_default(),
)? {
if !req.contains_key("version") {
- io.write_error(
- PhpMixed::String(format!(
- "You can also try re-running composer require with an explicit version constraint, e.g. \"composer require {}:*\" to figure out if any version is installable, or \"composer require {}:^2.1\" if you know which you need.",
- req.get("name").cloned().unwrap_or_default(),
- req.get("name").cloned().unwrap_or_default(),
- )),
- true,
- io_interface::NORMAL,
- );
+ io.write_error3(&format!(
+ "You can also try re-running composer require with an explicit version constraint, e.g. \"composer require {}:*\" to figure out if any version is installable, or \"composer require {}:^2.1\" if you know which you need.",
+ req.get("name").cloned().unwrap_or_default(),
+ req.get("name").cloned().unwrap_or_default(),
+ ), true, io_interface::NORMAL);
break;
}
}
@@ -969,8 +946,8 @@ impl RequireCommand {
version_selector.find_recommended_require_version(&*package),
);
}
- self.get_io().write_error(
- PhpMixed::String(sprintf(
+ self.get_io().write_error3(
+ &sprintf(
"Using version <info>%s</info> for <info>%s</info>",
&[
PhpMixed::String(
@@ -978,7 +955,7 @@ impl RequireCommand {
),
PhpMixed::String(package_name.clone()),
],
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -1018,7 +995,14 @@ impl RequireCommand {
remove_key,
sort_packages,
);
- if locker.is_locked() && composer.get_config().get("lock").as_bool().unwrap_or(false) {
+ if locker.is_locked()
+ && composer
+ .get_config()
+ .borrow_mut()
+ .get("lock")
+ .as_bool()
+ .unwrap_or(false)
+ {
let stability_flags = RootPackageLoader::extract_stability_flags(
&requirements,
composer.get_package().get_minimum_stability(),
@@ -1083,7 +1067,7 @@ impl RequireCommand {
composer_definition.shift_remove(remove_key);
}
}
- self.json.as_ref().unwrap().write(&PhpMixed::Array(
+ let _ = self.json.as_ref().unwrap().write(PhpMixed::Array(
composer_definition
.into_iter()
.map(|(k, v)| (k, Box::new(v)))
@@ -1126,11 +1110,11 @@ impl RequireCommand {
let io = self.get_io();
if self.newly_created {
- io.write_error(
- PhpMixed::String(format!(
+ io.write_error3(
+ &format!(
"\n<error>Installation failed, deleting {}.</error>",
self.file
- )),
+ ),
true,
io_interface::NORMAL,
);
@@ -1144,11 +1128,11 @@ impl RequireCommand {
} else {
" to its ".to_string()
};
- io.write_error(
- PhpMixed::String(format!(
+ io.write_error3(
+ &format!(
"\n<error>Installation failed, reverting {}{}original content.</error>",
self.file, msg
- )),
+ ),
true,
io_interface::NORMAL,
);