mirror of
https://github.com/git/git.git
synced 2024-11-27 12:03:55 +08:00
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
This commit is contained in:
commit
969230b64f
36
merge-ort.c
36
merge-ort.c
@ -2619,8 +2619,40 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
|
||||
}
|
||||
|
||||
assert(ci->filemask == 2 || ci->filemask == 4);
|
||||
assert(ci->dirmask == 0);
|
||||
strmap_remove(&opt->priv->paths, old_path, 0);
|
||||
assert(ci->dirmask == 0 || ci->dirmask == 1);
|
||||
if (ci->dirmask == 0)
|
||||
strmap_remove(&opt->priv->paths, old_path, 0);
|
||||
else {
|
||||
/*
|
||||
* This file exists on one side, but we still had a directory
|
||||
* at the old location that we can't remove until after
|
||||
* processing all paths below it. So, make a copy of ci in
|
||||
* new_ci and only put the file information into it.
|
||||
*/
|
||||
new_ci = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*new_ci));
|
||||
memcpy(new_ci, ci, sizeof(*ci));
|
||||
assert(!new_ci->match_mask);
|
||||
new_ci->dirmask = 0;
|
||||
new_ci->stages[1].mode = 0;
|
||||
oidcpy(&new_ci->stages[1].oid, null_oid());
|
||||
|
||||
/*
|
||||
* Now that we have the file information in new_ci, make sure
|
||||
* ci only has the directory information.
|
||||
*/
|
||||
ci->filemask = 0;
|
||||
ci->merged.clean = 1;
|
||||
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
|
||||
if (ci->dirmask & (1 << i))
|
||||
continue;
|
||||
/* zero out any entries related to files */
|
||||
ci->stages[i].mode = 0;
|
||||
oidcpy(&ci->stages[i].oid, null_oid());
|
||||
}
|
||||
|
||||
// Now we want to focus on new_ci, so reassign ci to it
|
||||
ci = new_ci;
|
||||
}
|
||||
|
||||
branch_with_new_path = (ci->filemask == 2) ? opt->branch1 : opt->branch2;
|
||||
branch_with_dir_rename = (ci->filemask == 2) ? opt->branch2 : opt->branch1;
|
||||
|
@ -5304,6 +5304,62 @@ test_expect_merge_algorithm failure success '12l (A into B): Rename into each ot
|
||||
)
|
||||
'
|
||||
|
||||
# Testcase 12m, Directory rename, plus change of parent dir to symlink
|
||||
# Commit O: dir/subdir/file
|
||||
# Commit A: renamed-dir/subdir/file
|
||||
# Commit B: dir/subdir
|
||||
# In words:
|
||||
# A: dir/subdir/ -> renamed-dir/subdir
|
||||
# B: delete dir/subdir/file, add dir/subdir as symlink
|
||||
#
|
||||
# Expected: CONFLICT (rename/delete): renamed-dir/subdir/file,
|
||||
# CONFLICT (file location): renamed-dir/subdir vs. dir/subdir
|
||||
# CONFLICT (directory/file): renamed-dir/subdir symlink has
|
||||
# renamed-dir/subdir in the way
|
||||
|
||||
test_setup_12m () {
|
||||
git init 12m &&
|
||||
(
|
||||
cd 12m &&
|
||||
|
||||
mkdir -p dir/subdir &&
|
||||
echo 1 >dir/subdir/file &&
|
||||
git add . &&
|
||||
git commit -m "O" &&
|
||||
|
||||
git branch O &&
|
||||
git branch A &&
|
||||
git branch B &&
|
||||
|
||||
git switch A &&
|
||||
git mv dir/ renamed-dir/ &&
|
||||
git add . &&
|
||||
git commit -m "A" &&
|
||||
|
||||
git switch B &&
|
||||
git rm dir/subdir/file &&
|
||||
mkdir dir &&
|
||||
ln -s /dev/null dir/subdir &&
|
||||
git add . &&
|
||||
git commit -m "B"
|
||||
)
|
||||
}
|
||||
|
||||
test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir to symlink on other side' '
|
||||
test_setup_12m &&
|
||||
(
|
||||
cd 12m &&
|
||||
|
||||
git checkout -q A^0 &&
|
||||
|
||||
test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
|
||||
|
||||
test_stdout_line_count = 3 git ls-files -s &&
|
||||
test_stdout_line_count = 2 ls -1 renamed-dir &&
|
||||
test_path_is_missing dir
|
||||
)
|
||||
'
|
||||
|
||||
###########################################################################
|
||||
# SECTION 13: Checking informational and conflict messages
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user