Commit 1d5220dcd16963ba592f135bd8a68e310500f11b

Vicent Martí 2013-03-29T10:13:54

Merge pull request #1445 from ethomson/reset_unmerged remove unmerged files during reset hard

diff --git a/src/checkout.c b/src/checkout.c
index 2a29b18..24fa210 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -235,10 +235,13 @@ static int checkout_action_wd_only(
 	/* check if item is tracked in the index but not in the checkout diff */
 	if (data->index != NULL) {
 		if (wd->mode != GIT_FILEMODE_TREE) {
-			if (git_index_get_bypath(data->index, wd->path, 0) != NULL) {
+			int error;
+
+			if ((error = git_index_find(NULL, data->index, wd->path)) == 0) {
 				notify = GIT_CHECKOUT_NOTIFY_DIRTY;
 				remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
-			}
+			} else if (error != GIT_ENOTFOUND)
+				return error;
 		} else {
 			/* for tree entries, we have to see if there are any index
 			 * entries that are contained inside that tree
diff --git a/tests-clar/reset/hard.c b/tests-clar/reset/hard.c
index 9bbce31..62371f8 100644
--- a/tests-clar/reset/hard.c
+++ b/tests-clar/reset/hard.c
@@ -15,8 +15,10 @@ void test_reset_hard__initialize(void)
 
 void test_reset_hard__cleanup(void)
 {
-	git_object_free(target);
-	target = NULL;
+	if (target != NULL) {
+		git_object_free(target);
+		target = NULL;
+	}
 
 	cl_git_sandbox_cleanup();
 }
@@ -100,6 +102,68 @@ void test_reset_hard__cannot_reset_in_a_bare_repository(void)
 	git_repository_free(bare);
 }
 
+static void index_entry_init(git_index *index, int side, git_oid *oid)
+{
+	git_index_entry entry;
+	
+	memset(&entry, 0x0, sizeof(git_index_entry));
+	
+	entry.path = "conflicting_file";
+	entry.flags = (side << GIT_IDXENTRY_STAGESHIFT);
+	entry.mode = 0100644;
+	git_oid_cpy(&entry.oid, oid);
+	
+	cl_git_pass(git_index_add(index, &entry));
+}
+
+static void unmerged_index_init(git_index *index, int entries)
+{
+	int write_ancestor = 1;
+	int write_ours = 2;
+	int write_theirs = 4;
+	git_oid ancestor, ours, theirs;
+	
+	git_oid_fromstr(&ancestor, "6bb0d9f700543ba3d318ba7075fc3bd696b4287b");
+	git_oid_fromstr(&ours, "b19a1e93bec1317dc6097229e12afaffbfa74dc2");
+	git_oid_fromstr(&theirs, "950b81b7eee953d050aa05a641f8e056c85dd1bd");
+	
+	cl_git_rewritefile("status/conflicting_file", "conflicting file\n");
+	
+	if (entries & write_ancestor)
+		index_entry_init(index, 1, &ancestor);
+	
+	if (entries & write_ours)
+		index_entry_init(index, 2, &ours);
+	
+	if (entries & write_theirs)
+		index_entry_init(index, 3, &theirs);
+}
+
+void test_reset_hard__resetting_reverts_unmerged(void)
+{
+	git_index *index;
+	int entries;
+	
+	/* Ensure every permutation of non-zero stage entries results in the
+	 * path being cleaned up. */
+	for (entries = 1; entries < 8; entries++) {
+		cl_git_pass(git_repository_index(&index, repo));
+		
+		unmerged_index_init(index, entries);
+		cl_git_pass(git_index_write(index));
+		
+		retrieve_target_from_oid(&target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f");
+		cl_git_pass(git_reset(repo, target, GIT_RESET_HARD));
+		
+		cl_assert(git_path_exists("status/conflicting_file") == 0);
+		
+		git_object_free(target);
+		target = NULL;
+		
+		git_index_free(index);	
+	}
+}
+
 void test_reset_hard__cleans_up_merge(void)
 {
 	git_buf merge_head_path = GIT_BUF_INIT,