]> git.proxmox.com Git - libgit2.git/blob - tests/libgit2/checkout/conflict.c
New upstream version 1.5.0+ds
[libgit2.git] / tests / libgit2 / checkout / conflict.c
1 #include "clar_libgit2.h"
2 #include "git2/repository.h"
3 #include "git2/sys/index.h"
4 #include "futils.h"
5 #include "repository.h"
6
7 static git_repository *g_repo;
8 static git_index *g_index;
9
10 #define TEST_REPO_PATH "merge-resolve"
11
12 #define CONFLICTING_ANCESTOR_OID "d427e0b2e138501a3d15cc376077a3631e15bd46"
13 #define CONFLICTING_OURS_OID "4e886e602529caa9ab11d71f86634bd1b6e0de10"
14 #define CONFLICTING_THEIRS_OID "2bd0a343aeef7a2cf0d158478966a6e587ff3863"
15
16 #define AUTOMERGEABLE_ANCESTOR_OID "6212c31dab5e482247d7977e4f0dd3601decf13b"
17 #define AUTOMERGEABLE_OURS_OID "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"
18 #define AUTOMERGEABLE_THEIRS_OID "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe"
19
20 #define LINK_ANCESTOR_OID "1a010b1c0f081b2e8901d55307a15c29ff30af0e"
21 #define LINK_OURS_OID "72ea499e108df5ff0a4a913e7655bbeeb1fb69f2"
22 #define LINK_THEIRS_OID "8bfb012a6d809e499bd8d3e194a3929bc8995b93"
23
24 #define LINK_ANCESTOR_TARGET "file"
25 #define LINK_OURS_TARGET "other-file"
26 #define LINK_THEIRS_TARGET "still-another-file"
27
28 #define CONFLICTING_OURS_FILE \
29 "this file is changed in master and branch\n"
30 #define CONFLICTING_THEIRS_FILE \
31 "this file is changed in branch and master\n"
32 #define CONFLICTING_DIFF3_FILE \
33 "<<<<<<< ours\n" \
34 "this file is changed in master and branch\n" \
35 "=======\n" \
36 "this file is changed in branch and master\n" \
37 ">>>>>>> theirs\n"
38
39 #define AUTOMERGEABLE_MERGED_FILE \
40 "this file is changed in master\n" \
41 "this file is automergeable\n" \
42 "this file is automergeable\n" \
43 "this file is automergeable\n" \
44 "this file is automergeable\n" \
45 "this file is automergeable\n" \
46 "this file is automergeable\n" \
47 "this file is automergeable\n" \
48 "this file is changed in branch\n"
49
50 struct checkout_index_entry {
51 uint16_t mode;
52 char oid_str[GIT_OID_HEXSZ+1];
53 int stage;
54 char path[128];
55 };
56
57 struct checkout_name_entry {
58 char ancestor[64];
59 char ours[64];
60 char theirs[64];
61 };
62
63 void test_checkout_conflict__initialize(void)
64 {
65 git_config *cfg;
66
67 g_repo = cl_git_sandbox_init(TEST_REPO_PATH);
68 git_repository_index(&g_index, g_repo);
69
70 cl_git_rewritefile(
71 TEST_REPO_PATH "/.gitattributes",
72 "* text eol=lf\n");
73
74 /* Ensure that the user's merge.conflictstyle doesn't interfere */
75 cl_git_pass(git_repository_config(&cfg, g_repo));
76 cl_git_pass(git_config_set_string(cfg, "merge.conflictstyle", "merge"));
77 git_config_free(cfg);
78 }
79
80 void test_checkout_conflict__cleanup(void)
81 {
82 git_index_free(g_index);
83 cl_git_sandbox_cleanup();
84 }
85
86 static void create_index(struct checkout_index_entry *entries, size_t entries_len)
87 {
88 git_str path = GIT_STR_INIT;
89 size_t i;
90
91 for (i = 0; i < entries_len; i++) {
92 git_str_joinpath(&path, TEST_REPO_PATH, entries[i].path);
93
94 if (entries[i].stage == 3 && (i == 0 || strcmp(entries[i-1].path, entries[i].path) != 0 || entries[i-1].stage != 2))
95 p_unlink(git_str_cstr(&path));
96
97 cl_git_pass(git_index_remove_bypath(g_index, entries[i].path));
98 }
99
100 for (i = 0; i < entries_len; i++) {
101 git_index_entry entry;
102
103 memset(&entry, 0x0, sizeof(git_index_entry));
104
105 entry.mode = entries[i].mode;
106 GIT_INDEX_ENTRY_STAGE_SET(&entry, entries[i].stage);
107 git_oid_fromstr(&entry.id, entries[i].oid_str);
108 entry.path = entries[i].path;
109
110 cl_git_pass(git_index_add(g_index, &entry));
111 }
112
113 git_str_dispose(&path);
114 }
115
116 static void create_index_names(struct checkout_name_entry *entries, size_t entries_len)
117 {
118 size_t i;
119
120 for (i = 0; i < entries_len; i++) {
121 cl_git_pass(git_index_name_add(g_index,
122 strlen(entries[i].ancestor) == 0 ? NULL : entries[i].ancestor,
123 strlen(entries[i].ours) == 0 ? NULL : entries[i].ours,
124 strlen(entries[i].theirs) == 0 ? NULL : entries[i].theirs));
125 }
126 }
127
128 static void create_conflicting_index(void)
129 {
130 struct checkout_index_entry checkout_index_entries[] = {
131 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting.txt" },
132 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" },
133 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" },
134 };
135
136 create_index(checkout_index_entries, 3);
137 cl_git_pass(git_index_write(g_index));
138 }
139
140 static void ensure_workdir_contents(const char *path, const char *contents)
141 {
142 git_str fullpath = GIT_STR_INIT, data_buf = GIT_STR_INIT;
143
144 cl_git_pass(
145 git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
146
147 cl_git_pass(git_futils_readbuffer(&data_buf, git_str_cstr(&fullpath)));
148 cl_assert(strcmp(git_str_cstr(&data_buf), contents) == 0);
149
150 git_str_dispose(&fullpath);
151 git_str_dispose(&data_buf);
152 }
153
154 static void ensure_workdir_oid(const char *path, const char *oid_str)
155 {
156 git_oid expected, actual;
157
158 cl_git_pass(git_oid_fromstr(&expected, oid_str));
159 cl_git_pass(git_repository_hashfile(&actual, g_repo, path, GIT_OBJECT_BLOB, NULL));
160 cl_assert_equal_oid(&expected, &actual);
161 }
162
163 static void ensure_workdir_mode(const char *path, int mode)
164 {
165 #ifdef GIT_WIN32
166 GIT_UNUSED(path);
167 GIT_UNUSED(mode);
168 #else
169 git_str fullpath = GIT_STR_INIT;
170 struct stat st;
171
172 cl_git_pass(
173 git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
174
175 cl_git_pass(p_stat(git_str_cstr(&fullpath), &st));
176 cl_assert_equal_i((mode & S_IRWXU), (st.st_mode & S_IRWXU));
177
178 git_str_dispose(&fullpath);
179 #endif
180 }
181
182 static void ensure_workdir(const char *path, int mode, const char *oid_str)
183 {
184 ensure_workdir_mode(path, mode);
185 ensure_workdir_oid(path, oid_str);
186 }
187
188 static void ensure_workdir_link(
189 git_repository *repo,
190 const char *path,
191 const char *target)
192 {
193 int symlinks;
194
195 cl_git_pass(git_repository__configmap_lookup(&symlinks, repo, GIT_CONFIGMAP_SYMLINKS));
196
197 if (!symlinks) {
198 ensure_workdir_contents(path, target);
199 } else {
200 git_str fullpath = GIT_STR_INIT;
201 char actual[1024];
202 struct stat st;
203 int len;
204
205 cl_git_pass(
206 git_str_joinpath(&fullpath, git_repository_workdir(g_repo), path));
207
208 cl_git_pass(p_lstat(git_str_cstr(&fullpath), &st));
209 cl_assert(S_ISLNK(st.st_mode));
210
211 cl_assert((len = p_readlink(git_str_cstr(&fullpath), actual, 1024)) > 0);
212 actual[len] = '\0';
213 cl_assert(strcmp(actual, target) == 0);
214
215 git_str_dispose(&fullpath);
216 }
217 }
218
219 void test_checkout_conflict__ignored(void)
220 {
221 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
222
223 opts.checkout_strategy |= GIT_CHECKOUT_SKIP_UNMERGED;
224
225 create_conflicting_index();
226 cl_git_pass(p_unlink(TEST_REPO_PATH "/conflicting.txt"));
227
228 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
229
230 cl_assert(!git_fs_path_exists(TEST_REPO_PATH "/conflicting.txt"));
231 }
232
233 void test_checkout_conflict__ours(void)
234 {
235 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
236
237 opts.checkout_strategy |= GIT_CHECKOUT_USE_OURS;
238
239 create_conflicting_index();
240
241 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
242
243 ensure_workdir_contents("conflicting.txt", CONFLICTING_OURS_FILE);
244 }
245
246 void test_checkout_conflict__theirs(void)
247 {
248 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
249
250 opts.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS;
251
252 create_conflicting_index();
253
254 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
255
256 ensure_workdir_contents("conflicting.txt", CONFLICTING_THEIRS_FILE);
257
258 }
259
260 void test_checkout_conflict__diff3(void)
261 {
262 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
263
264 create_conflicting_index();
265
266 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
267
268 ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE);
269 }
270
271 void test_checkout_conflict__automerge(void)
272 {
273 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
274
275 struct checkout_index_entry checkout_index_entries[] = {
276 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" },
277 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" },
278 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" },
279 };
280
281 create_index(checkout_index_entries, 3);
282 cl_git_pass(git_index_write(g_index));
283
284 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
285
286 ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE);
287 }
288
289 void test_checkout_conflict__directory_file(void)
290 {
291 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
292
293 struct checkout_index_entry checkout_index_entries[] = {
294 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" },
295 { 0100644, CONFLICTING_OURS_OID, 2, "df-1" },
296 { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" },
297
298 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" },
299 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" },
300 { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" },
301
302 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" },
303 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" },
304 { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" },
305
306 { 0100644, CONFLICTING_OURS_OID, 2, "df-4" },
307 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" },
308 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" },
309 };
310
311 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
312
313 create_index(checkout_index_entries, 12);
314 cl_git_pass(git_index_write(g_index));
315
316 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
317
318 ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID);
319 ensure_workdir_oid("df-1~ours", CONFLICTING_OURS_OID);
320 ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID);
321 ensure_workdir_oid("df-2~theirs", CONFLICTING_THEIRS_OID);
322 ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID);
323 ensure_workdir_oid("df-3~theirs", CONFLICTING_THEIRS_OID);
324 ensure_workdir_oid("df-4~ours", CONFLICTING_OURS_OID);
325 ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID);
326 }
327
328 void test_checkout_conflict__directory_file_with_custom_labels(void)
329 {
330 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
331
332 struct checkout_index_entry checkout_index_entries[] = {
333 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" },
334 { 0100644, CONFLICTING_OURS_OID, 2, "df-1" },
335 { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" },
336
337 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" },
338 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" },
339 { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" },
340
341 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" },
342 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" },
343 { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" },
344
345 { 0100644, CONFLICTING_OURS_OID, 2, "df-4" },
346 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" },
347 { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" },
348 };
349
350 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
351 opts.our_label = "HEAD";
352 opts.their_label = "branch";
353
354 create_index(checkout_index_entries, 12);
355 cl_git_pass(git_index_write(g_index));
356
357 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
358
359 ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID);
360 ensure_workdir_oid("df-1~HEAD", CONFLICTING_OURS_OID);
361 ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID);
362 ensure_workdir_oid("df-2~branch", CONFLICTING_THEIRS_OID);
363 ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID);
364 ensure_workdir_oid("df-3~branch", CONFLICTING_THEIRS_OID);
365 ensure_workdir_oid("df-4~HEAD", CONFLICTING_OURS_OID);
366 ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID);
367 }
368
369 void test_checkout_conflict__link_file(void)
370 {
371 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
372
373 struct checkout_index_entry checkout_index_entries[] = {
374 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-1" },
375 { 0100644, CONFLICTING_OURS_OID, 2, "link-1" },
376 { 0120000, LINK_THEIRS_OID, 3, "link-1" },
377
378 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-2" },
379 { 0120000, LINK_OURS_OID, 2, "link-2" },
380 { 0100644, CONFLICTING_THEIRS_OID, 3, "link-2" },
381
382 { 0120000, LINK_ANCESTOR_OID, 1, "link-3" },
383 { 0100644, CONFLICTING_OURS_OID, 2, "link-3" },
384 { 0120000, LINK_THEIRS_OID, 3, "link-3" },
385
386 { 0120000, LINK_ANCESTOR_OID, 1, "link-4" },
387 { 0120000, LINK_OURS_OID, 2, "link-4" },
388 { 0100644, CONFLICTING_THEIRS_OID, 3, "link-4" },
389 };
390
391 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
392
393 create_index(checkout_index_entries, 12);
394 cl_git_pass(git_index_write(g_index));
395
396 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
397
398 /* Typechange conflicts always keep the file in the workdir */
399 ensure_workdir_oid("link-1", CONFLICTING_OURS_OID);
400 ensure_workdir_oid("link-2", CONFLICTING_THEIRS_OID);
401 ensure_workdir_oid("link-3", CONFLICTING_OURS_OID);
402 ensure_workdir_oid("link-4", CONFLICTING_THEIRS_OID);
403 }
404
405 void test_checkout_conflict__links(void)
406 {
407 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
408
409 struct checkout_index_entry checkout_index_entries[] = {
410 { 0120000, LINK_ANCESTOR_OID, 1, "link-1" },
411 { 0120000, LINK_OURS_OID, 2, "link-1" },
412 { 0120000, LINK_THEIRS_OID, 3, "link-1" },
413
414 { 0120000, LINK_OURS_OID, 2, "link-2" },
415 { 0120000, LINK_THEIRS_OID, 3, "link-2" },
416 };
417
418 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
419
420 create_index(checkout_index_entries, 5);
421 cl_git_pass(git_index_write(g_index));
422
423 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
424
425 /* Conflicts with links always keep the ours side (even with -Xtheirs) */
426 ensure_workdir_link(g_repo, "link-1", LINK_OURS_TARGET);
427 ensure_workdir_link(g_repo, "link-2", LINK_OURS_TARGET);
428 }
429
430 void test_checkout_conflict__add_add(void)
431 {
432 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
433
434 struct checkout_index_entry checkout_index_entries[] = {
435 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" },
436 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" },
437 };
438
439 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
440
441 create_index(checkout_index_entries, 2);
442 cl_git_pass(git_index_write(g_index));
443
444 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
445
446 /* Add/add writes diff3 files */
447 ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE);
448 }
449
450 void test_checkout_conflict__mode_change(void)
451 {
452 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
453
454 struct checkout_index_entry checkout_index_entries[] = {
455 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-1" },
456 { 0100755, CONFLICTING_ANCESTOR_OID, 2, "executable-1" },
457 { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-1" },
458
459 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-2" },
460 { 0100644, CONFLICTING_OURS_OID, 2, "executable-2" },
461 { 0100755, CONFLICTING_ANCESTOR_OID, 3, "executable-2" },
462
463 { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-3" },
464 { 0100644, CONFLICTING_ANCESTOR_OID, 2, "executable-3" },
465 { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-3" },
466
467 { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-4" },
468 { 0100755, CONFLICTING_OURS_OID, 2, "executable-4" },
469 { 0100644, CONFLICTING_ANCESTOR_OID, 3, "executable-4" },
470
471 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-5" },
472 { 0100755, CONFLICTING_OURS_OID, 2, "executable-5" },
473 { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-5" },
474
475 { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-6" },
476 { 0100644, CONFLICTING_OURS_OID, 2, "executable-6" },
477 { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-6" },
478 };
479
480 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
481
482 create_index(checkout_index_entries, 18);
483 cl_git_pass(git_index_write(g_index));
484
485 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
486
487 /* Keep the modified mode */
488 ensure_workdir_oid("executable-1", CONFLICTING_THEIRS_OID);
489 ensure_workdir_mode("executable-1", 0100755);
490
491 ensure_workdir_oid("executable-2", CONFLICTING_OURS_OID);
492 ensure_workdir_mode("executable-2", 0100755);
493
494 ensure_workdir_oid("executable-3", CONFLICTING_THEIRS_OID);
495 ensure_workdir_mode("executable-3", 0100644);
496
497 ensure_workdir_oid("executable-4", CONFLICTING_OURS_OID);
498 ensure_workdir_mode("executable-4", 0100644);
499
500 ensure_workdir_contents("executable-5", CONFLICTING_DIFF3_FILE);
501 ensure_workdir_mode("executable-5", 0100755);
502
503 ensure_workdir_contents("executable-6", CONFLICTING_DIFF3_FILE);
504 ensure_workdir_mode("executable-6", 0100644);
505 }
506
507 void test_checkout_conflict__renames(void)
508 {
509 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
510
511 struct checkout_index_entry checkout_index_entries[] = {
512 { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
513 { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" },
514 { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" },
515 { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" },
516 { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" },
517 { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" },
518 { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" },
519 { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" },
520 { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" },
521 { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" },
522 { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" },
523 { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" },
524 { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" },
525 { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" },
526 { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" },
527 { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" },
528 { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" },
529 { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" },
530 { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" },
531 { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" },
532 { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" },
533 { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" },
534 { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" },
535 { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" },
536 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" },
537 { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" },
538 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" },
539 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" },
540 { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" },
541 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" },
542 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" },
543 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" },
544 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" },
545 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" },
546 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" },
547 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" },
548 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" },
549 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" },
550 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" },
551 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" },
552 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }
553 };
554
555 struct checkout_name_entry checkout_name_entries[] = {
556 {
557 "3a-renamed-in-ours-deleted-in-theirs.txt",
558 "3a-newname-in-ours-deleted-in-theirs.txt",
559 ""
560 },
561
562 {
563 "3b-renamed-in-theirs-deleted-in-ours.txt",
564 "",
565 "3b-newname-in-theirs-deleted-in-ours.txt"
566 },
567
568 {
569 "4a-renamed-in-ours-added-in-theirs.txt",
570 "4a-newname-in-ours-added-in-theirs.txt",
571 ""
572 },
573
574 {
575 "4b-renamed-in-theirs-added-in-ours.txt",
576 "",
577 "4b-newname-in-theirs-added-in-ours.txt"
578 },
579
580 {
581 "5a-renamed-in-ours-added-in-theirs.txt",
582 "5a-newname-in-ours-added-in-theirs.txt",
583 "5a-renamed-in-ours-added-in-theirs.txt"
584 },
585
586 {
587 "5b-renamed-in-theirs-added-in-ours.txt",
588 "5b-renamed-in-theirs-added-in-ours.txt",
589 "5b-newname-in-theirs-added-in-ours.txt"
590 },
591
592 {
593 "6-both-renamed-1-to-2.txt",
594 "6-both-renamed-1-to-2-ours.txt",
595 "6-both-renamed-1-to-2-theirs.txt"
596 },
597
598 {
599 "7-both-renamed-side-1.txt",
600 "7-both-renamed.txt",
601 "7-both-renamed-side-1.txt"
602 },
603
604 {
605 "7-both-renamed-side-2.txt",
606 "7-both-renamed-side-2.txt",
607 "7-both-renamed.txt"
608 }
609 };
610
611 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
612
613 create_index(checkout_index_entries, 41);
614 create_index_names(checkout_name_entries, 9);
615 cl_git_pass(git_index_write(g_index));
616
617 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
618
619 ensure_workdir("0a-no-change.txt",
620 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e");
621
622 ensure_workdir("0b-duplicated-in-ours.txt",
623 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6");
624
625 ensure_workdir("0b-rewritten-in-ours.txt",
626 0100644, "4c7e515d6d52d820496858f2f059ece69e99e2e3");
627
628 ensure_workdir("0c-duplicated-in-theirs.txt",
629 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31");
630
631 ensure_workdir("0c-rewritten-in-theirs.txt",
632 0100644, "4648d658682d1155c2a3db5b0c53305e26884ea5");
633
634 ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt",
635 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638");
636
637 ensure_workdir("1a-newname-in-ours.txt",
638 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb");
639
640 ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt",
641 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a");
642
643 ensure_workdir("1b-newname-in-theirs.txt",
644 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136");
645
646 ensure_workdir("2-newname-in-both.txt",
647 0100644, "178940b450f238a56c0d75b7955cb57b38191982");
648
649 ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt",
650 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9");
651
652 ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt",
653 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495");
654
655 ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~ours",
656 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c");
657
658 ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~theirs",
659 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a");
660
661 ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~ours",
662 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9");
663
664 ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~theirs",
665 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db");
666
667 ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~ours",
668 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436");
669
670 ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~theirs",
671 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714");
672
673 ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~ours",
674 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced");
675
676 ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~theirs",
677 0100644, "63247125386de9ec90a27ad36169307bf8a11a38");
678
679 ensure_workdir("6-both-renamed-1-to-2-ours.txt",
680 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450");
681
682 ensure_workdir("6-both-renamed-1-to-2-theirs.txt",
683 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450");
684
685 ensure_workdir("7-both-renamed.txt~ours",
686 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
687
688 ensure_workdir("7-both-renamed.txt~theirs",
689 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07");
690 }
691
692 void test_checkout_conflict__rename_keep_ours(void)
693 {
694 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
695
696 struct checkout_index_entry checkout_index_entries[] = {
697 { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
698 { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" },
699 { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" },
700 { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" },
701 { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" },
702 { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" },
703 { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" },
704 { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" },
705 { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" },
706 { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" },
707 { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" },
708 { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" },
709 { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" },
710 { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" },
711 { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" },
712 { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" },
713 { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" },
714 { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" },
715 { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" },
716 { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" },
717 { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" },
718 { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" },
719 { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" },
720 { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" },
721 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" },
722 { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" },
723 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" },
724 { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" },
725 { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" },
726 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" },
727 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" },
728 { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" },
729 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" },
730 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" },
731 { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" },
732 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" },
733 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" },
734 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" },
735 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" },
736 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" },
737 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }
738 };
739
740 struct checkout_name_entry checkout_name_entries[] = {
741 {
742 "3a-renamed-in-ours-deleted-in-theirs.txt",
743 "3a-newname-in-ours-deleted-in-theirs.txt",
744 ""
745 },
746
747 {
748 "3b-renamed-in-theirs-deleted-in-ours.txt",
749 "",
750 "3b-newname-in-theirs-deleted-in-ours.txt"
751 },
752
753 {
754 "4a-renamed-in-ours-added-in-theirs.txt",
755 "4a-newname-in-ours-added-in-theirs.txt",
756 ""
757 },
758
759 {
760 "4b-renamed-in-theirs-added-in-ours.txt",
761 "",
762 "4b-newname-in-theirs-added-in-ours.txt"
763 },
764
765 {
766 "5a-renamed-in-ours-added-in-theirs.txt",
767 "5a-newname-in-ours-added-in-theirs.txt",
768 "5a-renamed-in-ours-added-in-theirs.txt"
769 },
770
771 {
772 "5b-renamed-in-theirs-added-in-ours.txt",
773 "5b-renamed-in-theirs-added-in-ours.txt",
774 "5b-newname-in-theirs-added-in-ours.txt"
775 },
776
777 {
778 "6-both-renamed-1-to-2.txt",
779 "6-both-renamed-1-to-2-ours.txt",
780 "6-both-renamed-1-to-2-theirs.txt"
781 },
782
783 {
784 "7-both-renamed-side-1.txt",
785 "7-both-renamed.txt",
786 "7-both-renamed-side-1.txt"
787 },
788
789 {
790 "7-both-renamed-side-2.txt",
791 "7-both-renamed-side-2.txt",
792 "7-both-renamed.txt"
793 }
794 };
795
796 opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
797
798 create_index(checkout_index_entries, 41);
799 create_index_names(checkout_name_entries, 9);
800 cl_git_pass(git_index_write(g_index));
801
802 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
803
804 ensure_workdir("0a-no-change.txt",
805 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e");
806
807 ensure_workdir("0b-duplicated-in-ours.txt",
808 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6");
809
810 ensure_workdir("0b-rewritten-in-ours.txt",
811 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e");
812
813 ensure_workdir("0c-duplicated-in-theirs.txt",
814 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31");
815
816 ensure_workdir("0c-rewritten-in-theirs.txt",
817 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09");
818
819 ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt",
820 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638");
821
822 ensure_workdir("1a-newname-in-ours.txt",
823 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb");
824
825 ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt",
826 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a");
827
828 ensure_workdir("1b-newname-in-theirs.txt",
829 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136");
830
831 ensure_workdir("2-newname-in-both.txt",
832 0100644, "178940b450f238a56c0d75b7955cb57b38191982");
833
834 ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt",
835 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9");
836
837 ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt",
838 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495");
839
840 ensure_workdir("4a-newname-in-ours-added-in-theirs.txt",
841 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c");
842
843 ensure_workdir("4b-newname-in-theirs-added-in-ours.txt",
844 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9");
845
846 ensure_workdir("5a-newname-in-ours-added-in-theirs.txt",
847 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436");
848
849 ensure_workdir("5b-newname-in-theirs-added-in-ours.txt",
850 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced");
851
852 ensure_workdir("6-both-renamed-1-to-2-ours.txt",
853 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450");
854
855 ensure_workdir("7-both-renamed.txt",
856 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
857 }
858
859 void test_checkout_conflict__name_mangled_file_exists_in_workdir(void)
860 {
861 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
862
863 struct checkout_index_entry checkout_index_entries[] = {
864 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-one-side-one.txt" },
865 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-one-side-one.txt" },
866 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-one-side-two.txt" },
867 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-one-side-two.txt" },
868 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-one.txt" },
869 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-one.txt" },
870
871 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-two-side-one.txt" },
872 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-two-side-one.txt" },
873 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-two-side-two.txt" },
874 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-two-side-two.txt" },
875 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-two.txt" },
876 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-two.txt" },
877
878 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-three-side-one.txt" },
879 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-three-side-one.txt" },
880 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-three-side-two.txt" },
881 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-three-side-two.txt" },
882 { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-three.txt" },
883 { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-three.txt" },
884
885 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" },
886 { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" },
887 { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" },
888
889 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" },
890 { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" },
891 { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" },
892 };
893
894 struct checkout_name_entry checkout_name_entries[] = {
895 {
896 "test-one-side-one.txt",
897 "test-one.txt",
898 "test-one-side-one.txt"
899 },
900 {
901 "test-one-side-two.txt",
902 "test-one-side-two.txt",
903 "test-one.txt"
904 },
905
906 {
907 "test-two-side-one.txt",
908 "test-two.txt",
909 "test-two-side-one.txt"
910 },
911 {
912 "test-two-side-two.txt",
913 "test-two-side-two.txt",
914 "test-two.txt"
915 },
916
917 {
918 "test-three-side-one.txt",
919 "test-three.txt",
920 "test-three-side-one.txt"
921 },
922 {
923 "test-three-side-two.txt",
924 "test-three-side-two.txt",
925 "test-three.txt"
926 }
927 };
928
929 opts.checkout_strategy |= GIT_CHECKOUT_SAFE;
930
931 create_index(checkout_index_entries, 24);
932 create_index_names(checkout_name_entries, 6);
933 cl_git_pass(git_index_write(g_index));
934
935 /* Add some files on disk that conflict with the names that would be chosen
936 * for the files written for each side. */
937
938 cl_git_rewritefile("merge-resolve/test-one.txt~ours",
939 "Expect index contents to be written to ~ours_0");
940 cl_git_rewritefile("merge-resolve/test-one.txt~theirs",
941 "Expect index contents to be written to ~theirs_0");
942
943 cl_git_rewritefile("merge-resolve/test-two.txt~ours",
944 "Expect index contents to be written to ~ours_3");
945 cl_git_rewritefile("merge-resolve/test-two.txt~theirs",
946 "Expect index contents to be written to ~theirs_3");
947 cl_git_rewritefile("merge-resolve/test-two.txt~ours_0",
948 "Expect index contents to be written to ~ours_3");
949 cl_git_rewritefile("merge-resolve/test-two.txt~theirs_0",
950 "Expect index contents to be written to ~theirs_3");
951 cl_git_rewritefile("merge-resolve/test-two.txt~ours_1",
952 "Expect index contents to be written to ~ours_3");
953 cl_git_rewritefile("merge-resolve/test-two.txt~theirs_1",
954 "Expect index contents to be written to ~theirs_3");
955 cl_git_rewritefile("merge-resolve/test-two.txt~ours_2",
956 "Expect index contents to be written to ~ours_3");
957 cl_git_rewritefile("merge-resolve/test-two.txt~theirs_2",
958 "Expect index contents to be written to ~theirs_3");
959
960 cl_git_rewritefile("merge-resolve/test-three.txt~Ours",
961 "Expect case insensitive filesystems to create ~ours_0");
962 cl_git_rewritefile("merge-resolve/test-three.txt~THEIRS",
963 "Expect case insensitive filesystems to create ~theirs_0");
964
965 cl_git_rewritefile("merge-resolve/directory_file-one~ours",
966 "Index contents written to ~ours_0 in this D/F conflict");
967 cl_git_rewritefile("merge-resolve/directory_file-two~theirs",
968 "Index contents written to ~theirs_0 in this D/F conflict");
969
970 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
971
972 ensure_workdir("test-one.txt~ours_0",
973 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
974 ensure_workdir("test-one.txt~theirs_0",
975 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07");
976
977 ensure_workdir("test-two.txt~ours_3",
978 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
979 ensure_workdir("test-two.txt~theirs_3",
980 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07");
981
982 /* Name is mangled on case insensitive only */
983 #if defined(GIT_WIN32) || defined(__APPLE__)
984 ensure_workdir("test-three.txt~ours_0",
985 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
986 ensure_workdir("test-three.txt~theirs_0",
987 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07");
988 #else
989 ensure_workdir("test-three.txt~ours",
990 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
991 ensure_workdir("test-three.txt~theirs",
992 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07");
993 #endif
994
995 ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID);
996 ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID);
997 }
998
999 void test_checkout_conflict__update_only(void)
1000 {
1001 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1002
1003 struct checkout_index_entry checkout_index_entries[] = {
1004 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" },
1005 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" },
1006 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" },
1007
1008 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "modify-delete" },
1009 { 0100644, CONFLICTING_THEIRS_OID, 3, "modify-delete" },
1010
1011 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" },
1012 { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" },
1013 { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" },
1014
1015 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" },
1016 { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" },
1017 { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" },
1018 };
1019
1020 opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_ONLY;
1021
1022 create_index(checkout_index_entries, 3);
1023 cl_git_pass(git_index_write(g_index));
1024
1025 cl_git_pass(p_mkdir("merge-resolve/directory_file-two", 0777));
1026 cl_git_rewritefile("merge-resolve/directory_file-two/file", CONFLICTING_OURS_FILE);
1027
1028 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
1029
1030 ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE);
1031 ensure_workdir("directory_file-two/file", 0100644, CONFLICTING_OURS_OID);
1032
1033 cl_assert(!git_fs_path_exists("merge-resolve/modify-delete"));
1034 cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt"));
1035 cl_assert(!git_fs_path_exists("merge-resolve/test-one-side-one.txt"));
1036 cl_assert(!git_fs_path_exists("merge-resolve/test-one-side-two.txt"));
1037 cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt~ours"));
1038 cl_assert(!git_fs_path_exists("merge-resolve/test-one.txt~theirs"));
1039 cl_assert(!git_fs_path_exists("merge-resolve/directory_file-one/file"));
1040 cl_assert(!git_fs_path_exists("merge-resolve/directory_file-one~ours"));
1041 cl_assert(!git_fs_path_exists("merge-resolve/directory_file-two~theirs"));
1042 }
1043
1044 void test_checkout_conflict__path_filters(void)
1045 {
1046 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1047 char *paths[] = { "conflicting-1.txt", "conflicting-3.txt" };
1048 git_strarray patharray = {0};
1049
1050 struct checkout_index_entry checkout_index_entries[] = {
1051 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" },
1052 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" },
1053 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" },
1054
1055 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" },
1056 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" },
1057 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" },
1058
1059 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" },
1060 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" },
1061 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" },
1062
1063 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" },
1064 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" },
1065 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" },
1066 };
1067
1068 patharray.count = 2;
1069 patharray.strings = paths;
1070
1071 opts.paths = patharray;
1072
1073 create_index(checkout_index_entries, 12);
1074 cl_git_pass(git_index_write(g_index));
1075
1076 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
1077
1078 ensure_workdir_contents("conflicting-1.txt", CONFLICTING_DIFF3_FILE);
1079 cl_assert(!git_fs_path_exists("merge-resolve/conflicting-2.txt"));
1080 ensure_workdir_contents("conflicting-3.txt", AUTOMERGEABLE_MERGED_FILE);
1081 cl_assert(!git_fs_path_exists("merge-resolve/conflicting-4.txt"));
1082 }
1083
1084 static void collect_progress(
1085 const char *path,
1086 size_t completed_steps,
1087 size_t total_steps,
1088 void *payload)
1089 {
1090 git_vector *paths = payload;
1091
1092 GIT_UNUSED(completed_steps);
1093 GIT_UNUSED(total_steps);
1094
1095 if (path == NULL)
1096 return;
1097
1098 git_vector_insert(paths, strdup(path));
1099 }
1100
1101 void test_checkout_conflict__report_progress(void)
1102 {
1103 git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
1104 git_vector paths = GIT_VECTOR_INIT;
1105 char *path;
1106 size_t i;
1107
1108 struct checkout_index_entry checkout_index_entries[] = {
1109 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" },
1110 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" },
1111 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" },
1112
1113 { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" },
1114 { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" },
1115 { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" },
1116
1117 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" },
1118 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" },
1119 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" },
1120
1121 { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" },
1122 { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" },
1123 { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" },
1124 };
1125
1126 opts.progress_cb = collect_progress;
1127 opts.progress_payload = &paths;
1128
1129
1130 create_index(checkout_index_entries, 12);
1131 cl_git_pass(git_index_write(g_index));
1132
1133 cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
1134
1135 cl_assert_equal_i(4, git_vector_length(&paths));
1136 cl_assert_equal_s("conflicting-1.txt", git_vector_get(&paths, 0));
1137 cl_assert_equal_s("conflicting-2.txt", git_vector_get(&paths, 1));
1138 cl_assert_equal_s("conflicting-3.txt", git_vector_get(&paths, 2));
1139 cl_assert_equal_s("conflicting-4.txt", git_vector_get(&paths, 3));
1140
1141 git_vector_foreach(&paths, i, path)
1142 git__free(path);
1143
1144 git_vector_free(&paths);
1145 }