diff options
author | Junio C Hamano <gitster@pobox.com> | 2009-07-30 17:38:15 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2009-07-30 19:25:05 -0700 |
commit | c94736a27f89bfc268aed0de7264deecdc136a58 (patch) | |
tree | e8307e0e18ce73552f826928d5bcd85325e366e8 /merge-recursive.c | |
parent | 4258c212ca2c3674be4b7e00a19db705eee77a48 (diff) | |
download | git-c94736a27f89bfc268aed0de7264deecdc136a58.tar.gz |
merge-recursive: don't segfault while handling rename clashes
When a branch moves A to B while the other branch created B (or moved C to
B), the code tried to rename one of them to B~something to preserve both
versions, and failed to register temporary resolution for the original
path B at stage#0 during virtual ancestor computation. This left the
index in unmerged state and caused a segfault.
A better solution is to merge these two versions of B's in place and use
the (potentially conflicting) result as the intermediate merge result in
the virtual ancestor.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-recursive.c')
-rw-r--r-- | merge-recursive.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/merge-recursive.c b/merge-recursive.c index b97026bd5c..54d23b214c 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -947,9 +947,31 @@ static int process_renames(struct merge_options *o, "%s added in %s", ren1_src, ren1_dst, branch1, ren1_dst, branch2); - new_path = unique_path(o, ren1_dst, branch2); - output(o, 1, "Adding as %s instead", new_path); - update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); + if (o->call_depth) { + struct merge_file_info mfi; + struct diff_filespec one, a, b; + + one.path = a.path = b.path = + (char *)ren1_dst; + hashcpy(one.sha1, null_sha1); + one.mode = 0; + hashcpy(a.sha1, ren1->pair->two->sha1); + a.mode = ren1->pair->two->mode; + hashcpy(b.sha1, dst_other.sha1); + b.mode = dst_other.mode; + mfi = merge_file(o, &one, &a, &b, + branch1, + branch2); + output(o, 1, "Adding merged %s", ren1_dst); + update_file(o, 0, + mfi.sha, + mfi.mode, + ren1_dst); + } else { + new_path = unique_path(o, ren1_dst, branch2); + output(o, 1, "Adding as %s instead", new_path); + update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); + } } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) { ren2 = item->util; clean_merge = 0; |