1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
use crate::Config; use std::{fmt::Display, io, process::ExitStatus, string::FromUtf8Error, sync::Arc}; #[derive(Debug, Clone)] pub enum Error { NoArgumentsGiven, CommandIoError { message: String, source: Arc<io::Error>, }, NonZeroExitCode { full_command: String, exit_status: ExitStatus, }, InvalidUtf8ToStdout { full_command: String, source: Arc<FromUtf8Error>, }, InvalidUtf8ToStderr { full_command: String, source: Arc<FromUtf8Error>, }, } impl Error { pub(crate) fn command_io_error(config: &Config, error: io::Error) -> Error { Error::CommandIoError { message: format!("{}:\n {}", config.full_command(), error), source: Arc::new(error), } } } #[doc(hidden)] pub fn panic_on_error<T>(result: Result<T, Error>) -> T { match result { Ok(t) => t, Err(error) => panic!("cmd!: {}", error), } } impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::NoArgumentsGiven => write!(f, "no arguments given"), Error::CommandIoError { message, .. } => write!(f, "{}", message), Error::NonZeroExitCode { full_command, exit_status, } => write!(f, "{}:\n exited with {}", full_command, exit_status), Error::InvalidUtf8ToStdout { full_command, .. } => { write!(f, "{}:\n invalid utf-8 written to stdout", full_command) } Error::InvalidUtf8ToStderr { full_command, .. } => { write!(f, "{}:\n invalid utf-8 written to stderr", full_command) } } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Error::CommandIoError { source, .. } => Some(&**source), Error::InvalidUtf8ToStdout { source, .. } | Error::InvalidUtf8ToStderr { source, .. } => Some(&**source), Error::NoArgumentsGiven | Error::NonZeroExitCode { .. } => None, } } } #[cfg(test)] mod tests { use crate::{cmd_result, Stderr, StdoutUntrimmed}; use executable_path::executable_path; use std::error::Error; #[test] fn invalid_utf8_to_stdout_has_source() { let result: Result<StdoutUntrimmed, crate::Error> = cmd_result!( executable_path("cradle_test_helper").to_str().unwrap(), vec!["invalid utf-8 stdout"] ); assert!(result.unwrap_err().source().is_some()); } #[test] fn invalid_utf8_to_stderr_has_source() { let result: Result<Stderr, crate::Error> = cmd_result!( executable_path("cradle_test_helper").to_str().unwrap(), vec!["invalid utf-8 stderr"] ); assert!(result.unwrap_err().source().is_some()); } }