@@ -2163,7 +2163,7 @@ static int handle_content_merge(struct merge_options *opt,
2163
2163
/*
2164
2164
* FIXME: If opt->priv->call_depth && !clean, then we really
2165
2165
* should not make result->mode match either a->mode or
2166
- * b->mode; that causes t6036 "check conflicting mode for
2166
+ * b->mode; that causes t6416 "check conflicting mode for
2167
2167
* regular file" to fail. It would be best to use some other
2168
2168
* mode, but we'll confuse all kinds of stuff if we use one
2169
2169
* where S_ISREG(result->mode) isn't true, and if we use
@@ -2313,14 +2313,20 @@ static char *apply_dir_rename(struct strmap_entry *rename_info,
2313
2313
return strbuf_detach (& new_path , NULL );
2314
2314
}
2315
2315
2316
- static int path_in_way (struct strmap * paths , const char * path , unsigned side_mask )
2316
+ static int path_in_way (struct strmap * paths ,
2317
+ const char * path ,
2318
+ unsigned side_mask ,
2319
+ struct diff_filepair * p )
2317
2320
{
2318
2321
struct merged_info * mi = strmap_get (paths , path );
2319
2322
struct conflict_info * ci ;
2320
2323
if (!mi )
2321
2324
return 0 ;
2322
2325
INITIALIZE_CI (ci , mi );
2323
- return mi -> clean || (side_mask & (ci -> filemask | ci -> dirmask ));
2326
+ return mi -> clean || (side_mask & (ci -> filemask | ci -> dirmask ))
2327
+ // See testcases 12n, 12p, 12q for more details on this next condition
2328
+ || ((ci -> filemask & 0x01 ) &&
2329
+ strcmp (p -> one -> path , path ));
2324
2330
}
2325
2331
2326
2332
/*
@@ -2332,6 +2338,7 @@ static int path_in_way(struct strmap *paths, const char *path, unsigned side_mas
2332
2338
static char * handle_path_level_conflicts (struct merge_options * opt ,
2333
2339
const char * path ,
2334
2340
unsigned side_index ,
2341
+ struct diff_filepair * p ,
2335
2342
struct strmap_entry * rename_info ,
2336
2343
struct strmap * collisions )
2337
2344
{
@@ -2366,7 +2373,7 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
2366
2373
*/
2367
2374
if (c_info -> reported_already ) {
2368
2375
clean = 0 ;
2369
- } else if (path_in_way (& opt -> priv -> paths , new_path , 1 << side_index )) {
2376
+ } else if (path_in_way (& opt -> priv -> paths , new_path , 1 << side_index , p )) {
2370
2377
c_info -> reported_already = 1 ;
2371
2378
strbuf_add_separated_string_list (& collision_paths , ", " ,
2372
2379
& c_info -> source_files );
@@ -2520,7 +2527,7 @@ static void compute_collisions(struct strmap *collisions,
2520
2527
* happening, and fall back to no-directory-rename detection
2521
2528
* behavior for those paths.
2522
2529
*
2523
- * See testcases 9e and all of section 5 from t6043 for examples.
2530
+ * See testcases 9e and all of section 5 from t6423 for examples.
2524
2531
*/
2525
2532
for (i = 0 ; i < pairs -> nr ; ++ i ) {
2526
2533
struct strmap_entry * rename_info ;
@@ -2573,14 +2580,14 @@ static void free_collisions(struct strmap *collisions)
2573
2580
static char * check_for_directory_rename (struct merge_options * opt ,
2574
2581
const char * path ,
2575
2582
unsigned side_index ,
2583
+ struct diff_filepair * p ,
2576
2584
struct strmap * dir_renames ,
2577
2585
struct strmap * dir_rename_exclusions ,
2578
2586
struct strmap * collisions ,
2579
2587
int * clean_merge )
2580
2588
{
2581
2589
char * new_path ;
2582
2590
struct strmap_entry * rename_info ;
2583
- struct strmap_entry * otherinfo ;
2584
2591
const char * new_dir ;
2585
2592
int other_side = 3 - side_index ;
2586
2593
@@ -2615,14 +2622,13 @@ static char *check_for_directory_rename(struct merge_options *opt,
2615
2622
* to not let Side1 do the rename to dumbdir, since we know that is
2616
2623
* the source of one of our directory renames.
2617
2624
*
2618
- * That's why otherinfo and dir_rename_exclusions is here.
2625
+ * That's why dir_rename_exclusions is here.
2619
2626
*
2620
2627
* As it turns out, this also prevents N-way transient rename
2621
- * confusion; See testcases 9c and 9d of t6043 .
2628
+ * confusion; See testcases 9c and 9d of t6423 .
2622
2629
*/
2623
2630
new_dir = rename_info -> value ; /* old_dir = rename_info->key; */
2624
- otherinfo = strmap_get_entry (dir_rename_exclusions , new_dir );
2625
- if (otherinfo ) {
2631
+ if (strmap_contains (dir_rename_exclusions , new_dir )) {
2626
2632
path_msg (opt , INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME , 1 ,
2627
2633
rename_info -> key , path , new_dir , NULL ,
2628
2634
_ ("WARNING: Avoiding applying %s -> %s rename "
@@ -2631,7 +2637,7 @@ static char *check_for_directory_rename(struct merge_options *opt,
2631
2637
return NULL ;
2632
2638
}
2633
2639
2634
- new_path = handle_path_level_conflicts (opt , path , side_index ,
2640
+ new_path = handle_path_level_conflicts (opt , path , side_index , p ,
2635
2641
rename_info ,
2636
2642
& collisions [side_index ]);
2637
2643
* clean_merge &= (new_path != NULL );
@@ -2875,6 +2881,17 @@ static int process_renames(struct merge_options *opt,
2875
2881
newinfo = new_ent -> value ;
2876
2882
}
2877
2883
2884
+ /*
2885
+ * Directory renames can result in rename-to-self, which we
2886
+ * want to skip so we don't mark oldpath for deletion.
2887
+ *
2888
+ * Note that we can avoid strcmp here because of prior
2889
+ * diligence in apply_directory_rename_modifications() to
2890
+ * ensure we reused existing paths from opt->priv->paths.
2891
+ */
2892
+ if (oldpath == newpath )
2893
+ continue ;
2894
+
2878
2895
/*
2879
2896
* If pair->one->path isn't in opt->priv->paths, that means
2880
2897
* that either directory rename detection removed that
@@ -3419,7 +3436,7 @@ static int collect_renames(struct merge_options *opt,
3419
3436
}
3420
3437
3421
3438
new_path = check_for_directory_rename (opt , p -> two -> path ,
3422
- side_index ,
3439
+ side_index , p ,
3423
3440
dir_renames_for_side ,
3424
3441
rename_exclusions ,
3425
3442
collisions ,
0 commit comments