use std::fmt;
use std::process::ExitCode;
#[derive(Debug)]
pub enum EngineError {
CommandFailed {
task: String,
step: usize,
total: usize,
command: String,
code: ExitCode,
},
CommandBlockFailed {
task: String,
step: usize,
total: usize,
code: ExitCode,
},
CommandBlockStartFailed {
shell: String,
source: Box<EngineError>,
},
Interpolation(String),
ShellNotFound(String),
UnsupportedShell(String),
Runtime(String),
Io {
message: &'static str,
path: String,
source: std::io::Error,
},
}
impl fmt::Display for EngineError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CommandFailed {
task,
step,
total,
command,
code,
} => write!(
f,
"task '{task}' failed at step [{step}/{total}]\ncommand: `{command}`\nexit code: {code:?}"
),
Self::CommandBlockFailed {
task,
step,
total,
code,
} => write!(
f,
"task '{task}' failed at step [{step}/{total}]\ncommand block failed\nexit code: {code:?}"
),
Self::CommandBlockStartFailed { shell, source } => {
write!(
f,
"could not start command block with shell '{shell}'\n{source}"
)
}
Self::Interpolation(message) => f.write_str(message),
Self::ShellNotFound(message) => f.write_str(message),
Self::UnsupportedShell(shell) => write!(f, "shell '{shell}' is not supported"),
Self::Runtime(message) => f.write_str(message),
Self::Io {
message,
path,
source,
} => write!(f, "{message}: {path}: {source}"),
}
}
}
pub(crate) fn command_block_failed(
task: &str,
step_index: usize,
step_total: usize,
code: ExitCode,
) -> EngineError {
EngineError::CommandBlockFailed {
task: task.to_string(),
step: step_index,
total: step_total,
code,
}
}
impl std::error::Error for EngineError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io { source, .. } => Some(source),
Self::CommandBlockStartFailed { source, .. } => Some(source.as_ref()),
_ => None,
}
}
}
pub(crate) fn command_block_start_failed(shell: &str, source: EngineError) -> EngineError {
match source {
EngineError::ShellNotFound(_)
| EngineError::UnsupportedShell(_)
| EngineError::Io { .. } => EngineError::CommandBlockStartFailed {
shell: shell.to_string(),
source: Box::new(source),
},
other => other,
}
}
pub(crate) fn command_failed(
task: &str,
step_index: usize,
step_total: usize,
command: &str,
code: ExitCode,
) -> EngineError {
EngineError::CommandFailed {
task: task.to_string(),
step: step_index,
total: step_total,
command: command.to_string(),
code,
}
}