use std::{
io,
time::Duration,
};
use thiserror::Error;
use crate::{
CommandOutput,
OutputStream,
};
#[derive(Debug, Error)]
pub enum CommandError {
#[error("failed to spawn command `{command}`: {source}")]
SpawnFailed {
command: String,
source: io::Error,
},
#[error("failed to wait for command `{command}`: {source}")]
WaitFailed {
command: String,
source: io::Error,
},
#[error("failed to kill timed-out command `{command}` after {timeout:?}: {source}")]
KillFailed {
command: String,
timeout: Duration,
source: io::Error,
},
#[error("failed to read {stream} for command `{command}`: {source}")]
ReadOutputFailed {
command: String,
stream: OutputStream,
source: io::Error,
},
#[error("command `{command}` timed out after {timeout:?}")]
TimedOut {
command: String,
timeout: Duration,
output: Box<CommandOutput>,
},
#[error("command `{command}` exited with code {exit_code:?}; expected one of {expected:?}")]
UnexpectedExit {
command: String,
exit_code: Option<i32>,
expected: Vec<i32>,
output: Box<CommandOutput>,
},
}
impl CommandError {
#[inline]
pub const fn output(&self) -> Option<&CommandOutput> {
match self {
Self::TimedOut { output, .. } | Self::UnexpectedExit { output, .. } => Some(output),
_ => None,
}
}
#[inline]
pub fn command(&self) -> &str {
match self {
Self::SpawnFailed { command, .. }
| Self::WaitFailed { command, .. }
| Self::KillFailed { command, .. }
| Self::ReadOutputFailed { command, .. }
| Self::TimedOut { command, .. }
| Self::UnexpectedExit { command, .. } => command,
}
}
}