History

Move lookup_entry, lookup_entry_by_path to TreeRefIter

Adapt functions to new context. This mostly means copying the implementation from `gix::types::Tree` and applying minor changes related to `buffer` being passed as an argument.

Christoph Rüßler committed 1 year ago

Commit 32632e91 parent 1c6e4ae2 files · +47 −42Browse files

Unified · Split

2 files
  1. gix-object/src/tree/ref_iter.rs +45 −40
  2. gix-object/tests/object/tree/iter.rs +2 −2
gix-object/src/tree/ref_iter.rs+45−40
@@ -11,39 +11,6 @@ impl<'a> TreeRefIter<'a> { · 10 unmodified lines
1111 pub fn from_bytes(data: &'a [u8]) -> TreeRefIter<'a> {
1212 TreeRefIter { data }
1313 }
14−}
15−
16−impl<'a> TreeRef<'a> {
17− /// Deserialize a Tree from `data`.
18− pub fn from_bytes(mut data: &'a [u8]) -> Result<TreeRef<'a>, crate::decode::Error> {
19− let input = &mut data;
20− match decode::tree.parse_next(input) {
21− Ok(tag) => Ok(tag),
22− Err(err) => Err(crate::decode::Error::with_err(err, input)),
23− }
24− }
25−
26− /// Find an entry named `name` knowing if the entry is a directory or not, using a binary search.
27− ///
28− /// Note that it's impossible to binary search by name alone as the sort order is special.
29− pub fn bisect_entry(&self, name: &BStr, is_dir: bool) -> Option<EntryRef<'a>> {
30− static NULL_HASH: gix_hash::ObjectId = gix_hash::Kind::shortest().null();
31−
32− let search = EntryRef {
33− mode: if is_dir {
34− tree::EntryKind::Tree
35− } else {
36− tree::EntryKind::Blob
37− }
38− .into(),
39− filename: name,
40− oid: &NULL_HASH,
41− };
42− self.entries
43− .binary_search_by(|e| e.cmp(&search))
44− .ok()
45− .map(|idx| self.entries[idx])
46− }
4714
4815 /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
4916 /// is looked up and its tree entry is returned.
@@ -64,19 +31,24 @@ impl<'a> TreeRef<'a> { · 14 unmodified lines
6431 I: IntoIterator<Item = P>,
6532 P: PartialEq<BStr>,
6633 {
67− let mut path = path.into_iter().peekable();
68− let mut entries = self.entries.clone();
34+ buffer.clear();
6935
36+ let mut path = path.into_iter().peekable();
37+ buffer.extend_from_slice(&self.data);
7038 while let Some(component) = path.next() {
71− match entries.iter().find(|entry| component.eq(entry.filename)) {
39+ match TreeRefIter::from_bytes(&buffer)
40+ .filter_map(Result::ok)
41+ .find(|entry| component.eq(entry.filename))
42+ {
7243 Some(entry) => {
7344 if path.peek().is_none() {
74− return Ok(Some((*entry).into()));
45+ return Ok(Some(entry.into()));
7546 } else {
7647 let next_id = entry.oid.to_owned();
77− let obj = odb.find_tree(&next_id, buffer)?;
78−
79− entries = obj.entries;
48+ let obj = odb.find(&next_id, buffer)?;
49+ if !obj.kind.is_tree() {
50+ return Ok(None);
51+ }
8052 }
8153 }
8254 None => return Ok(None),
@@ -108,6 +80,39 @@ impl<'a> TreeRef<'a> { · 25 unmodified lines
10880 }),
10981 )
11082 }
83+}
84+
85+impl<'a> TreeRef<'a> {
86+ /// Deserialize a Tree from `data`.
87+ pub fn from_bytes(mut data: &'a [u8]) -> Result<TreeRef<'a>, crate::decode::Error> {
88+ let input = &mut data;
89+ match decode::tree.parse_next(input) {
90+ Ok(tag) => Ok(tag),
91+ Err(err) => Err(crate::decode::Error::with_err(err, input)),
92+ }
93+ }
94+
95+ /// Find an entry named `name` knowing if the entry is a directory or not, using a binary search.
96+ ///
97+ /// Note that it's impossible to binary search by name alone as the sort order is special.
98+ pub fn bisect_entry(&self, name: &BStr, is_dir: bool) -> Option<EntryRef<'a>> {
99+ static NULL_HASH: gix_hash::ObjectId = gix_hash::Kind::shortest().null();
100+
101+ let search = EntryRef {
102+ mode: if is_dir {
103+ tree::EntryKind::Tree
104+ } else {
105+ tree::EntryKind::Blob
106+ }
107+ .into(),
108+ filename: name,
109+ oid: &NULL_HASH,
110+ };
111+ self.entries
112+ .binary_search_by(|e| e.cmp(&search))
113+ .ok()
114+ .map(|idx| self.entries[idx])
115+ }
111116
112117 /// Create an instance of the empty tree.
113118 ///
gix-object/tests/object/tree/iter.rs+2−2
@@ -64,7 +64,7 @@ fn lookup_entry_toplevel() -> crate::Result { · 63 unmodified lines
6464 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
6565
6666 let mut buf = Vec::new();
67− let root_tree = odb.find_tree(&root_tree_id, &mut buf)?;
67+ let root_tree = odb.find_tree_iter(&root_tree_id, &mut buf)?;
6868
6969 let mut buf = Vec::new();
7070 let entry = root_tree.lookup_entry_by_path(&odb, &mut buf, "bin").unwrap().unwrap();
@@ -81,7 +81,7 @@ fn lookup_entry_nested_path() -> crate::Result { · 10 unmodified lines
8181 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
8282
8383 let mut buf = Vec::new();
84− let root_tree = odb.find_tree(&root_tree_id, &mut buf)?;
84+ let root_tree = odb.find_tree_iter(&root_tree_id, &mut buf)?;
8585
8686 let mut buf = Vec::new();
8787 let entry = root_tree