Skip to content

Commit

Permalink
feat: add Repository::head_tree() to more easily obtain the current…
Browse files Browse the repository at this point in the history
… tree.
  • Loading branch information
Byron committed Oct 12, 2023
1 parent 787a9aa commit c79a7da
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 13 deletions.
4 changes: 4 additions & 0 deletions gix/src/head/peel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ impl<'repo> Head<'repo> {
}

// TODO: tests
// TODO: Fix this! It's not consistently peeling tags. The whole peeling business should be reconsidered to do what people usually
// want which is to peel references, if present, and then peel objects with control over which object type to end at.
// Finding a good interface for that isn't easy as ideally, it's an iterator that shows the intermediate objects so the user
// can select which tag of a chain to choose.
/// 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.
///
Expand Down
23 changes: 19 additions & 4 deletions gix/src/reference/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ pub mod edit {

///
pub mod peel {
/// The error returned by [`Reference::peel_to_id_in_place(…)`][crate::Reference::peel_to_id_in_place()] and
/// [`Reference::into_fully_peeled_id(…)`][crate::Reference::into_fully_peeled_id()].
/// The error returned by [`Reference::peel_to_id_in_place(…)`](crate::Reference::peel_to_id_in_place()) and
/// [`Reference::into_fully_peeled_id(…)`](crate::Reference::into_fully_peeled_id()).
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
Expand All @@ -36,7 +36,7 @@ pub mod peel {

///
pub mod head_id {
/// The error returned by [`Repository::head_id(…)`][crate::Repository::head_id()].
/// The error returned by [`Repository::head_id(…)`](crate::Repository::head_id()).
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
Expand All @@ -51,7 +51,7 @@ pub mod head_id {

///
pub mod head_commit {
/// The error returned by [`Repository::head_commit`(…)][crate::Repository::head_commit()].
/// The error returned by [`Repository::head_commit`(…)](crate::Repository::head_commit()).
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
Expand All @@ -62,6 +62,21 @@ pub mod head_commit {
}
}

///
pub mod head_tree_id {
/// The error returned by [`Repository::head_tree_id`(…)](crate::Repository::head_tree_id()).
#[derive(Debug, thiserror::Error)]
#[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),
#[error(transparent)]
DecodeCommit(#[from] gix_object::decode::Error),
}
}

///
pub mod find {
///
Expand Down
2 changes: 1 addition & 1 deletion gix/src/reference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub mod iter;
pub mod remote;

mod errors;
pub use errors::{edit, find, head_commit, head_id, peel};
pub use errors::{edit, find, head_commit, head_id, head_tree_id, peel};

use crate::ext::ObjectIdExt;

Expand Down
1 change: 1 addition & 0 deletions gix/src/repository/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl crate::Repository {
}

/// Return the work tree containing all checked out files, if there is one.
#[doc(alias = "workdir", alias = "git2")]
pub fn work_dir(&self) -> Option<&std::path::Path> {
self.work_tree.as_deref()
}
Expand Down
9 changes: 9 additions & 0 deletions gix/src/repository/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ impl crate::Repository {
Ok(self.head()?.peel_to_commit_in_place()?)
}

/// Return the tree id the `HEAD` reference currently points to after peeling it fully.
///
/// Note that this may fail for various reasons, most notably because the 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<crate::Id<'_>, reference::head_tree_id::Error> {
Ok(self.head()?.peel_to_commit_in_place()?.tree_id()?)
}

/// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`,
/// or return an error if it wasn't found.
///
Expand Down
5 changes: 5 additions & 0 deletions gix/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct Id<'r> {
}

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

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

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

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

/// A decoded commit object with access to its owning repository.
#[derive(Clone)]
pub struct Commit<'repo> {
/// The id of the commit
pub id: ObjectId,
Expand Down
17 changes: 9 additions & 8 deletions gix/tests/object/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ fn short_id() -> crate::Result {
#[test]
fn tree() -> crate::Result {
let repo = basic_repo()?;
let commit = repo.head_commit()?;

let tree = commit.tree()?;
assert_eq!(tree.id, commit.tree_id().expect("id present"));
let tree_id = repo.head_tree_id()?;
assert_eq!(tree_id, hex_to_id("21d3ba9a26b790a4858d67754ae05d04dfce4d0c"));

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

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

0 comments on commit c79a7da

Please sign in to comment.