use std::ops::Deref;
use ring::digest::Digest;
use crate::utils::{as_hex, get_hash};
use crate::{Error, HashKind, error};
#[derive(Debug)]
pub struct Commit {
pub hash: Digest,
pub commit: gix_object::Commit,
}
impl Commit {
pub fn parse(raw: &[u8], hash_kind: HashKind) -> Result<Self, Error> {
let hash = get_hash("commit", raw, hash_kind);
let cref = gix_object::CommitRef::from_bytes(raw, hash_kind.into())
.map_err(|err| error!("could not parse commit: {err}"))?;
let commit = cref
.to_owned()
.map_err(|err| error!("could not convert commit ref to owned: {err}"))?;
Ok(Self { hash, commit })
}
#[must_use]
pub fn header(&self) -> CommitHeader<'_> {
CommitHeader { commit: self }
}
}
impl Deref for Commit {
type Target = gix_object::Commit;
fn deref(&self) -> &Self::Target {
&self.commit
}
}
pub struct CommitHeader<'a> {
commit: &'a Commit,
}
impl std::fmt::Display for CommitHeader<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let hash = as_hex(self.commit.hash.as_ref());
writeln!(f, "commit {hash}").unwrap();
let author = &self.commit.author;
writeln!(f, "Author: {} <{}>", author.name, author.email)?;
let zoned = author.time.to_zoned().unwrap();
let date = jiff::fmt::rfc2822::to_string(&zoned).unwrap();
writeln!(f, "Date: {date}")?;
writeln!(f)?;
let msg = String::from_utf8_lossy(&self.commit.message);
let message = msg.trim_end_matches('\n');
for line in message.split('\n') {
writeln!(f, " {line}")?;
}
Ok(())
}
}