@@ -172,7 +172,10 @@ impl<T: Change> Tracker<T> {
172
172
. relation ( )
173
173
. filter ( |_| matches ! ( change_kind, ChangeKind :: Addition | ChangeKind :: Deletion ) ) ;
174
174
let entry_kind = change. entry_mode ( ) . kind ( ) ;
175
- if let ( None | Some ( Relation :: ChildOfParent ( _) ) , EntryKind :: Commit | EntryKind :: Tree ) = ( relation, entry_kind) {
175
+ if entry_kind == EntryKind :: Commit {
176
+ return Some ( change) ;
177
+ }
178
+ if let ( None , EntryKind :: Tree ) = ( relation, entry_kind) {
176
179
return Some ( change) ;
177
180
} ;
178
181
@@ -221,27 +224,46 @@ impl<T: Change> Tracker<T> {
221
224
PushSourceTreeFn : FnMut ( & mut dyn FnMut ( T , & BStr ) ) -> Result < ( ) , E > ,
222
225
E : std:: error:: Error + Send + Sync + ' static ,
223
226
{
227
+ fn is_parent ( change : & impl Change ) -> bool {
228
+ matches ! ( change. relation( ) , Some ( Relation :: Parent ( _) ) )
229
+ }
224
230
diff_cache. options . skip_internal_diff_if_external_is_configured = false ;
225
231
232
+ // The point of this is to optimize for identity-based lookups, which should be easy to find
233
+ // by partitioning.
226
234
fn by_id_and_location < T : Change > ( a : & Item < T > , b : & Item < T > ) -> std:: cmp:: Ordering {
227
235
a. change
228
236
. id ( )
229
237
. cmp ( b. change . id ( ) )
230
238
. then_with ( || a. path . start . cmp ( & b. path . start ) . then ( a. path . end . cmp ( & b. path . end ) ) )
231
239
}
232
- self . items . sort_by ( by_id_and_location) ;
233
240
234
241
let mut out = Outcome {
235
242
options : self . rewrites ,
236
243
..Default :: default ( )
237
244
} ;
245
+ self . items . sort_by ( by_id_and_location) ;
246
+
247
+ // Rewrites by directory can be pruned out quickly, quickly pruning candidates
248
+ // for the following per-item steps.
249
+ self . match_pairs_of_kind (
250
+ visit:: SourceKind :: Rename ,
251
+ & mut cb,
252
+ None , /* by identity for parents */
253
+ & mut out,
254
+ diff_cache,
255
+ objects,
256
+ Some ( is_parent) ,
257
+ ) ?;
258
+
238
259
self . match_pairs_of_kind (
239
260
visit:: SourceKind :: Rename ,
240
261
& mut cb,
241
262
self . rewrites . percentage ,
242
263
& mut out,
243
264
diff_cache,
244
265
objects,
266
+ None ,
245
267
) ?;
246
268
247
269
if let Some ( copies) = self . rewrites . copies {
@@ -252,6 +274,7 @@ impl<T: Change> Tracker<T> {
252
274
& mut out,
253
275
diff_cache,
254
276
objects,
277
+ None ,
255
278
) ?;
256
279
257
280
match copies. source {
@@ -275,6 +298,7 @@ impl<T: Change> Tracker<T> {
275
298
& mut out,
276
299
diff_cache,
277
300
objects,
301
+ None ,
278
302
) ?;
279
303
}
280
304
}
@@ -299,6 +323,7 @@ impl<T: Change> Tracker<T> {
299
323
}
300
324
301
325
impl < T : Change > Tracker < T > {
326
+ #[ allow( clippy:: too_many_arguments) ]
302
327
fn match_pairs_of_kind (
303
328
& mut self ,
304
329
kind : visit:: SourceKind ,
@@ -307,10 +332,11 @@ impl<T: Change> Tracker<T> {
307
332
out : & mut Outcome ,
308
333
diff_cache : & mut crate :: blob:: Platform ,
309
334
objects : & impl gix_object:: FindObjectOrHeader ,
335
+ filter : Option < fn ( & T ) -> bool > ,
310
336
) -> Result < ( ) , emit:: Error > {
311
337
// we try to cheaply reduce the set of possibilities first, before possibly looking more exhaustively.
312
338
let needs_second_pass = !needs_exact_match ( percentage) ;
313
- if self . match_pairs ( cb, None /* by identity */ , kind, out, diff_cache, objects) ? == Action :: Cancel {
339
+ if self . match_pairs ( cb, None /* by identity */ , kind, out, diff_cache, objects, filter ) ? == Action :: Cancel {
314
340
return Ok ( ( ) ) ;
315
341
}
316
342
if needs_second_pass {
@@ -335,12 +361,13 @@ impl<T: Change> Tracker<T> {
335
361
}
336
362
} ;
337
363
if !is_limited {
338
- self . match_pairs ( cb, percentage, kind, out, diff_cache, objects) ?;
364
+ self . match_pairs ( cb, percentage, kind, out, diff_cache, objects, None ) ?;
339
365
}
340
366
}
341
367
Ok ( ( ) )
342
368
}
343
369
370
+ #[ allow( clippy:: too_many_arguments) ]
344
371
fn match_pairs (
345
372
& mut self ,
346
373
cb : & mut impl FnMut ( visit:: Destination < ' _ , T > , Option < visit:: Source < ' _ , T > > ) -> Action ,
@@ -349,10 +376,14 @@ impl<T: Change> Tracker<T> {
349
376
stats : & mut Outcome ,
350
377
diff_cache : & mut crate :: blob:: Platform ,
351
378
objects : & impl gix_object:: FindObjectOrHeader ,
379
+ filter : Option < fn ( & T ) -> bool > ,
352
380
) -> Result < Action , emit:: Error > {
353
381
let mut dest_ofs = 0 ;
354
382
while let Some ( ( mut dest_idx, dest) ) = self . items [ dest_ofs..] . iter ( ) . enumerate ( ) . find_map ( |( idx, item) | {
355
- ( !item. emitted && matches ! ( item. change. kind( ) , ChangeKind :: Addition ) ) . then_some ( ( idx, item) )
383
+ ( !item. emitted
384
+ && matches ! ( item. change. kind( ) , ChangeKind :: Addition )
385
+ && filter. map_or ( true , |f| f ( & item. change ) ) )
386
+ . then_some ( ( idx, item) )
356
387
} ) {
357
388
dest_idx += dest_ofs;
358
389
dest_ofs = dest_idx + 1 ;
0 commit comments