aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-12 01:01:35 +0900
committernsfisis <nsfisis@gmail.com>2026-06-12 01:01:43 +0900
commit1e44f5723e4c0e0903d00a61f254901e612fe5e1 (patch)
tree9c2e1eec364bbf6418a4072ee7767b04c3df0297 /crates/shirabe/src
parentddf0a624145b618c05c2ee47414545b99b685f37 (diff)
downloadphp-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.tar.gz
php-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.tar.zst
php-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.zip
feat(symfony-console): port Symfony Console and make the workspace compile
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src')
-rw-r--r--crates/shirabe/src/advisory/auditor.rs45
-rw-r--r--crates/shirabe/src/autoload/autoload_generator.rs2
-rw-r--r--crates/shirabe/src/command/archive_command.rs12
-rw-r--r--crates/shirabe/src/command/audit_command.rs10
-rw-r--r--crates/shirabe/src/command/base_command.rs57
-rw-r--r--crates/shirabe/src/command/base_config_command.rs32
-rw-r--r--crates/shirabe/src/command/base_dependency_command.rs20
-rw-r--r--crates/shirabe/src/command/bump_command.rs8
-rw-r--r--crates/shirabe/src/command/check_platform_reqs_command.rs6
-rw-r--r--crates/shirabe/src/command/config_command.rs74
-rw-r--r--crates/shirabe/src/command/create_project_command.rs38
-rw-r--r--crates/shirabe/src/command/dump_autoload_command.rs30
-rw-r--r--crates/shirabe/src/command/exec_command.rs20
-rw-r--r--crates/shirabe/src/command/fund_command.rs4
-rw-r--r--crates/shirabe/src/command/global_command.rs33
-rw-r--r--crates/shirabe/src/command/home_command.rs10
-rw-r--r--crates/shirabe/src/command/init_command.rs47
-rw-r--r--crates/shirabe/src/command/install_command.rs32
-rw-r--r--crates/shirabe/src/command/licenses_command.rs13
-rw-r--r--crates/shirabe/src/command/outdated_command.rs43
-rw-r--r--crates/shirabe/src/command/package_discovery_trait.rs1
-rw-r--r--crates/shirabe/src/command/reinstall_command.rs18
-rw-r--r--crates/shirabe/src/command/remove_command.rs52
-rw-r--r--crates/shirabe/src/command/repository_command.rs16
-rw-r--r--crates/shirabe/src/command/require_command.rs68
-rw-r--r--crates/shirabe/src/command/run_script_command.rs25
-rw-r--r--crates/shirabe/src/command/script_alias_command.rs4
-rw-r--r--crates/shirabe/src/command/search_command.rs14
-rw-r--r--crates/shirabe/src/command/show_command.rs163
-rw-r--r--crates/shirabe/src/command/status_command.rs8
-rw-r--r--crates/shirabe/src/command/suggests_command.rs17
-rw-r--r--crates/shirabe/src/command/update_command.rs68
-rw-r--r--crates/shirabe/src/command/validate_command.rs16
-rw-r--r--crates/shirabe/src/console/application.rs118
-rw-r--r--crates/shirabe/src/console/html_output_formatter.rs20
-rw-r--r--crates/shirabe/src/console/input/input_argument.rs7
-rw-r--r--crates/shirabe/src/console/input/input_option.rs5
-rw-r--r--crates/shirabe/src/dependency_resolver/problem.rs3
-rw-r--r--crates/shirabe/src/event_dispatcher/event_dispatcher.rs17
-rw-r--r--crates/shirabe/src/factory.rs16
-rw-r--r--crates/shirabe/src/installer/suggested_packages_reporter.rs1
-rw-r--r--crates/shirabe/src/io/buffer_io.rs33
-rw-r--r--crates/shirabe/src/io/console_io.rs156
-rw-r--r--crates/shirabe/src/question/strict_confirmation_question.rs32
44 files changed, 820 insertions, 594 deletions
diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs
index 2b71237..c12e131 100644
--- a/crates/shirabe/src/advisory/auditor.rs
+++ b/crates/shirabe/src/advisory/auditor.rs
@@ -417,12 +417,12 @@ impl Auditor {
}
.into());
}
- self.output_advisories_table(io_as_console.unwrap(), advisories);
+ self.output_advisories_table(io_as_console.unwrap(), advisories)?;
Ok(())
}
Self::FORMAT_PLAIN => {
- self.output_advisories_plain(io, advisories);
+ self.output_advisories_plain(io, advisories)?;
Ok(())
}
@@ -440,7 +440,7 @@ impl Auditor {
&self,
io: &ConsoleIO,
advisories: &IndexMap<String, Vec<AnySecurityAdvisory>>,
- ) {
+ ) -> Result<()> {
for package_advisories in advisories.values() {
for advisory in package_advisories {
let mut headers: Vec<String> = vec![
@@ -475,22 +475,26 @@ impl Auditor {
.unwrap_or_else(|| "None specified".to_string()),
);
}
- io.get_table()
+ let mut table = io.get_table();
+ table
.set_horizontal(true)
- .set_headers(headers.into_iter().map(|h| h.into()).collect())
- .add_row(ConsoleIO::sanitize(
- PhpMixed::List(
- row.into_iter()
- .map(|s| Box::new(PhpMixed::String(s)))
- .collect(),
- ),
- false,
- ))
+ .set_headers(headers.into_iter().map(|h| h.into()).collect());
+ table.add_row(ConsoleIO::sanitize(
+ PhpMixed::List(
+ row.into_iter()
+ .map(|s| Box::new(PhpMixed::String(s)))
+ .collect(),
+ ),
+ false,
+ ))??;
+ table
.set_column_width(1, 80)
.set_column_max_width(1, 80)
.render();
}
}
+
+ Ok(())
}
/// @param array<string, array<SecurityAdvisory>> $advisories
@@ -498,7 +502,7 @@ impl Auditor {
&self,
io: &mut dyn IOInterface,
advisories: &IndexMap<String, Vec<AnySecurityAdvisory>>,
- ) {
+ ) -> Result<()> {
let mut error: Vec<String> = vec![];
let mut first_advisory = true;
for package_advisories in advisories.values() {
@@ -513,11 +517,11 @@ impl Auditor {
error.push(format!("Severity: {}", self.get_severity(sa)));
error.push(format!("Advisory ID: {}", self.get_advisory_id(sa)));
error.push(format!("CVE: {}", self.get_cve(sa)));
- error.push(format!("Title: {}", OutputFormatter::escape(&sa.title)));
+ error.push(format!("Title: {}", OutputFormatter::escape(&sa.title)?));
error.push(format!("URL: {}", self.get_url(sa)));
error.push(format!(
"Affected versions: {}",
- OutputFormatter::escape(&sa.affected_versions().get_pretty_string())
+ OutputFormatter::escape(&sa.affected_versions().get_pretty_string())?
));
error.push(format!("Reported at: {}", sa.reported_at.format(DATE_ATOM)));
if let Some(ignored) = advisory.as_ignored() {
@@ -535,6 +539,8 @@ impl Auditor {
for line in &error {
io.write_error(line);
}
+
+ Ok(())
}
/// @param array<CompletePackageInterface> $packages
@@ -625,7 +631,8 @@ impl Auditor {
if package_url.is_some() {
format!(
"<href={}>{}</>",
- OutputFormatter::escape(&package_url.unwrap()),
+ OutputFormatter::escape(&package_url.unwrap())
+ .expect("OutputFormatter::escape does not fail"),
package.get_pretty_name()
)
} else {
@@ -673,8 +680,8 @@ impl Auditor {
let link = advisory.link.as_ref().unwrap();
format!(
"<href={}>{}</>",
- OutputFormatter::escape(link),
- OutputFormatter::escape(link)
+ OutputFormatter::escape(link).expect("OutputFormatter::escape does not fail"),
+ OutputFormatter::escape(link).expect("OutputFormatter::escape does not fail")
)
}
diff --git a/crates/shirabe/src/autoload/autoload_generator.rs b/crates/shirabe/src/autoload/autoload_generator.rs
index a380763..7167f04 100644
--- a/crates/shirabe/src/autoload/autoload_generator.rs
+++ b/crates/shirabe/src/autoload/autoload_generator.rs
@@ -464,7 +464,7 @@ impl AutoloadGenerator {
if !ambiguous_classes.is_empty() {
self.io.write_error(&format!(
"<info>To resolve ambiguity in classes not under your control you can ignore them by path using <href={}>exclude-from-classmap</>",
- OutputFormatter::escape("https://getcomposer.org/doc/04-schema.md#exclude-files-from-classmaps")
+ OutputFormatter::escape("https://getcomposer.org/doc/04-schema.md#exclude-files-from-classmaps")?
));
}
diff --git a/crates/shirabe/src/command/archive_command.rs b/crates/shirabe/src/command/archive_command.rs
index 53159f8..f657ef4 100644
--- a/crates/shirabe/src/command/archive_command.rs
+++ b/crates/shirabe/src/command/archive_command.rs
@@ -88,7 +88,7 @@ impl ArchiveCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| {
@@ -102,7 +102,7 @@ impl ArchiveCommand {
let dir = input
.borrow()
- .get_option("dir")
+ .get_option("dir")?
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| {
@@ -120,24 +120,24 @@ impl ArchiveCommand {
&config,
input
.borrow()
- .get_argument("package")
+ .get_argument("package")?
.as_string()
.map(|s| s.to_string()),
input
.borrow()
- .get_argument("version")
+ .get_argument("version")?
.as_string()
.map(|s| s.to_string()),
&format,
&dir,
input
.borrow()
- .get_option("file")
+ .get_option("file")?
.as_string()
.map(|s| s.to_string()),
input
.borrow()
- .get_option("ignore-filters")
+ .get_option("ignore-filters")?
.as_bool()
.unwrap_or(false),
composer.as_ref(),
diff --git a/crates/shirabe/src/command/audit_command.rs b/crates/shirabe/src/command/audit_command.rs
index 0e050cc..cd7a799 100644
--- a/crates/shirabe/src/command/audit_command.rs
+++ b/crates/shirabe/src/command/audit_command.rs
@@ -85,7 +85,7 @@ impl AuditCommand {
let abandoned = input
.borrow()
- .get_option("abandoned")
+ .get_option("abandoned")?
.as_string()
.map(|s| s.to_string());
if abandoned.is_some()
@@ -115,7 +115,7 @@ impl AuditCommand {
let mut ignore_severities: indexmap::IndexMap<String, Option<String>> =
indexmap::IndexMap::new();
- let cli_severities = input.borrow().get_option("ignore-severity");
+ let cli_severities = input.borrow().get_option("ignore-severity")?;
if let Some(list) = cli_severities.as_list() {
for sev in list {
if let Some(s) = sev.as_string() {
@@ -128,7 +128,7 @@ impl AuditCommand {
}
let ignore_unreachable = input
.borrow()
- .get_option("ignore-unreachable")
+ .get_option("ignore-unreachable")?
.as_bool()
.unwrap_or(false)
|| audit_config.ignore_unreachable;
@@ -158,7 +158,7 @@ impl AuditCommand {
let mut composer = crate::command::composer_full_mut(composer);
if input
.borrow()
- .get_option("locked")
+ .get_option("locked")?
.as_bool()
.unwrap_or(false)
{
@@ -173,7 +173,7 @@ impl AuditCommand {
let locked_repo = locker.get_locked_repository(
!input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false),
)?;
diff --git a/crates/shirabe/src/command/base_command.rs b/crates/shirabe/src/command/base_command.rs
index 9218497..af06ad9 100644
--- a/crates/shirabe/src/command/base_command.rs
+++ b/crates/shirabe/src/command/base_command.rs
@@ -369,10 +369,10 @@ impl<C: HasBaseCommandData> BaseCommand for C {
// shared Application handle is the prerequisite, so only the input flags are honoured here.
let mut disable_plugins = input
.borrow()
- .has_parameter_option(&["--no-plugins"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-plugins"]), false);
let mut disable_scripts = input
.borrow()
- .has_parameter_option(&["--no-scripts"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-scripts"]), false);
if self.is_self_update_command() {
disable_plugins = true;
@@ -411,7 +411,9 @@ impl<C: HasBaseCommandData> BaseCommand for C {
)?;
}
- if input.borrow().has_parameter_option(&["--no-ansi"], false)
+ if input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["--no-ansi"]), false)
&& input.borrow().has_option("no-progress")
{
input
@@ -443,7 +445,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if false
== input
.borrow()
- .get_option(option_name)
+ .get_option(option_name)?
.as_bool()
.unwrap_or(false)
&& Platform::get_env(env_name).map_or(false, |s| !s.is_empty() && s != "0")
@@ -459,7 +461,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if true == input.borrow().has_option("ignore-platform-reqs") {
if !input
.borrow()
- .get_option("ignore-platform-reqs")
+ .get_option("ignore-platform-reqs")?
.as_bool()
.unwrap_or(false)
&& Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQS")
@@ -477,13 +479,13 @@ impl<C: HasBaseCommandData> BaseCommand for C {
&& (!input.borrow().has_option("ignore-platform-reqs")
|| !input
.borrow()
- .get_option("ignore-platform-reqs")
+ .get_option("ignore-platform-reqs")?
.as_bool()
.unwrap_or(false))
{
let ignore_platform_req_env = Platform::get_env("COMPOSER_IGNORE_PLATFORM_REQ");
let ignore_str = ignore_platform_req_env.clone().unwrap_or_default();
- if 0 == count(&input.borrow().get_option("ignore-platform-req"))
+ if 0 == count(&input.borrow().get_option("ignore-platform-req")?)
&& ignore_platform_req_env.is_some()
&& "" != ignore_str
{
@@ -519,11 +521,11 @@ impl<C: HasBaseCommandData> BaseCommand for C {
let disable_plugins = disable_plugins
|| input
.borrow()
- .has_parameter_option(&["--no-plugins"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-plugins"]), false);
let disable_scripts = disable_scripts.unwrap_or(false)
|| input
.borrow()
- .has_parameter_option(&["--no-scripts"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-scripts"]), false);
// PHP: if ($app instanceof Application && $app->getDisablePluginsByDefault()) $disablePlugins = true;
// (same for getDisableScriptsByDefault()).
@@ -565,11 +567,11 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
if input.borrow().has_option("prefer-install")
- && is_string(&input.borrow().get_option("prefer-install"))
+ && is_string(&input.borrow().get_option("prefer-install")?)
{
if input
.borrow()
- .get_option("prefer-source")
+ .get_option("prefer-source")?
.as_bool()
.unwrap_or(false)
{
@@ -582,7 +584,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
if input
.borrow()
- .get_option("prefer-dist")
+ .get_option("prefer-dist")?
.as_bool()
.unwrap_or(false)
{
@@ -593,7 +595,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
}
.into());
}
- let prefer_install = input.borrow().get_option("prefer-install");
+ let prefer_install = input.borrow().get_option("prefer-install")?;
match prefer_install.as_string().unwrap_or("") {
"dist" => {
input
@@ -624,37 +626,37 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if input
.borrow()
- .get_option("prefer-source")
+ .get_option("prefer-source")?
.as_bool()
.unwrap_or(false)
|| input
.borrow()
- .get_option("prefer-dist")
+ .get_option("prefer-dist")?
.as_bool()
.unwrap_or(false)
|| (keep_vcs_requires_prefer_source
&& input.borrow().has_option("keep-vcs")
&& input
.borrow()
- .get_option("keep-vcs")
+ .get_option("keep-vcs")?
.as_bool()
.unwrap_or(false))
{
prefer_source = input
.borrow()
- .get_option("prefer-source")
+ .get_option("prefer-source")?
.as_bool()
.unwrap_or(false)
|| (keep_vcs_requires_prefer_source
&& input.borrow().has_option("keep-vcs")
&& input
.borrow()
- .get_option("keep-vcs")
+ .get_option("keep-vcs")?
.as_bool()
.unwrap_or(false));
prefer_dist = input
.borrow()
- .get_option("prefer-dist")
+ .get_option("prefer-dist")?
.as_bool()
.unwrap_or(false);
}
@@ -681,14 +683,14 @@ impl<C: HasBaseCommandData> BaseCommand for C {
if true
== input
.borrow()
- .get_option("ignore-platform-reqs")
+ .get_option("ignore-platform-reqs")?
.as_bool()
.unwrap_or(false)
{
return Ok(PlatformRequirementFilterFactory::ignore_all());
}
- let ignores = input.borrow().get_option("ignore-platform-req");
+ let ignores = input.borrow().get_option("ignore-platform-req")?;
if count(&ignores) > 0 {
return Ok(PlatformRequirementFilterFactory::from_bool_or_list(
ignores,
@@ -737,7 +739,10 @@ impl<C: HasBaseCommandData> BaseCommand for C {
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) {
let mut renderer = Table::new(output);
- renderer.set_style("compact");
+ renderer
+ .set_style(PhpMixed::from("compact"))
+ .expect("Table::set_style I/O cannot fail")
+ .expect("'compact' is a built-in table style");
renderer.set_rows(table).render();
let _ = TableSeparator::new();
}
@@ -771,7 +776,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
.into());
}
- let val = input.borrow().get_option(opt_name);
+ let val = input.borrow().get_option(opt_name)?;
let formats: Vec<Box<PhpMixed>> = Auditor::FORMATS
.iter()
.map(|s| Box::new(PhpMixed::String(s.to_string())))
@@ -800,14 +805,14 @@ impl<C: HasBaseCommandData> BaseCommand for C {
let audit = if input.borrow().has_option("audit") {
input
.borrow()
- .get_option("audit")
+ .get_option("audit")?
.as_bool()
.unwrap_or(false)
} else {
!(input.borrow().has_option("no-audit")
&& input
.borrow()
- .get_option("no-audit")
+ .get_option("no-audit")?
.as_bool()
.unwrap_or(false))
};
@@ -824,7 +829,7 @@ impl<C: HasBaseCommandData> BaseCommand for C {
|| (input.borrow().has_option("no-security-blocking")
&& input
.borrow()
- .get_option("no-security-blocking")
+ .get_option("no-security-blocking")?
.as_bool()
.unwrap_or(false))
{
diff --git a/crates/shirabe/src/command/base_config_command.rs b/crates/shirabe/src/command/base_config_command.rs
index bfdd33a..4f6fd59 100644
--- a/crates/shirabe/src/command/base_config_command.rs
+++ b/crates/shirabe/src/command/base_config_command.rs
@@ -31,10 +31,10 @@ pub trait BaseConfigCommand: BaseCommand {
if input
.borrow()
- .get_option("global")
+ .get_option("global")?
.as_bool()
.unwrap_or(false)
- && !input.borrow().get_option("file").is_null()
+ && !input.borrow().get_option("file")?.is_null()
{
return Err(anyhow::anyhow!("--file and --global can not be combined"));
}
@@ -48,7 +48,7 @@ pub trait BaseConfigCommand: BaseCommand {
// When using --global flag, set baseDir to home directory for correct absolute path resolution
if input
.borrow()
- .get_option("global")
+ .get_option("global")?
.as_bool()
.unwrap_or(false)
{
@@ -56,7 +56,7 @@ pub trait BaseConfigCommand: BaseCommand {
config_rc.borrow_mut().set_base_dir(Some(home));
}
- let config_file = self.get_composer_config_file(input.clone(), &*config_rc.borrow());
+ let config_file = self.get_composer_config_file(input.clone(), &*config_rc.borrow())?;
// Create global composer.json if invoked using `composer global [config-cmd]`
if (config_file == "composer.json" || config_file == "./composer.json")
@@ -77,7 +77,7 @@ pub trait BaseConfigCommand: BaseCommand {
// Initialize the global file if it's not there, ignoring any warnings or notices
if input
.borrow()
- .get_option("global")
+ .get_option("global")?
.as_bool()
.unwrap_or(false)
&& !self.config_file().unwrap().borrow().exists()
@@ -116,21 +116,21 @@ pub trait BaseConfigCommand: BaseCommand {
&self,
input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
config: &Config,
- ) -> String {
+ ) -> anyhow::Result<String> {
if input
.borrow()
- .get_option("global")
+ .get_option("global")?
.as_bool()
.unwrap_or(false)
{
- format!("{}/config.json", config.get("home"))
+ Ok(format!("{}/config.json", config.get("home")))
} else {
- input
+ Ok(input
.borrow()
- .get_option("file")
+ .get_option("file")?
.as_string()
.map(|s| s.to_string())
- .unwrap_or_else(|| Factory::get_composer_file().unwrap_or_default())
+ .unwrap_or_else(|| Factory::get_composer_file().unwrap_or_default()))
}
}
@@ -140,21 +140,21 @@ pub trait BaseConfigCommand: BaseCommand {
&self,
input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
config: &Config,
- ) -> String {
+ ) -> anyhow::Result<String> {
if input
.borrow()
- .get_option("global")
+ .get_option("global")?
.as_bool()
.unwrap_or(false)
{
- format!("{}/auth.json", config.get("home"))
+ Ok(format!("{}/auth.json", config.get("home")))
} else {
- let composer_config = self.get_composer_config_file(input, config);
+ let composer_config = self.get_composer_config_file(input, config)?;
let parent = std::path::Path::new(&composer_config)
.parent()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default();
- format!("{}/auth.json", parent)
+ Ok(format!("{}/auth.json", parent))
}
}
}
diff --git a/crates/shirabe/src/command/base_dependency_command.rs b/crates/shirabe/src/command/base_dependency_command.rs
index 27f3544..1ca8a76 100644
--- a/crates/shirabe/src/command/base_dependency_command.rs
+++ b/crates/shirabe/src/command/base_dependency_command.rs
@@ -59,7 +59,7 @@ pub trait BaseDependencyCommand: BaseCommand {
if input
.borrow()
- .get_option("locked")
+ .get_option("locked")?
.as_bool()
.unwrap_or(false)
{
@@ -94,7 +94,7 @@ pub trait BaseDependencyCommand: BaseCommand {
&& (root_pkg.get_requires().len() > 0 || root_pkg.get_dev_requires().len() > 0)
{
output.borrow().writeln(
- "<warning>No dependencies installed. Try running composer install or update, or use --locked.</warning>",
+ &["<warning>No dependencies installed. Try running composer install or update, or use --locked.</warning>".to_string()],
shirabe_external_packages::symfony::console::output::OUTPUT_NORMAL,
);
@@ -122,14 +122,14 @@ pub trait BaseDependencyCommand: BaseCommand {
let needle = input
.borrow()
- .get_argument(Self::ARGUMENT_PACKAGE)
+ .get_argument(Self::ARGUMENT_PACKAGE)?
.as_string()
.unwrap_or_default()
.to_string();
let text_constraint: String = if input.borrow().has_argument(Self::ARGUMENT_CONSTRAINT) {
input
.borrow()
- .get_argument(Self::ARGUMENT_CONSTRAINT)
+ .get_argument(Self::ARGUMENT_CONSTRAINT)?
.as_string()
.unwrap_or("*")
.to_string()
@@ -246,13 +246,13 @@ pub trait BaseDependencyCommand: BaseCommand {
let render_tree = input
.borrow()
- .get_option(Self::OPTION_TREE)
+ .get_option(Self::OPTION_TREE)?
.as_bool()
.unwrap_or(false);
let recursive = render_tree
|| input
.borrow()
- .get_option(Self::OPTION_RECURSIVE)
+ .get_option(Self::OPTION_RECURSIVE)?
.as_bool()
.unwrap_or(false);
@@ -357,7 +357,7 @@ pub trait BaseDependencyCommand: BaseCommand {
let name_with_link = match &package_url {
Some(url) => format!(
"<href={}>{}</>",
- OutputFormatter::escape(url),
+ OutputFormatter::escape(url).expect("OutputFormatter::escape never fails"),
package.get_pretty_name()
),
None => package.get_pretty_name().to_string(),
@@ -399,12 +399,12 @@ pub trait BaseDependencyCommand: BaseCommand {
"blue".to_string(),
];
for color in self.colors() {
- let style = OutputFormatterStyle::new(Some(color), None, None);
+ let style = OutputFormatterStyle::new(Some(color), None, vec![]);
output
.borrow()
.get_formatter()
.borrow_mut()
- .set_style(color, style);
+ .set_style(color, Box::new(style));
}
}
@@ -428,7 +428,7 @@ pub trait BaseDependencyCommand: BaseCommand {
let name_with_link = match &package_url {
Some(url) => format!(
"<href={}>{}</>",
- OutputFormatter::escape(url),
+ OutputFormatter::escape(url).expect("OutputFormatter::escape never fails"),
package.get_pretty_name()
),
None => package.get_pretty_name().to_string(),
diff --git a/crates/shirabe/src/command/bump_command.rs b/crates/shirabe/src/command/bump_command.rs
index 92b1331..6f947c2 100644
--- a/crates/shirabe/src/command/bump_command.rs
+++ b/crates/shirabe/src/command/bump_command.rs
@@ -62,7 +62,7 @@ impl BumpCommand {
) -> Result<i64> {
let packages_filter: Vec<String> = input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
@@ -73,17 +73,17 @@ impl BumpCommand {
let dev_only = input
.borrow()
- .get_option("dev-only")
+ .get_option("dev-only")?
.as_bool()
.unwrap_or(false);
let no_dev_only = input
.borrow()
- .get_option("no-dev-only")
+ .get_option("no-dev-only")?
.as_bool()
.unwrap_or(false);
let dry_run = input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false);
let io = self.get_io().clone();
diff --git a/crates/shirabe/src/command/check_platform_reqs_command.rs b/crates/shirabe/src/command/check_platform_reqs_command.rs
index 2742f6f..658d049 100644
--- a/crates/shirabe/src/command/check_platform_reqs_command.rs
+++ b/crates/shirabe/src/command/check_platform_reqs_command.rs
@@ -60,7 +60,7 @@ impl CheckPlatformReqsCommand {
let no_dev = input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false);
@@ -69,7 +69,7 @@ impl CheckPlatformReqsCommand {
let installed_repo_base: crate::repository::RepositoryInterfaceHandle = if input
.borrow()
- .get_option("lock")
+ .get_option("lock")?
.as_bool()
.unwrap_or(false)
{
@@ -248,7 +248,7 @@ impl CheckPlatformReqsCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.unwrap_or("text")
.to_string();
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index 135b47f..342797c 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -126,7 +126,7 @@ impl ConfigCommand {
self.initialize(input.clone(), output)?;
let auth_config_file =
- self.get_auth_config_file(input.clone(), &*self.config.as_ref().unwrap().borrow());
+ self.get_auth_config_file(input.clone(), &*self.config.as_ref().unwrap().borrow())?;
let auth_config_file_jf = std::rc::Rc::new(std::cell::RefCell::new(JsonFile::new(
auth_config_file,
@@ -137,7 +137,7 @@ impl ConfigCommand {
self.auth_config_source = Some(JsonConfigSource::new(auth_config_file_jf, true));
// Initialize the global file if it's not there, ignoring any warnings or notices
- if input.borrow().get_option("global").as_bool() == Some(true)
+ if input.borrow().get_option("global")?.as_bool() == Some(true)
&& !self.auth_config_file.as_ref().unwrap().borrow().exists()
{
touch(self.auth_config_file.as_ref().unwrap().borrow().get_path());
@@ -182,7 +182,7 @@ impl ConfigCommand {
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
// Open file in editor
- if input.borrow().get_option("editor").as_bool() == Some(true) {
+ if input.borrow().get_option("editor")?.as_bool() == Some(true) {
let mut editor = Platform::get_env("EDITOR");
if editor.is_none() || editor.as_deref() == Some("") {
if Platform::is_windows() {
@@ -202,7 +202,7 @@ impl ConfigCommand {
editor = Some(escapeshellcmd(&editor.unwrap()));
}
- let file = if input.borrow().get_option("auth").as_bool() == Some(true) {
+ let file = if input.borrow().get_option("auth")?.as_bool() == Some(true) {
self.auth_config_file
.as_ref()
.unwrap()
@@ -234,7 +234,7 @@ impl ConfigCommand {
return Ok(0);
}
- if input.borrow().get_option("global").as_bool() != Some(true) {
+ if input.borrow().get_option("global")?.as_bool() != Some(true) {
let config_read = self.config_file.as_ref().unwrap().borrow_mut().read()?;
let config_map = match config_read {
PhpMixed::Array(m) => m
@@ -272,7 +272,7 @@ impl ConfigCommand {
}
// List the configuration of the file settings
- if input.borrow().get_option("list").as_bool() == Some(true) {
+ if input.borrow().get_option("list")?.as_bool() == Some(true) {
let all_map = self.config.as_ref().unwrap().borrow_mut().all(0)?;
let raw_map = self.config.as_ref().unwrap().borrow().raw();
let to_mixed = |m: IndexMap<String, PhpMixed>| -> PhpMixed {
@@ -283,20 +283,20 @@ impl ConfigCommand {
to_mixed(raw_map),
output,
None,
- input.borrow().get_option("source").as_bool() == Some(true),
+ input.borrow().get_option("source")?.as_bool() == Some(true),
);
return Ok(0);
}
- let setting_key_arg = input.borrow().get_argument("setting-key");
+ let setting_key_arg = input.borrow().get_argument("setting-key")?;
let setting_key = match setting_key_arg.as_string() {
Some(s) => s.to_string(),
None => return Ok(0),
};
// If the user enters in a config variable, parse it and save to file
- let setting_values_raw = input.borrow().get_argument("setting-value");
+ let setting_values_raw = input.borrow().get_argument("setting-value")?;
let setting_values: Vec<String> = setting_values_raw
.as_list()
.map(|l| {
@@ -305,7 +305,7 @@ impl ConfigCommand {
.collect()
})
.unwrap_or_default();
- if !setting_values.is_empty() && input.borrow().get_option("unset").as_bool() == Some(true)
+ if !setting_values.is_empty() && input.borrow().get_option("unset")?.as_bool() == Some(true)
{
return Err(RuntimeException {
message: "You can not combine a setting value with --unset".to_string(),
@@ -315,7 +315,8 @@ impl ConfigCommand {
}
// show the value if no value is provided
- if setting_values.is_empty() && input.borrow().get_option("unset").as_bool() != Some(true) {
+ if setting_values.is_empty() && input.borrow().get_option("unset")?.as_bool() != Some(true)
+ {
let properties: Vec<&'static str> = Self::CONFIGURABLE_PACKAGE_PROPERTIES.to_vec();
let mut properties_defaults: IndexMap<String, PhpMixed> = IndexMap::new();
properties_defaults.insert("type".to_string(), PhpMixed::String("library".to_string()));
@@ -421,7 +422,7 @@ impl ConfigCommand {
{
value = self.config.as_ref().unwrap().borrow_mut().get_with_flags(
&setting_key,
- if input.borrow().get_option("absolute").as_bool() == Some(true) {
+ if input.borrow().get_option("absolute")?.as_bool() == Some(true) {
0
} else {
Config::RELATIVE_PATHS
@@ -504,7 +505,7 @@ impl ConfigCommand {
};
let mut source_of_config_value = String::new();
- if input.borrow().get_option("source").as_bool() == Some(true) {
+ if input.borrow().get_option("source")?.as_bool() == Some(true) {
source_of_config_value = format!(" ({})", source);
}
@@ -542,7 +543,7 @@ impl ConfigCommand {
let multi_config_values = build_multi_config_values();
// allow unsetting audit config entirely
- if input.borrow().get_option("unset").as_bool() == Some(true) && setting_key == "audit" {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) && setting_key == "audit" {
self.config_source
.as_mut()
.unwrap()
@@ -551,7 +552,7 @@ impl ConfigCommand {
return Ok(0);
}
- if input.borrow().get_option("unset").as_bool() == Some(true)
+ if input.borrow().get_option("unset")?.as_bool() == Some(true)
&& (unique_config_values.contains_key(&setting_key)
|| multi_config_values.contains_key(&setting_key))
{
@@ -596,7 +597,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -637,7 +638,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -668,7 +669,7 @@ impl ConfigCommand {
let unique_props = build_unique_props();
let multi_props = build_multi_props();
- if input.borrow().get_option("global").as_bool() == Some(true)
+ if input.borrow().get_option("global")?.as_bool() == Some(true)
&& (unique_props.contains_key(&setting_key)
|| multi_props.contains_key(&setting_key)
|| strpos(&setting_key, "extra.") == Some(0))
@@ -679,7 +680,7 @@ impl ConfigCommand {
}
.into());
}
- if input.borrow().get_option("unset").as_bool() == Some(true)
+ if input.borrow().get_option("unset")?.as_bool() == Some(true)
&& (unique_props.contains_key(&setting_key) || multi_props.contains_key(&setting_key))
{
self.config_source
@@ -709,7 +710,7 @@ impl ConfigCommand {
)
.unwrap_or(false)
{
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -731,7 +732,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
PhpMixed::Array(repo),
- input.borrow().get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append")?.as_bool() == Some(true),
);
return Ok(0);
@@ -747,7 +748,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
PhpMixed::Bool(false),
- input.borrow().get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append")?.as_bool() == Some(true),
);
return Ok(0);
@@ -757,7 +758,7 @@ impl ConfigCommand {
self.config_source.as_mut().unwrap().add_repository(
&matches[1],
value,
- input.borrow().get_option("append").as_bool() == Some(true),
+ input.borrow().get_option("append")?.as_bool() == Some(true),
);
return Ok(0);
@@ -774,7 +775,7 @@ impl ConfigCommand {
// handle extra
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^extra\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -784,9 +785,9 @@ impl ConfigCommand {
}
let mut value = PhpMixed::String(values[0].clone());
- if input.borrow().get_option("json").as_bool() == Some(true) {
+ if input.borrow().get_option("json")?.as_bool() == Some(true) {
value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?;
- if input.borrow().get_option("merge").as_bool() == Some(true) {
+ if input.borrow().get_option("merge")?.as_bool() == Some(true) {
let current_value_outer =
self.config_file.as_ref().unwrap().borrow_mut().read()?;
let bits = explode(".", &setting_key);
@@ -833,7 +834,7 @@ impl ConfigCommand {
// handle suggest
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^suggest\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -855,7 +856,7 @@ impl ConfigCommand {
setting_key.as_str().into(),
&vec!["suggest".to_string(), "extra".to_string()].into(),
true,
- ) && input.borrow().get_option("unset").as_bool() == Some(true)
+ ) && input.borrow().get_option("unset")?.as_bool() == Some(true)
{
self.config_source
.as_mut()
@@ -869,7 +870,7 @@ impl ConfigCommand {
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^platform\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false)
{
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -892,7 +893,8 @@ impl ConfigCommand {
}
// handle unsetting platform
- if setting_key == "platform" && input.borrow().get_option("unset").as_bool() == Some(true) {
+ if setting_key == "platform" && input.borrow().get_option("unset")?.as_bool() == Some(true)
+ {
self.config_source
.as_mut()
.unwrap()
@@ -911,7 +913,7 @@ impl ConfigCommand {
.into(),
true,
) {
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -926,7 +928,7 @@ impl ConfigCommand {
.map(|s| Box::new(PhpMixed::String(s.clone())))
.collect(),
);
- if input.borrow().get_option("json").as_bool() == Some(true) {
+ if input.borrow().get_option("json")?.as_bool() == Some(true) {
value = JsonFile::parse_json(Some(&values[0]), Some("composer.json"))?;
if !is_array(&value) {
return Err(RuntimeException {
@@ -937,7 +939,7 @@ impl ConfigCommand {
}
}
- if input.borrow().get_option("merge").as_bool() == Some(true) {
+ if input.borrow().get_option("merge")?.as_bool() == Some(true) {
let current_config = self.config_file.as_ref().unwrap().borrow_mut().read()?;
let key_suffix = str_replace("audit.", "", &setting_key);
let current_value = current_config
@@ -990,7 +992,7 @@ impl ConfigCommand {
// handle auth
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|custom-headers|bearer|forgejo-token)\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.auth_config_source.as_mut().unwrap().remove_config_setting(&format!("{}.{}", matches[1], matches[2]));
self.config_source.as_mut().unwrap().remove_config_setting(&format!("{}.{}", matches[1], matches[2]));
@@ -1096,7 +1098,7 @@ impl ConfigCommand {
// handle script
let mut matches: IndexMap<CaptureKey, String> = IndexMap::new();
if Preg::is_match3("/^scripts\\.(.+)/", &setting_key, Some(&mut matches)).unwrap_or(false) {
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
@@ -1124,7 +1126,7 @@ impl ConfigCommand {
}
// handle unsetting other top level properties
- if input.borrow().get_option("unset").as_bool() == Some(true) {
+ if input.borrow().get_option("unset")?.as_bool() == Some(true) {
self.config_source
.as_mut()
.unwrap()
diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs
index ba384d5..247941b 100644
--- a/crates/shirabe/src/command/create_project_command.rs
+++ b/crates/shirabe/src/command/create_project_command.rs
@@ -119,12 +119,12 @@ impl CreateProjectCommand {
let (prefer_source, prefer_dist) =
self.get_preferred_install_options(&config.borrow(), input.clone(), true)?;
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
io.write_error("<warning>You are using the deprecated option \"dev\". Dev packages are installed by default now.</warning>");
}
if input
.borrow()
- .get_option("no-custom-installers")
+ .get_option("no-custom-installers")?
.as_bool()
.unwrap_or(false)
{
@@ -135,9 +135,9 @@ impl CreateProjectCommand {
}
if input.borrow().is_interactive()
- && input.borrow().get_option("ask").as_bool().unwrap_or(false)
+ && input.borrow().get_option("ask")?.as_bool().unwrap_or(false)
{
- let package = input.borrow().get_argument("package");
+ let package = input.borrow().get_argument("package")?;
if package.is_null() {
return Err(RuntimeException {
message: "Not enough arguments (missing: \"package\").".to_string(),
@@ -156,8 +156,8 @@ impl CreateProjectCommand {
.set_argument("directory", io.ask(prompt, PhpMixed::Null));
}
- let repository_opt = input.borrow().get_option("repository");
- let repository_url_opt = input.borrow().get_option("repository-url");
+ let repository_opt = input.borrow().get_option("repository")?;
+ let repository_url_opt = input.borrow().get_option("repository-url")?;
let repositories = if repository_opt
.as_list()
.map(|l| l.len() > 0)
@@ -174,61 +174,61 @@ impl CreateProjectCommand {
input.clone(),
input
.borrow()
- .get_argument("package")
+ .get_argument("package")?
.as_string()
.map(|s| s.to_string()),
input
.borrow()
- .get_argument("directory")
+ .get_argument("directory")?
.as_string()
.map(|s| s.to_string()),
input
.borrow()
- .get_argument("version")
+ .get_argument("version")?
.as_string()
.map(|s| s.to_string()),
input
.borrow()
- .get_option("stability")
+ .get_option("stability")?
.as_string()
.map(|s| s.to_string()),
prefer_source,
prefer_dist,
!input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false),
repositories,
input
.borrow()
- .get_option("no-plugins")
+ .get_option("no-plugins")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("no-scripts")
+ .get_option("no-scripts")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("no-install")
+ .get_option("no-install")?
.as_bool()
.unwrap_or(false),
Some(self.get_platform_requirement_filter(input.clone())?),
!input
.borrow()
- .get_option("no-secure-http")
+ .get_option("no-secure-http")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("add-repository")
+ .get_option("add-repository")?
.as_bool()
.unwrap_or(false),
)
@@ -478,9 +478,9 @@ impl CreateProjectCommand {
}
let mut has_vcs = installed_from_vcs;
- let remove_vcs = !input.borrow().get_option("keep-vcs").as_bool().unwrap_or(false)
+ let remove_vcs = !input.borrow().get_option("keep-vcs")?.as_bool().unwrap_or(false)
&& installed_from_vcs
- && (input.borrow().get_option("remove-vcs").as_bool().unwrap_or(false)
+ && (input.borrow().get_option("remove-vcs")?.as_bool().unwrap_or(false)
|| !io.is_interactive()
|| io.ask_confirmation(
"<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>y,n</comment>]? ".to_string(),
diff --git a/crates/shirabe/src/command/dump_autoload_command.rs b/crates/shirabe/src/command/dump_autoload_command.rs
index de0a57d..ae51eac 100644
--- a/crates/shirabe/src/command/dump_autoload_command.rs
+++ b/crates/shirabe/src/command/dump_autoload_command.rs
@@ -86,7 +86,7 @@ impl DumpAutoloadCommand {
let optimize = input
.borrow()
- .get_option("optimize")
+ .get_option("optimize")?
.as_bool()
.unwrap_or(false)
|| config
@@ -96,7 +96,7 @@ impl DumpAutoloadCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| config
@@ -106,11 +106,15 @@ impl DumpAutoloadCommand {
.unwrap_or(false);
let apcu_prefix = input
.borrow()
- .get_option("apcu-prefix")
+ .get_option("apcu-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
- || input.borrow().get_option("apcu").as_bool().unwrap_or(false)
+ || input
+ .borrow()
+ .get_option("apcu")?
+ .as_bool()
+ .unwrap_or(false)
|| config
.borrow_mut()
.get("apcu-autoloader")
@@ -119,7 +123,7 @@ impl DumpAutoloadCommand {
if input
.borrow()
- .get_option("strict-psr")
+ .get_option("strict-psr")?
.as_bool()
.unwrap_or(false)
&& !optimize
@@ -133,7 +137,7 @@ impl DumpAutoloadCommand {
}
if input
.borrow()
- .get_option("strict-ambiguous")
+ .get_option("strict-ambiguous")?
.as_bool()
.unwrap_or(false)
&& !optimize
@@ -160,7 +164,7 @@ impl DumpAutoloadCommand {
let platform_requirement_filter = self.get_platform_requirement_filter(input.clone())?;
if input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false)
{
@@ -171,7 +175,7 @@ impl DumpAutoloadCommand {
}
if input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false)
{
@@ -180,10 +184,10 @@ impl DumpAutoloadCommand {
.borrow_mut()
.set_dev_mode(false);
}
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
if input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false)
{
@@ -218,7 +222,7 @@ impl DumpAutoloadCommand {
.set_platform_requirement_filter(platform_requirement_filter);
let strict_ambiguous = input
.borrow()
- .get_option("strict-ambiguous")
+ .get_option("strict-ambiguous")?
.as_bool()
.unwrap_or(false);
@@ -266,7 +270,7 @@ impl DumpAutoloadCommand {
if missing_dependencies
|| (input
.borrow()
- .get_option("strict-psr")
+ .get_option("strict-psr")?
.as_bool()
.unwrap_or(false)
&& !class_map.get_psr_violations().is_empty())
@@ -276,7 +280,7 @@ impl DumpAutoloadCommand {
if input
.borrow()
- .get_option("strict-ambiguous")
+ .get_option("strict-ambiguous")?
.as_bool()
.unwrap_or(false)
&& !class_map.get_ambiguous_classes(None)?.is_empty()
diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs
index 3aec024..3c9cee2 100644
--- a/crates/shirabe/src/command/exec_command.rs
+++ b/crates/shirabe/src/command/exec_command.rs
@@ -49,8 +49,12 @@ impl ExecCommand {
return Ok(());
}
- if input.borrow().get_argument("binary").as_string().is_some()
- || input.borrow().get_option("list").as_bool().unwrap_or(false)
+ if input.borrow().get_argument("binary")?.as_string().is_some()
+ || input
+ .borrow()
+ .get_option("list")?
+ .as_bool()
+ .unwrap_or(false)
{
return Ok(());
}
@@ -82,8 +86,12 @@ impl ExecCommand {
) -> Result<i64> {
let composer = self.require_composer(None, None)?;
- if input.borrow().get_option("list").as_bool().unwrap_or(false)
- || input.borrow().get_argument("binary").as_string().is_none()
+ if input
+ .borrow()
+ .get_option("list")?
+ .as_bool()
+ .unwrap_or(false)
+ || input.borrow().get_argument("binary")?.as_string().is_none()
{
let bins = self.get_binaries(true)?;
if bins.is_empty() {
@@ -115,7 +123,7 @@ impl ExecCommand {
let binary = input
.borrow()
- .get_argument("binary")
+ .get_argument("binary")?
.as_string()
.unwrap_or("")
.to_string();
@@ -141,7 +149,7 @@ impl ExecCommand {
let args = input
.borrow()
- .get_argument("args")
+ .get_argument("args")?
.as_list()
.map(|l| {
l.iter()
diff --git a/crates/shirabe/src/command/fund_command.rs b/crates/shirabe/src/command/fund_command.rs
index 277d3e4..6223def 100644
--- a/crates/shirabe/src/command/fund_command.rs
+++ b/crates/shirabe/src/command/fund_command.rs
@@ -122,7 +122,7 @@ impl FundCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.unwrap_or("text")
.to_string();
@@ -150,7 +150,7 @@ impl FundCommand {
}
io.write(&format!(
" <href={}>{}</>",
- OutputFormatter::escape(url),
+ OutputFormatter::escape(url)?,
url
));
}
diff --git a/crates/shirabe/src/command/global_command.rs b/crates/shirabe/src/command/global_command.rs
index f066721..e978dff 100644
--- a/crates/shirabe/src/command/global_command.rs
+++ b/crates/shirabe/src/command/global_command.rs
@@ -4,10 +4,12 @@ use std::path::Path;
use anyhow::Result;
use shirabe_external_packages::composer::pcre::Preg;
+use shirabe_external_packages::symfony::console::input::ArgvInput;
+use shirabe_external_packages::symfony::console::input::ArrayInput;
use shirabe_external_packages::symfony::console::input::InputInterface;
use shirabe_external_packages::symfony::console::input::StringInput;
use shirabe_external_packages::symfony::console::output::OutputInterface;
-use shirabe_php_shim::{LogicException, RuntimeException, chdir};
+use shirabe_php_shim::{AsAny, LogicException, RuntimeException, chdir};
use crate::command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::console::input::InputArgument;
@@ -56,12 +58,35 @@ impl GlobalCommand {
);
}
+ // TODO remove for Symfony 6+ as it is then in the interface.
+ // Mirrors PHP's `method_exists($input, '__toString')` guard followed by
+ // `$input->__toString()`. `InputInterface` does not declare `__toString`, so the
+ // concrete stringable input types are matched explicitly.
+ fn input_to_string(input: &dyn InputInterface) -> Result<String> {
+ let input_any = input.as_any();
+ if let Some(argv_input) = input_any.downcast_ref::<ArgvInput>() {
+ Ok(argv_input.to_string())
+ } else if let Some(array_input) = input_any.downcast_ref::<ArrayInput>() {
+ Ok(array_input.to_string())
+ } else if input_any.is::<StringInput>() {
+ // StringInput's stringification is not exposed by shirabe-external-packages
+ // (its inner ArgvInput is pub(crate) and it defines no public __toString).
+ todo!("StringInput::__toString is not accessible from the shirabe crate")
+ } else {
+ Err(LogicException {
+ message: "Expected an Input instance that is stringable".to_string(),
+ code: 0,
+ }
+ .into())
+ }
+ }
+
pub fn run(
&mut self,
input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
- let tokens = Preg::split(r"{\s+}", &input.borrow().to_input_string())?;
+ let tokens = Preg::split(r"{\s+}", &Self::input_to_string(&*input.borrow())?)?;
let mut args: Vec<String> = vec![];
for token in &tokens {
if !token.is_empty() && !token.starts_with('-') {
@@ -123,12 +148,12 @@ impl GlobalCommand {
let new_input_str = Preg::replace4(
r"{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}",
"",
- &input.borrow().to_input_string(),
+ &Self::input_to_string(&*input.borrow())?,
1,
)?;
self.get_application()?.reset_composer();
- Ok(StringInput::new(&new_input_str))
+ Ok(StringInput::new(&new_input_str)?)
}
pub fn is_proxy_command(&self) -> bool {
diff --git a/crates/shirabe/src/command/home_command.rs b/crates/shirabe/src/command/home_command.rs
index 6ddf0ca..029eaab 100644
--- a/crates/shirabe/src/command/home_command.rs
+++ b/crates/shirabe/src/command/home_command.rs
@@ -78,7 +78,7 @@ impl HomeCommand {
let packages: Vec<String> = input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
@@ -98,10 +98,14 @@ impl HomeCommand {
let show_homepage = input
.borrow()
- .get_option("homepage")
+ .get_option("homepage")?
+ .as_bool()
+ .unwrap_or(false);
+ let show_only = input
+ .borrow()
+ .get_option("show")?
.as_bool()
.unwrap_or(false);
- let show_only = input.borrow().get_option("show").as_bool().unwrap_or(false);
for package_name in &packages {
let mut handled = false;
diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs
index 1bafd74..aea9faf 100644
--- a/crates/shirabe/src/command/init_command.rs
+++ b/crates/shirabe/src/command/init_command.rs
@@ -5,6 +5,7 @@ use anyhow::Result;
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_external_packages::composer::spdx_licenses::SpdxLicenses;
+use shirabe_external_packages::symfony::console::helper::FormatBlockMessages;
use shirabe_external_packages::symfony::console::helper::FormatterHelper;
use shirabe_external_packages::symfony::console::input::ArrayInput;
use shirabe_external_packages::symfony::console::input::InputInterface;
@@ -189,7 +190,7 @@ impl InitCommand {
let repositories: Vec<String> = input
.borrow()
- .get_option("repository")
+ .get_option("repository")?
.as_list()
.map(|l| {
l.iter()
@@ -287,7 +288,7 @@ impl InitCommand {
autoload_path = Some(ap.clone());
let name = input
.borrow()
- .get_option("name")
+ .get_option("name")?
.as_string()
.unwrap_or("")
.to_string();
@@ -395,7 +396,7 @@ impl InitCommand {
if autoload_path.is_some() {
let name = input
.borrow()
- .get_option("name")
+ .get_option("name")?
.as_string()
.unwrap_or("")
.to_string();
@@ -420,11 +421,11 @@ impl InitCommand {
&mut self,
input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
- ) {
- self.initialize(input.clone(), output);
+ ) -> anyhow::Result<()> {
+ self.initialize(input.clone(), output)?;
if !input.borrow().is_interactive() {
- if input.borrow().get_option("name").is_null() {
+ if input.borrow().get_option("name")?.is_null() {
let name = self.get_default_package_name();
input
.borrow_mut()
@@ -432,7 +433,7 @@ impl InitCommand {
.expect("name option is defined");
}
- if input.borrow().get_option("author").is_null() {
+ if input.borrow().get_option("author")?.is_null() {
let author = self.get_default_author();
input
.borrow_mut()
@@ -440,6 +441,8 @@ impl InitCommand {
.expect("author option is defined");
}
}
+
+ Ok(())
}
pub(crate) fn interact(
@@ -459,7 +462,7 @@ impl InitCommand {
// initialize repos if configured
let repositories: Vec<String> = input
.borrow()
- .get_option("repository")
+ .get_option("repository")?
.as_list()
.map(|l| {
l.iter()
@@ -532,7 +535,9 @@ impl InitCommand {
&format!(
"\n{}\n",
formatter.format_block(
- &["Welcome to the Composer config generator"],
+ FormatBlockMessages::String(
+ "Welcome to the Composer config generator".to_string(),
+ ),
"bg=blue;fg=white",
true,
)
@@ -550,7 +555,7 @@ impl InitCommand {
let mut name = input
.borrow()
- .get_option("name")
+ .get_option("name")?
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| self.get_default_package_name());
@@ -598,7 +603,7 @@ impl InitCommand {
let description = input
.borrow()
- .get_option("description")
+ .get_option("description")?
.as_string()
.map(|s| s.to_string());
let description_default = description.clone();
@@ -615,7 +620,7 @@ impl InitCommand {
let author = input
.borrow()
- .get_option("author")
+ .get_option("author")?
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| self.get_default_author().unwrap_or_default());
@@ -663,7 +668,7 @@ impl InitCommand {
let minimum_stability = input
.borrow()
- .get_option("stability")
+ .get_option("stability")?
.as_string()
.map(|s| s.to_string());
let minimum_stability_default = minimum_stability.clone();
@@ -710,7 +715,7 @@ impl InitCommand {
.borrow_mut()
.set_option("stability", minimum_stability_value);
- let type_val = input.borrow().get_option("type");
+ let type_val = input.borrow().get_option("type")?;
let type_str = type_val.as_string().unwrap_or("").to_string();
let mut type_value = io.ask(
format!(
@@ -726,7 +731,7 @@ impl InitCommand {
let mut license = input
.borrow()
- .get_option("license")
+ .get_option("license")?
.as_string()
.map(|s| s.to_string());
if license.is_none() {
@@ -792,7 +797,7 @@ impl InitCommand {
let question = "Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ".to_string();
let require: Vec<String> = input
.borrow()
- .get_option("require")
+ .get_option("require")?
.as_list()
.map(|l| {
l.iter()
@@ -826,7 +831,7 @@ impl InitCommand {
let question = "Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ".to_string();
let require_dev: Vec<String> = input
.borrow()
- .get_option("require-dev")
+ .get_option("require-dev")?
.as_list()
.map(|l| {
l.iter()
@@ -861,14 +866,14 @@ impl InitCommand {
// --autoload - input and validation
let mut autoload = input
.borrow()
- .get_option("autoload")
+ .get_option("autoload")?
.as_string()
.map(|s| s.to_string())
.filter(|s| !s.is_empty())
.unwrap_or_else(|| "src/".to_string());
let name_str = input
.borrow()
- .get_option("name")
+ .get_option("name")?
.as_string()
.unwrap_or("")
.to_string();
@@ -1098,7 +1103,7 @@ impl InitCommand {
// TODO(phase-c): Application::find returns PhpMixed (the Symfony command registry is a
// todo!() stub), so the resolved command's run() cannot be invoked until the typed
// command registry is modelled.
- let _ = ArrayInput::new(IndexMap::new(), None);
+ let _ = ArrayInput::new(vec![], None);
let _ = output;
Ok(())
});
@@ -1121,7 +1126,7 @@ impl InitCommand {
// PHP: $command->run(new ArrayInput([]), $output);
// TODO(phase-c): same blocker as update_dependencies — Application::find returns
// PhpMixed (Symfony command registry todo!() stub), so run() cannot be invoked.
- let _ = ArrayInput::new(IndexMap::new(), None);
+ let _ = ArrayInput::new(vec![], None);
let _ = output;
Ok(())
});
diff --git a/crates/shirabe/src/command/install_command.rs b/crates/shirabe/src/command/install_command.rs
index f491820..182f855 100644
--- a/crates/shirabe/src/command/install_command.rs
+++ b/crates/shirabe/src/command/install_command.rs
@@ -69,19 +69,19 @@ impl InstallCommand {
) -> Result<i64> {
let io = self.get_io().clone();
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
io.write_error("<warning>You are using the deprecated option \"--dev\". It has no effect and will break in Composer 3.</warning>");
}
if input
.borrow()
- .get_option("no-suggest")
+ .get_option("no-suggest")?
.as_bool()
.unwrap_or(false)
{
io.write_error("<warning>You are using the deprecated option \"--no-suggest\". It has no effect and will break in Composer 3.</warning>");
}
- let args = input.borrow().get_argument("packages");
+ let args = input.borrow().get_argument("packages")?;
let args_vec: Vec<String> = args
.as_list()
.map(|l| {
@@ -101,7 +101,7 @@ impl InstallCommand {
if input
.borrow()
- .get_option("no-install")
+ .get_option("no-install")?
.as_bool()
.unwrap_or(false)
{
@@ -132,7 +132,7 @@ impl InstallCommand {
let optimize = input
.borrow()
- .get_option("optimize-autoloader")
+ .get_option("optimize-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
@@ -142,7 +142,7 @@ impl InstallCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| config
@@ -152,13 +152,13 @@ impl InstallCommand {
.unwrap_or(false);
let apcu_prefix = input
.borrow()
- .get_option("apcu-autoloader-prefix")
+ .get_option("apcu-autoloader-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
.borrow()
- .get_option("apcu-autoloader")
+ .get_option("apcu-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
@@ -173,7 +173,7 @@ impl InstallCommand {
.set_output_progress(
!input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
);
@@ -182,21 +182,21 @@ impl InstallCommand {
.set_dry_run(
input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false),
)
.set_download_only(
input
.borrow()
- .get_option("download-only")
+ .get_option("download-only")?
.as_bool()
.unwrap_or(false),
)
.set_verbose(
input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false),
)
@@ -205,14 +205,14 @@ impl InstallCommand {
.set_dev_mode(
!input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false),
)
.set_dump_autoloader(
!input
.borrow()
- .get_option("no-autoloader")
+ .get_option("no-autoloader")?
.as_bool()
.unwrap_or(false),
)
@@ -226,14 +226,14 @@ impl InstallCommand {
.set_error_on_audit(
input
.borrow()
- .get_option("audit")
+ .get_option("audit")?
.as_bool()
.unwrap_or(false),
);
if input
.borrow()
- .get_option("no-plugins")
+ .get_option("no-plugins")?
.as_bool()
.unwrap_or(false)
{
diff --git a/crates/shirabe/src/command/licenses_command.rs b/crates/shirabe/src/command/licenses_command.rs
index b8fa01d..5be2b41 100644
--- a/crates/shirabe/src/command/licenses_command.rs
+++ b/crates/shirabe/src/command/licenses_command.rs
@@ -8,6 +8,7 @@ use shirabe_external_packages::symfony::console::formatter::OutputFormatter;
use shirabe_external_packages::symfony::console::helper::Table;
use shirabe_external_packages::symfony::console::input::InputInterface;
use shirabe_external_packages::symfony::console::output::OutputInterface;
+use shirabe_external_packages::symfony::console::style::StyleInterface;
use shirabe_external_packages::symfony::console::style::SymfonyStyle;
use shirabe_php_shim::{PhpMixed, RuntimeException, UnexpectedValueException};
@@ -98,7 +99,7 @@ impl LicensesCommand {
let packages = if input
.borrow()
- .get_option("locked")
+ .get_option("locked")?
.as_bool()
.unwrap_or(false)
{
@@ -112,7 +113,7 @@ impl LicensesCommand {
}
let no_dev = input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false);
let repo = locker.get_locked_repository(!no_dev)?;
@@ -124,7 +125,7 @@ impl LicensesCommand {
if input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false)
{
@@ -146,7 +147,7 @@ impl LicensesCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.unwrap_or("text")
.to_string();
@@ -171,7 +172,7 @@ impl LicensesCommand {
io.write("");
let mut table = Table::new(output);
- table.set_style("compact");
+ table.set_style(shirabe_php_shim::PhpMixed::from("compact"))??;
table.set_headers(vec![
PhpMixed::String("Name".to_string()),
PhpMixed::String("Version".to_string()),
@@ -182,7 +183,7 @@ impl LicensesCommand {
let name = if let Some(link) = link {
format!(
"<href={}>{}</>",
- OutputFormatter::escape(&link),
+ OutputFormatter::escape(&link)?,
package.get_pretty_name()
)
} else {
diff --git a/crates/shirabe/src/command/outdated_command.rs b/crates/shirabe/src/command/outdated_command.rs
index 8eb67e6..c7ea773 100644
--- a/crates/shirabe/src/command/outdated_command.rs
+++ b/crates/shirabe/src/command/outdated_command.rs
@@ -62,7 +62,7 @@ impl OutdatedCommand {
if input
.borrow()
- .get_option("no-interaction")
+ .get_option("no-interaction")?
.as_bool()
.unwrap_or(false)
{
@@ -70,7 +70,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("no-plugins")
+ .get_option("no-plugins")?
.as_bool()
.unwrap_or(false)
{
@@ -78,7 +78,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("no-scripts")
+ .get_option("no-scripts")?
.as_bool()
.unwrap_or(false)
{
@@ -86,30 +86,30 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("no-cache")
+ .get_option("no-cache")?
.as_bool()
.unwrap_or(false)
{
args.insert("--no-cache".to_string(), PhpMixed::Bool(true));
}
- if !input.borrow().get_option("all").as_bool().unwrap_or(false) {
+ if !input.borrow().get_option("all")?.as_bool().unwrap_or(false) {
args.insert("--outdated".to_string(), PhpMixed::Bool(true));
}
if input
.borrow()
- .get_option("direct")
+ .get_option("direct")?
.as_bool()
.unwrap_or(false)
{
args.insert("--direct".to_string(), PhpMixed::Bool(true));
}
- let package_arg = input.borrow().get_argument("package");
+ let package_arg = input.borrow().get_argument("package")?;
if !matches!(package_arg, PhpMixed::Null) {
args.insert("package".to_string(), package_arg);
}
if input
.borrow()
- .get_option("strict")
+ .get_option("strict")?
.as_bool()
.unwrap_or(false)
{
@@ -117,7 +117,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("major-only")
+ .get_option("major-only")?
.as_bool()
.unwrap_or(false)
{
@@ -125,7 +125,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("minor-only")
+ .get_option("minor-only")?
.as_bool()
.unwrap_or(false)
{
@@ -133,7 +133,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("patch-only")
+ .get_option("patch-only")?
.as_bool()
.unwrap_or(false)
{
@@ -141,7 +141,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("locked")
+ .get_option("locked")?
.as_bool()
.unwrap_or(false)
{
@@ -149,7 +149,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false)
{
@@ -157,7 +157,7 @@ impl OutdatedCommand {
}
if input
.borrow()
- .get_option("sort-by-age")
+ .get_option("sort-by-age")?
.as_bool()
.unwrap_or(false)
{
@@ -165,20 +165,25 @@ impl OutdatedCommand {
}
args.insert(
"--ignore-platform-req".to_string(),
- input.borrow().get_option("ignore-platform-req"),
+ input.borrow().get_option("ignore-platform-req")?,
);
if input
.borrow()
- .get_option("ignore-platform-reqs")
+ .get_option("ignore-platform-reqs")?
.as_bool()
.unwrap_or(false)
{
args.insert("--ignore-platform-reqs".to_string(), PhpMixed::Bool(true));
}
- args.insert("--format".to_string(), input.borrow().get_option("format"));
- args.insert("--ignore".to_string(), input.borrow().get_option("ignore"));
+ args.insert("--format".to_string(), input.borrow().get_option("format")?);
+ args.insert("--ignore".to_string(), input.borrow().get_option("ignore")?);
- let input = ArrayInput::new(args, None);
+ let input = ArrayInput::new(
+ args.into_iter()
+ .map(|(k, v)| (PhpMixed::String(k), v))
+ .collect(),
+ None,
+ )?;
let input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>> =
std::rc::Rc::new(std::cell::RefCell::new(input));
diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs
index b5e6cd5..aa12719 100644
--- a/crates/shirabe/src/command/package_discovery_trait.rs
+++ b/crates/shirabe/src/command/package_discovery_trait.rs
@@ -123,6 +123,7 @@ pub trait PackageDiscoveryTrait {
&input
.borrow()
.get_option("stability")
+ .expect("get_minimum_stability returns String, not Result; stability option is guaranteed present by the has_option guard above")
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| "stable".to_string()),
diff --git a/crates/shirabe/src/command/reinstall_command.rs b/crates/shirabe/src/command/reinstall_command.rs
index e6cbac1..48f48a5 100644
--- a/crates/shirabe/src/command/reinstall_command.rs
+++ b/crates/shirabe/src/command/reinstall_command.rs
@@ -74,9 +74,9 @@ impl ReinstallCommand {
let mut packages_to_reinstall: Vec<crate::package::PackageInterfaceHandle> = vec![];
let mut package_names_to_reinstall: Vec<String> = vec![];
- let type_option = input.borrow().get_option("type");
+ let type_option = input.borrow().get_option("type")?;
let type_count = type_option.as_list().map_or(0, |l| l.len());
- let packages_arg = input.borrow().get_argument("packages");
+ let packages_arg = input.borrow().get_argument("packages")?;
let packages_count = packages_arg.as_list().map_or(0, |l| l.len());
if type_count > 0 {
@@ -198,13 +198,13 @@ impl ReinstallCommand {
installation_manager.borrow_mut().set_output_progress(
!input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
);
if input
.borrow()
- .get_option("no-plugins")
+ .get_option("no-plugins")?
.as_bool()
.unwrap_or(false)
{
@@ -245,13 +245,13 @@ impl ReinstallCommand {
if !input
.borrow()
- .get_option("no-autoloader")
+ .get_option("no-autoloader")?
.as_bool()
.unwrap_or(false)
{
let optimize = input
.borrow()
- .get_option("optimize-autoloader")
+ .get_option("optimize-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
@@ -261,7 +261,7 @@ impl ReinstallCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| config
@@ -271,13 +271,13 @@ impl ReinstallCommand {
.unwrap_or(false);
let apcu_prefix = input
.borrow()
- .get_option("apcu-autoloader-prefix")
+ .get_option("apcu-autoloader-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
.borrow()
- .get_option("apcu-autoloader")
+ .get_option("apcu-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
diff --git a/crates/shirabe/src/command/remove_command.rs b/crates/shirabe/src/command/remove_command.rs
index 6cd2424..b81b7ca 100644
--- a/crates/shirabe/src/command/remove_command.rs
+++ b/crates/shirabe/src/command/remove_command.rs
@@ -163,25 +163,27 @@ impl RemoveCommand {
) -> anyhow::Result<i64> {
if input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| l.is_empty())
.unwrap_or(true)
&& !input
.borrow()
- .get_option("unused")
+ .get_option("unused")?
.as_bool()
.unwrap_or(false)
{
- return Err(anyhow::anyhow!(InvalidArgumentException {
- message: "Not enough arguments (missing: \"packages\").".to_string(),
- code: 0,
- }));
+ return Err(anyhow::anyhow!(InvalidArgumentException(
+ shirabe_php_shim::InvalidArgumentException {
+ message: "Not enough arguments (missing: \"packages\").".to_string(),
+ code: 0,
+ }
+ )));
}
let mut packages: Vec<String> = input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
@@ -192,7 +194,7 @@ impl RemoveCommand {
if input
.borrow()
- .get_option("unused")
+ .get_option("unused")?
.as_bool()
.unwrap_or(false)
{
@@ -276,12 +278,12 @@ impl RemoveCommand {
false,
);
- let r#type = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ let r#type = if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
};
- let alt_type = if !input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ let alt_type = if !input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
@@ -290,7 +292,7 @@ impl RemoveCommand {
if input
.borrow()
- .get_option("update-with-dependencies")
+ .get_option("update-with-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -317,7 +319,7 @@ impl RemoveCommand {
let dry_run = input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false);
let mut to_remove: IndexMap<String, Vec<String>> = IndexMap::new();
@@ -447,7 +449,7 @@ impl RemoveCommand {
if input
.borrow()
- .get_option("no-update")
+ .get_option("no-update")?
.as_bool()
.unwrap_or(false)
{
@@ -534,7 +536,7 @@ impl RemoveCommand {
.set_output_progress(
!input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
);
@@ -543,12 +545,12 @@ impl RemoveCommand {
let update_dev_mode = !input
.borrow()
- .get_option("update-no-dev")
+ .get_option("update-no-dev")?
.as_bool()
.unwrap_or(false);
let optimize = input
.borrow()
- .get_option("optimize-autoloader")
+ .get_option("optimize-autoloader")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -559,7 +561,7 @@ impl RemoveCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -570,13 +572,13 @@ impl RemoveCommand {
.unwrap_or(false);
let apcu_prefix = input
.borrow()
- .get_option("apcu-autoloader-prefix")
+ .get_option("apcu-autoloader-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
.borrow()
- .get_option("apcu-autoloader")
+ .get_option("apcu-autoloader")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -587,7 +589,7 @@ impl RemoveCommand {
.unwrap_or(false);
let minimal_changes = input
.borrow()
- .get_option("minimal-changes")
+ .get_option("minimal-changes")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -602,12 +604,12 @@ impl RemoveCommand {
let mut flags = String::new();
if input
.borrow()
- .get_option("update-with-all-dependencies")
+ .get_option("update-with-all-dependencies")?
.as_bool()
.unwrap_or(false)
|| input
.borrow()
- .get_option("with-all-dependencies")
+ .get_option("with-all-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -616,7 +618,7 @@ impl RemoveCommand {
flags += " --with-all-dependencies";
} else if input
.borrow()
- .get_option("no-update-with-dependencies")
+ .get_option("no-update-with-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -633,7 +635,7 @@ impl RemoveCommand {
install.set_verbose(
input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false),
);
@@ -645,7 +647,7 @@ impl RemoveCommand {
install.set_install(
!input
.borrow()
- .get_option("no-install")
+ .get_option("no-install")?
.as_bool()
.unwrap_or(false),
);
diff --git a/crates/shirabe/src/command/repository_command.rs b/crates/shirabe/src/command/repository_command.rs
index a44df0d..3e0292a 100644
--- a/crates/shirabe/src/command/repository_command.rs
+++ b/crates/shirabe/src/command/repository_command.rs
@@ -74,24 +74,24 @@ impl RepositoryCommand {
let action = strtolower(
&input
.borrow()
- .get_argument("action")
+ .get_argument("action")?
.as_string()
.unwrap_or("")
.to_string(),
);
let name = input
.borrow()
- .get_argument("name")
+ .get_argument("name")?
.as_string()
.map(|s| s.to_string());
let arg1 = input
.borrow()
- .get_argument("arg1")
+ .get_argument("arg1")?
.as_string()
.map(|s| s.to_string());
let arg2 = input
.borrow()
- .get_argument("arg2")
+ .get_argument("arg2")?
.as_string()
.map(|s| s.to_string());
@@ -154,12 +154,12 @@ impl RepositoryCommand {
let before = input
.borrow()
- .get_option("before")
+ .get_option("before")?
.as_string()
.map(|s| s.to_string());
let after = input
.borrow()
- .get_option("after")
+ .get_option("after")?
.as_string()
.map(|s| s.to_string());
if before.is_some() && after.is_some() {
@@ -190,7 +190,7 @@ impl RepositoryCommand {
let append = input
.borrow()
- .get_option("append")
+ .get_option("append")?
.as_bool()
.unwrap_or(false);
self.config_source.as_mut().unwrap().add_repository(
@@ -291,7 +291,7 @@ impl RepositoryCommand {
if ["packagist", "packagist.org"].contains(&name_str) {
let append = input
.borrow()
- .get_option("append")
+ .get_option("append")?
.as_bool()
.unwrap_or(false);
self.config_source.as_mut().unwrap().add_repository(
diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs
index 3d15f86..dd91524 100644
--- a/crates/shirabe/src/command/require_command.rs
+++ b/crates/shirabe/src/command/require_command.rs
@@ -163,7 +163,7 @@ impl RequireCommand {
if input
.borrow()
- .get_option("no-suggest")
+ .get_option("no-suggest")?
.as_bool()
.unwrap_or(false)
{
@@ -240,7 +240,7 @@ impl RequireCommand {
return Ok(1);
}
- if input.borrow().get_option("fixed").as_bool() == Some(true) {
+ if input.borrow().get_option("fixed")?.as_bool() == Some(true) {
let config = self.json.as_ref().unwrap().borrow_mut().read()?;
let package_type = if empty(&config.get("type").cloned().unwrap_or(PhpMixed::Null)) {
@@ -255,7 +255,7 @@ impl RequireCommand {
/// @see https://github.com/composer/composer/pull/8313#issuecomment-532637955
if package_type != "project"
- && !input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ && !input.borrow().get_option("dev")?.as_bool().unwrap_or(false)
{
self.get_io().write_error3("<error>The \"--fixed\" option is only allowed for packages with a \"project\" type or for dev dependencies to prevent possible misuses.</error>", true, io_interface::NORMAL);
@@ -301,7 +301,7 @@ impl RequireCommand {
output.clone(),
input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
@@ -314,12 +314,12 @@ impl RequireCommand {
// if there is no update, we need to use the best possible version constraint directly as we cannot rely on the solver to guess the best constraint
input
.borrow()
- .get_option("no-update")
+ .get_option("no-update")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("fixed")
+ .get_option("fixed")?
.as_bool()
.unwrap_or(false),
);
@@ -346,7 +346,7 @@ impl RequireCommand {
let mut requirements = self.format_requirements(requirements)?;
- if !input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ if !input.borrow().get_option("dev")?.as_bool().unwrap_or(false)
&& self.get_io().is_interactive()
&& !composer.is_global()
{
@@ -422,12 +422,12 @@ impl RequireCommand {
// unset($devPackages, $pkgDevTags);
}
- let mut require_key = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ let mut require_key = if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"require-dev"
} else {
"require"
};
- let mut remove_key = if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ let mut remove_key = if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"require"
} else {
"require-dev"
@@ -470,7 +470,7 @@ impl RequireCommand {
PhpMixed::String(package.clone()),
PhpMixed::String(remove_key.to_string()),
PhpMixed::String(
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"with"
} else {
"without"
@@ -499,7 +499,7 @@ impl RequireCommand {
let q2 = sprintf(
"<info>Do you want to re-run the command %s --dev?</info> [<comment>yes</comment>]? ",
&[PhpMixed::String(
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
"without"
} else {
"with"
@@ -521,7 +521,7 @@ impl RequireCommand {
let sort_packages = input
.borrow()
- .get_option("sort-packages")
+ .get_option("sort-packages")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -551,7 +551,7 @@ impl RequireCommand {
if !input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false)
{
@@ -573,7 +573,7 @@ impl RequireCommand {
if input
.borrow()
- .get_option("no-update")
+ .get_option("no-update")?
.as_bool()
.unwrap_or(false)
{
@@ -596,7 +596,7 @@ impl RequireCommand {
);
let dry_run = input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false);
@@ -611,7 +611,7 @@ impl RequireCommand {
dry_run,
input
.borrow()
- .get_option("fixed")
+ .get_option("fixed")?
.as_bool()
.unwrap_or(false),
)?
@@ -752,7 +752,7 @@ impl RequireCommand {
if input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false)
{
@@ -804,12 +804,12 @@ impl RequireCommand {
let update_dev_mode = !input
.borrow()
- .get_option("update-no-dev")
+ .get_option("update-no-dev")?
.as_bool()
.unwrap_or(false);
let optimize = input
.borrow()
- .get_option("optimize-autoloader")
+ .get_option("optimize-autoloader")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -820,7 +820,7 @@ impl RequireCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -831,13 +831,13 @@ impl RequireCommand {
.unwrap_or(false);
let apcu_prefix = input
.borrow()
- .get_option("apcu-autoloader-prefix")
+ .get_option("apcu-autoloader-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
.borrow()
- .get_option("apcu-autoloader")
+ .get_option("apcu-autoloader")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -848,7 +848,7 @@ impl RequireCommand {
.unwrap_or(false);
let minimal_changes = input
.borrow()
- .get_option("minimal-changes")
+ .get_option("minimal-changes")?
.as_bool()
.unwrap_or(false)
|| composer
@@ -862,12 +862,12 @@ impl RequireCommand {
let mut flags = String::new();
if input
.borrow()
- .get_option("update-with-all-dependencies")
+ .get_option("update-with-all-dependencies")?
.as_bool()
.unwrap_or(false)
|| input
.borrow()
- .get_option("with-all-dependencies")
+ .get_option("with-all-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -876,12 +876,12 @@ impl RequireCommand {
flags += " --with-all-dependencies";
} else if input
.borrow()
- .get_option("update-with-dependencies")
+ .get_option("update-with-dependencies")?
.as_bool()
.unwrap_or(false)
|| input
.borrow()
- .get_option("with-dependencies")
+ .get_option("with-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -918,7 +918,7 @@ impl RequireCommand {
.set_output_progress(
!input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
);
@@ -935,14 +935,14 @@ impl RequireCommand {
.set_dry_run(
input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false),
)
.set_verbose(
input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false),
)
@@ -956,7 +956,7 @@ impl RequireCommand {
.set_install(
!input
.borrow()
- .get_option("no-install")
+ .get_option("no-install")?
.as_bool()
.unwrap_or(false),
)
@@ -968,14 +968,14 @@ impl RequireCommand {
.set_prefer_stable(
input
.borrow()
- .get_option("prefer-stable")
+ .get_option("prefer-stable")?
.as_bool()
.unwrap_or(false),
)
.set_prefer_lowest(
input
.borrow()
- .get_option("prefer-lowest")
+ .get_option("prefer-lowest")?
.as_bool()
.unwrap_or(false),
)
@@ -1001,7 +1001,7 @@ impl RequireCommand {
self,
input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs
index 9a28b5f..199dbab 100644
--- a/crates/shirabe/src/command/run_script_command.rs
+++ b/crates/shirabe/src/command/run_script_command.rs
@@ -123,8 +123,12 @@ impl RunScriptCommand {
return Ok(());
}
- if input.borrow().get_argument("script").as_string().is_some()
- || input.borrow().get_option("list").as_bool().unwrap_or(false)
+ if input.borrow().get_argument("script")?.as_string().is_some()
+ || input
+ .borrow()
+ .get_option("list")?
+ .as_bool()
+ .unwrap_or(false)
{
return Ok(());
}
@@ -154,11 +158,16 @@ impl RunScriptCommand {
input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
- if input.borrow().get_option("list").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("list")?
+ .as_bool()
+ .unwrap_or(false)
+ {
return self.list_scripts(output);
}
- let script = match input.borrow().get_argument("script").as_string() {
+ let script = match input.borrow().get_argument("script")?.as_string() {
None => {
return Err(RuntimeException {
message: "Missing required argument \"script\"".to_string(),
@@ -184,10 +193,10 @@ impl RunScriptCommand {
let dispatcher = crate::command::composer_full(&composer)
.get_event_dispatcher()
.clone();
- let dev_mode = input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ let dev_mode = input.borrow().get_option("dev")?.as_bool().unwrap_or(false)
|| !input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false);
let io = self.get_io();
@@ -213,7 +222,7 @@ impl RunScriptCommand {
let args: Vec<String> = input
.borrow()
- .get_argument("args")
+ .get_argument("args")?
.as_list()
.map(|l| {
l.iter()
@@ -222,7 +231,7 @@ impl RunScriptCommand {
})
.unwrap_or_default();
- if let Some(timeout_val) = input.borrow().get_option("timeout").as_string() {
+ if let Some(timeout_val) = input.borrow().get_option("timeout")?.as_string() {
let timeout_str = timeout_val.to_string();
if !timeout_str.chars().all(|c| c.is_ascii_digit()) {
return Err(RuntimeException {
diff --git a/crates/shirabe/src/command/script_alias_command.rs b/crates/shirabe/src/command/script_alias_command.rs
index 5c23e26..29c38cf 100644
--- a/crates/shirabe/src/command/script_alias_command.rs
+++ b/crates/shirabe/src/command/script_alias_command.rs
@@ -118,10 +118,10 @@ impl ScriptAliasCommand {
.into());
}
- let dev_mode = input.borrow().get_option("dev").as_bool().unwrap_or(false)
+ let dev_mode = input.borrow().get_option("dev")?.as_bool().unwrap_or(false)
|| !input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false);
diff --git a/crates/shirabe/src/command/search_command.rs b/crates/shirabe/src/command/search_command.rs
index b9eacf5..b2fb1df 100644
--- a/crates/shirabe/src/command/search_command.rs
+++ b/crates/shirabe/src/command/search_command.rs
@@ -53,7 +53,7 @@ impl SearchCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.map(|s| s.to_string())
.unwrap_or_else(|| "text".to_string());
@@ -109,13 +109,13 @@ impl SearchCommand {
let mut mode: i64 = repository_interface::SEARCH_FULLTEXT;
if input
.borrow()
- .get_option("only-name")
+ .get_option("only-name")?
.as_bool()
.unwrap_or(false)
{
if input
.borrow()
- .get_option("only-vendor")
+ .get_option("only-vendor")?
.as_bool()
.unwrap_or(false)
{
@@ -128,7 +128,7 @@ impl SearchCommand {
mode = repository_interface::SEARCH_NAME;
} else if input
.borrow()
- .get_option("only-vendor")
+ .get_option("only-vendor")?
.as_bool()
.unwrap_or(false)
{
@@ -137,11 +137,11 @@ impl SearchCommand {
let r#type = input
.borrow()
- .get_option("type")
+ .get_option("type")?
.as_string()
.map(|s| s.to_string());
- let tokens_arg = input.borrow().get_argument("tokens");
+ let tokens_arg = input.borrow().get_argument("tokens")?;
let token_strings: Vec<String> = tokens_arg
.as_array()
.map(|arr| {
@@ -182,7 +182,7 @@ impl SearchCommand {
if let Some(link) = link {
io.write(&format!(
"<href={}>{}</>{}{}{}",
- OutputFormatter::escape(link),
+ OutputFormatter::escape(link)?,
result.name,
" ".repeat(name_length as usize - result.name.len()),
warning,
diff --git a/crates/shirabe/src/command/show_command.rs b/crates/shirabe/src/command/show_command.rs
index 06abec4..27bda55 100644
--- a/crates/shirabe/src/command/show_command.rs
+++ b/crates/shirabe/src/command/show_command.rs
@@ -85,25 +85,25 @@ impl ShowCommand {
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> anyhow::Result<i64> {
self.version_parser = VersionParser::new();
- if input.borrow().get_option("tree").as_bool() == Some(true) {
+ if input.borrow().get_option("tree")?.as_bool() == Some(true) {
self.init_styles(output.clone());
}
let mut composer = self.try_composer(None, None);
- if input.borrow().get_option("installed").as_bool() == Some(true)
- && input.borrow().get_option("self").as_bool() != Some(true)
+ if input.borrow().get_option("installed")?.as_bool() == Some(true)
+ && input.borrow().get_option("self")?.as_bool() != Some(true)
{
self.get_io().write_error("<warning>You are using the deprecated option \"installed\". Only installed packages are shown by default now. The --all option can be used to show all packages.</warning>");
}
- if input.borrow().get_option("outdated").as_bool() == Some(true) {
+ if input.borrow().get_option("outdated")?.as_bool() == Some(true) {
input
.borrow_mut()
.set_option("latest", PhpMixed::Bool(true));
} else if input
.borrow()
- .get_option("ignore")
+ .get_option("ignore")?
.as_list()
.map_or(0, |l| l.len())
> 0
@@ -111,19 +111,19 @@ impl ShowCommand {
self.get_io().write_error("<warning>You are using the option \"ignore\" for action other than \"outdated\", it will be ignored.</warning>");
}
- if input.borrow().get_option("direct").as_bool() == Some(true)
- && (input.borrow().get_option("all").as_bool() == Some(true)
- || input.borrow().get_option("available").as_bool() == Some(true)
- || input.borrow().get_option("platform").as_bool() == Some(true))
+ if input.borrow().get_option("direct")?.as_bool() == Some(true)
+ && (input.borrow().get_option("all")?.as_bool() == Some(true)
+ || input.borrow().get_option("available")?.as_bool() == Some(true)
+ || input.borrow().get_option("platform")?.as_bool() == Some(true))
{
self.get_io().write_error("The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)");
return Ok(1);
}
- if input.borrow().get_option("tree").as_bool() == Some(true)
- && (input.borrow().get_option("all").as_bool() == Some(true)
- || input.borrow().get_option("available").as_bool() == Some(true))
+ if input.borrow().get_option("tree")?.as_bool() == Some(true)
+ && (input.borrow().get_option("all")?.as_bool() == Some(true)
+ || input.borrow().get_option("available")?.as_bool() == Some(true))
{
self.get_io().write_error("The --tree (-t) option is not usable in combination with --all or --available (-a)");
@@ -131,9 +131,9 @@ impl ShowCommand {
}
let only_count: usize = [
- input.borrow().get_option("patch-only").as_bool() == Some(true),
- input.borrow().get_option("minor-only").as_bool() == Some(true),
- input.borrow().get_option("major-only").as_bool() == Some(true),
+ input.borrow().get_option("patch-only")?.as_bool() == Some(true),
+ input.borrow().get_option("minor-only")?.as_bool() == Some(true),
+ input.borrow().get_option("major-only")?.as_bool() == Some(true),
]
.iter()
.filter(|b| **b)
@@ -146,8 +146,8 @@ impl ShowCommand {
return Ok(1);
}
- if input.borrow().get_option("tree").as_bool() == Some(true)
- && input.borrow().get_option("latest").as_bool() == Some(true)
+ if input.borrow().get_option("tree")?.as_bool() == Some(true)
+ && input.borrow().get_option("latest")?.as_bool() == Some(true)
{
self.get_io().write_error(
"The --tree (-t) option is not usable in combination with --latest (-l)",
@@ -156,8 +156,8 @@ impl ShowCommand {
return Ok(1);
}
- if input.borrow().get_option("tree").as_bool() == Some(true)
- && input.borrow().get_option("path").as_bool() == Some(true)
+ if input.borrow().get_option("tree")?.as_bool() == Some(true)
+ && input.borrow().get_option("path")?.as_bool() == Some(true)
{
self.get_io().write_error(
"The --tree (-t) option is not usable in combination with --path (-P)",
@@ -168,7 +168,7 @@ impl ShowCommand {
let format = input
.borrow()
- .get_option("format")
+ .get_option("format")?
.as_string()
.unwrap_or("text")
.to_string();
@@ -214,20 +214,25 @@ impl ShowCommand {
let installed_repo: RepositoryInterfaceHandle;
let repos: RepositoryInterfaceHandle;
- if input.borrow().get_option("self").as_bool() == Some(true)
- && input.borrow().get_option("installed").as_bool() != Some(true)
- && input.borrow().get_option("locked").as_bool() != Some(true)
+ if input.borrow().get_option("self")?.as_bool() == Some(true)
+ && input.borrow().get_option("installed")?.as_bool() != Some(true)
+ && input.borrow().get_option("locked")?.as_bool() != Some(true)
{
let composer = self.require_composer(None, None)?;
let package = crate::package::RootPackageInterfaceHandle::dup(
composer.borrow_partial().get_package(),
);
- if input.borrow().get_option("name-only").as_bool() == Some(true) {
+ if input.borrow().get_option("name-only")?.as_bool() == Some(true) {
self.get_io().write(&package.get_name());
return Ok(0);
}
- if input.borrow().get_argument("package").as_string().is_some() {
+ if input
+ .borrow()
+ .get_argument("package")?
+ .as_string()
+ .is_some()
+ {
return Err(InvalidArgumentException {
message: "You cannot use --self together with a package name".to_string(),
code: 0,
@@ -241,14 +246,14 @@ impl ShowCommand {
RepositoryInterfaceHandle::new(RootPackageRepository::new(package.clone())),
]));
single_package = Some(package.clone().into());
- } else if input.borrow().get_option("platform").as_bool() == Some(true) {
+ } else if input.borrow().get_option("platform")?.as_bool() == Some(true) {
installed_repo = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
platform_repo.clone().into(),
]));
repos = RepositoryInterfaceHandle::new(InstalledRepository::new(vec![
platform_repo.clone().into(),
]));
- } else if input.borrow().get_option("available").as_bool() == Some(true) {
+ } else if input.borrow().get_option("available")?.as_bool() == Some(true) {
let mut ir = InstalledRepository::new(vec![platform_repo.clone().into()]);
if let Some(ref composer) = composer {
let composer = crate::command::composer_full(composer);
@@ -281,7 +286,7 @@ impl ShowCommand {
));
installed_repo = RepositoryInterfaceHandle::new(ir);
}
- } else if input.borrow().get_option("all").as_bool() == Some(true) && composer.is_some() {
+ } else if input.borrow().get_option("all")?.as_bool() == Some(true) && composer.is_some() {
let mut composer_ref = crate::command::composer_full_mut(composer.as_ref().unwrap());
let local_repo = composer_ref
.get_repository_manager()
@@ -321,7 +326,7 @@ impl ShowCommand {
composite_input.push(r.clone());
}
repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
- } else if input.borrow().get_option("all").as_bool() == Some(true) {
+ } else if input.borrow().get_option("all")?.as_bool() == Some(true) {
let default_repos =
RepositoryFactory::default_repos_with_default_manager(self.get_io())?;
let names: Vec<String> = default_repos.keys().cloned().collect();
@@ -337,7 +342,7 @@ impl ShowCommand {
composite_input.push(v);
}
repos = RepositoryInterfaceHandle::new(CompositeRepository::new(composite_input));
- } else if input.borrow().get_option("locked").as_bool() == Some(true) {
+ } else if input.borrow().get_option("locked")?.as_bool() == Some(true) {
if composer.is_none()
|| !crate::command::composer_full_mut(composer.as_ref().unwrap())
.get_locker()
@@ -354,9 +359,9 @@ impl ShowCommand {
let locker_rc = composer_ref.get_locker().clone();
let mut locker = locker_rc.borrow_mut();
let lr = locker.get_locked_repository(
- input.borrow().get_option("no-dev").as_bool() != Some(true),
+ input.borrow().get_option("no-dev")?.as_bool() != Some(true),
)?;
- if input.borrow().get_option("self").as_bool() == Some(true) {
+ if input.borrow().get_option("self")?.as_bool() == Some(true) {
lr.add_package(
crate::package::RootPackageInterfaceHandle::dup(composer_ref.get_package())
.into(),
@@ -386,7 +391,7 @@ impl ShowCommand {
let root_pkg = composer_local.get_package();
let root_repo: RepositoryInterfaceHandle =
- if input.borrow().get_option("self").as_bool() == Some(true) {
+ if input.borrow().get_option("self")?.as_bool() == Some(true) {
RepositoryInterfaceHandle::new(RootPackageRepository::new(
crate::package::RootPackageInterfaceHandle::dup(
composer_local.get_package(),
@@ -395,7 +400,7 @@ impl ShowCommand {
} else {
RepositoryInterfaceHandle::new(InstalledArrayRepository::new()?)
};
- if input.borrow().get_option("no-dev").as_bool() == Some(true) {
+ if input.borrow().get_option("no-dev")?.as_bool() == Some(true) {
let local_packages = composer_local
.get_repository_manager()
.borrow()
@@ -468,7 +473,7 @@ impl ShowCommand {
.dispatch(Some(&command_event_name), Some(&mut command_event))?;
}
- if input.borrow().get_option("latest").as_bool() == Some(true) && composer.is_none() {
+ if input.borrow().get_option("latest")?.as_bool() == Some(true) && composer.is_none() {
self.get_io().write_error(
"No composer.json found in the current directory, disabling \"latest\" option",
);
@@ -479,7 +484,7 @@ impl ShowCommand {
let package_filter: Option<String> = input
.borrow()
- .get_argument("package")
+ .get_argument("package")?
.as_string()
.map(|s| s.to_string());
@@ -492,11 +497,11 @@ impl ShowCommand {
&*installed_repo.borrow(),
&repos,
pf,
- input.borrow().get_argument("version"),
+ input.borrow().get_argument("version")?,
)?;
if let Some(ref pkg) = matched_package {
- if input.borrow().get_option("direct").as_bool() == Some(true) {
+ if input.borrow().get_option("direct")?.as_bool() == Some(true) {
if !in_array(
PhpMixed::String(pkg.get_name()),
&PhpMixed::List(
@@ -522,7 +527,7 @@ impl ShowCommand {
if matched_package.is_none() {
let options = input.borrow().get_options();
let mut hint = String::new();
- if input.borrow().get_option("locked").as_bool() == Some(true) {
+ if input.borrow().get_option("locked")?.as_bool() == Some(true) {
hint.push_str(" in lock file");
}
if options.contains_key("working-dir") {
@@ -535,12 +540,12 @@ impl ShowCommand {
));
}
if PlatformRepository::is_platform_package(pf)
- && input.borrow().get_option("platform").as_bool() != Some(true)
+ && input.borrow().get_option("platform")?.as_bool() != Some(true)
{
hint.push_str(", try using --platform (-p) to show platform packages");
}
- if input.borrow().get_option("all").as_bool() != Some(true)
- && input.borrow().get_option("available").as_bool() != Some(true)
+ if input.borrow().get_option("all")?.as_bool() != Some(true)
+ && input.borrow().get_option("available")?.as_bool() != Some(true)
{
hint.push_str(
", try using --available (-a) to show all available packages",
@@ -562,7 +567,7 @@ impl ShowCommand {
// assert(isset($versions));
let mut exit_code: i64 = 0;
- if input.borrow().get_option("tree").as_bool() == Some(true) {
+ if input.borrow().get_option("tree")?.as_bool() == Some(true) {
let array_tree = self.generate_package_tree(
package.clone().into(),
&*installed_repo.borrow(),
@@ -591,31 +596,31 @@ impl ShowCommand {
}
let mut latest_package: Option<crate::package::PackageInterfaceHandle> = None;
- if input.borrow().get_option("latest").as_bool() == Some(true) {
+ if input.borrow().get_option("latest")?.as_bool() == Some(true) {
latest_package = self.find_latest_package(
package.clone().into(),
composer.as_ref().unwrap(),
&platform_repo,
input
.borrow()
- .get_option("major-only")
+ .get_option("major-only")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("minor-only")
+ .get_option("minor-only")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_option("patch-only")
+ .get_option("patch-only")?
.as_bool()
.unwrap_or(false),
platform_req_filter.clone(),
)?;
}
- if input.borrow().get_option("outdated").as_bool() == Some(true)
- && input.borrow().get_option("strict").as_bool() == Some(true)
+ if input.borrow().get_option("outdated")?.as_bool() == Some(true)
+ && input.borrow().get_option("strict")?.as_bool() == Some(true)
&& latest_package.is_some()
&& latest_package
.as_ref()
@@ -631,7 +636,7 @@ impl ShowCommand {
{
exit_code = 1;
}
- if input.borrow().get_option("path").as_bool() == Some(true) {
+ if input.borrow().get_option("path")?.as_bool() == Some(true) {
self.get_io().write_no_newline(&package.get_name());
let path = {
let composer_ref = composer.as_ref().unwrap();
@@ -672,7 +677,7 @@ impl ShowCommand {
}
// show tree view if requested
- if input.borrow().get_option("tree").as_bool() == Some(true) {
+ if input.borrow().get_option("tree")?.as_bool() == Some(true) {
let root_requires = self.get_root_requires();
let mut packages = installed_repo.get_packages()?;
packages.sort_by(|a, b| {
@@ -734,11 +739,11 @@ impl ShowCommand {
}
let mut package_list_filter: Option<Vec<String>> = None;
- if input.borrow().get_option("direct").as_bool() == Some(true) {
+ if input.borrow().get_option("direct")?.as_bool() == Some(true) {
package_list_filter = Some(self.get_root_requires());
}
- if input.borrow().get_option("path").as_bool() == Some(true) && composer.is_none() {
+ if input.borrow().get_option("path")?.as_bool() == Some(true) && composer.is_none() {
self.get_io().write_error(
"No composer.json found in the current directory, disabling \"path\" option",
);
@@ -831,15 +836,15 @@ impl ShowCommand {
}
}
- let show_all_types = input.borrow().get_option("all").as_bool() == Some(true);
- let show_latest = input.borrow().get_option("latest").as_bool() == Some(true);
- let show_major_only = input.borrow().get_option("major-only").as_bool() == Some(true);
- let show_minor_only = input.borrow().get_option("minor-only").as_bool() == Some(true);
- let show_patch_only = input.borrow().get_option("patch-only").as_bool() == Some(true);
+ let show_all_types = input.borrow().get_option("all")?.as_bool() == Some(true);
+ let show_latest = input.borrow().get_option("latest")?.as_bool() == Some(true);
+ let show_major_only = input.borrow().get_option("major-only")?.as_bool() == Some(true);
+ let show_minor_only = input.borrow().get_option("minor-only")?.as_bool() == Some(true);
+ let show_patch_only = input.borrow().get_option("patch-only")?.as_bool() == Some(true);
let ignored_packages_regex = base_package::package_names_to_regexp(
&input
.borrow()
- .get_option("ignore")
+ .get_option("ignore")?
.as_list()
.map(|l| {
l.iter()
@@ -898,21 +903,21 @@ impl ShowCommand {
}
}
- let write_path = input.borrow().get_option("name-only").as_bool() != Some(true)
- && input.borrow().get_option("path").as_bool() == Some(true);
- write_version = input.borrow().get_option("name-only").as_bool() != Some(true)
- && input.borrow().get_option("path").as_bool() != Some(true)
+ let write_path = input.borrow().get_option("name-only")?.as_bool() != Some(true)
+ && input.borrow().get_option("path")?.as_bool() == Some(true);
+ write_version = input.borrow().get_option("name-only")?.as_bool() != Some(true)
+ && input.borrow().get_option("path")?.as_bool() != Some(true)
&& *show_version;
let write_latest = write_version && show_latest;
- write_description = input.borrow().get_option("name-only").as_bool() != Some(true)
- && input.borrow().get_option("path").as_bool() != Some(true);
+ write_description = input.borrow().get_option("name-only")?.as_bool() != Some(true)
+ && input.borrow().get_option("path")?.as_bool() != Some(true);
let write_release_date = write_latest
- && (input.borrow().get_option("sort-by-age").as_bool() == Some(true)
+ && (input.borrow().get_option("sort-by-age")?.as_bool() == Some(true)
|| format == "json");
let mut has_outdated_packages = false;
- if input.borrow().get_option("sort-by-age").as_bool() == Some(true) {
+ if input.borrow().get_option("sort-by-age")?.as_bool() == Some(true) {
type_packages.sort_by(|_ka, a, _kb, b| match (a, b) {
(PackageOrName::Pkg(a), PackageOrName::Pkg(b)) => {
a.get_release_date().cmp(&b.get_release_date())
@@ -950,14 +955,14 @@ impl ShowCommand {
package_is_up_to_date || (latest_package.is_none() && show_major_only);
let package_is_ignored =
Preg::is_match(&ignored_packages_regex, &package.get_pretty_name())?;
- if input.borrow().get_option("outdated").as_bool() == Some(true)
+ if input.borrow().get_option("outdated")?.as_bool() == Some(true)
&& (package_is_up_to_date || package_is_ignored)
{
continue;
}
- if input.borrow().get_option("outdated").as_bool() == Some(true)
- || input.borrow().get_option("strict").as_bool() == Some(true)
+ if input.borrow().get_option("outdated")?.as_bool() == Some(true)
+ || input.borrow().get_option("strict")?.as_bool() == Some(true)
{
has_outdated_packages = true;
}
@@ -980,7 +985,7 @@ impl ShowCommand {
)),
);
if format != "json"
- || input.borrow().get_option("name-only").as_bool() != Some(true)
+ || input.borrow().get_option("name-only")?.as_bool() != Some(true)
{
package_view_data.insert(
"homepage".to_string(),
@@ -1159,7 +1164,7 @@ impl ShowCommand {
write_release_date,
},
);
- if input.borrow().get_option("strict").as_bool() == Some(true)
+ if input.borrow().get_option("strict")?.as_bool() == Some(true)
&& has_outdated_packages
{
exit_code = 1;
@@ -1194,7 +1199,7 @@ impl ShowCommand {
.collect(),
)));
} else {
- if input.borrow().get_option("latest").as_bool() == Some(true)
+ if input.borrow().get_option("latest")?.as_bool() == Some(true)
&& view_data.values().any(|v| !v.is_empty())
{
let io = self.get_io();
@@ -1202,7 +1207,7 @@ impl ShowCommand {
io.write_error("Legend:");
io.write_error("! patch or minor release available - update recommended");
io.write_error("~ major release available - update possible");
- if input.borrow().get_option("outdated").as_bool() != Some(true) {
+ if input.borrow().get_option("outdated")?.as_bool() != Some(true) {
io.write_error("= up to date version");
}
} else {
@@ -1211,7 +1216,7 @@ impl ShowCommand {
io.write_error(
"- <comment>major</comment> release available - update possible",
);
- if input.borrow().get_option("outdated").as_bool() != Some(true) {
+ if input.borrow().get_option("outdated")?.as_bool() != Some(true) {
io.write_error("- <info>up to date</info> version");
}
}
@@ -1254,7 +1259,7 @@ impl ShowCommand {
}
}
- if write_latest && input.borrow().get_option("direct").as_bool() != Some(true) {
+ if write_latest && input.borrow().get_option("direct")?.as_bool() != Some(true) {
let mut direct_deps: Vec<IndexMap<String, PhpMixed>> = Vec::new();
let mut transitive_deps: Vec<IndexMap<String, PhpMixed>> = Vec::new();
for pkg in packages.iter() {
@@ -1387,7 +1392,7 @@ impl ShowCommand {
io.write_no_newline(&format!(
"{}<href={}>{}</>{}",
indent,
- OutputFormatter::escape(&link),
+ OutputFormatter::escape(&link).expect("OutputFormatter::escape failed"),
name,
" ".repeat(pad)
));
@@ -2264,12 +2269,12 @@ impl ShowCommand {
];
for color in self.colors.iter() {
- let style = OutputFormatterStyle::new(Some(color.as_str()), None, None);
+ let style = OutputFormatterStyle::new(Some(color.as_str()), None, vec![]);
output
.borrow()
.get_formatter()
.borrow_mut()
- .set_style(color, style);
+ .set_style(color, Box::new(style));
}
}
diff --git a/crates/shirabe/src/command/status_command.rs b/crates/shirabe/src/command/status_command.rs
index 0febf1e..bbff681 100644
--- a/crates/shirabe/src/command/status_command.rs
+++ b/crates/shirabe/src/command/status_command.rs
@@ -218,7 +218,7 @@ impl StatusCommand {
for (path, changes) in &errors {
if input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false)
{
@@ -241,7 +241,7 @@ impl StatusCommand {
for (path, changes) in &unpushed_changes {
if input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false)
{
@@ -266,7 +266,7 @@ impl StatusCommand {
for (path, changes) in &vcs_version_changes {
if input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false)
{
@@ -332,7 +332,7 @@ impl StatusCommand {
if (!errors.is_empty() || !unpushed_changes.is_empty() || !vcs_version_changes.is_empty())
&& !input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false)
{
diff --git a/crates/shirabe/src/command/suggests_command.rs b/crates/shirabe/src/command/suggests_command.rs
index b93f7ec..393874f 100644
--- a/crates/shirabe/src/command/suggests_command.rs
+++ b/crates/shirabe/src/command/suggests_command.rs
@@ -69,7 +69,7 @@ impl SuggestsCommand {
let locked_repo = composer.get_locker().borrow_mut().get_locked_repository(
!input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false),
)?;
@@ -95,7 +95,7 @@ impl SuggestsCommand {
let mut installed_repo = InstalledRepository::new(installed_repos);
let mut reporter = SuggestedPackagesReporter::new(self.get_io().clone());
- let filter = input.borrow().get_argument("packages");
+ let filter = input.borrow().get_argument("packages")?;
let mut packages = RepositoryInterface::get_packages(&mut installed_repo)?;
let root_pkg_as_base: crate::package::BasePackageHandle =
composer.get_package().clone().into();
@@ -111,7 +111,7 @@ impl SuggestsCommand {
if input
.borrow()
- .get_option("by-suggestion")
+ .get_option("by-suggestion")?
.as_bool()
.unwrap_or(false)
{
@@ -119,18 +119,23 @@ impl SuggestsCommand {
}
if input
.borrow()
- .get_option("by-package")
+ .get_option("by-package")?
.as_bool()
.unwrap_or(false)
{
mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE;
}
- if input.borrow().get_option("list").as_bool().unwrap_or(false) {
+ if input
+ .borrow()
+ .get_option("list")?
+ .as_bool()
+ .unwrap_or(false)
+ {
mode = SuggestedPackagesReporter::MODE_LIST;
}
let only_dependents_of: Option<crate::package::PackageInterfaceHandle> =
- if empty(&filter) && !input.borrow().get_option("all").as_bool().unwrap_or(false) {
+ if empty(&filter) && !input.borrow().get_option("all")?.as_bool().unwrap_or(false) {
Some(composer.get_package().clone().into())
} else {
None
diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs
index eb618ca..60d2eac 100644
--- a/crates/shirabe/src/command/update_command.rs
+++ b/crates/shirabe/src/command/update_command.rs
@@ -78,7 +78,7 @@ impl UpdateCommand {
output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
) -> Result<i64> {
let io = self.get_io().clone();
- if input.borrow().get_option("dev").as_bool().unwrap_or(false) {
+ if input.borrow().get_option("dev")?.as_bool().unwrap_or(false) {
io.write_error3(
"<warning>You are using the deprecated option \"--dev\". It has no effect and will break in Composer 3.</warning>",
true,
@@ -87,7 +87,7 @@ impl UpdateCommand {
}
if input
.borrow()
- .get_option("no-suggest")
+ .get_option("no-suggest")?
.as_bool()
.unwrap_or(false)
{
@@ -111,7 +111,7 @@ impl UpdateCommand {
let mut packages: Vec<String> = input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
@@ -122,7 +122,7 @@ impl UpdateCommand {
let mut reqs: IndexMap<String, String> = self.format_requirements(
input
.borrow()
- .get_option("with")
+ .get_option("with")?
.as_list()
.map(|l| {
l.iter()
@@ -196,7 +196,7 @@ impl UpdateCommand {
if input
.borrow()
- .get_option("patch-only")
+ .get_option("patch-only")?
.as_bool()
.unwrap_or(false)
{
@@ -241,7 +241,7 @@ impl UpdateCommand {
if input
.borrow()
- .get_option("interactive")
+ .get_option("interactive")?
.as_bool()
.unwrap_or(false)
{
@@ -256,14 +256,14 @@ impl UpdateCommand {
if input
.borrow()
- .get_option("root-reqs")
+ .get_option("root-reqs")?
.as_bool()
.unwrap_or(false)
{
let mut requires: Vec<String> = array_keys(&root_package.get_requires());
if !input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false)
{
@@ -290,7 +290,11 @@ impl UpdateCommand {
true,
)
});
- let update_mirrors = input.borrow().get_option("lock").as_bool().unwrap_or(false)
+ let update_mirrors = input
+ .borrow()
+ .get_option("lock")?
+ .as_bool()
+ .unwrap_or(false)
|| filtered_packages.len() != packages.len();
packages = filtered_packages;
@@ -314,7 +318,7 @@ impl UpdateCommand {
.set_output_progress(
!input
.borrow()
- .get_option("no-progress")
+ .get_option("no-progress")?
.as_bool()
.unwrap_or(false),
);
@@ -327,7 +331,7 @@ impl UpdateCommand {
let optimize = input
.borrow()
- .get_option("optimize-autoloader")
+ .get_option("optimize-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
@@ -337,7 +341,7 @@ impl UpdateCommand {
.unwrap_or(false);
let authoritative = input
.borrow()
- .get_option("classmap-authoritative")
+ .get_option("classmap-authoritative")?
.as_bool()
.unwrap_or(false)
|| config
@@ -347,13 +351,13 @@ impl UpdateCommand {
.unwrap_or(false);
let apcu_prefix: Option<String> = input
.borrow()
- .get_option("apcu-autoloader-prefix")
+ .get_option("apcu-autoloader-prefix")?
.as_string()
.map(|s| s.to_string());
let apcu = apcu_prefix.is_some()
|| input
.borrow()
- .get_option("apcu-autoloader")
+ .get_option("apcu-autoloader")?
.as_bool()
.unwrap_or(false)
|| config
@@ -363,7 +367,7 @@ impl UpdateCommand {
.unwrap_or(false);
let minimal_changes = input
.borrow()
- .get_option("minimal-changes")
+ .get_option("minimal-changes")?
.as_bool()
.unwrap_or(false)
|| config
@@ -375,7 +379,7 @@ impl UpdateCommand {
let mut update_allow_transitive_dependencies = UpdateAllowTransitiveDeps::UpdateOnlyListed;
if input
.borrow()
- .get_option("with-all-dependencies")
+ .get_option("with-all-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -383,7 +387,7 @@ impl UpdateCommand {
UpdateAllowTransitiveDeps::UpdateListedWithTransitiveDeps;
} else if input
.borrow()
- .get_option("with-dependencies")
+ .get_option("with-dependencies")?
.as_bool()
.unwrap_or(false)
{
@@ -395,14 +399,14 @@ impl UpdateCommand {
.set_dry_run(
input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false),
)
.set_verbose(
input
.borrow()
- .get_option("verbose")
+ .get_option("verbose")?
.as_bool()
.unwrap_or(false),
)
@@ -411,14 +415,14 @@ impl UpdateCommand {
.set_dev_mode(
!input
.borrow()
- .get_option("no-dev")
+ .get_option("no-dev")?
.as_bool()
.unwrap_or(false),
)
.set_dump_autoloader(
!input
.borrow()
- .get_option("no-autoloader")
+ .get_option("no-autoloader")?
.as_bool()
.unwrap_or(false),
)
@@ -429,7 +433,7 @@ impl UpdateCommand {
.set_install(
!input
.borrow()
- .get_option("no-install")
+ .get_option("no-install")?
.as_bool()
.unwrap_or(false),
)
@@ -440,14 +444,14 @@ impl UpdateCommand {
.set_prefer_stable(
input
.borrow()
- .get_option("prefer-stable")
+ .get_option("prefer-stable")?
.as_bool()
.unwrap_or(false),
)
.set_prefer_lowest(
input
.borrow()
- .get_option("prefer-lowest")
+ .get_option("prefer-lowest")?
.as_bool()
.unwrap_or(false),
)
@@ -459,7 +463,7 @@ impl UpdateCommand {
if input
.borrow()
- .get_option("no-plugins")
+ .get_option("no-plugins")?
.as_bool()
.unwrap_or(false)
{
@@ -468,8 +472,14 @@ impl UpdateCommand {
let mut result = install.run()?;
- if result == 0 && !input.borrow().get_option("lock").as_bool().unwrap_or(false) {
- let mut bump_after_update = input.borrow().get_option("bump-after-update");
+ if result == 0
+ && !input
+ .borrow()
+ .get_option("lock")?
+ .as_bool()
+ .unwrap_or(false)
+ {
+ let mut bump_after_update = input.borrow().get_option("bump-after-update")?;
// PHP: false === $bumpAfterUpdate (strict)
if matches!(bump_after_update, PhpMixed::Bool(false)) {
bump_after_update = composer.get_config().borrow().get("bump-after-update");
@@ -489,12 +499,12 @@ impl UpdateCommand {
bump_after_update.as_string() == Some("no-dev"),
input
.borrow()
- .get_option("dry-run")
+ .get_option("dry-run")?
.as_bool()
.unwrap_or(false),
input
.borrow()
- .get_argument("packages")
+ .get_argument("packages")?
.as_list()
.map(|l| {
l.iter()
diff --git a/crates/shirabe/src/command/validate_command.rs b/crates/shirabe/src/command/validate_command.rs
index 73de63b..1d9d036 100644
--- a/crates/shirabe/src/command/validate_command.rs
+++ b/crates/shirabe/src/command/validate_command.rs
@@ -115,7 +115,7 @@ impl ValidateCommand {
) -> Result<i64> {
let file = input
.borrow()
- .get_argument("file")
+ .get_argument("file")?
.as_string()
.map(|s| s.to_string())
.map(Ok)
@@ -134,7 +134,7 @@ impl ValidateCommand {
let validator = ConfigValidator::new(io.clone());
let check_all = if input
.borrow()
- .get_option("no-check-all")
+ .get_option("no-check-all")?
.as_bool()
.unwrap_or(false)
{
@@ -144,17 +144,17 @@ impl ValidateCommand {
};
let check_publish = !input
.borrow()
- .get_option("no-check-publish")
+ .get_option("no-check-publish")?
.as_bool()
.unwrap_or(false);
let check_lock = !input
.borrow()
- .get_option("no-check-lock")
+ .get_option("no-check-lock")?
.as_bool()
.unwrap_or(false);
let check_version = if input
.borrow()
- .get_option("no-check-version")
+ .get_option("no-check-version")?
.as_bool()
.unwrap_or(false)
{
@@ -164,7 +164,7 @@ impl ValidateCommand {
};
let is_strict = input
.borrow()
- .get_option("strict")
+ .get_option("strict")?
.as_bool()
.unwrap_or(false);
let (mut errors, mut publish_errors, mut warnings) =
@@ -183,7 +183,7 @@ impl ValidateCommand {
.unwrap_or(true))
|| input
.borrow()
- .get_option("check-lock")
+ .get_option("check-lock")?
.as_bool()
.unwrap_or(false);
let locker = composer.get_locker().clone();
@@ -221,7 +221,7 @@ impl ValidateCommand {
if input
.borrow()
- .get_option("with-dependencies")
+ .get_option("with-dependencies")?
.as_bool()
.unwrap_or(false)
{
diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs
index 2eb9f9a..dcf30dc 100644
--- a/crates/shirabe/src/console/application.rs
+++ b/crates/shirabe/src/console/application.rs
@@ -6,12 +6,12 @@ use indexmap::IndexMap;
use shirabe_external_packages::composer::xdebug_handler::XdebugHandler;
use shirabe_external_packages::seld::json_lint::ParsingException;
use shirabe_external_packages::symfony::console::Application as BaseApplication;
-use shirabe_external_packages::symfony::console::SingleCommandApplication;
use shirabe_external_packages::symfony::console::command::Command;
use shirabe_external_packages::symfony::console::exception::CommandNotFoundException;
use shirabe_external_packages::symfony::console::exception::ExceptionInterface;
use shirabe_external_packages::symfony::console::helper::HelperInterface;
use shirabe_external_packages::symfony::console::helper::HelperSet;
+use shirabe_external_packages::symfony::console::helper::HelperSetKey;
use shirabe_external_packages::symfony::console::helper::QuestionHelper;
use shirabe_external_packages::symfony::console::input::InputDefinition;
use shirabe_external_packages::symfony::console::input::InputInterface;
@@ -103,8 +103,9 @@ impl Application {
const LOGO: &'static str = " ______\n / ____/___ ____ ___ ____ ____ ________ _____\n / / / __ \\/ __ `__ \\/ __ \\/ __ \\/ ___/ _ \\/ ___/\n/ /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /\n\\____/\\____/_/ /_/ /_/ .___/\\____/____/\\___/_/\n /_/\n";
pub fn new(name: String, mut version: String) -> Self {
- let mut inner = BaseApplication::new(&name, &version);
- inner.set_catch_errors(true);
+ // PHP: if (method_exists($this, 'setCatchErrors')) { $this->setCatchErrors(true); }
+ // This Symfony Console port does not provide `setCatchErrors`, so the guarded call
+ // is skipped, matching `method_exists` evaluating to false.
// PHP: static $shutdownRegistered = false; — register only once globally
static SHUTDOWN_REGISTERED: std::sync::OnceLock<()> = std::sync::OnceLock::new();
@@ -147,8 +148,7 @@ impl Application {
let initial_working_directory = getcwd();
// PHP: parent::__construct($name, $version);
- // BaseApplication is mock-imported; assume new(name, version) above also recorded the version.
- let _ = (name, version);
+ let inner = BaseApplication::__construct(&name, &version);
Self {
inner,
@@ -184,10 +184,10 @@ impl Application {
) -> anyhow::Result<i64> {
self.disable_plugins_by_default = input
.borrow()
- .has_parameter_option(&["--no-plugins"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-plugins"]), false);
self.disable_scripts_by_default = input
.borrow()
- .has_parameter_option(&["--no-scripts"], false);
+ .has_parameter_option(PhpMixed::from(vec!["--no-scripts"]), false);
// PHP: static $stdin = null; — cached across doRun calls so the php://stdin handle is
// opened once.
@@ -209,18 +209,29 @@ impl Application {
}
// PHP: $this->io = new ConsoleIO($input, $output, new HelperSet([new QuestionHelper()]));
- let helpers: Vec<std::rc::Rc<std::cell::RefCell<dyn HelperInterface>>> =
- vec![std::rc::Rc::new(std::cell::RefCell::new(QuestionHelper))];
+ let mut helpers: IndexMap<
+ HelperSetKey,
+ std::rc::Rc<std::cell::RefCell<dyn HelperInterface>>,
+ > = IndexMap::new();
+ helpers.insert(
+ HelperSetKey::Int(0),
+ std::rc::Rc::new(std::cell::RefCell::new(QuestionHelper::default())),
+ );
+ let helper_set = std::rc::Rc::new(std::cell::RefCell::new(HelperSet::default()));
+ HelperSet::new(&helper_set, helpers);
self.io = std::rc::Rc::new(std::cell::RefCell::new(ConsoleIO::new(
input.clone(),
output.clone(),
- HelperSet::new(helpers),
+ helper_set.borrow().clone(),
)));
// Register error handler again to pass it the IO instance
ErrorHandler::register(Some(self.io.clone()));
- if input.borrow().has_parameter_option(&["--no-cache"], false) {
+ if input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["--no-cache"]), false)
+ {
self.io
.write_error3("Disabling cache usage", true, io_interface::DEBUG);
Platform::put_env(
@@ -308,10 +319,22 @@ impl Application {
&& !file_exists(&Factory::get_composer_file().unwrap_or_default())
&& use_parent_dir_if_no_json_available.as_bool() != Some(false)
&& (command_name.as_deref() != Some("config")
- || (input.borrow().has_parameter_option(&["--file"], true) == false
- && input.borrow().has_parameter_option(&["-f"], true) == false))
- && input.borrow().has_parameter_option(&["--help"], true) == false
- && input.borrow().has_parameter_option(&["-h"], true) == false
+ || (input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["--file"]), true)
+ == false
+ && input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["-f"]), true)
+ == false))
+ && input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["--help"]), true)
+ == false
+ && input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["-h"]), true)
+ == false
{
let mut dir = dirname(&Platform::get_cwd(true).unwrap_or_default());
let home_value = Platform::get_env("HOME")
@@ -394,7 +417,7 @@ impl Application {
]);
let may_need_plugin_command = !input
.borrow()
- .has_parameter_option(&["--version", "-V"], false)
+ .has_parameter_option(PhpMixed::from(vec!["--version", "-V"]), false)
&& (command_name.is_none()
|| in_array(
command_name.as_deref().unwrap_or("").into(),
@@ -692,7 +715,7 @@ impl Application {
// reflection (instantiate_class) and stays PhpMixed; the
// SingleCommandApplication / Command typed registry it
// belongs to is an external-package todo!() stub.
- let _ = SingleCommandApplication::new;
+ // let _ = SingleCommandApplication::new;
// makes sure the command is find()'able by the name defined in composer.json, and the name isn't overridden in its configure()
// TODO(phase-c): cmd is the PhpMixed result of reflection
@@ -717,10 +740,15 @@ impl Application {
};
// Compatibility layer for symfony/console <7.4
- // TODO(phase-c): self.inner.add() takes PhpMixed but must
- // register a typed command instance; blocked on the Symfony
- // command-registry model (external-package todo!() stub).
- let _ = self.inner.add(cmd);
+ // TODO(phase-c): self.inner.add() takes Rc<RefCell<dyn Command>>
+ // but `cmd` here is the PhpMixed result of reflection-based
+ // plugin command instantiation; registering it as a typed
+ // command instance is blocked on the Symfony command-registry
+ // model (external-package todo!() stub).
+ let _ = &cmd;
+ todo!(
+ "plugin: register reflection-instantiated command on Application::add"
+ );
}
}
}
@@ -731,7 +759,10 @@ impl Application {
let mut start_time: Option<f64> = None;
let result_outcome: anyhow::Result<i64> = (|| -> anyhow::Result<i64> {
- if input.borrow().has_parameter_option(&["--profile"], false) {
+ if input
+ .borrow()
+ .has_parameter_option(PhpMixed::from(vec!["--profile"]), false)
+ {
start_time = Some(microtime(true));
// PHP: $this->io->enableDebugging($startTime).
// TODO(phase-c): enableDebugging exists only on ConsoleIO, not on IOInterface,
@@ -745,7 +776,7 @@ impl Application {
if input
.borrow()
- .has_parameter_option(&["--version", "-V"], true)
+ .has_parameter_option(PhpMixed::from(vec!["--version", "-V"]), true)
{
self.io.write_error(&sprintf(
"<info>PHP</info> version <comment>%s</comment> (%s)",
@@ -828,7 +859,11 @@ impl Application {
) -> anyhow::Result<Option<String>> {
let working_dir = input
.borrow()
- .get_parameter_option(&["--working-dir", "-d"], PhpMixed::Null, true)
+ .get_parameter_option(
+ PhpMixed::from(vec!["--working-dir", "-d"]),
+ PhpMixed::Null,
+ true,
+ )
.as_string()
.map(|s| s.to_string());
if let Some(ref wd) = working_dir {
@@ -1089,7 +1124,6 @@ impl Application {
// returns the application's typed InputDefinition, but the Symfony Application stub returns
// PhpMixed. Until both land, getFirstArgument cannot be computed and we return None.
let _ = input;
- let _ = self.inner.get_definition();
None
}
@@ -1115,45 +1149,45 @@ impl Application {
)
}
- pub(crate) fn get_default_input_definition(&self) -> InputDefinition {
+ pub(crate) fn get_default_input_definition(&self) -> anyhow::Result<InputDefinition> {
let mut definition = self.inner.get_default_input_definition();
definition.add_option(InputOption::new(
"--profile",
- None,
+ PhpMixed::Null,
Some(InputOption::VALUE_NONE),
- "Display timing and memory usage information",
+ "Display timing and memory usage information".to_string(),
PhpMixed::Null,
- ));
+ )?)?;
definition.add_option(InputOption::new(
"--no-plugins",
- None,
+ PhpMixed::Null,
Some(InputOption::VALUE_NONE),
- "Whether to disable plugins.",
+ "Whether to disable plugins.".to_string(),
PhpMixed::Null,
- ));
+ )?)?;
definition.add_option(InputOption::new(
"--no-scripts",
- None,
+ PhpMixed::Null,
Some(InputOption::VALUE_NONE),
- "Skips the execution of all scripts defined in composer.json file.",
+ "Skips the execution of all scripts defined in composer.json file.".to_string(),
PhpMixed::Null,
- ));
+ )?)?;
definition.add_option(InputOption::new(
"--working-dir",
- Some("-d"),
+ PhpMixed::from("-d"),
Some(InputOption::VALUE_REQUIRED),
- "If specified, use the given directory as working directory.",
+ "If specified, use the given directory as working directory.".to_string(),
PhpMixed::Null,
- ));
+ )?)?;
definition.add_option(InputOption::new(
"--no-cache",
- None,
+ PhpMixed::Null,
Some(InputOption::VALUE_NONE),
- "Prevent use of the cache",
+ "Prevent use of the cache".to_string(),
PhpMixed::Null,
- ));
+ )?)?;
- definition
+ Ok(definition)
}
fn get_plugin_commands(&mut self) -> anyhow::Result<Vec<Box<dyn Command>>> {
diff --git a/crates/shirabe/src/console/html_output_formatter.rs b/crates/shirabe/src/console/html_output_formatter.rs
index a2158fa..b516c83 100644
--- a/crates/shirabe/src/console/html_output_formatter.rs
+++ b/crates/shirabe/src/console/html_output_formatter.rs
@@ -3,7 +3,8 @@
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_external_packages::symfony::console::formatter::OutputFormatter;
-use shirabe_external_packages::symfony::console::formatter::OutputFormatterStyle;
+use shirabe_external_packages::symfony::console::formatter::OutputFormatterInterface;
+use shirabe_external_packages::symfony::console::formatter::OutputFormatterStyleInterface;
#[derive(Debug)]
pub struct HtmlOutputFormatter {
@@ -41,14 +42,19 @@ impl HtmlOutputFormatter {
//8 => "conceal"
];
- pub fn new(styles: IndexMap<String, OutputFormatterStyle>) -> Self {
+ pub fn new(styles: IndexMap<String, Box<dyn OutputFormatterStyleInterface>>) -> Self {
Self {
inner: OutputFormatter::new(true, styles),
}
}
- pub fn format(&self, message: Option<&str>) -> Option<String> {
- let formatted = self.inner.format(message.unwrap_or(""));
+ pub fn format(&mut self, message: Option<&str>) -> anyhow::Result<Option<String>> {
+ let formatted = self.inner.format(message)?;
+
+ let formatted = match formatted {
+ Some(formatted) => formatted,
+ None => return Ok(None),
+ };
let clear_escape_codes = "(?:39|49|0|22|24|25|27|28)";
let pattern = format!(
@@ -56,7 +62,11 @@ impl HtmlOutputFormatter {
clear_escape_codes, clear_escape_codes
);
- Preg::replace_callback(&pattern, |matches| self.format_html(matches), &formatted).ok()
+ Ok(Some(Preg::replace_callback(
+ &pattern,
+ |matches| self.format_html(matches),
+ &formatted,
+ )?))
}
fn format_html(&self, matches: &IndexMap<CaptureKey, String>) -> String {
diff --git a/crates/shirabe/src/console/input/input_argument.rs b/crates/shirabe/src/console/input/input_argument.rs
index 458ec61..81f38ac 100644
--- a/crates/shirabe/src/console/input/input_argument.rs
+++ b/crates/shirabe/src/console/input/input_argument.rs
@@ -21,7 +21,12 @@ impl InputArgument {
default: Option<PhpMixed>,
// TODO(cli-completion): suggested_values closure / list dropped along with completion support
) -> Result<Self> {
- let inner = BaseInputArgument::new(name, mode, description, default);
+ let inner = BaseInputArgument::new(
+ name.to_string(),
+ mode,
+ description.to_string(),
+ default.unwrap_or(PhpMixed::Null),
+ )?;
Ok(Self { inner })
}
}
diff --git a/crates/shirabe/src/console/input/input_option.rs b/crates/shirabe/src/console/input/input_option.rs
index 92c4a51..3298be0 100644
--- a/crates/shirabe/src/console/input/input_option.rs
+++ b/crates/shirabe/src/console/input/input_option.rs
@@ -24,9 +24,10 @@ impl InputOption {
default: Option<PhpMixed>,
// TODO(cli-completion): suggested_values closure / list dropped along with completion support
) -> Result<Self> {
- let shortcut_str = shortcut.as_ref().and_then(|s| s.as_string());
+ let shortcut = shortcut.unwrap_or(PhpMixed::Null);
let default_mixed = default.unwrap_or(PhpMixed::Null);
- let inner = BaseInputOption::new(name, shortcut_str, mode, description, default_mixed);
+ let inner =
+ BaseInputOption::new(name, shortcut, mode, description.to_string(), default_mixed)?;
Ok(Self { inner })
}
}
diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs
index 7841946..be2b0ad 100644
--- a/crates/shirabe/src/dependency_resolver/problem.rs
+++ b/crates/shirabe/src/dependency_resolver/problem.rs
@@ -816,7 +816,8 @@ impl Problem {
OutputFormatter::escape(&format!(
"https://packagist.org/security-advisories/{}",
advisory_id
- )),
+ ))
+ .expect("OutputFormatter::escape does not fail"),
advisory_id
);
}
diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
index 2124093..d209e1e 100644
--- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
+++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
@@ -587,14 +587,11 @@ impl EventDispatcher {
continue;
}
- let mut app = Application::new("", "");
+ let mut app = Application::__construct("UNKNOWN", "UNKNOWN");
app.set_catch_exceptions(false);
- if method_exists(
- &PhpMixed::String("Application".to_string()),
- "setCatchErrors",
- ) {
- app.set_catch_errors(false);
- }
+ // PHP: if (method_exists($app, 'setCatchErrors')) { $app->setCatchErrors(false); }
+ // This Symfony Console port does not provide `setCatchErrors`, so the
+ // guarded call is skipped, matching `method_exists` evaluating to false.
app.set_auto_exit(false);
// TODO(plugin): instantiate command class dynamically: `new $className($event->getName())`
todo!(
@@ -615,7 +612,7 @@ impl EventDispatcher {
let _refl_php_version_gate = PHP_VERSION_ID < 80100;
todo!("\\ReflectionProperty on ConsoleIO::$output")
} else {
- ConsoleOutput::new(0, None, None)
+ ConsoleOutput::new(None, None, None)?
};
let input_str = event
.get_flags()
@@ -623,8 +620,8 @@ impl EventDispatcher {
.and_then(|v| v.as_string())
.unwrap_or(&args)
.to_string();
- let mut input = StringInput::new(&input_str);
- let mut output = output;
+ let input = StringInput::new(&input_str)?;
+ let output = output;
Ok(app.run(
Some(std::rc::Rc::new(std::cell::RefCell::new(input))),
Some(std::rc::Rc::new(std::cell::RefCell::new(output))),
diff --git a/crates/shirabe/src/factory.rs b/crates/shirabe/src/factory.rs
index 975c558..78aa7ea 100644
--- a/crates/shirabe/src/factory.rs
+++ b/crates/shirabe/src/factory.rs
@@ -4,6 +4,7 @@ use indexmap::IndexMap;
use shirabe_external_packages::symfony::console::formatter::OutputFormatter;
use shirabe_external_packages::symfony::console::formatter::OutputFormatterStyle;
+use shirabe_external_packages::symfony::console::formatter::OutputFormatterStyleInterface;
use shirabe_external_packages::symfony::console::output::ConsoleOutput;
use shirabe_php_shim::{
InvalidArgumentException, PATHINFO_EXTENSION, PHP_EOL, PHP_OS, Phar, PhpMixed,
@@ -405,15 +406,19 @@ impl Factory {
}
}
- pub fn create_additional_styles() -> IndexMap<String, OutputFormatterStyle> {
- let mut styles: IndexMap<String, OutputFormatterStyle> = IndexMap::new();
+ pub fn create_additional_styles() -> IndexMap<String, Box<dyn OutputFormatterStyleInterface>> {
+ let mut styles: IndexMap<String, Box<dyn OutputFormatterStyleInterface>> = IndexMap::new();
styles.insert(
"highlight".to_string(),
- OutputFormatterStyle::new(Some("red"), None, Some(vec![])),
+ Box::new(OutputFormatterStyle::new(Some("red"), None, vec![])),
);
styles.insert(
"warning".to_string(),
- OutputFormatterStyle::new(Some("black"), Some("yellow"), Some(vec![])),
+ Box::new(OutputFormatterStyle::new(
+ Some("black"),
+ Some("yellow"),
+ vec![],
+ )),
);
styles
}
@@ -423,10 +428,11 @@ impl Factory {
let formatter = OutputFormatter::new(false, styles);
ConsoleOutput::new(
- shirabe_external_packages::symfony::console::output::output_interface::VERBOSITY_NORMAL,
+ Some(shirabe_external_packages::symfony::console::output::output_interface::VERBOSITY_NORMAL),
None,
Some(std::rc::Rc::new(std::cell::RefCell::new(formatter))),
)
+ .expect("ConsoleOutput::new does not fail for stdout/stderr streams")
}
/// Creates a Composer instance
diff --git a/crates/shirabe/src/installer/suggested_packages_reporter.rs b/crates/shirabe/src/installer/suggested_packages_reporter.rs
index 65977ac..875fdc6 100644
--- a/crates/shirabe/src/installer/suggested_packages_reporter.rs
+++ b/crates/shirabe/src/installer/suggested_packages_reporter.rs
@@ -201,6 +201,7 @@ impl SuggestedPackagesReporter {
fn escape_output(&self, string: &str) -> String {
OutputFormatter::escape(&self.remove_control_characters(string))
+ .expect("OutputFormatter::escape does not fail")
}
fn remove_control_characters(&self, string: &str) -> String {
diff --git a/crates/shirabe/src/io/buffer_io.rs b/crates/shirabe/src/io/buffer_io.rs
index 988c153..8c10dee 100644
--- a/crates/shirabe/src/io/buffer_io.rs
+++ b/crates/shirabe/src/io/buffer_io.rs
@@ -6,11 +6,11 @@ use shirabe_external_packages::composer::pcre::Preg;
use shirabe_external_packages::symfony::console::formatter::OutputFormatterInterface;
use shirabe_external_packages::symfony::console::helper::HelperInterface;
use shirabe_external_packages::symfony::console::helper::HelperSet;
+use shirabe_external_packages::symfony::console::helper::HelperSetKey;
use shirabe_external_packages::symfony::console::helper::QuestionHelper;
use shirabe_external_packages::symfony::console::input::InputInterface;
use shirabe_external_packages::symfony::console::input::StringInput;
use shirabe_external_packages::symfony::console::output::OutputInterface;
-use shirabe_external_packages::symfony::console::output::StreamOutput;
use shirabe_php_shim::{
PHP_EOL, PhpMixed, RuntimeException, fopen, fseek, fwrite, rewind, stream_get_contents,
strip_tags,
@@ -27,7 +27,7 @@ impl BufferIO {
verbosity: i64,
formatter: Option<Box<dyn OutputFormatterInterface>>,
) -> Result<Self> {
- let mut input_obj = StringInput::new(&input);
+ let mut input_obj = StringInput::new(&input)?;
input_obj.set_interactive(false);
let stream = fopen("php://memory", "rw");
@@ -39,21 +39,34 @@ impl BufferIO {
.into());
}
- let decorated = formatter.as_ref().map_or(false, |f| f.is_decorated());
- // TODO(phase-c): wire StreamOutput as the output. The console tree merge made StreamOutput
- // implement the unified OutputInterface; StreamOutput::new is still a stub.
+ let _decorated = formatter.as_ref().map_or(false, |f| f.is_decorated());
+ // TODO(phase-c): wire StreamOutput as the output. StreamOutput::new requires a
+ // PhpResource, but `fopen` here yields a PhpMixed; PhpMixed has no resource variant,
+ // so the stream cannot be passed through yet (same PhpResource/PhpMixed gap noted in
+ // QuestionHelper). The constructed StreamOutput is therefore not wired as the output.
+ // formatter, stream and verbosity feed the pending StreamOutput::new wiring below.
let _ = formatter;
- let _ = StreamOutput::new(stream, verbosity, Some(decorated));
+ let _ = stream;
+ let _ = verbosity;
let output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> =
- todo!("wire StreamOutput as the ConsoleIO output");
+ todo!("wire StreamOutput as the ConsoleIO output (needs PhpResource stream)");
+
+ let question_helper: std::rc::Rc<std::cell::RefCell<dyn HelperInterface>> =
+ std::rc::Rc::new(std::cell::RefCell::new(QuestionHelper::default()));
+ let mut helpers: indexmap::IndexMap<
+ HelperSetKey,
+ std::rc::Rc<std::cell::RefCell<dyn HelperInterface>>,
+ > = indexmap::IndexMap::new();
+ helpers.insert(HelperSetKey::Int(0), question_helper);
+ let helper_set = std::rc::Rc::new(std::cell::RefCell::new(HelperSet::default()));
+ HelperSet::new(&helper_set, helpers);
+ let helper_set = helper_set.borrow().clone();
- let helpers: Vec<std::rc::Rc<std::cell::RefCell<dyn HelperInterface>>> =
- vec![std::rc::Rc::new(std::cell::RefCell::new(QuestionHelper))];
let inner = ConsoleIO::new(
std::rc::Rc::new(std::cell::RefCell::new(input_obj))
as std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
output,
- HelperSet::new(helpers),
+ helper_set,
);
Ok(Self { inner })
diff --git a/crates/shirabe/src/io/console_io.rs b/crates/shirabe/src/io/console_io.rs
index 18287e3..2371dfa 100644
--- a/crates/shirabe/src/io/console_io.rs
+++ b/crates/shirabe/src/io/console_io.rs
@@ -10,6 +10,7 @@ use shirabe_external_packages::symfony::console::helper::ProgressBar;
use shirabe_external_packages::symfony::console::helper::QuestionHelper;
use shirabe_external_packages::symfony::console::helper::Table;
use shirabe_external_packages::symfony::console::input::InputInterface;
+use shirabe_external_packages::symfony::console::output::ConsoleOutput;
use shirabe_external_packages::symfony::console::output::ConsoleOutputInterface;
use shirabe_external_packages::symfony::console::output::output_interface::{
self as output_interface, OutputInterface,
@@ -17,9 +18,8 @@ use shirabe_external_packages::symfony::console::output::output_interface::{
use shirabe_external_packages::symfony::console::question::ChoiceQuestion;
use shirabe_external_packages::symfony::console::question::Question;
use shirabe_php_shim::{
- PhpMixed, array_filter, array_keys, array_search, count, function_exists, implode, in_array,
- is_array, is_string, mb_check_encoding, mb_convert_encoding, microtime, sprintf, str_repeat,
- strip_tags, strlen,
+ AsAny, PhpMixed, array_search, function_exists, implode, in_array, is_array, is_string,
+ mb_check_encoding, mb_convert_encoding, microtime, sprintf, str_repeat, strip_tags, strlen,
};
use std::cell::RefCell;
@@ -129,9 +129,18 @@ impl ConsoleIO {
messages
};
- if stderr && let Some(console_output) = self.output.borrow().as_console_output_interface() {
- console_output.get_error_output().borrow().write(
- &Self::to_string_list(&messages).join(if newline { "\n" } else { "" }),
+ let error_output = if stderr {
+ let output = self.output.borrow();
+ (*output)
+ .as_any()
+ .downcast_ref::<ConsoleOutput>()
+ .map(|console_output| console_output.get_error_output())
+ } else {
+ None
+ };
+ if let Some(error_output) = error_output {
+ error_output.borrow().write(
+ &[Self::to_string_list(&messages).join(if newline { "\n" } else { "" })],
newline,
sf_verbosity,
);
@@ -145,7 +154,7 @@ impl ConsoleIO {
}
self.output.borrow().write(
- &Self::to_string_list(&messages).join(if newline { "\n" } else { "" }),
+ &[Self::to_string_list(&messages).join(if newline { "\n" } else { "" })],
newline,
sf_verbosity,
);
@@ -239,7 +248,8 @@ impl ConsoleIO {
}
pub fn get_progress_bar(&self, max: i64) -> ProgressBar {
- ProgressBar::new(self.get_error_output(), max)
+ // PHP ProgressBar::__construct default $minSecondsBetweenRedraws = 1 / 25.
+ ProgressBar::new(self.get_error_output(), max, 1.0 / 25.0)
}
pub fn get_table(&self) -> Table {
@@ -247,8 +257,14 @@ impl ConsoleIO {
}
fn get_error_output(&self) -> std::rc::Rc<std::cell::RefCell<dyn OutputInterface>> {
- if let Some(console_output) = self.output.borrow().as_console_output_interface() {
- return console_output.get_error_output();
+ let output = self.output.borrow();
+ let error_output = (*output)
+ .as_any()
+ .downcast_ref::<ConsoleOutput>()
+ .map(|console_output| console_output.get_error_output());
+ drop(output);
+ if let Some(error_output) = error_output {
+ return error_output;
}
self.output.clone()
@@ -358,6 +374,31 @@ impl ConsoleIO {
_ => vec![],
}
}
+
+ /// Resolves the "question" helper and delegates to `QuestionHelper::ask`.
+ ///
+ /// PHP: `$this->helperSet->get('question')->ask($this->input, $this->getErrorOutput(), $question)`.
+ /// `HelperSet::get` and `QuestionHelper::ask` both surface PHP exceptions; ConsoleIO does not
+ /// catch them, so an unrecoverable error here is a PHP fatal. The double `Result` is collapsed:
+ /// the outer `anyhow::Result` (fatal) and the inner `MissingInputException` (unhandled, hence
+ /// also fatal in PHP) both abort.
+ fn ask_question(&self, question: &Question) -> PhpMixed {
+ let helper_rc = self
+ .helper_set
+ .get("question")
+ .expect("the \"question\" helper is always registered");
+ let error_output = self.get_error_output();
+ let mut helper = helper_rc.borrow_mut();
+ let question_helper = (*helper)
+ .as_any_mut()
+ .downcast_mut::<QuestionHelper>()
+ .expect("the \"question\" helper is a QuestionHelper");
+ let mut input = self.input.borrow_mut();
+ question_helper
+ .ask(&mut *input, error_output, question)
+ .expect("QuestionHelper::ask raised a fatal error")
+ .expect("QuestionHelper::ask returned no input")
+ }
}
impl IOInterfaceImmutable for ConsoleIO {
@@ -434,7 +475,6 @@ impl IOInterfaceImmutable for ConsoleIO {
}
fn ask(&self, question: String, default: PhpMixed) -> PhpMixed {
- let helper = self.helper_set.get::<QuestionHelper>("question");
let sanitized_question = Self::sanitize(PhpMixed::String(question), true)
.as_string()
.unwrap_or("")
@@ -444,15 +484,12 @@ impl IOInterfaceImmutable for ConsoleIO {
} else {
Some(default)
};
- let question = Question::new(&sanitized_question, sanitized_default);
+ let question = Question::new(sanitized_question, sanitized_default);
- helper
- .borrow()
- .ask(self.input.clone(), self.get_error_output(), &question)
+ self.ask_question(&question)
}
fn ask_confirmation(&self, question: String, default: bool) -> bool {
- let helper = self.helper_set.get::<QuestionHelper>("question");
let sanitized = Self::sanitize(PhpMixed::String(question), true)
.as_string()
.unwrap_or("")
@@ -464,11 +501,7 @@ impl IOInterfaceImmutable for ConsoleIO {
"/^no?$/i".to_string(),
);
- let result = helper.borrow().ask(
- self.input.clone(),
- self.get_error_output(),
- question.inner(),
- );
+ let result = self.ask_question(question.inner());
result.as_bool().unwrap_or(false)
}
@@ -488,18 +521,33 @@ impl IOInterfaceImmutable for ConsoleIO {
} else {
Some(default)
};
- let mut question = Question::new(&sanitized_question, sanitized_default);
- // Question::set_validator takes Fn(Option<PhpMixed>) -> Result<PhpMixed>; adapt the
- // None answer to PHP's null and forward the validator's Result unchanged.
- let adapted: Box<dyn Fn(Option<PhpMixed>) -> anyhow::Result<PhpMixed>> =
- Box::new(move |answer: Option<PhpMixed>| validator(answer.unwrap_or(PhpMixed::Null)));
+ let mut question = Question::new(sanitized_question, sanitized_default);
+ // Question::set_validator takes Fn(Option<PhpMixed>) -> Result<PhpMixed, InvalidArgumentException>;
+ // adapt the None answer to PHP's null and translate the validator's anyhow error into the
+ // InvalidArgumentException the Question validator type expects (QuestionHelper retries on it).
+ let adapted: Box<
+ dyn Fn(
+ Option<PhpMixed>,
+ ) -> Result<
+ PhpMixed,
+ shirabe_external_packages::symfony::console::exception::InvalidArgumentException,
+ >,
+ > = Box::new(move |answer: Option<PhpMixed>| {
+ validator(answer.unwrap_or(PhpMixed::Null)).map_err(|e| {
+ shirabe_external_packages::symfony::console::exception::InvalidArgumentException(
+ shirabe_php_shim::InvalidArgumentException {
+ message: e.to_string(),
+ code: 0,
+ },
+ )
+ })
+ });
question.set_validator(Some(adapted));
- question.set_max_attempts(attempts);
+ question
+ .set_max_attempts(attempts)
+ .map_err(|e| anyhow::anyhow!(e.0.message))?;
- let helper = self.helper_set.get::<QuestionHelper>("question");
- Ok(helper
- .borrow()
- .ask(self.input.clone(), self.get_error_output(), &question))
+ Ok(self.ask_question(&question))
}
fn ask_and_hide_answer(&self, question: String) -> Option<String> {
@@ -507,13 +555,13 @@ impl IOInterfaceImmutable for ConsoleIO {
.as_string()
.unwrap_or("")
.to_string();
- let mut question = Question::new(&sanitized_question, Some(PhpMixed::Null));
- question.set_hidden(true);
+ let mut question = Question::new(sanitized_question, Some(PhpMixed::Null));
+ // setHidden only throws when an autocompleter is set, which is not the case here.
+ question
+ .set_hidden(true)
+ .expect("a freshly constructed question has no autocompleter");
- let helper = self.helper_set.get::<QuestionHelper>("question");
- let result = helper
- .borrow()
- .ask(self.input.clone(), self.get_error_output(), &question);
+ let result = self.ask_question(&question);
result.as_string().map(|s| s.to_string())
}
@@ -533,35 +581,45 @@ impl IOInterfaceImmutable for ConsoleIO {
.map(|s| Box::new(PhpMixed::String(s)))
.collect(),
);
- let _helper = self.helper_set.get::<QuestionHelper>("question");
+ let _helper = self
+ .helper_set
+ .get("question")
+ .expect("the \"question\" helper is always registered");
let sanitized_question = Self::sanitize(PhpMixed::String(question), true)
.as_string()
.unwrap_or("")
.to_string();
- // TODO(phase-b): ChoiceQuestion::new expects Vec<PhpMixed>; collect from the
- // sanitized PhpMixed::List.
+ // ChoiceQuestion::new expects an IndexMap<String, Box<PhpMixed>>; project the
+ // sanitized choice list/map into the keyed form, preserving keys.
let sanitized_choices_mixed = Self::sanitize(choices.clone(), true);
- let sanitized_choices: Vec<PhpMixed> = match sanitized_choices_mixed {
- PhpMixed::List(l) => l.into_iter().map(|b| *b).collect(),
- PhpMixed::Array(a) => a.into_values().map(|b| *b).collect(),
- other => vec![other],
+ let sanitized_choices: IndexMap<String, Box<PhpMixed>> = match sanitized_choices_mixed {
+ PhpMixed::List(l) => l
+ .into_iter()
+ .enumerate()
+ .map(|(i, b)| (i.to_string(), b))
+ .collect(),
+ PhpMixed::Array(a) => a,
+ other => indexmap! { "0".to_string() => Box::new(other) },
};
let sanitized_default = if is_string(&default) {
Some(Self::sanitize(default, true))
} else {
Some(default)
};
+ // Empty choices raise a LogicException (programmer error in PHP).
let mut question =
- ChoiceQuestion::new(&sanitized_question, sanitized_choices, sanitized_default);
+ ChoiceQuestion::new(sanitized_question, sanitized_choices, sanitized_default)
+ .expect("select() always provides at least one choice");
// PHP: IOInterface requires false, and Question requires null or int
- let max_attempts = match attempts {
+ let _max_attempts = match attempts {
PhpMixed::Bool(false) => None,
PhpMixed::Int(i) => Some(i),
_ => None,
};
- // ChoiceQuestion delegates set_max_attempts to its inner Question.
- question.0.set_max_attempts(max_attempts);
- question.set_error_message(&error_message);
+ // TODO(phase-c): PHP calls $question->setMaxAttempts($attempts), inherited from Question.
+ // ChoiceQuestion (shirabe-external-packages) keeps its inner Question private and exposes
+ // no setMaxAttempts passthrough, so the attempts cannot be propagated here yet. See report.
+ question.set_error_message(error_message);
question.set_multiselect(multiselect);
// TODO(phase-c): QuestionHelper::ask takes a concrete `&Question`, but PHP passes a
diff --git a/crates/shirabe/src/question/strict_confirmation_question.rs b/crates/shirabe/src/question/strict_confirmation_question.rs
index 5ce32f2..725005a 100644
--- a/crates/shirabe/src/question/strict_confirmation_question.rs
+++ b/crates/shirabe/src/question/strict_confirmation_question.rs
@@ -1,6 +1,5 @@
//! ref: composer/src/Composer/Question/StrictConfirmationQuestion.php
-use anyhow::Result;
use shirabe_external_packages::composer::pcre::Preg;
use shirabe_external_packages::symfony::console::exception::InvalidArgumentException;
use shirabe_external_packages::symfony::console::question::Question;
@@ -19,7 +18,7 @@ impl StrictConfirmationQuestion {
true_answer_regex: String,
false_answer_regex: String,
) -> Self {
- let inner = Question::new(&question, Some(PhpMixed::Bool(default)));
+ let inner = Question::new(question, Some(PhpMixed::Bool(default)));
let mut this = Self {
inner,
true_answer_regex,
@@ -36,19 +35,19 @@ impl StrictConfirmationQuestion {
&self.inner
}
- fn get_default_normalizer(&self) -> Box<dyn Fn(&PhpMixed) -> PhpMixed> {
+ fn get_default_normalizer(&self) -> Box<dyn Fn(PhpMixed) -> PhpMixed> {
let default = self.inner.get_default();
let true_regex = self.true_answer_regex.clone();
let false_regex = self.false_answer_regex.clone();
- Box::new(move |answer: &PhpMixed| {
- if is_bool(answer) {
- return answer.clone();
+ Box::new(move |answer: PhpMixed| {
+ if is_bool(&answer) {
+ return answer;
}
- if empty(answer) && default.as_ref().is_some_and(|d| !empty(d)) {
- return default.clone().unwrap_or(PhpMixed::Null);
+ if empty(&answer) && !empty(&default) {
+ return default.clone();
}
- if let PhpMixed::String(s) = answer {
+ if let PhpMixed::String(s) = &answer {
if Preg::is_match(&true_regex, s).unwrap_or(false) {
return PhpMixed::Bool(true);
}
@@ -60,15 +59,18 @@ impl StrictConfirmationQuestion {
})
}
- fn get_default_validator(&self) -> Box<dyn Fn(Option<PhpMixed>) -> Result<PhpMixed>> {
+ fn get_default_validator(
+ &self,
+ ) -> Box<dyn Fn(Option<PhpMixed>) -> Result<PhpMixed, InvalidArgumentException>> {
Box::new(|answer: Option<PhpMixed>| {
let answer = answer.unwrap_or(PhpMixed::Null);
if !is_bool(&answer) {
- return Err(InvalidArgumentException {
- message: "Please answer yes, y, no, or n.".to_string(),
- code: 0,
- }
- .into());
+ return Err(InvalidArgumentException(
+ shirabe_php_shim::InvalidArgumentException {
+ message: "Please answer yes, y, no, or n.".to_string(),
+ code: 0,
+ },
+ ));
}
Ok(answer)
})