merge-recursive: avoid clobbering untracked files with directory renames
Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
3b9616f149
commit
7b3d3b0681
|
@ -1141,6 +1141,26 @@ static int conflict_rename_dir(struct merge_options *o,
|
||||||
{
|
{
|
||||||
const struct diff_filespec *dest = pair->two;
|
const struct diff_filespec *dest = pair->two;
|
||||||
|
|
||||||
|
if (!o->call_depth && would_lose_untracked(dest->path)) {
|
||||||
|
char *alt_path = unique_path(o, dest->path, rename_branch);
|
||||||
|
|
||||||
|
output(o, 1, _("Error: Refusing to lose untracked file at %s; "
|
||||||
|
"writing to %s instead."),
|
||||||
|
dest->path, alt_path);
|
||||||
|
/*
|
||||||
|
* Write the file in worktree at alt_path, but not in the
|
||||||
|
* index. Instead, write to dest->path for the index but
|
||||||
|
* only at the higher appropriate stage.
|
||||||
|
*/
|
||||||
|
if (update_file(o, 0, &dest->oid, dest->mode, alt_path))
|
||||||
|
return -1;
|
||||||
|
free(alt_path);
|
||||||
|
return update_stages(o, dest->path, NULL,
|
||||||
|
rename_branch == o->branch1 ? dest : NULL,
|
||||||
|
rename_branch == o->branch1 ? NULL : dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update dest->path both in index and in worktree */
|
||||||
if (update_file(o, 1, &dest->oid, dest->mode, dest->path))
|
if (update_file(o, 1, &dest->oid, dest->mode, dest->path))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1159,7 +1179,8 @@ static int handle_change_delete(struct merge_options *o,
|
||||||
const char *update_path = path;
|
const char *update_path = path;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (dir_in_way(path, !o->call_depth, 0)) {
|
if (dir_in_way(path, !o->call_depth, 0) ||
|
||||||
|
(!o->call_depth && would_lose_untracked(path))) {
|
||||||
update_path = alt_path = unique_path(o, path, change_branch);
|
update_path = alt_path = unique_path(o, path, change_branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1285,6 +1306,12 @@ static int handle_file(struct merge_options *o,
|
||||||
dst_name = unique_path(o, rename->path, cur_branch);
|
dst_name = unique_path(o, rename->path, cur_branch);
|
||||||
output(o, 1, _("%s is a directory in %s adding as %s instead"),
|
output(o, 1, _("%s is a directory in %s adding as %s instead"),
|
||||||
rename->path, other_branch, dst_name);
|
rename->path, other_branch, dst_name);
|
||||||
|
} else if (!o->call_depth &&
|
||||||
|
would_lose_untracked(rename->path)) {
|
||||||
|
dst_name = unique_path(o, rename->path, cur_branch);
|
||||||
|
output(o, 1, _("Refusing to lose untracked file at %s; "
|
||||||
|
"adding as %s instead"),
|
||||||
|
rename->path, dst_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ret = update_file(o, 0, &rename->oid, rename->mode, dst_name)))
|
if ((ret = update_file(o, 0, &rename->oid, rename->mode, dst_name)))
|
||||||
|
@ -1410,7 +1437,18 @@ static int conflict_rename_rename_2to1(struct merge_options *o,
|
||||||
char *new_path2 = unique_path(o, path, ci->branch2);
|
char *new_path2 = unique_path(o, path, ci->branch2);
|
||||||
output(o, 1, _("Renaming %s to %s and %s to %s instead"),
|
output(o, 1, _("Renaming %s to %s and %s to %s instead"),
|
||||||
a->path, new_path1, b->path, new_path2);
|
a->path, new_path1, b->path, new_path2);
|
||||||
remove_file(o, 0, path, 0);
|
if (would_lose_untracked(path))
|
||||||
|
/*
|
||||||
|
* Only way we get here is if both renames were from
|
||||||
|
* a directory rename AND user had an untracked file
|
||||||
|
* at the location where both files end up after the
|
||||||
|
* two directory renames. See testcase 10d of t6043.
|
||||||
|
*/
|
||||||
|
output(o, 1, _("Refusing to lose untracked file at "
|
||||||
|
"%s, even though it's in the way."),
|
||||||
|
path);
|
||||||
|
else
|
||||||
|
remove_file(o, 0, path, 0);
|
||||||
ret = update_file(o, 0, &mfi_c1.oid, mfi_c1.mode, new_path1);
|
ret = update_file(o, 0, &mfi_c1.oid, mfi_c1.mode, new_path1);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = update_file(o, 0, &mfi_c2.oid, mfi_c2.mode,
|
ret = update_file(o, 0, &mfi_c2.oid, mfi_c2.mode,
|
||||||
|
|
|
@ -2992,7 +2992,7 @@ test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure '10b-check: Overwrite untracked with dir rename + delete' '
|
test_expect_success '10b-check: Overwrite untracked with dir rename + delete' '
|
||||||
(
|
(
|
||||||
cd 10b &&
|
cd 10b &&
|
||||||
|
|
||||||
|
@ -3070,7 +3070,7 @@ test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2)
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure '10c-check: Overwrite untracked with dir rename/rename(1to2)' '
|
test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2)' '
|
||||||
(
|
(
|
||||||
cd 10c &&
|
cd 10c &&
|
||||||
|
|
||||||
|
@ -3145,7 +3145,7 @@ test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_failure '10d-check: Delete untracked with dir rename/rename(2to1)' '
|
test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' '
|
||||||
(
|
(
|
||||||
cd 10d &&
|
cd 10d &&
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue