Skip to content

Commit a81514f

Browse files
committed
feat: use gix-object::Find trait
1 parent 36f70dc commit a81514f

File tree

5 files changed

+82
-77
lines changed

5 files changed

+82
-77
lines changed

gix-worktree-state/src/checkout/chunk.rs

+16-26
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,22 @@ use std::{
44
};
55

66
use bstr::{BStr, BString};
7-
use gix_hash::oid;
87
use gix_worktree::Stack;
98

109
use crate::{checkout, checkout::entry};
1110

1211
mod reduce {
13-
use std::marker::PhantomData;
14-
1512
use crate::checkout;
1613

17-
pub struct Reduce<'entry, E> {
14+
pub struct Reduce<'entry> {
1815
pub aggregate: super::Outcome<'entry>,
19-
pub marker: PhantomData<E>,
2016
}
2117

22-
impl<'entry, E> gix_features::parallel::Reduce for Reduce<'entry, E>
23-
where
24-
E: std::error::Error + Send + Sync + 'static,
25-
{
26-
type Input = Result<super::Outcome<'entry>, checkout::Error<E>>;
18+
impl<'entry> gix_features::parallel::Reduce for Reduce<'entry> {
19+
type Input = Result<super::Outcome<'entry>, checkout::Error>;
2720
type FeedProduce = ();
2821
type Output = super::Outcome<'entry>;
29-
type Error = checkout::Error<E>;
22+
type Error = checkout::Error;
3023

3124
fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error> {
3225
let item = item?;
@@ -78,7 +71,7 @@ pub struct Outcome<'a> {
7871

7972
#[derive(Clone)]
8073
pub struct Context<Find: Clone> {
81-
pub find: Find,
74+
pub objects: Find,
8275
pub path_cache: Stack,
8376
pub filters: gix_filter::Pipeline,
8477
pub buf: Vec<u8>,
@@ -106,16 +99,15 @@ impl From<&checkout::Options> for Options {
10699
}
107100
}
108101

109-
pub fn process<'entry, Find, E>(
102+
pub fn process<'entry, Find>(
110103
entries_with_paths: impl Iterator<Item = (&'entry mut gix_index::Entry, &'entry BStr)>,
111104
files: &AtomicUsize,
112105
bytes: &AtomicUsize,
113106
delayed_filter_results: &mut Vec<DelayedFilteredStream<'entry>>,
114107
ctx: &mut Context<Find>,
115-
) -> Result<Outcome<'entry>, checkout::Error<E>>
108+
) -> Result<Outcome<'entry>, checkout::Error>
116109
where
117-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E> + Clone,
118-
E: std::error::Error + Send + Sync + 'static,
110+
Find: gix_object::Find + Clone,
119111
{
120112
let mut delayed_symlinks = Vec::new();
121113
let mut collisions = Vec::new();
@@ -162,16 +154,15 @@ where
162154
})
163155
}
164156

165-
pub fn process_delayed_filter_results<Find, E>(
157+
pub fn process_delayed_filter_results<Find>(
166158
mut delayed_filter_results: Vec<DelayedFilteredStream<'_>>,
167159
files: &AtomicUsize,
168160
bytes: &AtomicUsize,
169161
out: &mut Outcome<'_>,
170162
ctx: &mut Context<Find>,
171-
) -> Result<(), checkout::Error<E>>
163+
) -> Result<(), checkout::Error>
172164
where
173-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E> + Clone,
174-
E: std::error::Error + Send + Sync + 'static,
165+
Find: gix_object::Find + Clone,
175166
{
176167
let Options {
177168
destination_is_initially_empty,
@@ -288,30 +279,29 @@ where
288279
}
289280
}
290281

