Skip to content

Commit c79a7da

Browse files
committed
feat: add Repository::head_tree() to more easily obtain the current tree.
1 parent 787a9aa commit c79a7da

File tree

7 files changed

+48
-13
lines changed

7 files changed

+48
-13
lines changed

gix/src/head/peel.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ impl<'repo> Head<'repo> {
4747
}
4848

4949
// TODO: tests
50+
// TODO: Fix this! It's not consistently peeling tags. The whole peeling business should be reconsidered to do what people usually
51+
// want which is to peel references, if present, and then peel objects with control over which object type to end at.
52+
// Finding a good interface for that isn't easy as ideally, it's an iterator that shows the intermediate objects so the user
53+
// can select which tag of a chain to choose.
5054
/// Follow the symbolic reference of this head until its target object and peel it by following tag objects until there is no
5155
/// more object to follow, and return that object id.
5256
///

gix/src/reference/errors.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ pub mod edit {
2222

2323
///
2424
pub mod peel {
25-
/// The error returned by [`Reference::peel_to_id_in_place(…)`][crate::Reference::peel_to_id_in_place()] and
26-
/// [`Reference::into_fully_peeled_id(…)`][crate::Reference::into_fully_peeled_id()].
25+
/// The error returned by [`Reference::peel_to_id_in_place(…)`](crate::Reference::peel_to_id_in_place()) and
26+
/// [`Reference::into_fully_peeled_id(…)`](crate::Reference::into_fully_peeled_id()).
2727
#[derive(Debug, thiserror::Error)]
2828
#[allow(missing_docs)]
2929
pub enum Error {
@@ -36,7 +36,7 @@ pub mod peel {
3636

3737
///
3838
pub mod head_id {
39-
/// The error returned by [`Repository::head_id(…)`][crate::Repository::head_id()].
39+
/// The error returned by [`Repository::head_id(…)`](crate::Repository::head_id()).
4040
#[derive(Debug, thiserror::Error)]
4141
#[allow(missing_docs)]
4242
pub enum Error {
@@ -51,7 +51,7 @@ pub mod head_id {
5151

5252
///
5353
pub mod head_commit {
54-
/// The error returned by [`Repository::head_commit`(…)][crate::Repository::head_commit()].
54+
/// The error returned by [`Repository::head_commit`(…)](crate::Repository::head_commit()).
5555
#[derive(Debug, thiserror::Error)]
5656
#[allow(missing_docs)]
5757
pub enum Error {
@@ -62,6 +62,21 @@ pub mod head_commit {
6262
}
6363
}
6464

65+
///
66+
pub mod head_tree_id {
67+
/// The error returned by [`Repository::head_tree_id`(…)](crate::Repository::head_tree_id()).
68+
#[derive(Debug, thiserror::Error)]
69+
#[allow(missing_docs)]
70+
pub enum Error {
71+
#[error(transparent)]
72+
Head(#[from] crate::reference::find::existing::Error),
73+
#[error(transparent)]
74+
PeelToCommit(#[from] crate::head::peel::to_commit::Error),
75+
#[error(transparent)]
76+
DecodeCommit(#[from] gix_object::decode::Error),
77+
}
78+
}
79+
6580
///
6681
pub mod find {
6782
///

gix/src/reference/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub mod iter;
1010
pub mod remote;
1111

1212
mod errors;
13-
pub use errors::{edit, find, head_commit, head_id, peel};
13+
pub use errors::{edit, find, head_commit, head_id, head_tree_id, peel};
1414

1515
use crate::ext::ObjectIdExt;
1616

gix/src/repository/location.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ impl crate::Repository {
3737
}
3838

3939
/// Return the work tree containing all checked out files, if there is one.
40+
#[doc(alias = "workdir", alias = "git2")]
4041
pub fn work_dir(&self) -> Option<&std::path::Path> {
4142
self.work_tree.as_deref()
4243
}

gix/src/repository/reference.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,15 @@ impl crate::Repository {
212212
Ok(self.head()?.peel_to_commit_in_place()?)
213213
}
214214

215+
/// Return the tree id the `HEAD` reference currently points to after peeling it fully.
216+
///
217+
/// Note that this may fail for various reasons, most notably because the repository
218+
/// is freshly initialized and doesn't have any commits yet. It could also fail if the
219+
/// head does not point to a commit.
220+
pub fn head_tree_id(&self) -> Result<crate::Id<'_>, reference::head_tree_id::Error> {
221+
Ok(self.head()?.peel_to_commit_in_place()?.tree_id()?)
222+
}
223+
215224
/// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`,
216225
/// or return an error if it wasn't found.
217226
///

gix/src/types.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct Id<'r> {
3131
}
3232

3333
/// A decoded object with a reference to its owning repository.
34+
#[derive(Clone)]
3435
pub struct Object<'repo> {
3536
/// The id of the object
3637
pub id: ObjectId,
@@ -48,6 +49,7 @@ impl<'a> Drop for Object<'a> {
4849
}
4950

5051
/// A blob along with access to its owning repository.
52+
#[derive(Clone)]
5153
pub struct Blob<'repo> {
5254
/// The id of the tree
5355
pub id: ObjectId,
@@ -63,6 +65,7 @@ impl<'a> Drop for Blob<'a> {
6365
}
6466

6567
/// A decoded tree object with access to its owning repository.
68+
#[derive(Clone)]
6669
pub struct Tree<'repo> {
6770
/// The id of the tree
6871
pub id: ObjectId,
@@ -78,6 +81,7 @@ impl<'a> Drop for Tree<'a> {
7881
}
7982

8083
/// A decoded tag object with access to its owning repository.
84+
#[derive(Clone)]
8185
pub struct Tag<'repo> {
8286
/// The id of the tree
8387
pub id: ObjectId,
@@ -93,6 +97,7 @@ impl<'a> Drop for Tag<'a> {
9397
}
9498

9599
/// A decoded commit object with access to its owning repository.
100+
#[derive(Clone)]
96101
pub struct Commit<'repo> {
97102
/// The id of the commit
98103
pub id: ObjectId,

gix/tests/object/commit.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ fn short_id() -> crate::Result {
1818
#[test]
1919
fn tree() -> crate::Result {
2020
let repo = basic_repo()?;
21-
let commit = repo.head_commit()?;
22-
23-
let tree = commit.tree()?;
24-
assert_eq!(tree.id, commit.tree_id().expect("id present"));
21+
let tree_id = repo.head_tree_id()?;
22+
assert_eq!(tree_id, hex_to_id("21d3ba9a26b790a4858d67754ae05d04dfce4d0c"));
2523

26-
// It's possible to convert a `gix::Tree` into a lower-level tree modify it.
27-
let _modififyable_tree: gix::objs::Tree = tree.try_into()?;
24+
let tree = tree_id.object()?.into_tree();
25+
assert_eq!(tree.id, tree_id);
2826

27+
// It's possible to convert a `gix::Tree` into a lower-level tree and modify it.
28+
let _modififyable_tree: gix::objs::Tree = tree.clone().try_into()?;
2929
assert_eq!(
30-
commit.tree_id().ok().map(gix::Id::detach),
31-
Some(hex_to_id("21d3ba9a26b790a4858d67754ae05d04dfce4d0c"))
30+
_modififyable_tree,
31+
tree.decode()?.into(),
32+
"try_from and decode() yield the same object"
3233
);
3334
Ok(())
3435
}

0 commit comments

Comments
 (0)