Skip to content

Commit ca80e10

Browse files
committed
Merge branch 'en/ort-rename-fixes' into seen
Various bugs about rename handling in "ort" merge strategy have been fixed. * en/ort-rename-fixes: merge-ort: fix directory rename on top of source of other rename/delete merge-ort: fix incorrect file handling t6423: fix missed staging of file in testcases 12i,12j,12k t6423: document two bugs with rename-to-self testcases merge-ort: drop unnecessary temporary in check_for_directory_rename() merge-ort: update comments to modern testfile location
2 parents e2c8e7e + 6e44390 commit ca80e10

File tree

2 files changed

+534
-27
lines changed

2 files changed

+534
-27
lines changed

merge-ort.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,7 @@ static int handle_content_merge(struct merge_options *opt,
21632163
/*
21642164
* FIXME: If opt->priv->call_depth && !clean, then we really
21652165
* 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
21672167
* regular file" to fail. It would be best to use some other
21682168
* mode, but we'll confuse all kinds of stuff if we use one
21692169
* 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,
23132313
return strbuf_detach(&new_path, NULL);
23142314
}
23152315

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)
23172320
{
23182321
struct merged_info *mi = strmap_get(paths, path);
23192322
struct conflict_info *ci;
23202323
if (!mi)
23212324
return 0;
23222325
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));
23242330
}
23252331

23262332
/*
@@ -2332,6 +2338,7 @@ static int path_in_way(struct strmap *paths, const char *path, unsigned side_mas
23322338
static char *handle_path_level_conflicts(struct merge_options *opt,
23332339
const char *path,
23342340
unsigned side_index,
2341+
struct diff_filepair *p,
23352342
struct strmap_entry *rename_info,
23362343
struct strmap *collisions)
23372344
{
@@ -2366,7 +2373,7 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
23662373
*/
23672374
if (c_info->reported_already) {
23682375
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)) {
23702377
c_info->reported_already = 1;
23712378
strbuf_add_separated_string_list(&collision_paths, ", ",
23722379
&c_info->source_files);
@@ -2520,7 +2527,7 @@ static void compute_collisions(struct strmap *collisions,
25202527
* happening, and fall back to no-directory-rename detection
25212528
* behavior for those paths.
25222529
*
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.
25242531
*/
25252532
for (i = 0; i < pairs->nr; ++i) {
25262533
struct strmap_entry *rename_info;
@@ -2573,14 +2580,14 @@ static void free_collisions(struct strmap *collisions)
25732580
static char *check_for_directory_rename(struct merge_options *opt,
25742581
const char *path,
25752582
unsigned side_index,
2583+
struct diff_filepair *p,
25762584
struct strmap *dir_renames,
25772585
struct strmap *dir_rename_exclusions,
25782586
struct strmap *collisions,
25792587
int *clean_merge)
25802588
{
25812589
char *new_path;
25822590
struct strmap_entry *rename_info;
2583-
struct strmap_entry *otherinfo;
25842591
const char *new_dir;
25852592
int other_side = 3 - side_index;
25862593

@@ -2615,14 +2622,13 @@ static char *check_for_directory_rename(struct merge_options *opt,
26152622
* to not let Side1 do the rename to dumbdir, since we know that is
26162623
* the source of one of our directory renames.
26172624
*
2618-
* That's why otherinfo and dir_rename_exclusions is here.
2625+
* That's why dir_rename_exclusions is here.
26192626
*
26202627
* 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.
26222629
*/
26232630
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)) {
26262632
path_msg(opt, INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME, 1,
26272633
rename_info->key, path, new_dir, NULL,
26282634
_("WARNING: Avoiding applying %s -> %s rename "
@@ -2631,7 +2637,7 @@ static char *check_for_directory_rename(struct merge_options *opt,
26312637
return NULL;
26322638
}
26332639

2634-
new_path = handle_path_level_conflicts(opt, path, side_index,
2640+
new_path = handle_path_level_conflicts(opt, path, side_index, p,
26352641
rename_info,
26362642
&collisions[side_index]);
26372643
*clean_merge &= (new_path != NULL);
@@ -2875,6 +2881,17 @@ static int process_renames(struct merge_options *opt,
28752881
newinfo = new_ent->value;
28762882
}
28772883

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+
28782895
/*
28792896
* If pair->one->path isn't in opt->priv->paths, that means
28802897
* that either directory rename detection removed that
@@ -3419,7 +3436,7 @@ static int collect_renames(struct merge_options *opt,
34193436
}
34203437

34213438
new_path = check_for_directory_rename(opt, p->two->path,
3422-
side_index,
3439+
side_index, p,
34233440
dir_renames_for_side,
34243441
rename_exclusions,
34253442
collisions,

0 commit comments

Comments
 (0)