thin_fetch/object/
commit.rs1use std::ops::Deref;
2
3use ring::digest::Digest;
4
5use crate::utils::{as_hex, get_hash};
6use crate::{Error, HashKind, error};
7
8#[derive(Debug)]
9pub struct Commit {
10 pub hash: Digest,
11 pub commit: gix_object::Commit,
12}
13
14impl Commit {
15 pub fn parse(raw: &[u8], hash_kind: HashKind) -> Result<Self, Error> {
21 let hash = get_hash("commit", raw, hash_kind);
22
23 let cref = gix_object::CommitRef::from_bytes(raw, hash_kind.into())
24 .map_err(|err| error!("could not parse commit: {err}"))?;
25
26 let commit = cref
27 .to_owned()
28 .map_err(|err| error!("could not convert commit ref to owned: {err}"))?;
29
30 Ok(Self { hash, commit })
31 }
32
33 #[must_use]
35 pub fn header(&self) -> CommitHeader<'_> {
36 CommitHeader { commit: self }
37 }
38}
39
40impl Deref for Commit {
41 type Target = gix_object::Commit;
42
43 fn deref(&self) -> &Self::Target {
44 &self.commit
45 }
46}
47
48pub struct CommitHeader<'a> {
49 commit: &'a Commit,
50}
51
52impl std::fmt::Display for CommitHeader<'_> {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 let hash = as_hex(self.commit.hash.as_ref());
55
56 writeln!(f, "commit {hash}").unwrap();
57
58 let author = &self.commit.author;
59 writeln!(f, "Author: {} <{}>", author.name, author.email)?;
60
61 let zoned = author.time.to_zoned().unwrap();
62 let date = jiff::fmt::rfc2822::to_string(&zoned).unwrap();
63 writeln!(f, "Date: {date}")?;
64 writeln!(f)?;
65
66 let msg = String::from_utf8_lossy(&self.commit.message);
67 let message = msg.trim_end_matches('\n');
68
69 for line in message.split('\n') {
70 writeln!(f, " {line}")?;
71 }
72
73 Ok(())
74 }
75}