Skip to content

Commit d7f4991

Browse files
committed
refactors
- return `EntryRef` - more structured tests
1 parent 54e399f commit d7f4991

File tree

2 files changed

+72
-62
lines changed

2 files changed

+72
-62
lines changed

gix-object/src/tree/ref_iter.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,36 @@ use winnow::{error::ParserError, prelude::*};
33

44
use crate::{tree, tree::EntryRef, TreeRef, TreeRefIter};
55

6-
/// The error type returned by the [`Tree`](crate::Tree) trait.
7-
pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
8-
96
impl<'a> TreeRefIter<'a> {
107
/// Instantiate an iterator from the given tree data.
118
pub fn from_bytes(data: &'a [u8]) -> TreeRefIter<'a> {
129
TreeRefIter { data }
1310
}
1411

15-
/// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
16-
/// is looked up and its tree entry is returned.
12+
/// Follow a sequence of `path` components starting from this instance, and look them up in `odb` one by one using `buffer`
13+
/// until the last component is looked up and its tree entry is returned.
1714
///
1815
/// # Performance Notes
1916
///
2017
/// Searching tree entries is currently done in sequence, which allows the search to be allocation free. It would be possible
2118
/// to reuse a vector and use a binary search instead, which might be able to improve performance over all.
2219
/// However, a benchmark should be created first to have some data and see which trade-off to choose here.
23-
///
2420
pub fn lookup_entry<I, P>(
2521
&self,
2622
odb: impl crate::Find,
2723
buffer: &'a mut Vec<u8>,
2824
path: I,
29-
) -> Result<Option<tree::Entry>, Error>
25+
) -> Result<Option<tree::Entry>, crate::find::Error>
3026
where
3127
I: IntoIterator<Item = P>,
3228
P: PartialEq<BStr>,
3329
{
3430
buffer.clear();
3531

3632
let mut path = path.into_iter().peekable();
37-
buffer.extend_from_slice(&self.data);
33+
buffer.extend_from_slice(self.data);
3834
while let Some(component) = path.next() {
39-
match TreeRefIter::from_bytes(&buffer)
35+
match TreeRefIter::from_bytes(buffer)
4036
.filter_map(Result::ok)
4137
.find(|entry| component.eq(entry.filename))
4238
{
@@ -46,10 +42,9 @@ impl<'a> TreeRefIter<'a> {
4642
} else {
4743
let next_id = entry.oid.to_owned();
4844
let obj = odb.try_find(&next_id, buffer)?;
49-
if let Some(obj) = obj {
50-
if !obj.kind.is_tree() {
51-
return Ok(None);
52-
}
45+
let Some(obj) = obj else { return Ok(None) };
46+
if !obj.kind.is_tree() {
47+
return Ok(None);
5348
}
5449
}
5550
}
@@ -59,7 +54,9 @@ impl<'a> TreeRefIter<'a> {
5954
Ok(None)
6055
}
6156

62-
/// Like [`Self::lookup_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.
57+
/// Like [`Self::lookup_entry()`], but takes any [`AsRef<Path>`](`std::path::Path`) directly via `relative_path`,
58+
/// a path relative to this tree.
59+
/// `odb` and `buffer` are used to lookup intermediate trees.
6360
///
6461
/// # Note
6562
///
@@ -70,7 +67,7 @@ impl<'a> TreeRefIter<'a> {
7067
odb: impl crate::Find,
7168
buffer: &'a mut Vec<u8>,
7269
relative_path: impl AsRef<std::path::Path>,
73-
) -> Result<Option<tree::Entry>, Error> {
70+
) -> Result<Option<tree::Entry>, crate::find::Error> {
7471
use crate::bstr::ByteSlice;
7572
self.lookup_entry(
7673
odb,

gix-object/tests/object/tree/iter.rs

+60-47
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use bstr::BString;
21
use gix_object::{
32
bstr::ByteSlice,
4-
tree::{self, Entry, EntryRef},
3+
tree::{self, EntryRef},
54
TreeRefIter,
65
};
76
use pretty_assertions::assert_eq;
@@ -59,59 +58,73 @@ fn everything() -> crate::Result {
5958
Ok(())
6059
}
6160

62-
#[test]
63-
fn lookup_entry_toplevel() -> crate::Result {
64-
let entry = utils::lookup_entry_by_path("bin")?;
65-
66-
let mode: tree::EntryMode = tree::EntryMode(33188);
67-
let filename: BString = "bin".into();
68-
let oid = hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
69-
70-
assert_eq!(entry, Some(Entry { mode, filename, oid }));
71-
72-
Ok(())
73-
}
74-
75-
#[test]
76-
fn lookup_entry_nested_path() -> crate::Result {
77-
let entry = utils::lookup_entry_by_path("file/a")?;
78-
79-
let mode: tree::EntryMode = tree::EntryMode(33188);
80-
let filename: BString = "a".into();
81-
let oid = hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
82-
83-
assert_eq!(entry, Some(Entry { mode, filename, oid }));
84-
85-
Ok(())
86-
}
61+
mod lookup_entry {
62+
use crate::hex_to_id;
63+
use gix_object::tree::EntryKind;
64+
use utils::entry;
65+
66+
#[test]
67+
fn top_level_directory() -> crate::Result {
68+
assert_eq!(
69+
utils::lookup_entry_by_path("bin")?,
70+
entry(
71+
"bin",
72+
EntryKind::Blob,
73+
hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
74+
)
75+
);
76+
Ok(())
77+
}
8778

88-
#[test]
89-
fn lookup_entry_that_does_not_exist() -> crate::Result {
90-
let entry = utils::lookup_entry_by_path("file/does-not-exist")?;
79+
#[test]
80+
fn nested_file() -> crate::Result {
81+
assert_eq!(
82+
utils::lookup_entry_by_path("file/a")?,
83+
entry(
84+
"a",
85+
EntryKind::Blob,
86+
hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
87+
)
88+
);
89+
Ok(())
90+
}
9191

92-
assert_eq!(entry, None);
92+
#[test]
93+
fn non_existing_nested_file() -> crate::Result {
94+
for path in ["file/does-not-exist", "non-existing", "file/a/through-file"] {
95+
let actual = utils::lookup_entry_by_path(path)?;
96+
assert_eq!(actual, None);
97+
}
98+
Ok(())
99+
}
93100

94-
Ok(())
95-
}
101+
mod utils {
102+
use crate::hex_to_id;
96103

97-
mod utils {
98-
use crate::hex_to_id;
104+
use gix_object::{tree, FindExt};
99105

100-
use gix_object::FindExt;
106+
pub(super) fn entry(filename: &str, mode: tree::EntryKind, oid: gix_hash::ObjectId) -> Option<tree::Entry> {
107+
Some(tree::Entry {
108+
mode: mode.into(),
109+
filename: filename.into(),
110+
oid,
111+
})
112+
}
101113

102-
pub(super) fn tree_odb() -> gix_testtools::Result<gix_odb::Handle> {
103-
let root = gix_testtools::scripted_fixture_read_only("make_trees.sh")?;
104-
Ok(gix_odb::at(root.join(".git/objects"))?)
105-
}
114+
pub(super) fn tree_odb() -> gix_testtools::Result<gix_odb::Handle> {
115+
let root = gix_testtools::scripted_fixture_read_only("make_trees.sh")?;
116+
Ok(gix_odb::at(root.join(".git/objects"))?)
117+
}
106118

107-
pub(super) fn lookup_entry_by_path(path: &str) -> gix_testtools::Result<Option<gix_object::tree::Entry>> {
108-
let odb = tree_odb()?;
109-
let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
119+
pub(super) fn lookup_entry_by_path(path: &str) -> gix_testtools::Result<Option<gix_object::tree::Entry>> {
120+
let odb = tree_odb()?;
121+
let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
110122

111-
let mut buf = Vec::new();
112-
let root_tree = odb.find_tree_iter(&root_tree_id, &mut buf)?;
123+
let mut buf = Vec::new();
124+
let root_tree = odb.find_tree_iter(&root_tree_id, &mut buf)?;
113125

114-
let mut buf = Vec::new();
115-
Ok(root_tree.lookup_entry_by_path(&odb, &mut buf, path).unwrap())
126+
let mut buf = Vec::new();
127+
root_tree.lookup_entry_by_path(&odb, &mut buf, path)
128+
}
116129
}
117130
}

0 commit comments

Comments
 (0)