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
11 pub fn from_bytes(data: &'a [u8]) -> TreeRefIter<'a> {11 pub fn from_bytes(data: &'a [u8]) -> TreeRefIter<'a> {
12 TreeRefIter { data }12 TreeRefIter { data }
13 }13 }
14}
15
16impl<'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 }
47 14
48 /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component15 /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
49 /// is looked up and its tree entry is returned.16 /// is looked up and its tree entry is returned.
@@ -64,19 +31,24 @@ impl<'a> TreeRef<'a> { · 14 unmodified lines
64 I: IntoIterator<Item = P>,31 I: IntoIterator<Item = P>,
65 P: PartialEq<BStr>,32 P: PartialEq<BStr>,
66 {33 {
67 let mut path = path.into_iter().peekable();34 buffer.clear();
68 let mut entries = self.entries.clone();
69 35
36 let mut path = path.into_iter().peekable();
37 buffer.extend_from_slice(&self.data);
70 while let Some(component) = path.next() {38 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 {
72 Some(entry) => {43 Some(entry) => {
73 if path.peek().is_none() {44 if path.peek().is_none() {
74 return Ok(Some((*entry).into()));45 return Ok(Some(entry.into()));
75 } else {46 } else {
76 let next_id = entry.oid.to_owned();47 let next_id = entry.oid.to_owned();
77 let obj = odb.find_tree(&next_id, buffer)?;48 let obj = odb.find(&next_id, buffer)?;
78 49 if !obj.kind.is_tree() {
79 entries = obj.entries;50 return Ok(None);
51 }
80 }52 }
81 }53 }
82 None => return Ok(None),54 None => return Ok(None),
@@ -108,6 +80,39 @@ impl<'a> TreeRef<'a> { · 25 unmodified lines
108 }),80 }),
109 )81 )
110 }82 }
83}
84
85impl<'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 }
111 116
112 /// Create an instance of the empty tree.117 /// Create an instance of the empty tree.
113 ///118 ///
gix-object/tests/object/tree/iter.rs+2−2
@@ -64,7 +64,7 @@ fn lookup_entry_toplevel() -> crate::Result { · 63 unmodified lines
64 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");64 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
65 65
66 let mut buf = Vec::new();66 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)?;
68 68
69 let mut buf = Vec::new();69 let mut buf = Vec::new();
70 let entry = root_tree.lookup_entry_by_path(&odb, &mut buf, "bin").unwrap().unwrap();70 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
81 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");81 let root_tree_id = hex_to_id("ff7e7d2aecae1c3fb15054b289a4c58aa65b8646");
82 82
83 let mut buf = Vec::new();83 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)?;
85 85
86 let mut buf = Vec::new();86 let mut buf = Vec::new();
87 let entry = root_tree87 let entry = root_tree