Skip to content

Commit d121fe7

Browse files
cruesslerByron
authored andcommitted
Add lookup_entry, lookup_entry_by_path to TreeRef
1 parent e8b3b41 commit d121fe7

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gix-object/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ gix-hashtable = { version = "^0.6.0", path = "../gix-hashtable" }
5050
gix-validate = { version = "^0.9.2", path = "../gix-validate" }
5151
gix-actor = { version = "^0.33.1", path = "../gix-actor" }
5252
gix-date = { version = "^0.9.2", path = "../gix-date" }
53+
gix-path = { version = "^0.10.12", path = "../gix-path" }
5354
gix-utils = { version = "^0.1.13", path = "../gix-utils" }
5455

5556
itoa = "1.0.1"

gix-object/src/tree/ref_iter.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,52 @@ impl<'a> TreeRef<'a> {
4242
.map(|idx| self.entries[idx])
4343
}
4444

45+
/// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
46+
/// is looked up and its tree entry is returned.
47+
///
48+
/// # Performance Notes
49+
///
50+
/// Searching tree entries is currently done in sequence, which allows to the search to be allocation free. It would be possible
51+
/// to reuse a vector and use a binary search instead, which might be able to improve performance over all.
52+
/// However, a benchmark should be created first to have some data and see which trade-off to choose here.
53+
///
54+
pub fn lookup_entry<I, P>(&self, path: I) -> Option<EntryRef<'a>>
55+
where
56+
I: IntoIterator<Item = P>,
57+
P: PartialEq<BStr>,
58+
{
59+
let mut path = path.into_iter().peekable();
60+
61+
while let Some(component) = path.next() {
62+
match self.entries.iter().find(|entry| component.eq(entry.filename)) {
63+
Some(entry) => {
64+
if path.peek().is_none() {
65+
return Some(*entry);
66+
} else if !entry.mode.is_tree() {
67+
return None;
68+
}
69+
}
70+
None => return None,
71+
}
72+
}
73+
None
74+
}
75+
76+
/// Like [`Self::lookup_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.
77+
///
78+
/// # Note
79+
///
80+
/// If any path component contains illformed UTF-8 and thus can't be converted to bytes on platforms which can't do so natively,
81+
/// the returned component will be empty which makes the lookup fail.
82+
pub fn lookup_entry_by_path(&self, relative_path: impl AsRef<std::path::Path>) -> Option<EntryRef<'a>> {
83+
use crate::bstr::ByteSlice;
84+
self.lookup_entry(relative_path.as_ref().components().map(|c: std::path::Component<'_>| {
85+
gix_path::os_str_into_bstr(c.as_os_str())
86+
.unwrap_or_else(|_| "".into())
87+
.as_bytes()
88+
}))
89+
}
90+
4591
/// Create an instance of the empty tree.
4692
///
4793
/// It's particularly useful as static part of a program.

0 commit comments

Comments
 (0)