This allows a stable/non-changing buffer to be used.
Unified · Split
| @@ -3,7 +3,7 @@ use std::collections::BTreeSet; · 2 unmodified lines | ||
| 3 | 3 | use git_hash::ObjectId; |
| 4 | 4 | |
| 5 | 5 | use crate::{ |
| 6 | − peel, | |
| 6 | + packed, peel, | |
| 7 | 7 | raw::Reference, |
| 8 | 8 | store_impl::{file, file::log}, |
| 9 | 9 | Target, |
| @@ -27,11 +27,28 @@ pub trait ReferenceExt: Sealed { · 17 unmodified lines | ||
| 27 | 27 | find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>, |
| 28 | 28 | ) -> Result<ObjectId, peel::to_id::Error>; |
| 29 | 29 | |
| 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 | + | |
| 30 | 43 | /// Follow this symbolic reference one level and return the ref it refers to, |
| 31 | 44 | /// possibly providing access to `packed` references for lookup if it contains the referent. |
| 32 | 45 | /// |
| 33 | 46 | /// 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>>; | |
| 35 | 52 | } |
| 36 | 53 | |
| 37 | 54 | impl ReferenceExt for Reference { |
| @@ -50,9 +67,21 @@ impl ReferenceExt for Reference { · 12 unmodified lines | ||
| 50 | 67 | } |
| 51 | 68 | |
| 52 | 69 | 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>( | |
| 53 | 81 | &mut self, |
| 54 | 82 | store: &file::Store, |
| 55 | 83 | mut find: impl FnMut(git_hash::ObjectId, &mut Vec<u8>) -> Result<Option<(git_object::Kind, &[u8])>, E>, |
| 84 | + packed: Option<&packed::Buffer>, | |
| 56 | 85 | ) -> Result<ObjectId, peel::to_id::Error> { |
| 57 | 86 | match self.peeled { |
| 58 | 87 | Some(peeled) => { |
| @@ -63,7 +92,7 @@ impl ReferenceExt for Reference { · 4 unmodified lines | ||
| 63 | 92 | if self.target.kind() == crate::Kind::Symbolic { |
| 64 | 93 | let mut seen = BTreeSet::new(); |
| 65 | 94 | let cursor = &mut *self; |
| 66 | − while let Some(next) = cursor.follow(store) { | |
| 95 | + while let Some(next) = cursor.follow_packed(store, packed) { | |
| 67 | 96 | let next = next?; |
| 68 | 97 | if seen.contains(&next.name) { |
| 69 | 98 | 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 | ||
| 107 | 136 | } |
| 108 | 137 | |
| 109 | 138 | 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>> { | |
| 110 | 154 | match self.peeled { |
| 111 | 155 | Some(peeled) => Some(Ok(Reference { |
| 112 | 156 | name: self.name.clone(), |
| @@ -115,21 +159,13 @@ impl ReferenceExt for Reference { · 2 unmodified lines | ||
| 115 | 159 | })), |
| 116 | 160 | None => match &self.target { |
| 117 | 161 | 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 | + }, | |
| 133 | 169 | }, |
| 134 | 170 | } |
| 135 | 171 | } |