From 3b0913a2e6695e4e9e94341ef48d2ba3b4a518e6 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 26 Jan 2022 20:57:43 +0800 Subject: [PATCH] feat: `easy::Head::peel_to_commit_in_place()` (#298) It allows to quickly get a commit from the head, something most people want when getting started with any kind of tool. --- git-repository/src/easy/head.rs | 35 ++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/git-repository/src/easy/head.rs b/git-repository/src/easy/head.rs index decf3ed463a..d155474c6e8 100644 --- a/git-repository/src/easy/head.rs +++ b/git-repository/src/easy/head.rs @@ -117,6 +117,22 @@ pub mod peel { } pub use error::Error; + mod peel_to_commit { + use crate::easy; + + /// 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)] + Peel(#[from] super::Error), + #[error("Branch '{name}' does not have any commits")] + Unborn { name: git_ref::FullName }, + #[error(transparent)] + ObjectKind(#[from] easy::object::try_into::Error), + } + } + impl<'repo> Head<'repo> { // TODO: tests /// Peel this instance to make obtaining its final target id possible, while returning an error on unborn heads. @@ -126,7 +142,7 @@ pub mod peel { } // TODO: tests - /// Follow the symbolic reference of this head until its target object and peel it by following tag objects there is no + /// 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, and return that object id. /// /// Returns `None` if the head is unborn. @@ -163,6 +179,23 @@ pub mod peel { }) } + // TODO: tests + // TODO: something similar in `easy::Reference` + /// 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, peel_to_commit::Error> { + let id = self + .peel_to_id_in_place() + .ok_or_else(|| peel_to_commit::Error::Unborn { + name: self.referent_name().expect("unborn").to_owned(), + })??; + id.object() + .map_err(|err| peel_to_commit::Error::Peel(Error::FindExistingObject(err))) + .and_then(|object| object.try_into_commit().map_err(Into::into)) + } + /// Consume this instance and transform it into the final object that it points to, or `None` if the `HEAD` /// reference is yet to be born. pub fn into_fully_peeled_id(self) -> Option, Error>> {