Commit 2d24816b4611a7392617855f497f81f385092f34

Edward Thomson 2014-11-06T18:49:37

checkout_index: Remove stage 0 when checking out conflicts

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
 }