Skip to content

Commit

Permalink
Stop using process:exit for error code handling (#1652)
Browse files Browse the repository at this point in the history
  • Loading branch information
maciektr authored Oct 21, 2024
1 parent 57dd424 commit c29cd35
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 22 deletions.
3 changes: 2 additions & 1 deletion scarb/src/bin/scarb/commands/fmt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::Result;
use std::process::ExitCode;

use crate::args::{EmitTarget, FmtArgs};
use crate::errors::error_with_exit_code;
Expand Down Expand Up @@ -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)
}
}

Expand Down
11 changes: 6 additions & 5 deletions scarb/src/bin/scarb/commands/run.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::args::ScriptsRunnerArgs;
use crate::errors::ErrorWithExitCode;
use anyhow::{anyhow, Result};
use indoc::formatdoc;
use itertools::Itertools;
Expand All @@ -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<()> {
Expand Down Expand Up @@ -79,8 +79,9 @@ fn build_exit_error(errors: Vec<anyhow::Error>) -> Result<()> {
err.downcast_ref::<ScriptExecutionError>()
.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())
Expand Down
15 changes: 8 additions & 7 deletions scarb/src/bin/scarb/errors.rs
Original file line number Diff line number Diff line change
@@ -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<anyhow::Error>,
/// 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,
Expand All @@ -31,16 +32,16 @@ impl ErrorWithExitCode {

impl From<anyhow::Error> for ErrorWithExitCode {
fn from(err: anyhow::Error) -> ErrorWithExitCode {
ErrorWithExitCode::new(err, 1)
ErrorWithExitCode::new(err, ExitCode::FAILURE)
}
}

impl From<std::io::Error> 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<T>(code: i32) -> Result<T> {
pub fn error_with_exit_code<T>(code: ExitCode) -> Result<T> {
Err(ErrorWithExitCode::code(code).into())
}
15 changes: 9 additions & 6 deletions scarb/src/bin/scarb/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::env;
use std::process::ExitCode;
use std::str::FromStr;

use anyhow::{Error, Result};
Expand All @@ -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`.
Expand All @@ -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::<ErrorWithExitCode>() {
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::<ScriptExecutionError>()
{
std::process::exit(*exit_code);
*exit_code
} else {
ui.anyhow(&err);
std::process::exit(1);
ExitCode::FAILURE
}
}

Expand Down
7 changes: 4 additions & 3 deletions scarb/src/core/errors.rs
Original file line number Diff line number Diff line change
@@ -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 }
}
}
4 changes: 4 additions & 0 deletions scarb/src/ops/scripts.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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(())
Expand Down

0 comments on commit c29cd35

Please sign in to comment.