diff --git a/src/errors.rs b/src/errors.rs index bdf2841f..544272dc 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,3 +1,6 @@ +use std::process::{ExitCode, Termination}; + +use log::warn; use miette::Diagnostic; use thiserror::Error; @@ -152,9 +155,9 @@ impl BinstallError { /// - 1 and 2 (catchall and shell) /// - 16 (binstall errors not handled here) /// - 64 (generic error) - pub fn exit_code(&self) -> u8 { + pub fn exit_code(&self) -> ExitCode { use BinstallError::*; - let code = match self { + let code: u8 = match self { UserAbort => 32, UrlParse(_) => 65, Unzip(_) => 66, @@ -173,6 +176,18 @@ impl BinstallError { // reserved codes debug_assert!(code != 64 && code != 16 && code != 1 && code != 2 && code != 0); - code + code.into() + } +} + +impl Termination for BinstallError { + fn report(self) -> ExitCode { + if let BinstallError::UserAbort = self { + warn!("Installation cancelled"); + } else { + eprintln!("{self:?}"); + } + + self.exit_code() } } diff --git a/src/main.rs b/src/main.rs index 1b842388..2fe56c1b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,9 @@ -use std::{path::PathBuf, process::exit, str::FromStr, time::Instant}; +use std::{ + path::PathBuf, + process::{ExitCode, Termination}, + str::FromStr, + time::{Duration, Instant}, +}; use cargo_toml::{Package, Product}; use log::{debug, error, info, warn, LevelFilter}; @@ -75,7 +80,29 @@ struct Options { pkg_url: Option, } -fn main() -> ! { +enum MainExit { + Success(Duration), + Error(BinstallError), + Report(miette::Report), +} + +impl Termination for MainExit { + fn report(self) -> ExitCode { + match self { + Self::Success(spent) => { + info!("Installation complete! [{spent:?}]"); + ExitCode::SUCCESS + } + Self::Error(err) => err.report(), + Self::Report(err) => { + eprintln!("{err:?}"); + ExitCode::from(16) + } + } + } +} + +fn main() -> MainExit { let start = Instant::now(); let rt = Runtime::new().unwrap(); @@ -83,27 +110,15 @@ fn main() -> ! { drop(rt); let done = start.elapsed(); + debug!("run time: {done:?}"); if let Err(err) = result { - debug!("run time: {done:?}"); - match err.downcast::() { - Ok(liberr @ BinstallError::UserAbort) => { - warn!("Installation cancelled"); - exit(liberr.exit_code() as _); - } - Ok(liberr) => { - eprintln!("{liberr:?}"); - exit(liberr.exit_code() as _); - } - Err(binerr) => { - eprintln!("{binerr:?}"); - exit(16); - } + Ok(liberr) => MainExit::Error(liberr), + Err(binerr) => MainExit::Report(binerr), } } else { - info!("Installation complete! [{done:?}]"); - exit(0); + MainExit::Success(done) } }