Merge pull request #1445 from ethomson/reset_unmerged remove unmerged files during reset hard
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
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,