From c29cd35c4d693b536ae9c1569acc15c623514532 Mon Sep 17 00:00:00 2001 From: maciektr Date: Mon, 21 Oct 2024 16:39:35 +0200 Subject: [PATCH] Stop using process:exit for error code handling (#1652) --- scarb/src/bin/scarb/commands/fmt.rs | 3 ++- scarb/src/bin/scarb/commands/run.rs | 11 ++++++----- scarb/src/bin/scarb/errors.rs | 15 ++++++++------- scarb/src/bin/scarb/main.rs | 15 +++++++++------ scarb/src/core/errors.rs | 7 ++++--- scarb/src/ops/scripts.rs | 4 ++++ 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/scarb/src/bin/scarb/commands/fmt.rs b/scarb/src/bin/scarb/commands/fmt.rs index 3fb56218c..e70174e04 100644 --- a/scarb/src/bin/scarb/commands/fmt.rs +++ b/scarb/src/bin/scarb/commands/fmt.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use std::process::ExitCode; use crate::args::{EmitTarget, FmtArgs}; use crate::errors::error_with_exit_code; @@ -35,7 +36,7 @@ pub fn run(args: FmtArgs, config: &Config) -> Result<()> { )? { Ok(()) } else { - error_with_exit_code(1) + error_with_exit_code(ExitCode::FAILURE) } } diff --git a/scarb/src/bin/scarb/commands/run.rs b/scarb/src/bin/scarb/commands/run.rs index 652f90640..2ad3d7e6d 100644 --- a/scarb/src/bin/scarb/commands/run.rs +++ b/scarb/src/bin/scarb/commands/run.rs @@ -1,3 +1,5 @@ +use crate::args::ScriptsRunnerArgs; +use crate::errors::ErrorWithExitCode; use anyhow::{anyhow, Result}; use indoc::formatdoc; use itertools::Itertools; @@ -10,9 +12,7 @@ use smol_str::SmolStr; use std::collections::BTreeMap; use std::ffi::OsString; use std::fmt::Write; - -use crate::args::ScriptsRunnerArgs; -use crate::errors::ErrorWithExitCode; +use std::process::ExitCode; #[tracing::instrument(skip_all, level = "info")] pub fn run(args: ScriptsRunnerArgs, config: &Config) -> Result<()> { @@ -79,8 +79,9 @@ fn build_exit_error(errors: Vec) -> Result<()> { err.downcast_ref::() .map(|err| err.exit_code) }) - .find(|exit_code| *exit_code != 0) - .unwrap_or(1); + .take(1) + .collect_vec(); + let exit_code = exit_code.first().cloned().unwrap_or(ExitCode::FAILURE); let msg = errors .into_iter() .map(|err| err.to_string()) diff --git a/scarb/src/bin/scarb/errors.rs b/scarb/src/bin/scarb/errors.rs index 30d495d4c..94dd1e06c 100644 --- a/scarb/src/bin/scarb/errors.rs +++ b/scarb/src/bin/scarb/errors.rs @@ -1,27 +1,28 @@ use anyhow::Result; +use std::process::ExitCode; use thiserror::Error; /// The ErrorWithExitCode is the error type used at Scarb's CLI-layer. #[derive(Error, Debug)] -#[error("ErrorWithExitCode exit_code: {exit_code}")] +#[error("ErrorWithExitCode exit_code: {:?}", exit_code)] pub struct ErrorWithExitCode { /// The error to display. This can be `None` in rare cases to exit with a /// code without displaying a message. #[source] pub source: Option, /// The process exit code. - pub exit_code: i32, + pub exit_code: ExitCode, } impl ErrorWithExitCode { - pub fn new(error: anyhow::Error, code: i32) -> Self { + pub fn new(error: anyhow::Error, code: ExitCode) -> Self { Self { source: Some(error), exit_code: code, } } - pub fn code(code: i32) -> Self { + pub fn code(code: ExitCode) -> Self { Self { source: None, exit_code: code, @@ -31,16 +32,16 @@ impl ErrorWithExitCode { impl From for ErrorWithExitCode { fn from(err: anyhow::Error) -> ErrorWithExitCode { - ErrorWithExitCode::new(err, 1) + ErrorWithExitCode::new(err, ExitCode::FAILURE) } } impl From for ErrorWithExitCode { fn from(err: std::io::Error) -> ErrorWithExitCode { - ErrorWithExitCode::new(err.into(), 1) + ErrorWithExitCode::new(err.into(), ExitCode::FAILURE) } } -pub fn error_with_exit_code(code: i32) -> Result { +pub fn error_with_exit_code(code: ExitCode) -> Result { Err(ErrorWithExitCode::code(code).into()) } diff --git a/scarb/src/bin/scarb/main.rs b/scarb/src/bin/scarb/main.rs index 07df66318..881ed3f3f 100644 --- a/scarb/src/bin/scarb/main.rs +++ b/scarb/src/bin/scarb/main.rs @@ -1,4 +1,5 @@ use std::env; +use std::process::ExitCode; use std::str::FromStr; use anyhow::{Error, Result}; @@ -19,7 +20,7 @@ mod commands; mod errors; mod interactive; -fn main() { +fn main() -> ExitCode { let args = ScarbArgs::parse(); // Pre-create Ui used in logging & error reporting, because we will move `args` to `cli_main`. @@ -39,25 +40,27 @@ fn main() { .init(); if let Err(err) = cli_main(args) { - exit_with_error(err, &ui); + return exit_with_error(err, &ui); } + + ExitCode::SUCCESS } -fn exit_with_error(err: Error, ui: &Ui) { +fn exit_with_error(err: Error, ui: &Ui) -> ExitCode { debug!("exit_with_error; err={:?}", err); if let Some(ErrorWithExitCode { source, exit_code }) = err.downcast_ref::() { if let Some(source_err) = source { ui.anyhow(source_err); } - std::process::exit(*exit_code); + *exit_code } else if let Some(ScriptExecutionError { exit_code }) = err.downcast_ref::() { - std::process::exit(*exit_code); + *exit_code } else { ui.anyhow(&err); - std::process::exit(1); + ExitCode::FAILURE } } diff --git a/scarb/src/core/errors.rs b/scarb/src/core/errors.rs index f790a3a8b..7e944a600 100644 --- a/scarb/src/core/errors.rs +++ b/scarb/src/core/errors.rs @@ -1,14 +1,15 @@ +use std::process::ExitCode; use thiserror::Error; #[derive(Debug, Error)] -#[error("script failed with exit code: {exit_code}")] +#[error("script failed with exit code: {:?}", exit_code)] pub struct ScriptExecutionError { /// The process exit code. - pub exit_code: i32, + pub exit_code: ExitCode, } impl ScriptExecutionError { - pub fn new(exit_code: i32) -> Self { + pub fn new(exit_code: ExitCode) -> Self { Self { exit_code } } } diff --git a/scarb/src/ops/scripts.rs b/scarb/src/ops/scripts.rs index 063d1d7e7..8c60cd417 100644 --- a/scarb/src/ops/scripts.rs +++ b/scarb/src/ops/scripts.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::env; use std::ffi::OsString; +use std::process::ExitCode; use std::rc::Rc; use anyhow::Result; @@ -56,6 +57,9 @@ pub fn execute_script( )); if exit_code != 0 { + let exit_code: ExitCode = u8::try_from(exit_code) + .map(Into::into) + .unwrap_or(ExitCode::FAILURE); Err(ScriptExecutionError::new(exit_code).into()) } else { Ok(())