@@ -7,8 +7,8 @@ use gix_features::parallel::{in_parallel_if, Reduce};
7
7
8
8
use crate :: {
9
9
index_as_worktree:: {
10
- content ,
11
- content :: CompareBlobs ,
10
+ traits ,
11
+ traits :: { CompareBlobs , SubmoduleStatus } ,
12
12
types:: { Error , Options } ,
13
13
Change , VisitEntry ,
14
14
} ,
@@ -26,20 +26,23 @@ use crate::{
26
26
/// like whether a file has conflicts, and files that were added with `git add` are shown as a special
27
27
/// changes despite not technically requiring a change to the index since `git add` already added the file to the index.
28
28
#[ allow( clippy:: too_many_arguments) ]
29
- pub fn index_as_worktree < ' index , T , Find , E > (
29
+ pub fn index_as_worktree < ' index , T , U , Find , E1 , E2 > (
30
30
index : & ' index mut gix_index:: State ,
31
31
worktree : & Path ,
32
- collector : & mut impl VisitEntry < ' index , ContentChange = T > ,
32
+ collector : & mut impl VisitEntry < ' index , ContentChange = T , SubmoduleStatus = U > ,
33
33
compare : impl CompareBlobs < Output = T > + Send + Clone ,
34
+ submodule : impl SubmoduleStatus < Output = U , Error = E2 > + Send + Clone ,
34
35
find : Find ,
35
36
progress : & mut dyn gix_features:: progress:: Progress ,
36
37
pathspec : impl Pathspec + Send + Clone ,
37
38
options : Options ,
38
39
) -> Result < ( ) , Error >
39
40
where
40
41
T : Send ,
41
- E : std:: error:: Error + Send + Sync + ' static ,
42
- Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > + Send + Clone ,
42
+ U : Send ,
43
+ E1 : std:: error:: Error + Send + Sync + ' static ,
44
+ E2 : std:: error:: Error + Send + Sync + ' static ,
45
+ Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E1 > + Send + Clone ,
43
46
{
44
47
// the order is absolutely critical here we use the old timestamp to detect racy index entries
45
48
// (modified at or after the last index update) during the index update we then set those
@@ -78,16 +81,17 @@ where
78
81
options,
79
82
} ,
80
83
compare,
84
+ submodule,
81
85
find,
82
86
pathspec,
83
87
)
84
88
}
85
89
} ,
86
- |entries, ( state, diff , find, pathspec) | {
90
+ |entries, ( state, blobdiff , submdule , find, pathspec) | {
87
91
entries
88
92
. iter_mut ( )
89
93
. filter_map ( |entry| {
90
- let res = state. process ( entry, diff , find, pathspec) ;
94
+ let res = state. process ( entry, blobdiff , submdule , find, pathspec) ;
91
95
count. fetch_add ( 1 , Ordering :: Relaxed ) ;
92
96
res
93
97
} )
@@ -109,19 +113,21 @@ struct State<'a, 'b> {
109
113
options : & ' a Options ,
110
114
}
111
115
112
- type StatusResult < ' index , T > = Result < ( & ' index gix_index:: Entry , & ' index BStr , Option < Change < T > > , bool ) , Error > ;
116
+ type StatusResult < ' index , T , U > = Result < ( & ' index gix_index:: Entry , & ' index BStr , Option < Change < T , U > > , bool ) , Error > ;
113
117
114
118
impl < ' index > State < ' _ , ' index > {
115
- fn process < T , Find , E > (
119
+ fn process < T , U , Find , E1 , E2 > (
116
120
& mut self ,
117
121
entry : & ' index mut gix_index:: Entry ,
118
122
diff : & mut impl CompareBlobs < Output = T > ,
123
+ submodule : & mut impl SubmoduleStatus < Output = U , Error = E2 > ,
119
124
find : & mut Find ,
120
125
pathspec : & mut impl Pathspec ,
121
- ) -> Option < StatusResult < ' index , T > >
126
+ ) -> Option < StatusResult < ' index , T , U > >
122
127
where
123
- E : std:: error:: Error + Send + Sync + ' static ,
124
- Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > ,
128
+ E1 : std:: error:: Error + Send + Sync + ' static ,
129
+ E2 : std:: error:: Error + Send + Sync + ' static ,
130
+ Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E1 > ,
125
131
{
126
132
let conflict = match entry. stage ( ) {
127
133
0 => false ,
@@ -140,7 +146,7 @@ impl<'index> State<'_, 'index> {
140
146
if !pathspec. is_included ( path, Some ( false ) ) {
141
147
return None ;
142
148
}
143
- let status = self . compute_status ( & mut * entry, path, diff, find) ;
149
+ let status = self . compute_status ( & mut * entry, path, diff, submodule , find) ;
144
150
Some ( status. map ( move |status| ( & * entry, path, status, conflict) ) )
145
151
}
146
152
@@ -183,18 +189,20 @@ impl<'index> State<'_, 'index> {
183
189
/// which is a constant.
184
190
///
185
191
/// Adapted from [here](https://github.com/Byron/gitoxide/pull/805#discussion_r1164676777).
186
- fn compute_status < T , Find , E > (
192
+ fn compute_status < T , U , Find , E1 , E2 > (
187
193
& mut self ,
188
194
entry : & mut gix_index:: Entry ,
189
- git_path : & BStr ,
195
+ rela_path : & BStr ,
190
196
diff : & mut impl CompareBlobs < Output = T > ,
197
+ submodule : & mut impl SubmoduleStatus < Output = U , Error = E2 > ,
191
198
find : & mut Find ,
192
- ) -> Result < Option < Change < T > > , Error >
199
+ ) -> Result < Option < Change < T , U > > , Error >
193
200
where
194
- E : std:: error:: Error + Send + Sync + ' static ,
195
- Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > ,
201
+ E1 : std:: error:: Error + Send + Sync + ' static ,
202
+ E2 : std:: error:: Error + Send + Sync + ' static ,
203
+ Find : for < ' a > FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E1 > ,
196
204
{
197
- let worktree_path = gix_path:: try_from_bstr ( git_path ) . map_err ( |_| Error :: IllformedUtf8 ) ?;
205
+ let worktree_path = gix_path:: try_from_bstr ( rela_path ) . map_err ( |_| Error :: IllformedUtf8 ) ?;
198
206
let worktree_path = match self . path_stack . verified_path ( worktree_path. as_ref ( ) ) {
199
207
Ok ( path) => path,
200
208
Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: NotFound => return Ok ( Some ( Change :: Removed ) ) ,
@@ -206,11 +214,17 @@ impl<'index> State<'_, 'index> {
206
214
// if a file turned into a directory it was removed
207
215
// the only exception here are submodules which are
208
216
// part of the index despite being directories
209
- //
210
- // TODO: submodules:
211
- // if entry.mode.contains(Mode::COMMIT) &&
212
- // resolve_gitlink_ref(ce->name, "HEAD", &sub))
213
- return Ok ( Some ( Change :: Removed ) ) ;
217
+ if entry. mode . is_submodule ( ) {
218
+ let status = submodule
219
+ . status ( entry, rela_path)
220
+ . map_err ( |err| Error :: SubmoduleStatus {
221
+ rela_path : rela_path. into ( ) ,
222
+ source : Box :: new ( err) ,
223
+ } ) ?;
224
+ return Ok ( status. map ( |status| Change :: SubmoduleModification ( status) ) ) ;
225
+ } else {
226
+ return Ok ( Some ( Change :: Removed ) ) ;
227
+ }
214
228
}
215
229
Ok ( metadata) => metadata,
216
230
Err ( err) if err. kind ( ) == io:: ErrorKind :: NotFound => return Ok ( Some ( Change :: Removed ) ) ,
@@ -265,7 +279,7 @@ impl<'index> State<'_, 'index> {
265
279
id : & entry. id ,
266
280
find,
267
281
} ;
268
- let content_change = diff. compare_blobs :: < Error > ( entry, metadata. len ( ) as usize , read_file, read_blob) ?;
282
+ let content_change = diff. compare_blobs ( entry, metadata. len ( ) as usize , read_file, read_blob) ?;
269
283
// This file is racy clean! Set the size to 0 so we keep detecting this as the file is updated.
270
284
if content_change. is_some ( ) && racy_clean {
271
285
entry. stat . size = 0 ;
@@ -288,8 +302,10 @@ struct ReduceChange<'a, 'index, T: VisitEntry<'index>> {
288
302
phantom : PhantomData < fn ( & ' index ( ) ) > ,
289
303
}
290
304
291
- impl < ' index , T , C : VisitEntry < ' index , ContentChange = T > > Reduce for ReduceChange < ' _ , ' index , C > {
292
- type Input = Vec < StatusResult < ' index , T > > ;
305
+ impl < ' index , T , U , C : VisitEntry < ' index , ContentChange = T , SubmoduleStatus = U > > Reduce
306
+ for ReduceChange < ' _ , ' index , C >
307
+ {
308
+ type Input = Vec < StatusResult < ' index , T , U > > ;
293
309
294
310
type FeedProduce = ( ) ;
295
311
@@ -327,7 +343,7 @@ where
327
343
find : Find ,
328
344
}
329
345
330
- impl < ' a > content :: ReadDataOnce < ' a , Error > for WorktreeBlob < ' a > {
346
+ impl < ' a > traits :: ReadDataOnce < ' a > for WorktreeBlob < ' a > {
331
347
fn read_data ( self ) -> Result < & ' a [ u8 ] , Error > {
332
348
let res = read:: data_to_buf_with_meta (
333
349
self . path ,
@@ -339,7 +355,7 @@ impl<'a> content::ReadDataOnce<'a, Error> for WorktreeBlob<'a> {
339
355
}
340
356
}
341
357
342
- impl < ' a , Find , E > content :: ReadDataOnce < ' a , Error > for OdbBlob < ' a , Find , E >
358
+ impl < ' a , Find , E > traits :: ReadDataOnce < ' a > for OdbBlob < ' a , Find , E >
343
359
where
344
360
E : std:: error:: Error + Send + Sync + ' static ,
345
361
Find : FnMut ( & gix_hash:: oid , & ' a mut Vec < u8 > ) -> Result < gix_object:: BlobRef < ' a > , E > ,
0 commit comments