use std::path::PathBuf;
use crate::{CommandError, CommitSha};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CommitRecord {
pub sha: CommitSha,
pub summary: String,
pub body: Option<String>,
}
#[derive(Clone, Debug, thiserror::Error, miette::Diagnostic, PartialEq, Eq)]
#[non_exhaustive]
pub enum CommitWalkError {
#[error(transparent)]
Command(#[from] CommandError),
#[error("reference `{ref_name}` was not found")]
#[diagnostic(
code(E054),
help("Check if the reference or tag exists in local or remote Git refs.")
)]
RefNotFound { ref_name: String },
#[error("commit walk failed: {message}")]
#[diagnostic(code(E026))]
Backend { message: String },
}
pub trait CommitWalker {
fn commits_since(
&self,
since_ref: Option<&str>,
pathspecs: &[PathBuf],
) -> Result<Vec<CommitRecord>, CommitWalkError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_commit_walker_is_object_safe() {
struct Empty;
impl CommitWalker for Empty {
fn commits_since(
&self,
_since_ref: Option<&str>,
_pathspecs: &[PathBuf],
) -> Result<Vec<CommitRecord>, CommitWalkError> {
Ok(Vec::new())
}
}
let walker: &dyn CommitWalker = &Empty;
assert!(walker.commits_since(None, &[]).unwrap().is_empty());
}
#[test]
fn test_command_error_converts_transparently() {
let err: CommitWalkError = CommandError::NotFound {
program: "git".to_string(),
}
.into();
assert!(matches!(err, CommitWalkError::Command(_)));
assert_eq!(
err.to_string(),
"`git` was not found; callisto requires it to be available"
);
}
}