Skip to content

Commit

Permalink
merge-ort: add implementation of type-changed rename handling
Browse files Browse the repository at this point in the history
Implement cases where renames are involved in type changes (i.e. the
side of history that didn't rename the file changed its type from a
regular file to a symlink or submodule).  There was some code to handle
this in merge-recursive but only in the special case when the renamed
file had no content changes.  The code here works differently -- it
knows process_entry() can handle mode conflicts, so it does a few
minimal tweaks to ensure process_entry() can just finish the job as
needed.

Signed-off-by: Elijah Newren <newren@gmail.com>
  • Loading branch information
newren committed Dec 13, 2020
1 parent 2fc5afb commit 9e0a3a6
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions merge-ort.c
Expand Up @@ -778,7 +778,32 @@ static int process_renames(struct merge_options *opt,
S_ISREG(newinfo->stages[target_index].mode));
if (type_changed && collision) {
/* special handling so later blocks can handle this */
die("Not yet implemented");
/*
* if type_changed && collision are both true, then this
* was really a double rename, but one side wasn't
* detected due to lack of break detection. I.e.
* something like
* orig: has normal file 'foo'
* side1: renames 'foo' to 'bar', adds 'foo' symlink
* side2: renames 'foo' to 'bar'
* In this case, the foo->bar rename on side1 won't be
* detected because the new symlink named 'foo' is
* there and we don't do break detection. But we detect
* this here because we don't want to merge the content
* of the foo symlink with the foo->bar file, so we
* have some logic to handle this special case. The
* easiest way to do that is make 'bar' on side1 not
* be considered a colliding file but the other part
* of a normal rename. If the file is very different,
* well we're going to get content merge conflicts
* anyway so it doesn't hurt. And if the colliding
* file also has a different type, that'll be handled
* by the content merge logic in process_entry() too.
*
* See also t6430, 'rename vs. rename/symlink'
*/
collision = 0;
}
if (source_deleted) {
if (target_index == 1) {
rename_branch = opt->branch1;
Expand Down Expand Up @@ -858,7 +883,11 @@ static int process_renames(struct merge_options *opt,
newinfo->pathnames[0] = oldpath;
if (type_changed) {
/* rename vs. typechange */
die("Not yet implemented");
/* Mark the original as resolved by removal */
memcpy(&oldinfo->stages[0].oid, &null_oid,
sizeof(oldinfo->stages[0].oid));
oldinfo->stages[0].mode = 0;
oldinfo->filemask &= 0x06;
} else if (source_deleted) {
/* rename/delete */
newinfo->path_conflict = 1;
Expand Down

0 comments on commit 9e0a3a6

Please sign in to comment.