use std::{io, process::ExitStatus};
use thiserror::Error;
pub(crate) type Result<T> = std::result::Result<T, AppError>;
#[derive(Debug, Error)]
pub(crate) enum AppError {
#[error("{0}")]
Message(String),
#[error("{context}: {source}")]
Io {
context: String,
#[source]
source: io::Error,
},
#[error("Git executable was not found on PATH. Install Git or make sure `git` is available on PATH.")]
GitNotFound,
#[error("{command} exited with {status}: {output}")]
GitCommandFailed {
command: &'static str,
status: ExitStatus,
output: String,
},
#[error("{command} exited with {status}")]
GitCommandFailedWithoutOutput {
command: &'static str,
status: ExitStatus,
},
}
impl AppError {
pub(crate) fn message(message: impl Into<String>) -> Self {
Self::Message(message.into())
}
pub(crate) fn io(context: impl Into<String>, source: io::Error) -> Self {
Self::Io {
context: context.into(),
source,
}
}
pub(crate) fn git_spawn(source: io::Error) -> Self {
if source.kind() == io::ErrorKind::NotFound {
Self::GitNotFound
} else {
Self::io("failed to run git", source)
}
}
pub(crate) fn git_command_failed(
command: &'static str,
status: ExitStatus,
output: String,
) -> Self {
Self::GitCommandFailed {
command,
status,
output,
}
}
pub(crate) fn git_command_failed_without_output(
command: &'static str,
status: ExitStatus,
) -> Self {
Self::GitCommandFailedWithoutOutput { command, status }
}
}