Skip to content

Commit 969230b

Browse files
committed
Merge branch 'en/ort-dir-rename-and-symlink-fix'
Merging a branch with directory renames into a branch that changes the directory to a symlink was mishandled by the ort merge strategy, which has been corrected. * en/ort-dir-rename-and-symlink-fix: merge-ort: fix bug with dir rename vs change dir to symlink
2 parents a23e0b6 + 2b86c10 commit 969230b

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

merge-ort.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,8 +2619,40 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
26192619
}
26202620

26212621
assert(ci->filemask == 2 || ci->filemask == 4);
2622-
assert(ci->dirmask == 0);
2623-
strmap_remove(&opt->priv->paths, old_path, 0);
2622+
assert(ci->dirmask == 0 || ci->dirmask == 1);
2623+
if (ci->dirmask == 0)
2624+
strmap_remove(&opt->priv->paths, old_path, 0);
2625+
else {
2626+
/*
2627+
* This file exists on one side, but we still had a directory
2628+
* at the old location that we can't remove until after
2629+
* processing all paths below it. So, make a copy of ci in
2630+
* new_ci and only put the file information into it.
2631+
*/
2632+
new_ci = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*new_ci));
2633+
memcpy(new_ci, ci, sizeof(*ci));
2634+
assert(!new_ci->match_mask);
2635+
new_ci->dirmask = 0;
2636+
new_ci->stages[1].mode = 0;
2637+
oidcpy(&new_ci->stages[1].oid, null_oid());
2638+
2639+
/*
2640+
* Now that we have the file information in new_ci, make sure
2641+
* ci only has the directory information.
2642+
*/
2643+
ci->filemask = 0;
2644+
ci->merged.clean = 1;
2645+
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
2646+
if (ci->dirmask & (1 << i))
2647+
continue;
2648+
/* zero out any entries related to files */
2649+
ci->stages[i].mode = 0;
2650+
oidcpy(&ci->stages[i].oid, null_oid());
2651+
}
2652+
2653+
// Now we want to focus on new_ci, so reassign ci to it
2654+
ci = new_ci;
2655+
}
26242656

26252657
branch_with_new_path = (ci->filemask == 2) ? opt->branch1 : opt->branch2;
26262658
branch_with_dir_rename = (ci->filemask == 2) ? opt->branch2 : opt->branch1;

t/t6423-merge-rename-directories.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5304,6 +5304,62 @@ test_expect_merge_algorithm failure success '12l (A into B): Rename into each ot
53045304
)
53055305
'
53065306

5307+
# Testcase 12m, Directory rename, plus change of parent dir to symlink
5308+
# Commit O: dir/subdir/file
5309+
# Commit A: renamed-dir/subdir/file
5310+
# Commit B: dir/subdir
5311+
# In words:
5312+
# A: dir/subdir/ -> renamed-dir/subdir
5313+
# B: delete dir/subdir/file, add dir/subdir as symlink
5314+
#
5315+
# Expected: CONFLICT (rename/delete): renamed-dir/subdir/file,
5316+
# CONFLICT (file location): renamed-dir/subdir vs. dir/subdir
5317+
# CONFLICT (directory/file): renamed-dir/subdir symlink has
5318+
# renamed-dir/subdir in the way
5319+
5320+
test_setup_12m () {
5321+
git init 12m &&
5322+
(
5323+
cd 12m &&
5324+
5325+
mkdir -p dir/subdir &&
5326+
echo 1 >dir/subdir/file &&
5327+
git add . &&
5328+
git commit -m "O" &&
5329+
5330+
git branch O &&
5331+
git branch A &&
5332+
git branch B &&
5333+
5334+
git switch A &&
5335+
git mv dir/ renamed-dir/ &&
5336+
git add . &&
5337+
git commit -m "A" &&
5338+
5339+
git switch B &&
5340+
git rm dir/subdir/file &&
5341+
mkdir dir &&
5342+
ln -s /dev/null dir/subdir &&
5343+
git add . &&
5344+
git commit -m "B"
5345+
)
5346+
}
5347+
5348+
test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir to symlink on other side' '
5349+
test_setup_12m &&
5350+
(
5351+
cd 12m &&
5352+
5353+
git checkout -q A^0 &&
5354+
5355+
test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
5356+
5357+
test_stdout_line_count = 3 git ls-files -s &&
5358+
test_stdout_line_count = 2 ls -1 renamed-dir &&
5359+
test_path_is_missing dir
5360+
)
5361+
'
5362+
53075363
###########################################################################
53085364
# SECTION 13: Checking informational and conflict messages
53095365
#

0 commit comments

Comments
 (0)