From 2c3373a7466c31f5cce7c2867c00a91afaa8e128 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 2 Aug 2026 08:55:56 +0900 Subject: fix(io): propagate ask/select errors instead of panicking IOInterface::ask/select now return anyhow::Result, and ConsoleIO::ask_question forwards QuestionHelper errors (validator failures, MissingInputException) instead of collapsing them with .expect(). In PHP these exceptions propagate from QuestionHelper through ConsoleIO to the caller, so callers such as UpdateCommand's interactive package selection must be able to observe them; the MissingInputException is wrapped with its concrete type preserved so Application's ExceptionInterface downcast keeps working. All call sites now propagate with `?` (Perforce::query_p4_user becomes Result-returning: PHP declares it void but exceptions still escape), and the previously ignored test_interactive_mode_throws_if_no_package_entered passes. ask_confirmation/ask_and_hide_answer still collapse errors; extending propagation to them is left as TODO(phase-c) pending a decision. Co-Authored-By: Claude Fable 5 --- crates/shirabe/src/command/create_project_command.rs | 2 +- crates/shirabe/src/command/exec_command.rs | 2 +- crates/shirabe/src/command/init_command.rs | 6 +++--- crates/shirabe/src/command/package_discovery_trait.rs | 4 ++-- crates/shirabe/src/command/run_script_command.rs | 2 +- crates/shirabe/src/command/update_command.rs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) (limited to 'crates/shirabe/src/command') diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index 68024b69..545ed533 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -173,7 +173,7 @@ impl Command for CreateProjectCommand { ); input .borrow_mut() - .set_argument("directory", io.ask(prompt, PhpMixed::Null)); + .set_argument("directory", io.ask(prompt, PhpMixed::Null)?); } let repository_opt = input.borrow().get_option("repository")?; diff --git a/crates/shirabe/src/command/exec_command.rs b/crates/shirabe/src/command/exec_command.rs index 057c9eb2..63017cd1 100644 --- a/crates/shirabe/src/command/exec_command.rs +++ b/crates/shirabe/src/command/exec_command.rs @@ -128,7 +128,7 @@ impl Command for ExecCommand { PhpMixed::Int(1), "Invalid binary name \"%s\"".to_string(), false, - ); + )?; if let Some(idx) = binary.as_int() { input.borrow_mut().set_argument( diff --git a/crates/shirabe/src/command/init_command.rs b/crates/shirabe/src/command/init_command.rs index 1ff4089a..4523d910 100644 --- a/crates/shirabe/src/command/init_command.rs +++ b/crates/shirabe/src/command/init_command.rs @@ -595,7 +595,7 @@ impl Command for InitCommand { description_default .map(PhpMixed::String) .unwrap_or(PhpMixed::Null), - ); + )?; input.borrow_mut().set_option("description", description); let author = input @@ -701,7 +701,7 @@ impl Command for InitCommand { type_str ), type_val, - ); + )?; if type_value.as_string() == Some("") || matches!(type_value, PhpMixed::Bool(false)) { type_value = PhpMixed::Null; } @@ -734,7 +734,7 @@ impl Command for InitCommand { license.clone().unwrap_or_default() ), license.map(PhpMixed::String).unwrap_or(PhpMixed::Null), - ); + )?; let spdx = SpdxLicenses::new(); if !license.is_null() && !spdx.validate(license.as_string().unwrap_or("")) diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index 6fb83676..229d84e9 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -227,7 +227,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { let io = self.get_io(); loop { - let package_input = io.ask("Search for a package: ".to_string(), PhpMixed::Null); + let package_input = io.ask("Search for a package: ".to_string(), PhpMixed::Null)?; let mut package = match package_input.as_string() { Some(s) => s.to_string(), None => break, @@ -694,7 +694,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { PhpMixed::Int(1), "No package named \"%s\" is installed.".to_string(), false, - ); + )?; if let Some(idx_str) = result_mixed.as_string() && let Ok(idx) = idx_str.parse::() && let Some(selected) = similar.get(idx) diff --git a/crates/shirabe/src/command/run_script_command.rs b/crates/shirabe/src/command/run_script_command.rs index faa3a6dd..0887eb89 100644 --- a/crates/shirabe/src/command/run_script_command.rs +++ b/crates/shirabe/src/command/run_script_command.rs @@ -214,7 +214,7 @@ impl Command for RunScriptCommand { PhpMixed::Int(1), "Invalid script name \"%s\"".to_string(), false, - ); + )?; input.borrow_mut().set_argument("script", script)?; diff --git a/crates/shirabe/src/command/update_command.rs b/crates/shirabe/src/command/update_command.rs index 686e784d..5c0aae8a 100644 --- a/crates/shirabe/src/command/update_command.rs +++ b/crates/shirabe/src/command/update_command.rs @@ -715,7 +715,7 @@ impl UpdateCommand { PhpMixed::Int(1), "No package named \"%s\" is installed.".to_string(), true, - ); + )?; let packages: Vec = match select_result { PhpMixed::List(l) => l .into_iter() -- cgit v1.3.1