@@ -2344,6 +2344,67 @@ static void resolve_diffpair_statuses(struct diff_queue_struct *q)
2344
2344
}
2345
2345
}
2346
2346
2347
+ static void cache_new_pair (struct rename_info * renames ,
2348
+ int side ,
2349
+ char * old_path ,
2350
+ char * new_path ,
2351
+ int free_old_value )
2352
+ {
2353
+ char * old_value ;
2354
+ new_path = xstrdup (new_path );
2355
+ old_value = strmap_put (& renames -> cached_pairs [side ],
2356
+ old_path , new_path );
2357
+ strset_add (& renames -> cached_target_names [side ], new_path );
2358
+ if (free_old_value )
2359
+ free (old_value );
2360
+ else
2361
+ assert (!old_value );
2362
+ }
2363
+
2364
+ static void possibly_cache_new_pair (struct rename_info * renames ,
2365
+ struct diff_filepair * p ,
2366
+ unsigned side ,
2367
+ char * new_path )
2368
+ {
2369
+ int dir_renamed_side = 0 ;
2370
+
2371
+ if (new_path ) {
2372
+ /*
2373
+ * Directory renames happen on the other side of history from
2374
+ * the side that adds new files to the old directory.
2375
+ */
2376
+ dir_renamed_side = 3 - side ;
2377
+ } else {
2378
+ int val = strintmap_get (& renames -> relevant_sources [side ],
2379
+ p -> one -> path );
2380
+ if (val == RELEVANT_NO_MORE ) {
2381
+ assert (p -> status == 'D' );
2382
+ strset_add (& renames -> cached_irrelevant [side ],
2383
+ p -> one -> path );
2384
+ }
2385
+ if (val <= 0 )
2386
+ return ;
2387
+ }
2388
+
2389
+ if (p -> status == 'D' ) {
2390
+ /*
2391
+ * If we already had this delete, we'll just set it's value
2392
+ * to NULL again, so no harm.
2393
+ */
2394
+ strmap_put (& renames -> cached_pairs [side ], p -> one -> path , NULL );
2395
+ } else if (p -> status == 'R' ) {
2396
+ if (!new_path )
2397
+ new_path = p -> two -> path ;
2398
+ else
2399
+ cache_new_pair (renames , dir_renamed_side ,
2400
+ p -> two -> path , new_path , 0 );
2401
+ cache_new_pair (renames , side , p -> one -> path , new_path , 1 );
2402
+ } else if (p -> status == 'A' && new_path ) {
2403
+ cache_new_pair (renames , dir_renamed_side ,
2404
+ p -> two -> path , new_path , 0 );
2405
+ }
2406
+ }
2407
+
2347
2408
static int compare_pairs (const void * a_ , const void * b_ )
2348
2409
{
2349
2410
const struct diff_filepair * a = * ((const struct diff_filepair * * )a_ );
@@ -2426,6 +2487,7 @@ static int collect_renames(struct merge_options *opt,
2426
2487
char * new_path ; /* non-NULL only with directory renames */
2427
2488
2428
2489
if (p -> status != 'A' && p -> status != 'R' ) {
2490
+ possibly_cache_new_pair (renames , p , side_index , NULL );
2429
2491
diff_free_filepair (p );
2430
2492
continue ;
2431
2493
}
@@ -2437,6 +2499,7 @@ static int collect_renames(struct merge_options *opt,
2437
2499
& collisions ,
2438
2500
& clean );
2439
2501
2502
+ possibly_cache_new_pair (renames , p , side_index , new_path );
2440
2503
if (p -> status != 'R' && !new_path ) {
2441
2504
diff_free_filepair (p );
2442
2505
continue ;
@@ -3720,8 +3783,16 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
3720
3783
NULL , 1 );
3721
3784
strmap_init_with_options (& renames -> dir_renames [i ],
3722
3785
NULL , 0 );
3786
+ /*
3787
+ * relevant_sources uses -1 for the default, because we need
3788
+ * to be able to distinguish not-in-strintmap from valid
3789
+ * relevant_source values from enum file_rename_relevance.
3790
+ * In particular, possibly_cache_new_pair() expects a negative
3791
+ * value for not-found entries.
3792
+ */
3723
3793
strintmap_init_with_options (& renames -> relevant_sources [i ],
3724
- 0 , NULL , 0 );
3794
+ -1 /* explicitly invalid */ ,
3795
+ NULL , 0 );
3725
3796
strmap_init_with_options (& renames -> cached_pairs [i ],
3726
3797
NULL , 1 );
3727
3798
strset_init_with_options (& renames -> cached_irrelevant [i ],
0 commit comments