History

feat: add Reference::peel_to_id_in_place_packed() and Reference::follow_packed() (#263)

This allows a stable/non-changing buffer to be used.

Sebastian Thiel committed 4 years ago

Commit 03bcac21 parent d3f92271 file · +54 −18Browse files

Unified · Split

git-ref/src/store/file/raw_ext.rs+54−18
@@ -3,7 +3,7 @@ use std::collections::BTreeSet; · 2 unmodified lines
33 use git_hash::ObjectId;
44
55 use crate::{
6− peel,
6+ packed, peel,
77 raw::Reference,
88 store_impl::{file, file::log},
99 Target,
@@ -27,11 +27,28 @@ pub trait ReferenceExt: Sealed { · 17 unmodified lines
2727 find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>,
2828 ) -> Result<ObjectId, peel::to_id::Error>;
2929
30+ /// For details, see [Reference::peel_to_id_in_place()], with support for a known stable packed buffer.
31+ fn peel_to_id_in_place_packed<E: std::error::Error + Send + Sync + 'static>(
32+ &mut self,
33+ store: &file::Store,
34+ find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>,
35+ packed: Option<&packed::Buffer>,
36+ ) -> Result<ObjectId, peel::to_id::Error>;
37+
38+ /// Follow this symbolic reference one level and return the ref it refers to.
39+ ///
40+ /// Returns `None` if this is not a symbolic reference, hence the leaf of the chain.
41+ fn follow(&self, store: &file::Store) -> Option<Result<Reference, file::find::existing::Error>>;
42+
3043 /// Follow this symbolic reference one level and return the ref it refers to,
3144 /// possibly providing access to `packed` references for lookup if it contains the referent.
3245 ///
3346 /// Returns `None` if this is not a symbolic reference, hence the leaf of the chain.
34− fn follow(&self, store: &file::Store) -> Option<Result<Reference, file::find::existing::Error>>;
47+ fn follow_packed(
48+ &self,
49+ store: &file::Store,
50+ packed: Option<&packed::Buffer>,
51+ ) -> Option<Result<Reference, file::find::existing::Error>>;
3552 }
3653
3754 impl ReferenceExt for Reference {
@@ -50,9 +67,21 @@ impl ReferenceExt for Reference { · 12 unmodified lines
5067 }
5168
5269 fn peel_to_id_in_place<E: std::error::Error + Send + Sync + 'static>(
70+ &mut self,
71+ store: &file::Store,
72+ find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>,
73+ ) -> Result<ObjectId, peel::to_id::Error> {
74+ let packed = store.assure_packed_refs_uptodate().map_err(|err| {
75+ peel::to_id::Error::Follow(file::find::existing::Error::Find(file::find::Error::PackedOpen(err)))
76+ })?;
77+ self.peel_to_id_in_place_packed(store, find, packed.as_deref())
78+ }
79+
80+ fn peel_to_id_in_place_packed<E: std::error::Error + Send + Sync + 'static>(
5381 &mut self,
5482 store: &file::Store,
5583 mut find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>,
84+ packed: Option<&packed::Buffer>,
5685 ) -> Result<ObjectId, peel::to_id::Error> {
5786 match self.peeled {
5887 Some(peeled) => {
@@ -63,7 +92,7 @@ impl ReferenceExt for Reference { · 4 unmodified lines
6392 if self.target.kind() == crate::Kind::Symbolic {
6493 let mut seen = BTreeSet::new();
6594 let cursor = &mut *self;
66− while let Some(next) = cursor.follow(store) {
95+ while let Some(next) = cursor.follow_packed(store, packed) {
6796 let next = next?;
6897 if seen.contains(&next.name) {
6998 return Err(peel::to_id::Error::Cycle(store.base.join(cursor.name.to_path())));
@@ -107,6 +136,21 @@ impl ReferenceExt for Reference { · 37 unmodified lines
107136 }
108137
109138 fn follow(&self, store: &file::Store) -> Option<Result<Reference, file::find::existing::Error>> {
139+ let packed = match store
140+ .assure_packed_refs_uptodate()
141+ .map_err(|err| file::find::existing::Error::Find(file::find::Error::PackedOpen(err)))
142+ {
143+ Ok(packed) => packed,
144+ Err(err) => return Some(Err(err)),
145+ };
146+ self.follow_packed(store, packed.as_deref())
147+ }
148+
149+ fn follow_packed(
150+ &self,
151+ store: &file::Store,
152+ packed: Option<&packed::Buffer>,
153+ ) -> Option<Result<Reference, file::find::existing::Error>> {
110154 match self.peeled {
111155 Some(peeled) => Some(Ok(Reference {
112156 name: self.name.clone(),
@@ -115,21 +159,13 @@ impl ReferenceExt for Reference { · 2 unmodified lines
115159 })),
116160 None => match &self.target {
117161 Target::Peeled(_) => None,
118− Target::Symbolic(full_name) => {
119− let path = full_name.to_path();
120− let packed = match store
121− .assure_packed_refs_uptodate()
122− .map_err(|err| file::find::existing::Error::Find(file::find::Error::PackedOpen(err)))
123− {
124− Ok(packed) => packed,
125− Err(err) => return Some(Err(err)),
126− };
127− match store.find_one_with_verified_input(path.as_ref(), packed.as_deref()) {
128− Ok(Some(next)) => Some(Ok(next)),
129− Ok(None) => Some(Err(file::find::existing::Error::NotFound(path.into_owned()))),
130− Err(err) => Some(Err(file::find::existing::Error::Find(err))),
131− }
132− }
162+ Target::Symbolic(full_name) => match store.try_find_packed(full_name.to_partial(), packed) {
163+ Ok(Some(next)) => Some(Ok(next)),
164+ Ok(None) => Some(Err(file::find::existing::Error::NotFound(
165+ full_name.to_path().into_owned(),
166+ ))),
167+ Err(err) => Some(Err(file::find::existing::Error::Find(err))),
168+ },
133169 },
134170 }
135171 }