diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-20 15:37:24 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-20 15:45:19 +0900 |
| commit | 1b38bdb5a1de127ca8040f5a132d08c73ccb3c67 (patch) | |
| tree | 71cd969054fa56845d737abf4e55e10a12c378a0 /crates/shirabe/src/console | |
| parent | b7c3981fd60662cdf500aaf1a7e49a77b967968d (diff) | |
| download | php-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')
| -rw-r--r-- | crates/shirabe/src/console/application.rs | 18 |
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); } |
