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