Skip to content

Commit bf1e688

Browse files
committed
change!: Use the gix-object::Find trait
1 parent 1165de0 commit bf1e688

File tree

11 files changed

+100
-109
lines changed

11 files changed

+100
-109
lines changed

gix-worktree-stream/src/entry.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ use crate::{protocol, Entry, Stream};
1313
pub enum Error {
1414
#[error(transparent)]
1515
Io(#[from] std::io::Error),
16-
#[error("Could not find a blob or tree for archival")]
17-
Find(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
16+
#[error("Could not find a tree's leaf, typically a blob")]
17+
Find(#[from] gix_object::find::existing::Error),
18+
#[error("Could not find a tree to traverse")]
19+
FindTree(#[from] gix_object::find::existing_iter::Error),
1820
#[error("Could not query attributes for path \"{path}\"")]
1921
Attributes {
2022
path: BString,

gix-worktree-stream/src/from_tree/mod.rs

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::io::Write;
22

33
use gix_object::bstr::BStr;
4+
use gix_object::FindExt;
45

56
use crate::{entry, entry::Error, protocol, AdditionalEntry, SharedErrorSlot, Stream};
67

7-
/// Use `find` to traverse `tree` and fetch the contained blobs to return as [`Stream`], which makes them queryable
8+
/// Use `objects` to traverse `tree` and fetch the contained blobs to return as [`Stream`], which makes them queryable
89
/// on demand with support for streaming each entry.
910
///
1011
/// `pipeline` is used to convert blobs to their worktree representation, and `attributes` is used to read
@@ -32,26 +33,25 @@ use crate::{entry, entry::Error, protocol, AdditionalEntry, SharedErrorSlot, Str
3233
/// ### Limitations
3334
///
3435
/// * `export-subst` is not support, as it requires the entire formatting engine of `git log`.
35-
pub fn from_tree<Find, E1, E2>(
36+
pub fn from_tree<Find, E>(
3637
tree: gix_hash::ObjectId,
37-
find: Find,
38+
objects: Find,
3839
pipeline: gix_filter::Pipeline,
39-
attributes: impl FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), E2>
40+
attributes: impl FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), E>
4041
+ Send
4142
+ 'static,
4243
) -> Stream
4344
where
44-
Find: for<'a> FnMut(&gix_hash::oid, &'a mut Vec<u8>) -> Result<gix_object::Data<'a>, E1> + Clone + Send + 'static,
45-
E1: std::error::Error + Send + Sync + 'static,
46-
E2: std::error::Error + Send + Sync + 'static,
45+
Find: gix_object::Find + Clone + Send + 'static,
46+
E: std::error::Error + Send + Sync + 'static,
4747
{
4848
let (stream, mut write, additional_entries) = Stream::new();
4949
std::thread::spawn({
5050
let slot = stream.err.clone();
5151
move || {
5252
if let Err(err) = run(
5353
tree,
54-
find,
54+
objects,
5555
pipeline,
5656
attributes,
5757
&mut write,
@@ -76,28 +76,26 @@ where
7676
stream
7777
}
7878

79-
fn run<Find, E1, E2>(
79+
fn run<Find, E>(
8080
tree: gix_hash::ObjectId,
81-
mut find: Find,
81+
objects: Find,
8282
mut pipeline: gix_filter::Pipeline,
83-
mut attributes: impl FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), E2>
83+
mut attributes: impl FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), E>
8484
+ Send
8585
+ 'static,
8686
out: &mut gix_features::io::pipe::Writer,
8787
err: SharedErrorSlot,
8888
additional_entries: std::sync::mpsc::Receiver<AdditionalEntry>,
8989
) -> Result<(), Error>
9090
where
91-
Find: for<'a> FnMut(&gix_hash::oid, &'a mut Vec<u8>) -> Result<gix_object::Data<'a>, E1> + Clone + Send + 'static,
92-
E1: std::error::Error + Send + Sync + 'static,
93-
E2: std::error::Error + Send + Sync + 'static,
91+
Find: gix_object::Find + Clone,
92+
E: std::error::Error + Send + Sync + 'static,
9493
{
9594
let mut buf = Vec::new();
96-
let obj = find(tree.as_ref(), &mut buf).map_err(|err| Error::Find(Box::new(err)))?;
95+
let tree_iter = objects.find_tree_iter(tree.as_ref(), &mut buf)?;
9796
if pipeline.driver_context_mut().treeish.is_none() {
9897
pipeline.driver_context_mut().treeish = Some(tree);
9998
}
100-
let tree = gix_object::TreeRefIter::from_bytes(obj.data);
10199

102100
let mut attrs = gix_attributes::search::Outcome::default();
103101
attrs.initialize_with_selection(&Default::default(), Some("export-ignore"));
@@ -106,10 +104,7 @@ where
106104
err,
107105
pipeline,
108106
attrs,
109-
find: {
110-
let mut find = find.clone();
111-
move |a: &gix_hash::oid, b: &mut Vec<u8>| find(a, b).map_err(|err| Error::Find(Box::new(err)))
112-
},
107+
objects: objects.clone(),
113108
fetch_attributes: move |a: &BStr, b: gix_object::tree::EntryMode, c: &mut gix_attributes::search::Outcome| {
114109
attributes(a, b, c).map_err(|err| Error::Attributes {
115110
source: Box::new(err),
@@ -121,13 +116,9 @@ where
121116
buf: Vec::with_capacity(1024),
122117
};
123118
gix_traverse::tree::breadthfirst(
124-
tree,
119+
tree_iter,
125120
gix_traverse::tree::breadthfirst::State::default(),
126-
|id, buf| {
127-
find(id, buf)
128-
.map(|obj| gix_object::TreeRefIter::from_bytes(obj.data))
129-
.ok()
130-
},
121+
&objects,
131122
&mut dlg,
132123
)?;
133124

gix-worktree-stream/src/from_tree/traverse.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ use std::{collections::VecDeque, io::Write};
33
use gix_filter::{driver::apply::MaybeDelayed, pipeline::convert::ToWorktreeOutcome};
44
use gix_object::{
55
bstr::{BStr, BString, ByteSlice, ByteVec},
6-
tree,
6+
tree, FindExt,
77
};
88
use gix_traverse::tree::{visit::Action, Visit};
99

1010
use crate::{entry::Error, protocol, SharedErrorSlot};
1111

12-
pub struct Delegate<'a, AttributesFn, FindFn>
12+
pub struct Delegate<'a, AttributesFn, Find>
1313
where
14-
FindFn: for<'b> FnMut(&gix_hash::oid, &'b mut Vec<u8>) -> Result<gix_object::Data<'b>, Error> + 'static,
14+
Find: gix_object::Find,
1515
{
1616
pub(crate) out: &'a mut gix_features::io::pipe::Writer,
1717
pub(crate) err: SharedErrorSlot,
@@ -20,13 +20,13 @@ where
2020
pub(crate) pipeline: gix_filter::Pipeline,
2121
pub(crate) attrs: gix_attributes::search::Outcome,
2222
pub(crate) fetch_attributes: AttributesFn,
23-
pub(crate) find: FindFn,
23+
pub(crate) objects: Find,
2424
pub(crate) buf: Vec<u8>,
2525
}
2626

27-
impl<AttributesFn, FindFn> Delegate<'_, AttributesFn, FindFn>
27+
impl<AttributesFn, Find> Delegate<'_, AttributesFn, Find>
2828
where
29-
FindFn: for<'b> FnMut(&gix_hash::oid, &'b mut Vec<u8>) -> Result<gix_object::Data<'b>, Error> + 'static,
29+
Find: gix_object::Find,
3030
AttributesFn:
3131
FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), Error> + 'static,
3232
{
@@ -62,7 +62,7 @@ where
6262
if self.ignore_state().is_set() {
6363
return Ok(Action::Continue);
6464
}
65-
(self.find)(entry.oid, &mut self.buf)?;
65+
self.objects.find(entry.oid, &mut self.buf)?;
6666

6767
self.pipeline.driver_context_mut().blob = Some(entry.oid.into());
6868
let converted = self.pipeline.convert_to_worktree(
@@ -99,9 +99,9 @@ where
9999
}
100100
}
101101

102-
impl<AttributesFn, FindFn> Visit for Delegate<'_, AttributesFn, FindFn>
102+
impl<AttributesFn, Find> Visit for Delegate<'_, AttributesFn, Find>
103103
where
104-
FindFn: for<'a> FnMut(&gix_hash::oid, &'a mut Vec<u8>) -> Result<gix_object::Data<'a>, Error> + 'static,
104+
Find: gix_object::Find,
105105
AttributesFn:
106106
FnMut(&BStr, gix_object::tree::EntryMode, &mut gix_attributes::search::Outcome) -> Result<(), Error> + 'static,
107107
{

gix-worktree-stream/tests/stream.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,45 @@ mod from_tree {
1212
};
1313

1414
use gix_attributes::glob::pattern::Case;
15-
use gix_object::FindExt;
15+
use gix_hash::oid;
1616
use gix_object::{bstr::ByteSlice, tree::EntryMode};
17+
use gix_object::{Data, FindExt};
1718
use gix_testtools::once_cell::sync::Lazy;
1819
use gix_worktree::stack::state::attributes::Source;
1920

2021
use crate::hex_to_id;
2122

23+
#[derive(Clone)]
24+
struct FailObjectRetrieval;
25+
26+
impl gix_object::Find for FailObjectRetrieval {
27+
fn try_find<'a>(
28+
&self,
29+
_id: &oid,
30+
_buffer: &'a mut Vec<u8>,
31+
) -> Result<Option<Data<'a>>, gix_object::find::Error> {
32+
Err(Box::new(Error::new(ErrorKind::Other, "object retrieval failed")))
33+
}
34+
}
35+
2236
#[test]
2337
fn can_receive_err_if_root_is_not_found() {
2438
let mut stream = gix_worktree_stream::from_tree(
2539
gix_hash::Kind::Sha1.null(),
26-
|_, _| Err(Error::new(ErrorKind::Other, "object retrieval failed")),
40+
FailObjectRetrieval,
2741
mutating_pipeline(false),
2842
|_, _, _| -> Result<_, Infallible> { unreachable!("must not be called") },
2943
);
3044
let err = stream.next_entry().unwrap_err();
31-
assert_eq!(err.to_string(), "Could not find a blob or tree for archival");
45+
assert_eq!(err.to_string(), "Could not find a tree to traverse");
3246
}
3347

3448
#[test]
3549
fn can_receive_err_if_attribute_not_found() -> gix_testtools::Result {
3650
let (_dir, head_tree, odb, _cache) = basic()?;
37-
let mut stream = gix_worktree_stream::from_tree(
38-
head_tree,
39-
move |id, buf| odb.find(id, buf),
40-
mutating_pipeline(false),
41-
|_, _, _| Err(Error::new(ErrorKind::Other, "attribute retrieval failed")),
42-
);
51+
let mut stream = gix_worktree_stream::from_tree(head_tree, odb, mutating_pipeline(false), |_, _, _| {
52+
Err(Error::new(ErrorKind::Other, "attribute retrieval failed"))
53+
});
4354
let err = stream.next_entry().unwrap_err();
4455
assert_eq!(
4556
err.to_string(),
@@ -53,10 +64,7 @@ mod from_tree {
5364
let (dir, head_tree, odb, mut cache) = basic()?;
5465
let mut stream = gix_worktree_stream::from_tree(
5566
head_tree,
56-
{
57-
let odb = odb.clone();
58-
move |id, buf| odb.find(id, buf)
59-
},
67+
odb.clone(),
6068
mutating_pipeline(true),
6169
move |rela_path, mode, attrs| {
6270
cache
@@ -214,10 +222,7 @@ mod from_tree {
214222
let (_dir, head_tree, odb, mut cache) = basic()?;
215223
let mut stream = gix_worktree_stream::from_tree(
216224
head_tree,
217-
{
218-
let odb = odb.clone();
219-
move |id, buf| odb.find(id, buf)
220-
},
225+
odb.clone(),
221226
mutating_pipeline(false),
222227
move |rela_path, mode, attrs| {
223228
cache

gix-worktree/src/stack/delegate.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,13 @@ pub struct Statistics {
1818
pub pop_directory: usize,
1919
}
2020

21-
pub(crate) type FindFn<'a> = dyn for<'b> FnMut(
22-
&gix_hash::oid,
23-
&'b mut Vec<u8>,
24-
) -> Result<gix_object::BlobRef<'b>, Box<dyn std::error::Error + Send + Sync>>
25-
+ 'a;
26-
2721
pub(crate) struct StackDelegate<'a, 'find> {
2822
pub state: &'a mut State,
2923
pub buf: &'a mut Vec<u8>,
3024
#[cfg_attr(not(feature = "attributes"), allow(dead_code))]
3125
pub is_dir: bool,
3226
pub id_mappings: &'a Vec<PathIdMapping>,
33-
pub find: &'find mut FindFn<'find>,
27+
pub objects: &'find dyn gix_object::Find,
3428
pub case: gix_glob::pattern::Case,
3529
pub statistics: &'a mut super::Statistics,
3630
}
@@ -63,7 +57,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
6357
rela_dir,
6458
self.buf,
6559
self.id_mappings,
66-
self.find,
60+
self.objects,
6761
&mut self.statistics.attributes,
6862
)?;
6963
}
@@ -75,7 +69,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
7569
rela_dir,
7670
self.buf,
7771
self.id_mappings,
78-
&mut self.find,
72+
self.objects,
7973
&mut self.statistics.attributes,
8074
)?;
8175
ignore.push_directory(
@@ -84,7 +78,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
8478
rela_dir,
8579
self.buf,
8680
self.id_mappings,
87-
&mut self.find,
81+
self.objects,
8882
self.case,
8983
&mut self.statistics.ignore,
9084
)?
@@ -95,7 +89,7 @@ impl<'a, 'find> gix_fs::stack::Delegate for StackDelegate<'a, 'find> {
9589
rela_dir,
9690
self.buf,
9791
self.id_mappings,
98-
&mut self.find,
92+
self.objects,
9993
self.case,
10094
&mut self.statistics.ignore,
10195
)?,

gix-worktree/src/stack/mod.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
use std::path::{Path, PathBuf};
33

44
use bstr::{BStr, ByteSlice};
5-
use gix_hash::oid;
65

76
use super::Stack;
87
use crate::PathIdMapping;
@@ -106,26 +105,25 @@ impl Stack {
106105
/// symlinks are in that path.
107106
/// Unless `is_dir` is known with `Some(…)`, then `relative` points to a directory itself in which case the entire resulting
108107
/// path is created as directory. If it's not known it is assumed to be a file.
109-
/// `find` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()], with mappnigs
108+
/// `objects` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()], with mappnigs
110109
///
111110
/// Provide access to cached information for that `relative` path via the returned platform.
112-
pub fn at_path<Find, E>(
111+
pub fn at_path<Find>(
113112
&mut self,
114113
relative: impl AsRef<Path>,
115114
is_dir: Option<bool>,
116-
mut find: Find,
115+
objects: Find,
117116
) -> std::io::Result<Platform<'_>>
118117
where
119-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E>,
120-
E: std::error::Error + Send + Sync + 'static,
118+
Find: gix_object::Find,
121119
{
122120
self.statistics.platforms += 1;
123121
let mut delegate = StackDelegate {
124122
state: &mut self.state,
125123
buf: &mut self.buf,
126124
is_dir: is_dir.unwrap_or(false),
127125
id_mappings: &self.id_mappings,
128-
find: &mut |oid, buf| Ok(find(oid, buf).map_err(Box::new)?),
126+
objects: &objects,
129127
case: self.case,
130128
statistics: &mut self.statistics,
131129
};
@@ -136,31 +134,30 @@ impl Stack {
136134

137135
/// Obtain a platform for lookups from a repo-`relative` path, typically obtained from an index entry. `is_dir` should reflect
138136
/// whether it's a directory or not, or left at `None` if unknown.
139-
/// `find` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()].
137+
/// `objects` maybe used to lookup objects from an [id mapping][crate::stack::State::id_mappings_from_index()].
140138
/// All effects are similar to [`at_path()`][Self::at_path()].
141139
///
142140
/// If `relative` ends with `/` and `is_dir` is `None`, it is automatically assumed to be a directory.
143141
///
144142
/// ### Panics
145143
///
146144
/// on illformed UTF8 in `relative`
147-
pub fn at_entry<'r, Find, E>(
145+
pub fn at_entry<'r, Find>(
148146
&mut self,
149147
relative: impl Into<&'r BStr>,
150148
is_dir: Option<bool>,
151-
find: Find,
149+
objects: Find,
152150
) -> std::io::Result<Platform<'_>>
153151
where
154-
Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E>,
155-
E: std::error::Error + Send + Sync + 'static,
152+
Find: gix_object::Find,
156153
{
157154
let relative = relative.into();
158155
let relative_path = gix_path::from_bstr(relative);
159156

160157
self.at_path(
161158
relative_path,
162159
is_dir.or_else(|| relative.ends_with_str("/").then_some(true)),
163-
find,
160+
objects,
164161
)
165162
}
166163
}

0 commit comments

Comments
 (0)