1 use crate::{bstr, bstr::BStr, Commit, ObjectDetached, Tree}
;
6 #[derive(Debug, thiserror::Error)]
10 FindExistingObject(#[from] object::find::existing::Error),
11 #[error("The commit could not be decoded fully or partially")]
12 Decode(#[from] gix_object::decode::Error),
13 #[error("Expected object of type {}, but got {}", .expected, .actual)]
15 expected
: gix_object
::Kind
,
16 actual
: gix_object
::Kind
,
23 impl<'repo
> Commit
<'repo
> {
24 /// Create an owned instance of this object, copying our data in the process.
25 pub fn detached(&self) -> ObjectDetached
{
28 kind
: gix_object
::Kind
::Commit
,
29 data
: self.data
.clone(),
33 /// Sever the connection to the `Repository` and turn this instance into a standalone object.
34 pub fn detach(self) -> ObjectDetached
{
39 impl<'repo
> Commit
<'repo
> {
40 /// Turn this objects id into a shortened id with a length in hex as configured by `core.abbrev`.
41 pub fn short_id(&self) -> Result
<gix_hash
::Prefix
, crate::id
::shorten
::Error
> {
42 use crate::ext
::ObjectIdExt
;
43 self.id
.attach(self.repo
).shorten()
46 /// Parse the commits message into a [`MessageRef`][gix_object::commit::MessageRef]
47 pub fn message(&self) -> Result
<gix_object
::commit
::MessageRef
<'_
>, gix_object
::decode
::Error
> {
48 Ok(gix_object
::commit
::MessageRef
::from_bytes(self.message_raw()?
))
50 /// Decode the commit object until the message and return it.
51 pub fn message_raw(&self) -> Result
<&'_ BStr
, gix_object
::decode
::Error
> {
52 gix_object
::CommitRefIter
::from_bytes(&self.data
).message()
54 /// Obtain the message by using intricate knowledge about the encoding, which is fastest and
55 /// can't fail at the expense of error handling.
56 pub fn message_raw_sloppy(&self) -> &BStr
{
60 .map(|pos
| &self.data
[pos
+ 2..])
65 /// Decode the commit and obtain the time at which the commit was created.
67 /// For the time at which it was authored, refer to `.decode()?.author.time`.
68 pub fn time(&self) -> Result
<gix_date
::Time
, Error
> {
69 Ok(self.committer()?
.time
)
72 /// Decode the entire commit object and return it for accessing all commit information.
74 /// It will allocate only if there are more than 2 parents.
76 /// Note that the returned commit object does make lookup easy and should be
77 /// used for successive calls to string-ish information to avoid decoding the object
79 pub fn decode(&self) -> Result
<gix_object
::CommitRef
<'_
>, gix_object
::decode
::Error
> {
80 gix_object
::CommitRef
::from_bytes(&self.data
)
83 /// Return an iterator over tokens, representing this commit piece by piece.
84 pub fn iter(&self) -> gix_object
::CommitRefIter
<'_
> {
85 gix_object
::CommitRefIter
::from_bytes(&self.data
)
88 /// Return the commits author, with surrounding whitespace trimmed.
89 pub fn author(&self) -> Result
<gix_actor
::SignatureRef
<'_
>, gix_object
::decode
::Error
> {
90 gix_object
::CommitRefIter
::from_bytes(&self.data
)
95 /// Return the commits committer. with surrounding whitespace trimmed.
96 pub fn committer(&self) -> Result
<gix_actor
::SignatureRef
<'_
>, gix_object
::decode
::Error
> {
97 gix_object
::CommitRefIter
::from_bytes(&self.data
)
102 /// Decode this commits parent ids on the fly without allocating.
104 pub fn parent_ids(&self) -> impl Iterator
<Item
= crate::Id
<'repo
>> + '_
{
105 use crate::ext
::ObjectIdExt
;
106 let repo
= self.repo
;
107 gix_object
::CommitRefIter
::from_bytes(&self.data
)
109 .map(move |id
| id
.attach(repo
))
112 /// Parse the commit and return the tree object it points to.
113 pub fn tree(&self) -> Result
<Tree
<'repo
>, Error
> {
114 match self.tree_id()?
.object()?
.try_into_tree() {
115 Ok(tree
) => Ok(tree
),
116 Err(crate::object
::try_into
::Error { actual, expected, .. }
) => Err(Error
::ObjectKind { actual, expected }
),
120 /// Parse the commit and return the tree id it points to.
121 pub fn tree_id(&self) -> Result
<crate::Id
<'repo
>, gix_object
::decode
::Error
> {
122 gix_object
::CommitRefIter
::from_bytes(&self.data
)
124 .map(|id
| crate::Id
::from_id(id
, self.repo
))
127 /// Return our id own id with connection to this repository.
128 pub fn id(&self) -> crate::Id
<'repo
> {
129 use crate::ext
::ObjectIdExt
;
130 self.id
.attach(self.repo
)
133 /// Obtain a platform for traversing ancestors of this commit.
134 pub fn ancestors(&self) -> crate::revision
::walk
::Platform
<'repo
> {
135 self.id().ancestors()
138 /// Create a platform to further configure a `git describe` operation to find a name for this commit by looking
139 /// at the closest annotated tags (by default) in its past.
140 #[cfg(feature = "revision")]
141 pub fn describe(&self) -> crate::commit
::describe
::Platform
<'repo
> {
142 crate::commit
::describe
::Platform
{
145 select
: Default
::default(),
147 id_as_fallback
: false,
152 /// Extracts the PGP signature and the data that was used to create the signature, or `None` if it wasn't signed.
153 // TODO: make it possible to verify the signature, probably by wrapping `SignedData`. It's quite some work to do it properly.
156 ) -> Result
<Option
<(std
::borrow
::Cow
<'_
, BStr
>, gix_object
::commit
::SignedData
<'_
>)>, gix_object
::decode
::Error
>
158 gix_object
::CommitRefIter
::signature(&self.data
)
162 impl<'r
> std
::fmt
::Debug
for Commit
<'r
> {
163 fn fmt(&self, f
: &mut std
::fmt
::Formatter
<'_
>) -> std
::fmt
::Result
{
164 write
!(f
, "Commit({})", self.id
)