diff options
author | Pierre-Olivier Latour <pol@mac.com> | 2015-06-17 08:55:09 -0700 |
---|---|---|
committer | Pierre-Olivier Latour <pol@mac.com> | 2015-06-22 21:37:41 -0700 |
commit | cb63e7e8971134e41e99a7010d9b2ad54e6639ff (patch) | |
tree | a8fde7d90bac3c3c578534c54a5c01da65019286 | |
parent | 91c1833af1bdc0680b42e9f2934665330f826c18 (diff) | |
download | libgit2-cb63e7e8971134e41e99a7010d9b2ad54e6639ff.tar.gz |
Explicitly handle GIT_DELTA_CONFLICTED in git_diff_merge()
This fixes a bug where if a file was in conflicted state in either diff,
it would not always remain in conflicted state in the merged diff.
-rw-r--r-- | src/diff_tform.c | 11 | ||||
-rw-r--r-- | tests/diff/workdir.c | 36 |
2 files changed, 47 insertions, 0 deletions
diff --git a/src/diff_tform.c b/src/diff_tform.c index 03dd9c9f7..041592fbf 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -65,6 +65,12 @@ static git_diff_delta *diff_delta__merge_like_cgit( * f3 = b->new_file */ + /* If one of the diffs is a conflict, just dup it */ + if (b->status == GIT_DELTA_CONFLICTED) + return diff_delta__dup(b, pool); + if (a->status == GIT_DELTA_CONFLICTED) + return diff_delta__dup(a, pool); + /* if f2 == f3 or f2 is deleted, then just dup the 'a' diff */ if (b->status == GIT_DELTA_UNMODIFIED || a->status == GIT_DELTA_DELETED) return diff_delta__dup(a, pool); @@ -111,6 +117,11 @@ static git_diff_delta *diff_delta__merge_like_cgit_reversed( /* reversed version of above logic */ + if (a->status == GIT_DELTA_CONFLICTED) + return diff_delta__dup(a, pool); + if (b->status == GIT_DELTA_CONFLICTED) + return diff_delta__dup(b, pool); + if (a->status == GIT_DELTA_UNMODIFIED) return diff_delta__dup(b, pool); diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c index 6b72f3286..ecc556ce2 100644 --- a/tests/diff/workdir.c +++ b/tests/diff/workdir.c @@ -1745,3 +1745,39 @@ void test_diff_workdir__binary_detection(void) git_index_free(idx); git_buf_free(&b); } + +void test_diff_workdir__to_index_conflicted(void) { + const char *a_commit = "26a125ee1bf"; /* the current HEAD */ + git_index_entry ancestor = {{0}}, ours = {{0}}, theirs = {{0}}; + git_tree *a; + git_index *index; + git_diff *diff1, *diff2; + const git_diff_delta *delta; + + g_repo = cl_git_sandbox_init("status"); + a = resolve_commit_oid_to_tree(g_repo, a_commit); + + cl_git_pass(git_repository_index(&index, g_repo)); + + ancestor.path = ours.path = theirs.path = "_file"; + ancestor.mode = ours.mode = theirs.mode = 0100644; + git_oid_fromstr(&ancestor.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + git_oid_fromstr(&ours.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + git_oid_fromstr(&theirs.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + cl_git_pass(git_index_conflict_add(index, &ancestor, &ours, &theirs)); + + cl_git_pass(git_diff_tree_to_index(&diff1, g_repo, a, index, NULL)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, index, NULL)); + cl_git_pass(git_diff_merge(diff1, diff2)); + + cl_assert_equal_i(git_diff_num_deltas(diff1), 12); + delta = git_diff_get_delta(diff1, 0); + cl_assert_equal_s(delta->old_file.path, "_file"); + cl_assert_equal_i(delta->nfiles, 1); + cl_assert_equal_i(delta->status, GIT_DELTA_CONFLICTED); + + git_diff_free(diff2); + git_diff_free(diff1); + git_index_free(index); + git_tree_free(a); +} |