291-
pub fn checkout_entry_handle_result<'entry, Find, E>(
282+
pub fn checkout_entry_handle_result<'entry, Find>(
292283
entry: &'entry mut gix_index::Entry,
293284
entry_path: &'entry BStr,
294285
errors: &mut Vec<checkout::ErrorRecord>,
295286
collisions: &mut Vec<checkout::Collision>,
296287
files: &AtomicUsize,
297288
bytes: &AtomicUsize,
298289
Context {
299-
find,
290+
objects,
300291
path_cache,
301292
filters,
302293
buf,
303294
options,
304295
}: &mut Context<Find>,
305-
) -> Result<entry::Outcome<'entry>, checkout::Error<E>>
296+
) -> Result<entry::Outcome<'entry>, checkout::Error>
306297
where
307-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E> + Clone,
308-
E: std::error::Error + Send + Sync + 'static,
298+
Find: gix_object::Find + Clone,
309299
{
310300
let res = entry::checkout(
311301
entry,
312302
entry_path,
313303
entry::Context {
314-
find,
304+
objects,
315305
path_cache,
316306
filters,
317307
buf,

gix-worktree-state/src/checkout/entry.rs

+21-23
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use std::{
66

77
use bstr::BStr;
88
use gix_filter::{driver::apply::MaybeDelayed, pipeline::convert::ToWorktreeOutcome};
9-
use gix_hash::oid;
109
use gix_index::{entry::Stat, Entry};
10+
use gix_object::FindExt;
1111
use gix_worktree::Stack;
1212
use io_close::Close;
1313

1414
pub struct Context<'a, Find> {
15-
pub find: &'a mut Find,
15+
pub objects: &'a mut Find,
1616
pub path_cache: &'a mut Stack,
1717
pub filters: &'a mut gix_filter::Pipeline,
1818
pub buf: &'a mut Vec<u8>,
@@ -53,11 +53,11 @@ impl Outcome<'_> {
5353
}
5454

5555
#[cfg_attr(not(unix), allow(unused_variables))]
56-
pub fn checkout<'entry, Find, E>(
56+
pub fn checkout<'entry, Find>(
5757
entry: &'entry mut Entry,
5858
entry_path: &'entry BStr,
5959
Context {
60-
find,
60+
objects,
6161
filters,
6262
path_cache,
6363
buf,
@@ -73,25 +73,25 @@ pub fn checkout<'entry, Find, E>(
7373
filter_process_delay,
7474
..
7575
}: crate::checkout::chunk::Options,
76-
) -> Result<Outcome<'entry>, crate::checkout::Error<E>>
76+
) -> Result<Outcome<'entry>, crate::checkout::Error>
7777
where
78-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E>,
79-
E: std::error::Error + Send + Sync + 'static,
78+
Find: gix_object::Find,
8079
{
8180
let dest_relative = gix_path::try_from_bstr(entry_path).map_err(|_| crate::checkout::Error::IllformedUtf8 {
8281
path: entry_path.to_owned(),
8382
})?;
8483
let is_dir = Some(entry.mode == gix_index::entry::Mode::COMMIT || entry.mode == gix_index::entry::Mode::DIR);
85-
let path_cache = path_cache.at_path(dest_relative, is_dir, &mut *find)?;
84+
let path_cache = path_cache.at_path(dest_relative, is_dir, &*objects)?;
8685
let dest = path_cache.path();
8786

8887
let object_size = match entry.mode {
8988
gix_index::entry::Mode::FILE | gix_index::entry::Mode::FILE_EXECUTABLE => {
90-
let obj = find(&entry.id, buf).map_err(|err| crate::checkout::Error::Find {
91-
err,
92-
oid: entry.id,
93-
path: dest.to_path_buf(),
94-
})?;
89+
let obj = (&*objects)
90+
.find_blob(&entry.id, buf)
91+
.map_err(|err| crate::checkout::Error::Find {
92+
err,
93+
path: dest.to_path_buf(),
94+
})?;
9595

9696
let filtered = filters.convert_to_worktree(
9797
obj.data,
@@ -140,11 +140,12 @@ where
140140
num_bytes
141141
}
142142
gix_index::entry::Mode::SYMLINK => {
143-
let obj = find(&entry.id, buf).map_err(|err| crate::checkout::Error::Find {
144-
err,
145-
oid: entry.id,
146-
path: dest.to_path_buf(),
147-
})?;
143+
let obj = (&*objects)
144+
.find_blob(&entry.id, buf)
145+
.map_err(|err| crate::checkout::Error::Find {
146+
err,
147+
path: dest.to_path_buf(),
148+
})?;
148149
let symlink_destination = gix_path::try_from_byte_slice(obj.data)
149150
.map_err(|_| crate::checkout::Error::IllformedUtf8 { path: obj.data.into() })?;
150151

@@ -269,14 +270,11 @@ pub(crate) fn open_file(
269270

270271
/// Close `file` and store its stats in `entry`, possibly setting `file` executable depending on `set_executable_after_creation`.
271272
#[cfg_attr(windows, allow(unused_variables))]
272-
pub(crate) fn finalize_entry<E>(
273+
pub(crate) fn finalize_entry(
273274
entry: &mut gix_index::Entry,
274275
file: std::fs::File,
275276
set_executable_after_creation: Option<&Path>,
276-
) -> Result<(), crate::checkout::Error<E>>
277-
where
278-
E: std::error::Error + Send + Sync + 'static,
279-
{
277+
) -> Result<(), crate::checkout::Error> {
280278
// For possibly existing, overwritten files, we must change the file mode explicitly.
281279
#[cfg(unix)]
282280
if let Some(path) = set_executable_after_creation {

gix-worktree-state/src/checkout/function.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::sync::atomic::AtomicBool;
22

33
use gix_features::{interrupt, parallel::in_parallel_with_finalize};
4-
use gix_hash::oid;
54
use gix_worktree::{stack, Stack};
65

76
use crate::checkout::chunk;
87

9-
/// Checkout the entire `index` into `dir`, and resolve objects found in index entries with `find` to write their content to their
8+
/// Checkout the entire `index` into `dir`, and resolve objects found in index entries with `objects` to write their content to their
109
/// respective path in `dir`.
1110
/// Use `files` to count each fully checked out file, and count the amount written `bytes`. If `should_interrupt` is `true`, the
1211
/// operation will abort.
@@ -17,39 +16,37 @@ use crate::checkout::chunk;
1716
/// Note that interruption still produce an `Ok(…)` value, so the caller should look at `should_interrupt` to communicate the outcome.
1817
///
1918
#[allow(clippy::too_many_arguments)]
20-
pub fn checkout<Find, E>(
19+
pub fn checkout<Find>(
2120
index: &mut gix_index::State,
2221
dir: impl Into<std::path::PathBuf>,
23-
find: Find,
22+
objects: Find,
2423
files: &dyn gix_features::progress::Count,
2524
bytes: &dyn gix_features::progress::Count,
2625
should_interrupt: &AtomicBool,
2726
options: crate::checkout::Options,
28-
) -> Result<crate::checkout::Outcome, crate::checkout::Error<E>>
27+
) -> Result<crate::checkout::Outcome, crate::checkout::Error>
2928
where
30-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E> + Send + Clone,
31-
E: std::error::Error + Send + Sync + 'static,
29+
Find: gix_object::Find + Send + Clone,
3230
{
3331
let paths = index.take_path_backing();
34-
let res = checkout_inner(index, &paths, dir, find, files, bytes, should_interrupt, options);
32+
let res = checkout_inner(index, &paths, dir, objects, files, bytes, should_interrupt, options);
3533
index.return_path_backing(paths);
3634
res
3735
}
3836

3937
#[allow(clippy::too_many_arguments)]
40-
fn checkout_inner<Find, E>(
38+
fn checkout_inner<Find>(
4139
index: &mut gix_index::State,
4240
paths: &gix_index::PathStorage,
4341
dir: impl Into<std::path::PathBuf>,
44-
find: Find,
42+
objects: Find,
4543
files: &dyn gix_features::progress::Count,
4644
bytes: &dyn gix_features::progress::Count,
4745
should_interrupt: &AtomicBool,
4846
mut options: crate::checkout::Options,
49-
) -> Result<crate::checkout::Outcome, crate::checkout::Error<E>>
47+
) -> Result<crate::checkout::Outcome, crate::checkout::Error>
5048
where
51-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E> + Send + Clone,
52-
E: std::error::Error + Send + Sync + 'static,
49+
Find: gix_object::Find + Send + Clone,
5350
{
5451
let num_files = files.counter();
5552
let num_bytes = bytes.counter();
@@ -72,7 +69,7 @@ where
7269
paths,
7370
),
7471
filters: options.filters,
75-
find,
72+
objects,
7673
};
7774

7875
let chunk::Outcome {
@@ -123,7 +120,6 @@ where
123120
},
124121
chunk::Reduce {
125122
aggregate: Default::default(),
126-
marker: Default::default(),
127123
},
128124
)?
129125
};

gix-worktree-state/src/checkout/mod.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,17 @@ pub struct Options {
7171
/// The error returned by the [checkout()][crate::checkout()] function.
7272
#[derive(Debug, thiserror::Error)]
7373
#[allow(missing_docs)]
74-
pub enum Error<E: std::error::Error + Send + Sync + 'static> {
74+
pub enum Error {
7575
#[error("Could not convert path to UTF8: {}", .path)]
7676
IllformedUtf8 { path: BString },
7777
#[error("The clock was off when reading file related metadata after updating a file on disk")]
7878
Time(#[from] std::time::SystemTimeError),
7979
#[error("IO error while writing blob or reading file metadata or changing filetype")]
8080
Io(#[from] std::io::Error),
81-
#[error("object {} for checkout at {} could not be retrieved from object database", .oid.to_hex(), .path.display())]
81+
#[error("object for checkout at {} could not be retrieved from object database", .path.display())]
8282
Find {
8383
#[source]
84-
err: E,
85-
oid: gix_hash::ObjectId,
84+
err: gix_object::find::existing_object::Error,
8685
path: std::path::PathBuf,
8786
},
8887
#[error(transparent)]

gix-worktree-state/tests/state/checkout.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99

1010
use gix_features::progress;
1111
use gix_object::bstr::ByteSlice;
12-
use gix_object::FindExt;
12+
use gix_object::Data;
1313
use gix_testtools::tempfile::TempDir;
1414
use gix_worktree_state::checkout::Collision;
1515
use once_cell::sync::Lazy;
@@ -487,7 +487,7 @@ fn checkout_index_in_tmp_dir(
487487
fn checkout_index_in_tmp_dir_opts(
488488
opts: gix_worktree_state::checkout::Options,
489489
name: &str,
490-
mut allow_return_object: impl FnMut(&gix_hash::oid) -> bool + Send + Clone,
490+
allow_return_object: impl FnMut(&gix_hash::oid) -> bool + Send + Clone,
491491
prep_dest: impl Fn(&Path) -> std::io::Result<()>,
492492
) -> crate::Result<(PathBuf, TempDir, gix_index::File, gix_worktree_state::checkout::Outcome)> {
493493
let source_tree = fixture_path(name);
@@ -497,16 +497,38 @@ fn checkout_index_in_tmp_dir_opts(
497497
let destination = gix_testtools::tempfile::tempdir_in(std::env::current_dir()?)?;
498498
prep_dest(destination.path()).expect("preparation must succeed");
499499

500+
#[derive(Clone)]
501+
struct MaybeFind<Allow: Clone, Find: Clone> {
502+
allow: std::cell::RefCell<Allow>,
503+
objects: Find,
504+
}
505+
506+
impl<Allow, Find> gix_object::Find for MaybeFind<Allow, Find>
507+
where
508+
Allow: FnMut(&gix_hash::oid) -> bool + Send + Clone,
509+
Find: gix_object::Find + Send + Clone,
510+
{
511+
fn try_find<'a>(
512+
&self,
513+
id: &gix_hash::oid,
514+
buf: &'a mut Vec<u8>,
515+
) -> Result<Option<Data<'a>>, gix_object::find::Error> {
516+
if (self.allow.borrow_mut())(id) {
517+
self.objects.try_find(id, buf)
518+
} else {
519+
Ok(None)
520+
}
521+
}
522+
}
523+
524+
let db = MaybeFind {
525+
allow: allow_return_object.into(),
526+
objects: odb,
527+
};
500528
let outcome = gix_worktree_state::checkout(
501529
&mut index,
502530
destination.path(),
503-
move |oid, buf| {
504-
if allow_return_object(oid) {
505-
odb.find_blob(oid, buf)
506-
} else {
507-
Err(gix_object::find::existing_object::Error::NotFound { oid: oid.to_owned() })
508-
}
509-
},
531+
db,
510532
&progress::Discard,
511533
&progress::Discard,
512534
&AtomicBool::default(),

0 commit comments

Comments
 (0)