diff --git a/gix/src/head/peel.rs b/gix/src/head/peel.rs index a371b6a0dd3..4ee116ed0db 100644 --- a/gix/src/head/peel.rs +++ b/gix/src/head/peel.rs @@ -42,7 +42,20 @@ pub mod into_id { pub mod to_commit { use crate::object; - /// The error returned by [`Head::peel_to_commit_in_place()`][super::Head::peel_to_commit_in_place()]. + /// The error returned by [`Head::peel_to_commit_in_place()`](super::Head::peel_to_commit_in_place()). + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error(transparent)] + PeelToObject(#[from] super::to_object::Error), + #[error(transparent)] + ObjectKind(#[from] object::try_into::Error), + } +} + +/// +pub mod to_object { + /// The error returned by [`Head::peel_to_object_in_place()`](super::Head::peel_to_object_in_place()). #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { @@ -50,13 +63,11 @@ pub mod to_commit { Peel(#[from] super::Error), #[error("Branch '{name}' does not have any commits")] Unborn { name: gix_ref::FullName }, - #[error(transparent)] - ObjectKind(#[from] object::try_into::Error), } } impl<'repo> Head<'repo> { - /// Peel this instance and consume to make obtaining its final target id possible, while returning an error on unborn heads. + /// Peel this instance and consume it to make obtaining its final target id possible, while returning an error on unborn heads. /// /// The final target is obtained by following symbolic references and peeling tags to their final destination, which /// typically is a commit, but can be any object. @@ -68,6 +79,14 @@ impl<'repo> Head<'repo> { }) } + /// Peel this instance and consume it to make obtaining its final target object possible, while returning an error on unborn heads. + /// + /// The final target is obtained by following symbolic references and peeling tags to their final destination, which + /// typically is a commit, but can be any object as well. + pub fn into_peeled_object(mut self) -> Result, to_object::Error> { + self.peel_to_object_in_place() + } + /// Consume this instance and transform it into the final object that it points to, or `Ok(None)` if the `HEAD` /// reference is yet to be born. /// @@ -120,15 +139,21 @@ impl<'repo> Head<'repo> { /// more object to follow, transform the id into a commit if possible and return that. /// /// Returns an error if the head is unborn or if it doesn't point to a commit. - pub fn peel_to_commit_in_place(&mut self) -> Result, to_commit::Error> { + pub fn peel_to_object_in_place(&mut self) -> Result, to_object::Error> { let id = self .try_peel_to_id_in_place()? - .ok_or_else(|| to_commit::Error::Unborn { + .ok_or_else(|| to_object::Error::Unborn { name: self.referent_name().expect("unborn").to_owned(), })?; - Ok(id - .object() - .map_err(|err| to_commit::Error::Peel(Error::FindExistingObject(err)))? - .try_into_commit()?) + id.object() + .map_err(|err| to_object::Error::Peel(Error::FindExistingObject(err))) + } + + /// Follow the symbolic reference of this head until its target object and peel it by following tag objects until there is no + /// more object to follow, transform the id into a commit if possible and return that. + /// + /// Returns an error if the head is unborn or if it doesn't point to a commit. + pub fn peel_to_commit_in_place(&mut self) -> Result, to_commit::Error> { + Ok(self.peel_to_object_in_place()?.try_into_commit()?) } } diff --git a/gix/src/reference/errors.rs b/gix/src/reference/errors.rs index fdd70ee1d04..d5b09f78e0b 100644 --- a/gix/src/reference/errors.rs +++ b/gix/src/reference/errors.rs @@ -67,9 +67,7 @@ pub mod head_tree_id { #[allow(missing_docs)] pub enum Error { #[error(transparent)] - Head(#[from] crate::reference::find::existing::Error), - #[error(transparent)] - PeelToCommit(#[from] crate::head::peel::to_commit::Error), + HeadCommit(#[from] crate::reference::head_commit::Error), #[error(transparent)] DecodeCommit(#[from] gix_object::decode::Error), } diff --git a/gix/src/repository/reference.rs b/gix/src/repository/reference.rs index 4ae3897c199..b977c6ea872 100644 --- a/gix/src/repository/reference.rs +++ b/gix/src/repository/reference.rs @@ -216,7 +216,7 @@ impl crate::Repository { /// is freshly initialized and doesn't have any commits yet. It could also fail if the /// head does not point to a commit. pub fn head_tree_id(&self) -> Result, reference::head_tree_id::Error> { - Ok(self.head()?.peel_to_commit_in_place()?.tree_id()?) + Ok(self.head_commit()?.tree_id()?) } /// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`, diff --git a/gix/tests/head/mod.rs b/gix/tests/head/mod.rs index c2516ea49f8..69ead585ffc 100644 --- a/gix/tests/head/mod.rs +++ b/gix/tests/head/mod.rs @@ -7,11 +7,13 @@ mod peel { for name in ["detached", "symbolic", "tag-detached", "tag-symbolic"] { let repo = named_subrepo_opts("make_head_repos.sh", name, gix::open::Options::isolated())?; assert_eq!(repo.head()?.into_peeled_id()?, expected_commit); + assert_eq!(repo.head()?.into_peeled_object()?.id, expected_commit); assert_eq!(repo.head_id()?, expected_commit); let commit = repo.head_commit()?; assert_eq!(commit.id, expected_commit); assert_eq!(repo.head_tree_id()?, commit.tree_id()?); assert_eq!(repo.head()?.try_into_peeled_id()?.expect("born"), expected_commit); + assert_eq!(repo.head()?.peel_to_object_in_place()?.id, expected_commit); assert_eq!(repo.head()?.try_peel_to_id_in_place()?.expect("born"), expected_commit); } Ok(())