History

fix!: `Tree::lookup_entry()` looses its `buf` argument.

The buffer will now be previded from the free-list of the repository.

Sebastian Thiel committed 2 years ago

Commit c545d711 parent a10e7c23 files · +13 −21Browse files

Unified · Split

3 files
  1. gix/src/object/tree/mod.rs +11 −14
  2. gix/src/repository/object.rs +1 −1
  3. gix/tests/object/tree/mod.rs +1 −6
gix/src/object/tree/mod.rs+11−14
@@ -41,7 +41,6 @@ impl<'repo> Tree<'repo> { · 40 unmodified lines
41 41
42 /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component42 /// Follow a sequence of `path` components starting from this instance, and look them up one by one until the last component
43 /// is looked up and its tree entry is returned.43 /// is looked up and its tree entry is returned.
44 /// Use `buf` as temporary location for sub-trees to avoid allocating a temporary buffer for each lookup.
45 ///44 ///
46 /// # Performance Notes45 /// # Performance Notes
47 ///46 ///
@@ -49,16 +48,18 @@ impl<'repo> Tree<'repo> { · 1 unmodified line
49 /// to reuse a vector and use a binary search instead, which might be able to improve performance over all.48 /// to reuse a vector and use a binary search instead, which might be able to improve performance over all.
50 /// However, a benchmark should be created first to have some data and see which trade-off to choose here.49 /// However, a benchmark should be created first to have some data and see which trade-off to choose here.
51 ///50 ///
52 pub fn lookup_entry<I, P>(&self, path: I, buf: &mut Vec<u8>) -> Result<Option<Entry<'repo>>, find::existing::Error>51 pub fn lookup_entry<I, P>(&self, path: I) -> Result<Option<Entry<'repo>>, find::existing::Error>
53 where52 where
54 I: IntoIterator<Item = P>,53 I: IntoIterator<Item = P>,
55 P: PartialEq<BStr>,54 P: PartialEq<BStr>,
56 {55 {
57 let mut path = path.into_iter().peekable();56 let mut buf = self.repo.shared_empty_buf();
58 buf.clear();57 buf.clear();
58
59 let mut path = path.into_iter().peekable();
59 buf.extend_from_slice(&self.data);60 buf.extend_from_slice(&self.data);
60 while let Some(component) = path.next() {61 while let Some(component) = path.next() {
61 match TreeRefIter::from_bytes(buf)62 match TreeRefIter::from_bytes(&buf)
62 .filter_map(Result::ok)63 .filter_map(Result::ok)
63 .find(|entry| component.eq(entry.filename))64 .find(|entry| component.eq(entry.filename))
64 {65 {
@@ -70,7 +71,7 @@ impl<'repo> Tree<'repo> { · 5 unmodified lines
70 }));71 }));
71 } else {72 } else {
72 let next_id = entry.oid.to_owned();73 let next_id = entry.oid.to_owned();
73 let obj = self.repo.objects.find(&next_id, buf)?;74 let obj = self.repo.objects.find(&next_id, &mut buf)?;
74 if !obj.kind.is_tree() {75 if !obj.kind.is_tree() {
75 return Ok(None);76 return Ok(None);
76 }77 }
@@ -134,17 +135,13 @@ impl<'repo> Tree<'repo> { · 57 unmodified lines
134 pub fn lookup_entry_by_path(135 pub fn lookup_entry_by_path(
135 &self,136 &self,
136 relative_path: impl AsRef<std::path::Path>,137 relative_path: impl AsRef<std::path::Path>,
137 buf: &mut Vec<u8>,
138 ) -> Result<Option<Entry<'repo>>, find::existing::Error> {138 ) -> Result<Option<Entry<'repo>>, find::existing::Error> {
139 use crate::bstr::ByteSlice;139 use crate::bstr::ByteSlice;
140 self.lookup_entry(140 self.lookup_entry(relative_path.as_ref().components().map(|c: std::path::Component<'_>| {
141 relative_path.as_ref().components().map(|c: std::path::Component<'_>| {141 gix_path::os_str_into_bstr(c.as_os_str())
142 gix_path::os_str_into_bstr(c.as_os_str())142 .unwrap_or_else(|_| "".into())
143 .unwrap_or_else(|_| "".into())143 .as_bytes()
144 .as_bytes()144 }))
145 }),
146 buf,
147 )
148 }145 }
149 146
150 /// Like [`Self::peel_to_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.147 /// Like [`Self::peel_to_entry()`], but takes a `Path` directly via `relative_path`, a path relative to this tree.
gix/src/repository/object.rs+1−1
@@ -139,7 +139,7 @@ impl crate::Repository { · 138 unmodified lines
139 }139 }
140 }140 }
141 141
142 fn shared_empty_buf(&self) -> std::cell::RefMut<'_, Vec<u8>> {142 pub(crate) fn shared_empty_buf(&self) -> std::cell::RefMut<'_, Vec<u8>> {
143 let mut bufs = self.bufs.borrow_mut();143 let mut bufs = self.bufs.borrow_mut();
144 if bufs.last().is_none() {144 if bufs.last().is_none() {
145 bufs.push(Vec::with_capacity(512));145 bufs.push(Vec::with_capacity(512));
gix/tests/object/tree/mod.rs+1−6
@@ -17,11 +17,6 @@ fn find_entry() -> crate::Result { · 16 unmodified lines
17fn lookup_entry_by_path() -> crate::Result {17fn lookup_entry_by_path() -> crate::Result {
18 let repo = named_subrepo_opts("make_worktree_repo.sh", "repo", gix::open::Options::isolated())?;18 let repo = named_subrepo_opts("make_worktree_repo.sh", "repo", gix::open::Options::isolated())?;
19 let tree = repo.head_commit()?.tree()?;19 let tree = repo.head_commit()?.tree()?;
20 assert_eq!(20 assert_eq!(tree.lookup_entry_by_path("dir/c")?.expect("present").filename(), "c");
21 tree.lookup_entry_by_path("dir/c", &mut Vec::new())?
22 .expect("present")
23 .filename(),
24 "c"
25 );
26 Ok(())21 Ok(())
27}22}