#[derive(Debug, thiserror::Error)]
pub enum GitError {
#[error("{command}: {stderr}")]
CommandFailed {
command: String,
stderr: String,
},
#[error("{0}")]
OutputParse(String),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("Join error: {0}")]
Join(#[from] tokio::task::JoinError),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn command_failed_display_includes_command_and_stderr() {
let error = GitError::CommandFailed {
command: "git push origin main".to_string(),
stderr: "fatal: could not read Username".to_string(),
};
let display = error.to_string();
assert!(matches!(
error,
GitError::CommandFailed {
ref command,
ref stderr,
} if command == "git push origin main" && stderr == "fatal: could not read Username"
));
assert_eq!(
display,
"git push origin main: fatal: could not read Username"
);
}
#[test]
fn output_parse_display_shows_message() {
let error = GitError::OutputParse("unexpected rev-parse output".to_string());
assert!(
matches!(error, GitError::OutputParse(ref message) if message == "unexpected rev-parse output")
);
assert_eq!(error.to_string(), "unexpected rev-parse output");
}
#[test]
fn io_error_converts_via_from() {
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file missing");
let error = GitError::from(io_error);
assert!(matches!(error, GitError::Io(_)));
assert!(error.to_string().contains("file missing"));
}
}