Skip to content

Commit d6e7201

Browse files
committed
change!: Use gix-object::Find trait
1 parent 2637f8f commit d6e7201

File tree

10 files changed

+190
-167
lines changed

10 files changed

+190
-167
lines changed

gix-pack/src/bundle/write/mod.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ pub use types::{Options, Outcome};
2121

2222
use crate::bundle::write::types::SharedTempFile;
2323

24-
type ThinPackLookupFn = Box<dyn for<'a> FnMut(gix_hash::ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>>;
25-
type ThinPackLookupFnSend =
26-
Box<dyn for<'a> FnMut(gix_hash::ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>> + Send + 'static>;
27-
2824
/// The progress ids used in [`write_to_directory()`][crate::Bundle::write_to_directory()].
2925
///
3026
/// Use this information to selectively extract the progress of interest in case the parent application has custom visualization.
@@ -54,7 +50,7 @@ impl crate::Bundle {
5450
///
5551
/// * `progress` provides detailed progress information which can be discarded with [`gix_features::progress::Discard`].
5652
/// * `should_interrupt` is checked regularly and when true, the whole operation will stop.
57-
/// * `thin_pack_base_object_lookup_fn` If set, we expect to see a thin-pack with objects that reference their base object by object id which is
53+
/// * `thin_pack_base_object_lookup` If set, we expect to see a thin-pack with objects that reference their base object by object id which is
5854
/// expected to exist in the object database the bundle is contained within.
5955
/// `options` further configure how the task is performed.
6056
///
@@ -68,7 +64,7 @@ impl crate::Bundle {
6864
directory: Option<&Path>,
6965
progress: &mut dyn DynNestedProgress,
7066
should_interrupt: &AtomicBool,
71-
thin_pack_base_object_lookup_fn: Option<ThinPackLookupFn>,
67+
thin_pack_base_object_lookup: Option<impl gix_object::Find>,
7268
options: Options,
7369
) -> Result<Outcome, Error> {
7470
let _span = gix_features::trace::coarse!("gix_pack::Bundle::write_to_directory()");
@@ -90,8 +86,8 @@ impl crate::Bundle {
9086
let (pack_entries_iter, pack_version): (
9187
Box<dyn Iterator<Item = Result<data::input::Entry, data::input::Error>>>,
9288
_,
93-
) = match thin_pack_base_object_lookup_fn {
94-
Some(thin_pack_lookup_fn) => {
89+
) = match thin_pack_base_object_lookup {
90+
Some(thin_pack_lookup) => {
9591
let pack = interrupt::Read {
9692
inner: pack,
9793
should_interrupt,
@@ -104,7 +100,7 @@ impl crate::Bundle {
104100
data::input::EntryDataMode::KeepAndCrc32,
105101
object_hash,
106102
)?,
107-
thin_pack_lookup_fn,
103+
thin_pack_lookup,
108104
);
109105
let pack_version = pack_entries_iter.inner.version();
110106
let pack_entries_iter = data::input::EntriesToBytesIter::new(
@@ -178,7 +174,7 @@ impl crate::Bundle {
178174
directory: Option<impl AsRef<Path>>,
179175
progress: &mut dyn DynNestedProgress,
180176
should_interrupt: &'static AtomicBool,
181-
thin_pack_base_object_lookup_fn: Option<ThinPackLookupFnSend>,
177+
thin_pack_base_object_lookup: Option<impl gix_object::Find + Send + 'static>,
182178
options: Options,
183179
) -> Result<Outcome, Error> {
184180
let _span = gix_features::trace::coarse!("gix_pack::Bundle::write_to_directory_eagerly()");
@@ -198,8 +194,8 @@ impl crate::Bundle {
198194
let (pack_entries_iter, pack_version): (
199195
Box<dyn Iterator<Item = Result<data::input::Entry, data::input::Error>> + Send + 'static>,
200196
_,
201-
) = match thin_pack_base_object_lookup_fn {
202-
Some(thin_pack_lookup_fn) => {
197+
) = match thin_pack_base_object_lookup {
198+
Some(thin_pack_lookup) => {
203199
let pack = interrupt::Read {
204200
inner: pack,
205201
should_interrupt,
@@ -212,7 +208,7 @@ impl crate::Bundle {
212208
data::input::EntryDataMode::KeepAndCrc32,
213209
object_hash,
214210
)?,
215-
thin_pack_lookup_fn,
211+
thin_pack_lookup,
216212
);
217213
let pack_kind = pack_entries_iter.inner.version();
218214
(Box::new(pack_entries_iter), pack_kind)

gix-pack/src/data/input/lookup_ref_delta_objects.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use gix_hash::ObjectId;
55
use crate::data::{entry::Header, input};
66

77
/// An iterator to resolve thin packs on the fly.
8-
pub struct LookupRefDeltaObjectsIter<I, LFn> {
8+
pub struct LookupRefDeltaObjectsIter<I, Find> {
99
/// The inner iterator whose entries we will resolve.
1010
pub inner: I,
11-
lookup: LFn,
11+
lookup: Find,
1212
/// The cached delta to provide next time we are called, it's the delta to go with the base we just resolved in its place.
1313
next_delta: Option<input::Entry>,
1414
/// Fuse to stop iteration after first missing object.
@@ -21,14 +21,14 @@ pub struct LookupRefDeltaObjectsIter<I, LFn> {
2121
buf: Vec<u8>,
2222
}
2323

24-
impl<I, LFn> LookupRefDeltaObjectsIter<I, LFn>
24+
impl<I, Find> LookupRefDeltaObjectsIter<I, Find>
2525
where
2626
I: Iterator<Item = Result<input::Entry, input::Error>>,
27-
LFn: for<'a> FnMut(ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>,
27+
Find: gix_object::Find,
2828
{
2929
/// Create a new instance wrapping `iter` and using `lookup` as function to retrieve objects that will serve as bases
3030
/// for ref deltas seen while traversing `iter`.
31-
pub fn new(iter: I, lookup: LFn) -> Self {
31+
pub fn new(iter: I, lookup: Find) -> Self {
3232
LookupRefDeltaObjectsIter {
3333
inner: iter,
3434
lookup,
@@ -75,10 +75,10 @@ where
7575
}
7676
}
7777

78-
impl<I, LFn> Iterator for LookupRefDeltaObjectsIter<I, LFn>
78+
impl<I, Find> Iterator for LookupRefDeltaObjectsIter<I, Find>
7979
where
8080
I: Iterator<Item = Result<input::Entry, input::Error>>,
81-
LFn: for<'a> FnMut(ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>,
81+
Find: gix_object::Find,
8282
{
8383
type Item = Result<input::Entry, input::Error>;
8484

@@ -94,7 +94,7 @@ where
9494
Header::RefDelta { base_id } => {
9595
match self.inserted_entry_length_at_offset.iter().rfind(|e| e.oid == base_id) {
9696
None => {
97-
let base_entry = match (self.lookup)(base_id, &mut self.buf) {
97+
let base_entry = match self.lookup.try_find(&base_id, &mut self.buf).ok()? {
9898
Some(obj) => {
9999
let current_pack_offset = entry.pack_offset;
100100
let mut entry = match input::Entry::from_data_obj(&obj, 0) {

gix-pack/src/data/output/count/objects/mod.rs

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,11 @@ pub fn objects_unthreaded(
114114
}
115115

116116
mod expand {
117+
use std::cell::RefCell;
117118
use std::sync::atomic::{AtomicBool, Ordering};
118119

119120
use gix_hash::{oid, ObjectId};
120-
use gix_object::{CommitRefIter, TagRefIter};
121+
use gix_object::{CommitRefIter, Data, TagRefIter};
121122

122123
use super::{
123124
tree,
@@ -206,24 +207,15 @@ mod expand {
206207

207208
let objects_ref = if parent_commit_ids.is_empty() {
208209
traverse_delegate.clear();
210+
let objects = ExpandedCountingObjects::new(db, out, objects);
209211
gix_traverse::tree::breadthfirst(
210212
current_tree_iter,
211213
&mut tree_traversal_state,
212-
|oid, buf| {
213-
stats.decoded_objects += 1;
214-
match db.find(oid, buf).ok() {
215-
Some((obj, location)) => {
216-
objects.fetch_add(1, Ordering::Relaxed);
217-
stats.expanded_objects += 1;
218-
out.push(output::Count::from_data(oid, location));
219-
obj.try_into_tree_iter()
220-
}
221-
None => None,
222-
}
223-
},
214+
&objects,
224215
&mut traverse_delegate,
225216
)
226217
.map_err(Error::TreeTraverse)?;
218+
out = objects.dissolve(stats);
227219
&traverse_delegate.non_trees
228220
} else {
229221
for commit_id in &parent_commit_ids {
@@ -252,17 +244,16 @@ mod expand {
252244
};
253245

254246
changes_delegate.clear();
247+
let objects = CountingObjects::new(db);
255248
gix_diff::tree::Changes::from(Some(parent_tree))
256249
.needed_to_obtain(
257250
current_tree_iter.clone(),
258251
&mut tree_diff_state,
259-
|oid, buf| {
260-
stats.decoded_objects += 1;
261-
db.find_tree_iter(oid, buf).map(|t| t.0)
262-
},
252+
&objects,
263253
&mut changes_delegate,
264254
)
265255
.map_err(Error::TreeChanges)?;
256+
stats.decoded_objects += objects.into_count();
266257
}
267258
&changes_delegate.objects
268259
};
@@ -283,24 +274,17 @@ mod expand {
283274
match obj.0.kind {
284275
Tree => {
285276
traverse_delegate.clear();
286-
gix_traverse::tree::breadthfirst(
287-
gix_object::TreeRefIter::from_bytes(obj.0.data),
288-
&mut tree_traversal_state,
289-
|oid, buf| {
290-
stats.decoded_objects += 1;
291-
match db.find(oid, buf).ok() {
292-
Some((obj, location)) => {
293-
objects.fetch_add(1, Ordering::Relaxed);
294-
stats.expanded_objects += 1;
295-
out.push(output::Count::from_data(oid, location));
296-
obj.try_into_tree_iter()
297-
}
298-
None => None,
299-
}
300-
},
301-
&mut traverse_delegate,
302-
)
303-
.map_err(Error::TreeTraverse)?;
277+
{
278+
let objects = ExpandedCountingObjects::new(db, out, objects);
279+
gix_traverse::tree::breadthfirst(
280+
gix_object::TreeRefIter::from_bytes(obj.0.data),
281+
&mut tree_traversal_state,
282+
&objects,
283+
&mut traverse_delegate,
284+
)
285+
.map_err(Error::TreeTraverse)?;
286+
out = objects.dissolve(stats);
287+
}
304288
for id in &traverse_delegate.non_trees {
305289
out.push(id_to_count(db, buf1, id, objects, stats, allow_pack_lookups));
306290
}
@@ -374,4 +358,76 @@ mod expand {
374358
},
375359
}
376360
}
361+
362+
struct CountingObjects<'a> {
363+
decoded_objects: std::cell::RefCell<usize>,
364+
objects: &'a dyn crate::Find,
365+
}
366+
367+
impl<'a> CountingObjects<'a> {
368+
fn new(objects: &'a dyn crate::Find) -> Self {
369+
Self {
370+
decoded_objects: Default::default(),
371+
objects,
372+
}
373+
}
374+
375+
fn into_count(self) -> usize {
376+
self.decoded_objects.into_inner()
377+
}
378+
}
379+
380+
impl gix_object::Find for CountingObjects<'_> {
381+
fn try_find<'a>(&self, id: &oid, buffer: &'a mut Vec<u8>) -> Result<Option<Data<'a>>, gix_object::find::Error> {
382+
let res = Ok(self.objects.try_find(id, buffer)?.map(|t| t.0));
383+
*self.decoded_objects.borrow_mut() += 1;
384+
res
385+
}
386+
}
387+
388+
struct ExpandedCountingObjects<'a> {
389+
decoded_objects: std::cell::RefCell<usize>,
390+
expanded_objects: std::cell::RefCell<usize>,
391+
out: std::cell::RefCell<Vec<output::Count>>,
392+
objects_count: &'a gix_features::progress::AtomicStep,
393+
objects: &'a dyn crate::Find,
394+
}
395+
396+
impl<'a> ExpandedCountingObjects<'a> {
397+
fn new(
398+
objects: &'a dyn crate::Find,
399+
out: Vec<output::Count>,
400+
objects_count: &'a gix_features::progress::AtomicStep,
401+
) -> Self {
402+
Self {
403+
decoded_objects: Default::default(),
404+
expanded_objects: Default::default(),
405+
out: RefCell::new(out),
406+
objects_count,
407+
objects,
408+
}
409+
}
410+
411+
fn dissolve(self, stats: &mut Outcome) -> Vec<output::Count> {
412+
stats.decoded_objects += self.decoded_objects.into_inner();
413+
stats.expanded_objects += self.expanded_objects.into_inner();
414+
self.out.into_inner()
415+
}
416+
}
417+
418+
impl gix_object::Find for ExpandedCountingObjects<'_> {
419+
fn try_find<'a>(&self, id: &oid, buffer: &'a mut Vec<u8>) -> Result<Option<Data<'a>>, gix_object::find::Error> {
420+
let maybe_obj = self.objects.try_find(id, buffer)?;
421+
*self.decoded_objects.borrow_mut() += 1;
422+
match maybe_obj {
423+
None => Ok(None),
424+
Some((obj, location)) => {
425+
self.objects_count.fetch_add(1, Ordering::Relaxed);
426+
*self.expanded_objects.borrow_mut() += 1;
427+
self.out.borrow_mut().push(output::Count::from_data(id, location));
428+
Ok(Some(obj))
429+
}
430+
}
431+
}
432+
}
377433
}

gix-pack/src/data/output/count/objects/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub enum Error {
8484
#[error(transparent)]
8585
CommitDecode(gix_object::decode::Error),
8686
#[error(transparent)]
87-
FindExisting(#[from] crate::find::existing::Error),
87+
FindExisting(#[from] gix_object::find::existing::Error),
8888
#[error(transparent)]
8989
InputIteration(Box<dyn std::error::Error + Send + Sync + 'static>),
9090
#[error(transparent)]

gix-pack/src/data/output/entry/iter_from_counts.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ pub(crate) mod function {
204204
stats.objects_copied_from_pack += 1;
205205
entry
206206
}
207-
None => match db.try_find(&count.id, buf).map_err(Error::FindExisting)? {
207+
None => match db.try_find(&count.id, buf).map_err(Error::Find)? {
208208
Some((obj, _location)) => {
209209
stats.decoded_and_recompressed_objects += 1;
210210
output::Entry::from_data(count, &obj)
@@ -216,7 +216,7 @@ pub(crate) mod function {
216216
},
217217
}
218218
}
219-
None => match db.try_find(&count.id, buf).map_err(Error::FindExisting)? {
219+
None => match db.try_find(&count.id, buf).map_err(Error::Find)? {
220220
Some((obj, _location)) => {
221221
stats.decoded_and_recompressed_objects += 1;
222222
output::Entry::from_data(count, &obj)
@@ -397,7 +397,7 @@ mod types {
397397
#[allow(missing_docs)]
398398
pub enum Error {
399399
#[error(transparent)]
400-
FindExisting(crate::find::Error),
400+
Find(gix_object::find::Error),
401401
#[error(transparent)]
402402
NewEntry(#[from] entry::Error),
403403
}

gix-pack/src/find.rs

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,3 @@
1-
/// The error returned by methods of the [Find](crate::Find) trait.
2-
pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
3-
4-
///
5-
pub mod existing {
6-
use gix_hash::ObjectId;
7-
8-
/// The error returned by the [`find(…)`](crate::FindExt::find()) trait methods.
9-
#[derive(Debug, thiserror::Error)]
10-
#[allow(missing_docs)]
11-
pub enum Error {
12-
#[error(transparent)]
13-
Find(crate::find::Error),
14-
#[error("An object with id {} could not be found", .oid)]
15-
NotFound { oid: ObjectId },
16-
}
17-
}
18-
19-
///
20-
pub mod existing_object {
21-
use gix_hash::ObjectId;
22-
23-
/// The error returned by the various [`find_*`](crate::FindExt::find_commit()) trait methods.
24-
#[derive(Debug, thiserror::Error)]
25-
#[allow(missing_docs)]
26-
pub enum Error {
27-
#[error(transparent)]
28-
Find(crate::find::Error),
29-
#[error(transparent)]
30-
Decode(gix_object::decode::Error),
31-
#[error("An object with id {} could not be found", .oid)]
32-
NotFound { oid: ObjectId },
33-
#[error("Expected object of kind {} something else", .expected)]
34-
ObjectKind { expected: gix_object::Kind },
35-
}
36-
}
37-
38-
///
39-
pub mod existing_iter {
40-
use gix_hash::ObjectId;
41-
42-
/// The error returned by the various [`find_*`](crate::FindExt::find_commit()) trait methods.
43-
#[derive(Debug, thiserror::Error)]
44-
#[allow(missing_docs)]
45-
pub enum Error {
46-
#[error(transparent)]
47-
Find(crate::find::Error),
48-
#[error("An object with id {} could not be found", .oid)]
49-
NotFound { oid: ObjectId },
50-
#[error("Expected object of kind {} something else", .expected)]
51-
ObjectKind { expected: gix_object::Kind },
52-
}
53-
}
54-
551
/// An Entry in a pack providing access to its data.
562
///
573
/// Its commonly retrieved by reading from a pack index file followed by a read from a pack data file.

0 commit comments

Comments
 (0)