aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/console/application.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-20 15:37:24 +0900
committernsfisis <nsfisis@gmail.com>2026-06-20 15:45:19 +0900
commit1b38bdb5a1de127ca8040f5a132d08c73ccb3c67 (patch)
tree71cd969054fa56845d737abf4e55e10a12c378a0 /crates/shirabe/src/console/application.rs
parentb7c3981fd60662cdf500aaf1a7e49a77b967968d (diff)
downloadphp-shirabe-1b38bdb5a1de127ca8040f5a132d08c73ccb3c67.tar.gz
php-shirabe-1b38bdb5a1de127ca8040f5a132d08c73ccb3c67.tar.zst
php-shirabe-1b38bdb5a1de127ca8040f5a132d08c73ccb3c67.zip
refactor(console): propagate getComposer's exit(1) as ExitException
Composer's Application::getComposer() calls exit(1) when a required Composer instance fails to build under areExceptionsCaught(). Replace the deep std::process::exit with a php-shim ExitException that mirrors PHP's `exit` construct: it bypasses parent::doRun()'s catch and Symfony's renderThrowable (excluded at both broad catches), so the already-written plain error message is not re-rendered and the process exits with code 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/console/application.rs')
-rw-r--r--crates/shirabe/src/console/application.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs
index 6622a2d..9c3ef01 100644
--- a/crates/shirabe/src/console/application.rs
+++ b/crates/shirabe/src/console/application.rs
@@ -953,6 +953,13 @@ impl Application {
let outcome = match result_outcome {
Ok(r) => Ok(r),
Err(e) => {
+ // PHP's `exit` bypasses parent::doRun()'s catch entirely; re-raise it untouched so
+ // the GitHub Actions annotation and error hints below are skipped.
+ if e.downcast_ref::<shirabe_php_shim::ExitException>()
+ .is_some()
+ {
+ return Err(e);
+ }
if let Some(see) = e.downcast_ref::<ScriptExecutionException>() {
if application.borrow().get_disable_plugins_by_default()
&& application.borrow().is_running_as_root()
@@ -1203,7 +1210,10 @@ impl Application {
if required {
self.io.write_error(&e.to_string());
if self.are_exceptions_caught() {
- std::process::exit(1);
+ // PHP calls `exit(1)` here, terminating before parent::run() can
+ // re-render the exception. Propagate it as an ExitException so the
+ // top-level handler turns it into exit code 1 without re-rendering.
+ return Err(shirabe_php_shim::ExitException { code: 1 }.into());
}
return Err(e);
}
@@ -1471,6 +1481,12 @@ impl Application {
let exit_code = match result {
Ok(exit_code) => exit_code,
Err(e) => {
+ // PHP's `exit` bypasses Symfony's try/catch: it never renders and forces the exit
+ // code it carries. The message, if any, has already been written at the exit site.
+ if let Some(exit) = e.downcast_ref::<shirabe_php_shim::ExitException>() {
+ return Ok(exit.code as i32);
+ }
+
if !application.borrow().catch_exceptions {
return Err(e);
}