]> git.proxmox.com Git - libgit2.git/commitdiff
Explicitly handle GIT_DELTA_CONFLICTED in git_diff_merge()
authorPierre-Olivier Latour <pol@mac.com>
Wed, 17 Jun 2015 15:55:09 +0000 (08:55 -0700)
committerPierre-Olivier Latour <pol@mac.com>
Tue, 23 Jun 2015 04:37:41 +0000 (21:37 -0700)
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.

src/diff_tform.c
tests/diff/workdir.c

index 03dd9c9f74c115d10c2a542572ae39c4301e3cbc..041592fbf492c6c8d8e8e8e51fc22b6bcd02e6eb 100644 (file)
@@ -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);
 
index 6b72f3286b458e582c1b63a45ef47e7ebbe8f80b..ecc556ce2d17be0b2ad2bb88bf45d8781a9681d6 100644 (file)
@@ -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);
+}