Skip to content

Commit f0d8a49

Browse files
committed
feat: Repository::head_id() (#364)
A long-needed shortcut.
1 parent 29822c6 commit f0d8a49

File tree

5 files changed

+40
-11
lines changed

5 files changed

+40
-11
lines changed

git-repository/src/head.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ pub mod peel {
124124

125125
use crate::head::Kind;
126126

127-
mod peel_to_commit {
127+
///
128+
pub mod to_commit {
128129
use crate::object;
129130

130131
/// The error returned by [Head::peel_to_commit_in_place()][super::Head::peel_to_commit_in_place()].
@@ -192,14 +193,12 @@ pub mod peel {
192193
/// more object to follow, transform the id into a commit if possible and return that.
193194
///
194195
/// Returns an error if the head is unborn or if it doesn't point to a commit.
195-
pub fn peel_to_commit_in_place(&mut self) -> Result<crate::Commit<'repo>, peel_to_commit::Error> {
196-
let id = self
197-
.peel_to_id_in_place()
198-
.ok_or_else(|| peel_to_commit::Error::Unborn {
199-
name: self.referent_name().expect("unborn").to_owned(),
200-
})??;
196+
pub fn peel_to_commit_in_place(&mut self) -> Result<crate::Commit<'repo>, to_commit::Error> {
197+
let id = self.peel_to_id_in_place().ok_or_else(|| to_commit::Error::Unborn {
198+
name: self.referent_name().expect("unborn").to_owned(),
199+
})??;
201200
id.object()
202-
.map_err(|err| peel_to_commit::Error::Peel(Error::FindExistingObject(err)))
201+
.map_err(|err| to_commit::Error::Peel(Error::FindExistingObject(err)))
203202
.and_then(|object| object.try_into_commit().map_err(Into::into))
204203
}
205204

git-repository/src/reference/errors.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ pub mod peel {
2828
}
2929
}
3030

31+
///
32+
pub mod head_id {
33+
/// The error returned by [Repository::head_id(…)][crate::Repository::head_id()].
34+
#[derive(Debug, thiserror::Error)]
35+
#[allow(missing_docs)]
36+
pub enum Error {
37+
#[error(transparent)]
38+
Head(#[from] crate::reference::find::existing::Error),
39+
#[error(transparent)]
40+
PeelToId(#[from] crate::head::peel::Error),
41+
#[error("Branch '{name}' does not have any commits")]
42+
Unborn { name: git_ref::FullName },
43+
}
44+
}
45+
3146
///
3247
pub mod find {
3348
///

git-repository/src/reference/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{Id, Reference};
88
pub mod iter;
99

1010
mod errors;
11-
12-
pub use errors::{edit, find, peel};
11+
pub use errors::{edit, find, head_id, peel};
1312

1413
use crate::ext::ObjectIdExt;
1514

git-repository/src/repository/reference.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,22 @@ impl crate::Repository {
184184
.attach(self))
185185
}
186186

187+
/// Resolve the head, follow and peel its target and obtain its object id.
188+
///
189+
/// Note that this may fail for various reasons, most notably because the repository
190+
/// is freshly initialized and doesn't have any commits yet.
191+
///
192+
/// Also note that the returned id is likely to point to a commit, but could also
193+
/// point to a tree or blob. It won't, however, point to a tag as these are always peeled.
194+
pub fn head_id(&self) -> Result<crate::Id<'_>, crate::reference::head_id::Error> {
195+
let mut head = self.head()?;
196+
head.peel_to_id_in_place()
197+
.ok_or_else(|| crate::reference::head_id::Error::Unborn {
198+
name: head.referent_name().expect("unborn").to_owned(),
199+
})?
200+
.map_err(Into::into)
201+
}
202+
187203
/// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`,
188204
/// or return an error if it wasn't found.
189205
///

git-repository/tests/easy/ext/object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ mod tag {
4545
#[test]
4646
fn simple() -> crate::Result {
4747
let (repo, _keep) = crate::repo_rw("make_basic_repo.sh")?;
48-
let current_head_id = repo.head()?.peeled()?.id().expect("born");
48+
let current_head_id = repo.head_id()?;
4949
let message = "a multi\nline message";
5050
let tag_ref = repo.tag(
5151
"v1.0.0",

0 commit comments

Comments
 (0)