1 #include "clar_libgit2.h"
3 #include "git2/repository.h"
6 static git_repository
*repo
;
7 static git_index
*repo_index
;
9 #define TEST_REPO_PATH "mergedrepo"
10 #define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
12 /* Fixture setup and teardown */
13 void test_index_conflicts__initialize(void)
15 repo
= cl_git_sandbox_init("mergedrepo");
16 git_repository_index(&repo_index
, repo
);
19 void test_index_conflicts__cleanup(void)
21 git_index_free(repo_index
);
24 cl_git_sandbox_cleanup();
27 void test_index_conflicts__add(void)
29 git_index_entry ancestor_entry
, our_entry
, their_entry
;
31 cl_assert(git_index_entrycount(repo_index
) == 8);
33 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
34 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
35 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
37 ancestor_entry
.path
= "test-one.txt";
38 ancestor_entry
.mode
= 0100644;
39 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 1);
40 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
42 our_entry
.path
= "test-one.txt";
43 our_entry
.mode
= 0100644;
44 GIT_INDEX_ENTRY_STAGE_SET(&our_entry
, 2);
45 git_oid_fromstr(&our_entry
.id
, CONFLICTS_ONE_OUR_OID
);
47 their_entry
.path
= "test-one.txt";
48 their_entry
.mode
= 0100644;
49 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 2);
50 git_oid_fromstr(&their_entry
.id
, CONFLICTS_ONE_THEIR_OID
);
52 cl_git_pass(git_index_conflict_add(repo_index
, &ancestor_entry
, &our_entry
, &their_entry
));
54 cl_assert(git_index_entrycount(repo_index
) == 11);
57 void test_index_conflicts__add_fixes_incorrect_stage(void)
59 git_index_entry ancestor_entry
, our_entry
, their_entry
;
60 const git_index_entry
*conflict_entry
[3];
62 cl_assert(git_index_entrycount(repo_index
) == 8);
64 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
65 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
66 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
68 ancestor_entry
.path
= "test-one.txt";
69 ancestor_entry
.mode
= 0100644;
70 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 3);
71 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
73 our_entry
.path
= "test-one.txt";
74 our_entry
.mode
= 0100644;
75 GIT_INDEX_ENTRY_STAGE_SET(&our_entry
, 1);
76 git_oid_fromstr(&our_entry
.id
, CONFLICTS_ONE_OUR_OID
);
78 their_entry
.path
= "test-one.txt";
79 their_entry
.mode
= 0100644;
80 GIT_INDEX_ENTRY_STAGE_SET(&their_entry
, 2);
81 git_oid_fromstr(&their_entry
.id
, CONFLICTS_ONE_THEIR_OID
);
83 cl_git_pass(git_index_conflict_add(repo_index
, &ancestor_entry
, &our_entry
, &their_entry
));
85 cl_assert(git_index_entrycount(repo_index
) == 11);
87 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1], &conflict_entry
[2], repo_index
, "test-one.txt"));
89 cl_assert(git_index_entry_stage(conflict_entry
[0]) == 1);
90 cl_assert(git_index_entry_stage(conflict_entry
[1]) == 2);
91 cl_assert(git_index_entry_stage(conflict_entry
[2]) == 3);
94 void test_index_conflicts__add_detects_invalid_filemode(void)
96 git_index_entry ancestor_entry
, our_entry
, their_entry
;
97 git_index_entry
*conflict_entry
[3];
100 cl_assert(git_index_entrycount(repo_index
) == 8);
102 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
103 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
104 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
106 conflict_entry
[0] = &ancestor_entry
;
107 conflict_entry
[1] = &our_entry
;
108 conflict_entry
[2] = &their_entry
;
110 for (i
= 0; i
< 3; i
++) {
111 ancestor_entry
.path
= "test-one.txt";
112 ancestor_entry
.mode
= 0100644;
113 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 3);
114 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
116 our_entry
.path
= "test-one.txt";
117 our_entry
.mode
= 0100644;
118 GIT_INDEX_ENTRY_STAGE_SET(&our_entry
, 1);
119 git_oid_fromstr(&our_entry
.id
, CONFLICTS_ONE_OUR_OID
);
121 their_entry
.path
= "test-one.txt";
122 their_entry
.mode
= 0100644;
123 GIT_INDEX_ENTRY_STAGE_SET(&their_entry
, 2);
124 git_oid_fromstr(&their_entry
.id
, CONFLICTS_ONE_THEIR_OID
);
126 /* Corrupt the conflict entry's mode */
127 conflict_entry
[i
]->mode
= 027431745;
129 cl_git_fail(git_index_conflict_add(repo_index
, &ancestor_entry
, &our_entry
, &their_entry
));
132 cl_assert(git_index_entrycount(repo_index
) == 8);
136 void test_index_conflicts__add_removes_stage_zero(void)
138 git_index_entry ancestor_entry
, our_entry
, their_entry
;
139 const git_index_entry
*conflict_entry
[3];
141 cl_assert(git_index_entrycount(repo_index
) == 8);
143 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
144 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
145 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
147 cl_git_mkfile("./mergedrepo/test-one.txt", "new-file\n");
148 cl_git_pass(git_index_add_bypath(repo_index
, "test-one.txt"));
149 cl_assert(git_index_entrycount(repo_index
) == 9);
151 ancestor_entry
.path
= "test-one.txt";
152 ancestor_entry
.mode
= 0100644;
153 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 3);
154 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
156 our_entry
.path
= "test-one.txt";
157 our_entry
.mode
= 0100644;
158 GIT_INDEX_ENTRY_STAGE_SET(&our_entry
, 1);
159 git_oid_fromstr(&our_entry
.id
, CONFLICTS_ONE_OUR_OID
);
161 their_entry
.path
= "test-one.txt";
162 their_entry
.mode
= 0100644;
163 GIT_INDEX_ENTRY_STAGE_SET(&their_entry
, 2);
164 git_oid_fromstr(&their_entry
.id
, CONFLICTS_ONE_THEIR_OID
);
166 cl_git_pass(git_index_conflict_add(repo_index
, &ancestor_entry
, &our_entry
, &their_entry
));
168 cl_assert(git_index_entrycount(repo_index
) == 11);
170 cl_assert_equal_p(NULL
, git_index_get_bypath(repo_index
, "test-one.txt", 0));
172 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1], &conflict_entry
[2], repo_index
, "test-one.txt"));
174 cl_assert_equal_oid(&ancestor_entry
.id
, &conflict_entry
[0]->id
);
175 cl_assert_equal_i(1, git_index_entry_stage(conflict_entry
[0]));
176 cl_assert_equal_oid(&our_entry
.id
, &conflict_entry
[1]->id
);
177 cl_assert_equal_i(2, git_index_entry_stage(conflict_entry
[1]));
178 cl_assert_equal_oid(&their_entry
.id
, &conflict_entry
[2]->id
);
179 cl_assert_equal_i(3, git_index_entry_stage(conflict_entry
[2]));
182 void test_index_conflicts__get(void)
184 const git_index_entry
*conflict_entry
[3];
187 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1],
188 &conflict_entry
[2], repo_index
, "conflicts-one.txt"));
190 cl_assert_equal_s("conflicts-one.txt", conflict_entry
[0]->path
);
192 git_oid_fromstr(&oid
, CONFLICTS_ONE_ANCESTOR_OID
);
193 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
195 git_oid_fromstr(&oid
, CONFLICTS_ONE_OUR_OID
);
196 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
198 git_oid_fromstr(&oid
, CONFLICTS_ONE_THEIR_OID
);
199 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);
201 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1],
202 &conflict_entry
[2], repo_index
, "conflicts-two.txt"));
204 cl_assert_equal_s("conflicts-two.txt", conflict_entry
[0]->path
);
206 git_oid_fromstr(&oid
, CONFLICTS_TWO_ANCESTOR_OID
);
207 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
209 git_oid_fromstr(&oid
, CONFLICTS_TWO_OUR_OID
);
210 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
212 git_oid_fromstr(&oid
, CONFLICTS_TWO_THEIR_OID
);
213 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);
216 void test_index_conflicts__iterate(void)
218 git_index_conflict_iterator
*iterator
;
219 const git_index_entry
*conflict_entry
[3];
222 cl_git_pass(git_index_conflict_iterator_new(&iterator
, repo_index
));
224 cl_git_pass(git_index_conflict_next(&conflict_entry
[0], &conflict_entry
[1], &conflict_entry
[2], iterator
));
226 git_oid_fromstr(&oid
, CONFLICTS_ONE_ANCESTOR_OID
);
227 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
228 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-one.txt") == 0);
230 git_oid_fromstr(&oid
, CONFLICTS_ONE_OUR_OID
);
231 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
232 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-one.txt") == 0);
234 git_oid_fromstr(&oid
, CONFLICTS_ONE_THEIR_OID
);
235 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);
236 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-one.txt") == 0);
238 cl_git_pass(git_index_conflict_next(&conflict_entry
[0], &conflict_entry
[1], &conflict_entry
[2], iterator
));
240 git_oid_fromstr(&oid
, CONFLICTS_TWO_ANCESTOR_OID
);
241 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
242 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-two.txt") == 0);
244 git_oid_fromstr(&oid
, CONFLICTS_TWO_OUR_OID
);
245 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
246 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-two.txt") == 0);
248 git_oid_fromstr(&oid
, CONFLICTS_TWO_THEIR_OID
);
249 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);
250 cl_assert(git__strcmp(conflict_entry
[0]->path
, "conflicts-two.txt") == 0);
252 cl_assert(git_index_conflict_next(&conflict_entry
[0], &conflict_entry
[1], &conflict_entry
[2], iterator
) == GIT_ITEROVER
);
254 cl_assert(conflict_entry
[0] == NULL
);
255 cl_assert(conflict_entry
[2] == NULL
);
256 cl_assert(conflict_entry
[2] == NULL
);
258 git_index_conflict_iterator_free(iterator
);
261 void test_index_conflicts__remove(void)
263 const git_index_entry
*entry
;
266 cl_assert(git_index_entrycount(repo_index
) == 8);
268 cl_git_pass(git_index_conflict_remove(repo_index
, "conflicts-one.txt"));
269 cl_assert(git_index_entrycount(repo_index
) == 5);
271 for (i
= 0; i
< git_index_entrycount(repo_index
); i
++) {
272 cl_assert(entry
= git_index_get_byindex(repo_index
, i
));
273 cl_assert(strcmp(entry
->path
, "conflicts-one.txt") != 0);
276 cl_git_pass(git_index_conflict_remove(repo_index
, "conflicts-two.txt"));
277 cl_assert(git_index_entrycount(repo_index
) == 2);
279 for (i
= 0; i
< git_index_entrycount(repo_index
); i
++) {
280 cl_assert(entry
= git_index_get_byindex(repo_index
, i
));
281 cl_assert(strcmp(entry
->path
, "conflicts-two.txt") != 0);
285 void test_index_conflicts__moved_to_reuc_on_add(void)
287 const git_index_entry
*entry
;
290 cl_assert(git_index_entrycount(repo_index
) == 8);
292 cl_git_mkfile("./mergedrepo/conflicts-one.txt", "new-file\n");
294 cl_git_pass(git_index_add_bypath(repo_index
, "conflicts-one.txt"));
296 cl_assert(git_index_entrycount(repo_index
) == 6);
298 for (i
= 0; i
< git_index_entrycount(repo_index
); i
++) {
299 cl_assert(entry
= git_index_get_byindex(repo_index
, i
));
301 if (strcmp(entry
->path
, "conflicts-one.txt") == 0)
302 cl_assert(!git_index_entry_is_conflict(entry
));
306 void test_index_conflicts__moved_to_reuc_on_remove(void)
308 const git_index_entry
*entry
;
311 cl_assert(git_index_entrycount(repo_index
) == 8);
313 cl_git_pass(p_unlink("./mergedrepo/conflicts-one.txt"));
315 cl_git_pass(git_index_remove_bypath(repo_index
, "conflicts-one.txt"));
317 cl_assert(git_index_entrycount(repo_index
) == 5);
319 for (i
= 0; i
< git_index_entrycount(repo_index
); i
++) {
320 cl_assert(entry
= git_index_get_byindex(repo_index
, i
));
321 cl_assert(strcmp(entry
->path
, "conflicts-one.txt") != 0);
325 void test_index_conflicts__remove_all_conflicts(void)
328 const git_index_entry
*entry
;
330 cl_assert(git_index_entrycount(repo_index
) == 8);
332 cl_assert_equal_i(true, git_index_has_conflicts(repo_index
));
334 git_index_conflict_cleanup(repo_index
);
336 cl_assert_equal_i(false, git_index_has_conflicts(repo_index
));
338 cl_assert(git_index_entrycount(repo_index
) == 2);
340 for (i
= 0; i
< git_index_entrycount(repo_index
); i
++) {
341 cl_assert(entry
= git_index_get_byindex(repo_index
, i
));
342 cl_assert(!git_index_entry_is_conflict(entry
));
346 void test_index_conflicts__partial(void)
348 git_index_entry ancestor_entry
, our_entry
, their_entry
;
349 const git_index_entry
*conflict_entry
[3];
351 cl_assert(git_index_entrycount(repo_index
) == 8);
353 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
354 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
355 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
357 ancestor_entry
.path
= "test-one.txt";
358 ancestor_entry
.mode
= 0100644;
359 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, 1);
360 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
362 cl_git_pass(git_index_conflict_add(repo_index
, &ancestor_entry
, NULL
, NULL
));
363 cl_assert(git_index_entrycount(repo_index
) == 9);
365 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1],
366 &conflict_entry
[2], repo_index
, "test-one.txt"));
368 cl_assert_equal_oid(&ancestor_entry
.id
, &conflict_entry
[0]->id
);
369 cl_assert(conflict_entry
[1] == NULL
);
370 cl_assert(conflict_entry
[2] == NULL
);
373 void test_index_conflicts__case_matters(void)
375 const git_index_entry
*conflict_entry
[3];
377 const char *upper_case
= "DIFFERS-IN-CASE.TXT";
378 const char *mixed_case
= "Differs-In-Case.txt";
379 const char *correct_case
;
380 bool ignorecase
= cl_repo_get_bool(repo
, "core.ignorecase");
382 git_index_entry ancestor_entry
, our_entry
, their_entry
;
384 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
385 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
386 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
388 ancestor_entry
.path
= upper_case
;
389 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, GIT_INDEX_STAGE_ANCESTOR
);
390 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_ONE_ANCESTOR_OID
);
391 ancestor_entry
.mode
= GIT_FILEMODE_BLOB
;
393 our_entry
.path
= upper_case
;
394 GIT_INDEX_ENTRY_STAGE_SET(&our_entry
, GIT_INDEX_STAGE_OURS
);
395 git_oid_fromstr(&our_entry
.id
, CONFLICTS_ONE_OUR_OID
);
396 our_entry
.mode
= GIT_FILEMODE_BLOB
;
398 their_entry
.path
= upper_case
;
399 GIT_INDEX_ENTRY_STAGE_SET(&their_entry
, GIT_INDEX_STAGE_THEIRS
);
400 git_oid_fromstr(&their_entry
.id
, CONFLICTS_ONE_THEIR_OID
);
401 their_entry
.mode
= GIT_FILEMODE_BLOB
;
403 cl_git_pass(git_index_conflict_add(repo_index
,
404 &ancestor_entry
, &our_entry
, &their_entry
));
406 ancestor_entry
.path
= mixed_case
;
407 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, GIT_INDEX_STAGE_ANCESTOR
);
408 git_oid_fromstr(&ancestor_entry
.id
, CONFLICTS_TWO_ANCESTOR_OID
);
409 ancestor_entry
.mode
= GIT_FILEMODE_BLOB
;
411 our_entry
.path
= mixed_case
;
412 GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry
, GIT_INDEX_STAGE_ANCESTOR
);
413 git_oid_fromstr(&our_entry
.id
, CONFLICTS_TWO_OUR_OID
);
414 ancestor_entry
.mode
= GIT_FILEMODE_BLOB
;
416 their_entry
.path
= mixed_case
;
417 GIT_INDEX_ENTRY_STAGE_SET(&their_entry
, GIT_INDEX_STAGE_THEIRS
);
418 git_oid_fromstr(&their_entry
.id
, CONFLICTS_TWO_THEIR_OID
);
419 their_entry
.mode
= GIT_FILEMODE_BLOB
;
421 cl_git_pass(git_index_conflict_add(repo_index
,
422 &ancestor_entry
, &our_entry
, &their_entry
));
424 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1],
425 &conflict_entry
[2], repo_index
, upper_case
));
428 * We inserted with mixed case last, so on a case-insensitive
429 * fs we should get the mixed case.
432 correct_case
= mixed_case
;
434 correct_case
= upper_case
;
436 cl_assert_equal_s(correct_case
, conflict_entry
[0]->path
);
437 git_oid_fromstr(&oid
, ignorecase
? CONFLICTS_TWO_ANCESTOR_OID
: CONFLICTS_ONE_ANCESTOR_OID
);
438 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
440 cl_assert_equal_s(correct_case
, conflict_entry
[1]->path
);
441 git_oid_fromstr(&oid
, ignorecase
? CONFLICTS_TWO_OUR_OID
: CONFLICTS_ONE_OUR_OID
);
442 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
444 cl_assert_equal_s(correct_case
, conflict_entry
[2]->path
);
445 git_oid_fromstr(&oid
, ignorecase
? CONFLICTS_TWO_THEIR_OID
: CONFLICTS_ONE_THEIR_OID
);
446 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);
448 cl_git_pass(git_index_conflict_get(&conflict_entry
[0], &conflict_entry
[1],
449 &conflict_entry
[2], repo_index
, mixed_case
));
451 cl_assert_equal_s(mixed_case
, conflict_entry
[0]->path
);
452 git_oid_fromstr(&oid
, CONFLICTS_TWO_ANCESTOR_OID
);
453 cl_assert_equal_oid(&oid
, &conflict_entry
[0]->id
);
455 cl_assert_equal_s(mixed_case
, conflict_entry
[1]->path
);
456 git_oid_fromstr(&oid
, CONFLICTS_TWO_OUR_OID
);
457 cl_assert_equal_oid(&oid
, &conflict_entry
[1]->id
);
459 cl_assert_equal_s(mixed_case
, conflict_entry
[2]->path
);
460 git_oid_fromstr(&oid
, CONFLICTS_TWO_THEIR_OID
);
461 cl_assert_equal_oid(&oid
, &conflict_entry
[2]->id
);