History

[object #177] migrate immutable::commit into crate::commit

Sebastian Thiel committed 5 years ago

Commit 45d39341 parent 7f1955911 files · +75 −67Browse files

Showing the changes to git-object/src/commit/mod.rs (1 of 11 files). Show all

Unified · Split

git-object/src/commit/mod.rs+74−0
@@ -0,0 +1,74 @@
1+use bstr::{BStr, ByteSlice};
2+
3+pub use ref_iter::RefIter;
4+
5+use crate::{immutable, TagRef};
6+use crate::{immutable::object, CommitRef};
7+
8+mod decode;
9+
10+///
11+pub mod ref_iter;
12+
13+impl<'a> CommitRef<'a> {
14+ /// Deserialize a commit from the given `data` bytes while avoiding most allocations.
15+ pub fn from_bytes(data: &'a [u8]) -> Result<CommitRef<'a>, object::decode::Error> {
16+ decode::commit(data)
17+ .map(|(_, t)| t)
18+ .map_err(object::decode::Error::from)
19+ }
20+ /// Return the `tree` fields hash digest.
21+ pub fn tree(&self) -> git_hash::ObjectId {
22+ git_hash::ObjectId::from_hex(self.tree).expect("prior validation of tree hash during parsing")
23+ }
24+
25+ /// Returns an iterator of parent object ids
26+ pub fn parents(&self) -> impl Iterator<Item = git_hash::ObjectId> + '_ {
27+ self.parents
28+ .iter()
29+ .map(|hex_hash| git_hash::ObjectId::from_hex(hex_hash).expect("prior validation of hashes during parsing"))
30+ }
31+
32+ /// Returns a convenient iterator over all extra headers.
33+ pub fn extra_headers(&self) -> crate::commit::ExtraHeaders<impl Iterator<Item = (&BStr, &BStr)>> {
34+ crate::commit::ExtraHeaders::new(self.extra_headers.iter().map(|(k, v)| (*k, v.as_ref())))
35+ }
36+}
37+
38+/// An iterator over extra headers in [owned][crate::Commit] and [borrowed][crate::CommitRef] commits.
39+pub struct ExtraHeaders<I> {
40+ inner: I,
41+}
42+
43+/// Instantiation and convenience.
44+impl<'a, I> ExtraHeaders<I>
45+where
46+ I: Iterator<Item = (&'a BStr, &'a BStr)>,
47+{
48+ /// Create a new instance from an iterator over tuples of (name, value) pairs.
49+ pub fn new(iter: I) -> Self {
50+ ExtraHeaders { inner: iter }
51+ }
52+ /// Find the _value_ of the _first_ header with the given `name`.
53+ pub fn find(mut self, name: &str) -> Option<&'a BStr> {
54+ self.inner
55+ .find_map(move |(k, v)| if k == name.as_bytes().as_bstr() { Some(v) } else { None })
56+ }
57+ /// Return an iterator over all _values_ of headers with the given `name`.
58+ pub fn find_all(self, name: &'a str) -> impl Iterator<Item = &'a BStr> {
59+ self.inner
60+ .filter_map(move |(k, v)| if k == name.as_bytes().as_bstr() { Some(v) } else { None })
61+ }
62+ /// Return an iterator over all git mergetags.
63+ ///
64+ /// A merge tag is a tag object embedded within the respective header field of a commit, making
65+ /// it a child object of sorts.
66+ pub fn mergetags(self) -> impl Iterator<Item = Result<TagRef<'a>, immutable::object::decode::Error>> {
67+ self.find_all("mergetag").map(|b| TagRef::from_bytes(b))
68+ }
69+
70+ /// Return the cryptographic signature provided by gpg/pgp verbatim.
71+ pub fn pgp_signature(self) -> Option<&'a BStr> {
72+ self.find("gpgsig")
73+ }
74+}