checkout_index: Remove stage 0 when checking out conflicts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/src/checkout.c b/src/checkout.c
index 8ffd40d..8203c39 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1912,6 +1912,20 @@ done:
return error;
}
+static int checkout_conflict_add(
+ checkout_data *data,
+ const git_index_entry *conflict)
+{
+ int error = git_index_remove(data->index, conflict->path, 0);
+
+ if (error == GIT_ENOTFOUND)
+ giterr_clear();
+ else if (error < 0)
+ return error;
+
+ return git_index_add(data->index, conflict);
+}
+
static int checkout_conflict_update_index(
checkout_data *data,
checkout_conflictdata *conflict)
@@ -1919,13 +1933,13 @@ static int checkout_conflict_update_index(
int error = 0;
if (conflict->ancestor)
- error = git_index_add(data->index, conflict->ancestor);
+ error = checkout_conflict_add(data, conflict->ancestor);
if (!error && conflict->ours)
- error = git_index_add(data->index, conflict->ours);
+ error = checkout_conflict_add(data, conflict->ours);
if (!error && conflict->theirs)
- error = git_index_add(data->index, conflict->theirs);
+ error = checkout_conflict_add(data, conflict->theirs);
return error;
}
diff --git a/tests/checkout/index.c b/tests/checkout/index.c
index 3c01e24..f945562 100644
--- a/tests/checkout/index.c
+++ b/tests/checkout/index.c
@@ -619,17 +619,14 @@ void test_checkout_index__can_get_repo_from_index(void)
git_index_free(index);
}
-static void add_conflict(void)
+static void add_conflict(git_index *index, const char *path)
{
- git_index *index;
git_index_entry entry;
memset(&entry, 0, sizeof(git_index_entry));
- cl_git_pass(git_repository_index(&index, g_repo));
-
entry.mode = 0100644;
- entry.path = "conflicting.txt";
+ entry.path = path;
git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT);
@@ -642,17 +639,19 @@ static void add_conflict(void)
git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT);
cl_git_pass(git_index_add(index, &entry));
-
- cl_git_pass(git_index_write(index));
- git_index_free(index);
}
void test_checkout_index__writes_conflict_file(void)
{
+ git_index *index;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
git_buf conflicting_buf = GIT_BUF_INIT;
- add_conflict();
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ add_conflict(index, "conflicting.txt");
+ cl_git_pass(git_index_write(index));
+
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
@@ -663,18 +662,46 @@ void test_checkout_index__writes_conflict_file(void)
"this file is changed in branch and master\n"
">>>>>>> theirs\n") == 0);
git_buf_free(&conflicting_buf);
+
+ git_index_free(index);
+}
+
+void test_checkout_index__adding_conflict_removes_stage_0(void)
+{
+ git_index *new_index, *index;
+ git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
+
+ cl_git_pass(git_index_new(&new_index));
+
+ add_conflict(new_index, "new.txt");
+ cl_git_pass(git_checkout_index(g_repo, new_index, &opts));
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ cl_assert(git_index_get_bypath(index, "new.txt", 0) == NULL);
+ cl_assert(git_index_get_bypath(index, "new.txt", 1) != NULL);
+ cl_assert(git_index_get_bypath(index, "new.txt", 2) != NULL);
+ cl_assert(git_index_get_bypath(index, "new.txt", 3) != NULL);
+
+ git_index_free(index);
+ git_index_free(new_index);
}
void test_checkout_index__conflicts_honor_coreautocrlf(void)
{
#ifdef GIT_WIN32
+ git_index *index;
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
git_buf conflicting_buf = GIT_BUF_INIT;
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
cl_repo_set_bool(g_repo, "core.autocrlf", true);
- add_conflict();
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ add_conflict(index, "conflicting.txt");
+ cl_git_pass(git_index_write(index));
+
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
@@ -685,5 +712,7 @@ void test_checkout_index__conflicts_honor_coreautocrlf(void)
"this file is changed in branch and master\r\n"
">>>>>>> theirs\r\n") == 0);
git_buf_free(&conflicting_buf);
+
+ git_index_free(index);
#endif
}