Merge pull request #2534 from libgit2/ntk/case_index_conflicts Failing test for case sensitive conflicts in the index
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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dec40e4..359e78d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,10 +41,11 @@ v0.23 + 1
with which to implement the transactional/atomic semantics for the
configuration backend.
-* `git_index_add` will now use the case as provided by the caller on
- case insensitive systems. Previous versions would keep the case as
- it existed in the index. This does not affect the higher-level
- `git_index_add_bypath` or `git_index_add_frombuffer` functions.
+* `git_index_add` and `git_index_conflict_add()` will now use the case
+ as provided by the caller on case insensitive systems. Previous
+ versions would keep the case as it existed in the index. This does
+ not affect the higher-level `git_index_add_bypath` or
+ `git_index_add_frombuffer` functions.
* The `notify_payload` field of `git_diff_options` was renamed to `payload`
to reflect that it's also the payload for the new progress callback.
diff --git a/src/index.c b/src/index.c
index dcf46fe..d3b8afd 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1691,7 +1691,7 @@ int git_index_conflict_add(git_index *index,
for (i = 0; i < 3; i++) {
if (entries[i] && !valid_filemode(entries[i]->mode)) {
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
- i);
+ i + 1);
return -1;
}
}
@@ -1718,7 +1718,7 @@ int git_index_conflict_add(git_index *index,
/* Make sure stage is correct */
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
- if ((ret = index_insert(index, &entries[i], 0, true, true)) < 0)
+ if ((ret = index_insert(index, &entries[i], 1, true, true)) < 0)
goto on_error;
entries[i] = NULL; /* don't free if later entry fails */
diff --git a/tests/index/conflicts.c b/tests/index/conflicts.c
index b7a2456..8e94cd4 100644
--- a/tests/index/conflicts.c
+++ b/tests/index/conflicts.c
@@ -342,3 +342,94 @@ void test_index_conflicts__partial(void)
cl_assert(conflict_entry[1] == NULL);
cl_assert(conflict_entry[2] == NULL);
}
+
+void test_index_conflicts__case_matters(void)
+{
+ const git_index_entry *conflict_entry[3];
+ git_oid oid;
+ const char *upper_case = "DIFFERS-IN-CASE.TXT";
+ const char *mixed_case = "Differs-In-Case.txt";
+ const char *correct_case;
+ bool ignorecase = cl_repo_get_bool(repo, "core.ignorecase");
+
+ git_index_entry ancestor_entry, our_entry, their_entry;
+
+ memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
+ memset(&our_entry, 0x0, sizeof(git_index_entry));
+ memset(&their_entry, 0x0, sizeof(git_index_entry));
+
+ ancestor_entry.path = upper_case;
+ GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
+ git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
+ ancestor_entry.mode = GIT_FILEMODE_BLOB;
+
+ our_entry.path = upper_case;
+ GIT_IDXENTRY_STAGE_SET(&our_entry, GIT_INDEX_STAGE_OURS);
+ git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
+ our_entry.mode = GIT_FILEMODE_BLOB;
+
+ their_entry.path = upper_case;
+ GIT_IDXENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
+ git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
+ their_entry.mode = GIT_FILEMODE_BLOB;
+
+ cl_git_pass(git_index_conflict_add(repo_index,
+ &ancestor_entry, &our_entry, &their_entry));
+
+ ancestor_entry.path = mixed_case;
+ GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
+ git_oid_fromstr(&ancestor_entry.id, CONFLICTS_TWO_ANCESTOR_OID);
+ ancestor_entry.mode = GIT_FILEMODE_BLOB;
+
+ our_entry.path = mixed_case;
+ GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
+ git_oid_fromstr(&our_entry.id, CONFLICTS_TWO_OUR_OID);
+ ancestor_entry.mode = GIT_FILEMODE_BLOB;
+
+ their_entry.path = mixed_case;
+ GIT_IDXENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
+ git_oid_fromstr(&their_entry.id, CONFLICTS_TWO_THEIR_OID);
+ their_entry.mode = GIT_FILEMODE_BLOB;
+
+ cl_git_pass(git_index_conflict_add(repo_index,
+ &ancestor_entry, &our_entry, &their_entry));
+
+ cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
+ &conflict_entry[2], repo_index, upper_case));
+
+ /*
+ * We inserted with mixed case last, so on a case-insensitive
+ * fs we should get the mixed case.
+ */
+ if (ignorecase)
+ correct_case = mixed_case;
+ else
+ correct_case = upper_case;
+
+ cl_assert_equal_s(correct_case, conflict_entry[0]->path);
+ git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_ANCESTOR_OID : CONFLICTS_ONE_ANCESTOR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
+
+ cl_assert_equal_s(correct_case, conflict_entry[1]->path);
+ git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_OUR_OID : CONFLICTS_ONE_OUR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
+
+ cl_assert_equal_s(correct_case, conflict_entry[2]->path);
+ git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_THEIR_OID : CONFLICTS_ONE_THEIR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
+
+ cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
+ &conflict_entry[2], repo_index, mixed_case));
+
+ cl_assert_equal_s(mixed_case, conflict_entry[0]->path);
+ git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
+
+ cl_assert_equal_s(mixed_case, conflict_entry[1]->path);
+ git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
+
+ cl_assert_equal_s(mixed_case, conflict_entry[2]->path);
+ git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
+ cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
+}