use std::process::ExitCode;
#[cfg(not(test))]
pub fn main() -> ExitCode {
report(crate::run(std::env::args_os()))
}
fn report(result: anyhow::Result<i32>) -> ExitCode {
match result {
Ok(code) => ExitCode::from(code as u8),
Err(err) => match err.downcast_ref::<clap::Error>() {
Some(clap_err) => {
let _ = clap_err.print();
ExitCode::from(clap_err.exit_code() as u8)
}
None => {
eprintln!("error: {err:#}");
ExitCode::from(1)
}
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::error::ErrorKind;
#[test]
fn a_success_code_becomes_that_exit_code() {
assert_eq!(report(Ok(0)), ExitCode::from(0));
assert_eq!(report(Ok(3)), ExitCode::from(3));
}
#[test]
fn a_plain_failure_exits_one() {
assert_eq!(
report(Err(anyhow::anyhow!("the gate found violations"))),
ExitCode::from(1)
);
}
#[test]
fn a_usage_mistake_carries_claps_own_exit_code() {
let clap_err = clap::Error::new(ErrorKind::InvalidValue);
let expected = clap_err.exit_code() as u8;
assert_eq!(report(Err(clap_err.into())), ExitCode::from(expected));
assert_eq!(expected, 2, "clap reports a usage mistake as 2");
}
#[test]
fn a_help_request_exits_zero_rather_than_as_a_failure() {
let help = clap::Error::new(ErrorKind::DisplayHelp);
assert_eq!(report(Err(help.into())), ExitCode::from(0));
}
}