1 #include "clar_libgit2.h"
2 #include "checkout_helpers.h"
4 #include "git2/checkout.h"
6 #include "repository.h"
9 static git_repository
*g_repo
;
11 void test_checkout_index__initialize(void)
15 g_repo
= cl_git_sandbox_init("testrepo");
17 cl_git_pass(git_repository_head_tree(&tree
, g_repo
));
19 reset_index_to_treeish((git_object
*)tree
);
23 "./testrepo/.gitattributes",
27 void test_checkout_index__cleanup(void)
29 cl_git_sandbox_cleanup();
31 /* try to remove alternative dir */
32 if (git_path_isdir("alternative"))
33 git_futils_rmdir_r("alternative", NULL
, GIT_RMDIR_REMOVE_FILES
);
36 void test_checkout_index__cannot_checkout_a_bare_repository(void)
38 test_checkout_index__cleanup();
40 g_repo
= cl_git_sandbox_init("testrepo.git");
42 cl_git_fail(git_checkout_index(g_repo
, NULL
, NULL
));
45 void test_checkout_index__can_create_missing_files(void)
47 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
49 cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
50 cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
51 cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
53 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
55 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
57 check_file_contents("./testrepo/README", "hey there\n");
58 check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
59 check_file_contents("./testrepo/new.txt", "my new file\n");
62 void test_checkout_index__can_remove_untracked_files(void)
64 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
66 git_futils_mkdir("./testrepo/dir/subdir/subsubdir", 0755, GIT_MKDIR_PATH
);
67 cl_git_mkfile("./testrepo/dir/one", "one\n");
68 cl_git_mkfile("./testrepo/dir/subdir/two", "two\n");
70 cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir"));
72 opts
.checkout_strategy
=
74 GIT_CHECKOUT_RECREATE_MISSING
|
75 GIT_CHECKOUT_REMOVE_UNTRACKED
;
77 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
79 cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
82 void test_checkout_index__honor_the_specified_pathspecs(void)
84 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
85 char *entries
[] = { "*.txt" };
87 opts
.paths
.strings
= entries
;
90 cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
91 cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
92 cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
94 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
96 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
98 cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
99 check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
100 check_file_contents("./testrepo/new.txt", "my new file\n");
103 void test_checkout_index__honor_the_gitattributes_directives(void)
105 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
106 const char *attributes
=
107 "branch_file.txt text eol=crlf\n"
108 "new.txt text eol=lf\n";
110 cl_git_mkfile("./testrepo/.gitattributes", attributes
);
111 cl_repo_set_bool(g_repo
, "core.autocrlf", false);
113 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
115 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
117 check_file_contents("./testrepo/README", "hey there\n");
118 check_file_contents("./testrepo/new.txt", "my new file\n");
119 check_file_contents("./testrepo/branch_file.txt", "hi\r\nbye!\r\n");
122 void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
125 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
126 const char *expected_readme_text
= "hey there\r\n";
128 cl_git_pass(p_unlink("./testrepo/.gitattributes"));
129 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
131 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
133 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
135 check_file_contents("./testrepo/README", expected_readme_text
);
139 void test_checkout_index__honor_coresymlinks_default(void)
141 git_repository
*repo
;
144 char cwd
[GIT_PATH_MAX
];
146 const char *url
= git_repository_path(g_repo
);
148 cl_assert(getcwd(cwd
, sizeof(cwd
)) != NULL
);
149 cl_assert_equal_i(0, p_mkdir("readonly", 0555)); // Read-only directory
150 cl_assert_equal_i(0, chdir("readonly"));
151 cl_git_pass(git_repository_init(&repo
, "../symlink.git", true));
152 cl_assert_equal_i(0, chdir(cwd
));
153 cl_assert_equal_i(0, p_mkdir("symlink", 0777));
154 cl_git_pass(git_repository_set_workdir(repo
, "symlink", 1));
156 cl_git_pass(git_remote_create(&origin
, repo
, GIT_REMOTE_ORIGIN
, url
));
157 cl_git_pass(git_remote_fetch(origin
, NULL
, NULL
, NULL
));
158 git_remote_free(origin
);
160 cl_git_pass(git_revparse_single(&target
, repo
, "remotes/origin/master"));
161 cl_git_pass(git_reset(repo
, target
, GIT_RESET_HARD
, NULL
));
162 git_object_free(target
);
163 git_repository_free(repo
);
166 check_file_contents("./symlink/link_to_new.txt", "new.txt");
169 char link_data
[1024];
170 size_t link_size
= 1024;
172 link_size
= p_readlink("./symlink/link_to_new.txt", link_data
, link_size
);
173 link_data
[link_size
] = '\0';
174 cl_assert_equal_i(link_size
, strlen("new.txt"));
175 cl_assert_equal_s(link_data
, "new.txt");
176 check_file_contents("./symlink/link_to_new.txt", "my new file\n");
180 cl_fixture_cleanup("symlink");
183 void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
185 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
187 cl_repo_set_bool(g_repo
, "core.symlinks", true);
189 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
191 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
194 check_file_contents("./testrepo/link_to_new.txt", "new.txt");
197 char link_data
[1024];
198 size_t link_size
= 1024;
200 link_size
= p_readlink("./testrepo/link_to_new.txt", link_data
, link_size
);
201 link_data
[link_size
] = '\0';
202 cl_assert_equal_i(link_size
, strlen("new.txt"));
203 cl_assert_equal_s(link_data
, "new.txt");
204 check_file_contents("./testrepo/link_to_new.txt", "my new file\n");
209 void test_checkout_index__honor_coresymlinks_setting_set_to_false(void)
211 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
213 cl_repo_set_bool(g_repo
, "core.symlinks", false);
215 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
217 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
219 check_file_contents("./testrepo/link_to_new.txt", "new.txt");
222 void test_checkout_index__donot_overwrite_modified_file_by_default(void)
224 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
226 cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
228 /* set this up to not return an error code on conflicts, but it
229 * still will not have permission to overwrite anything...
231 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_ALLOW_CONFLICTS
;
233 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
235 check_file_contents("./testrepo/new.txt", "This isn't what's stored!");
238 void test_checkout_index__can_overwrite_modified_file(void)
240 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
242 cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
244 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
246 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
248 check_file_contents("./testrepo/new.txt", "my new file\n");
251 void test_checkout_index__options_disable_filters(void)
253 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
255 cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n");
257 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
258 opts
.disable_filters
= false;
260 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
262 check_file_contents("./testrepo/new.txt", "my new file\r\n");
264 p_unlink("./testrepo/new.txt");
266 opts
.disable_filters
= true;
267 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
269 check_file_contents("./testrepo/new.txt", "my new file\n");
272 void test_checkout_index__options_dir_modes(void)
274 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
280 if (!cl_is_chmod_supported())
283 cl_git_pass(git_reference_name_to_id(&oid
, g_repo
, "refs/heads/dir"));
284 cl_git_pass(git_commit_lookup(&commit
, g_repo
, &oid
));
286 reset_index_to_treeish((git_object
*)commit
);
288 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
289 opts
.dir_mode
= 0701;
291 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
293 /* umask will influence actual directory creation mode */
294 (void)p_umask(um
= p_umask(022));
296 cl_git_pass(p_stat("./testrepo/a", &st
));
297 /* Haiku & Hurd use other mode bits, so we must mask them out */
298 cl_assert_equal_i_fmt(st
.st_mode
& (S_IFMT
| 07777), (GIT_FILEMODE_TREE
| 0701) & ~um
, "%07o");
300 /* File-mode test, since we're on the 'dir' branch */
301 cl_git_pass(p_stat("./testrepo/a/b.txt", &st
));
302 cl_assert_equal_i_fmt(st
.st_mode
& (S_IFMT
| 07777), GIT_FILEMODE_BLOB_EXECUTABLE
& ~um
, "%07o");
304 git_commit_free(commit
);
307 void test_checkout_index__options_override_file_modes(void)
309 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
312 if (!cl_is_chmod_supported())
315 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
316 opts
.file_mode
= 0700;
318 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
320 cl_git_pass(p_stat("./testrepo/new.txt", &st
));
321 cl_assert_equal_i_fmt(st
.st_mode
& GIT_MODE_PERMS_MASK
, 0700, "%07o");
324 void test_checkout_index__options_open_flags(void)
326 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
328 cl_git_mkfile("./testrepo/new.txt", "hi\n");
330 opts
.checkout_strategy
=
331 GIT_CHECKOUT_FORCE
| GIT_CHECKOUT_DONT_REMOVE_EXISTING
;
332 opts
.file_open_flags
= O_CREAT
| O_RDWR
| O_APPEND
;
334 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
336 check_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
344 static int test_checkout_notify_cb(
345 git_checkout_notify_t why
,
347 const git_diff_file
*baseline
,
348 const git_diff_file
*target
,
349 const git_diff_file
*workdir
,
352 struct notify_data
*expectations
= (struct notify_data
*)payload
;
356 cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT
, why
);
357 cl_assert_equal_s(expectations
->file
, path
);
358 cl_assert_equal_i(0, git_oid_streq(&baseline
->id
, expectations
->sha
));
359 cl_assert_equal_i(0, git_oid_streq(&target
->id
, expectations
->sha
));
364 void test_checkout_index__can_notify_of_skipped_files(void)
366 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
367 struct notify_data data
;
369 cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
373 * 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README
374 * 100644 blob 3697d64be941a53d4ae8f6a271e4e3fa56b022cc branch_file.txt
375 * 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt
377 data
.file
= "new.txt";
378 data
.sha
= "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd";
380 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|
381 GIT_CHECKOUT_RECREATE_MISSING
|
382 GIT_CHECKOUT_ALLOW_CONFLICTS
;
383 opts
.notify_flags
= GIT_CHECKOUT_NOTIFY_CONFLICT
;
384 opts
.notify_cb
= test_checkout_notify_cb
;
385 opts
.notify_payload
= &data
;
387 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
390 static int dont_notify_cb(
391 git_checkout_notify_t why
,
393 const git_diff_file
*baseline
,
394 const git_diff_file
*target
,
395 const git_diff_file
*workdir
,
400 GIT_UNUSED(baseline
);
410 void test_checkout_index__wont_notify_of_expected_line_ending_changes(void)
412 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
414 cl_git_pass(p_unlink("./testrepo/.gitattributes"));
415 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
417 cl_git_mkfile("./testrepo/new.txt", "my new file\r\n");
419 opts
.checkout_strategy
=
421 GIT_CHECKOUT_RECREATE_MISSING
|
422 GIT_CHECKOUT_ALLOW_CONFLICTS
;
423 opts
.notify_flags
= GIT_CHECKOUT_NOTIFY_CONFLICT
;
424 opts
.notify_cb
= dont_notify_cb
;
425 opts
.notify_payload
= NULL
;
427 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
430 static void checkout_progress_counter(
431 const char *path
, size_t cur
, size_t tot
, void *payload
)
433 GIT_UNUSED(path
); GIT_UNUSED(cur
); GIT_UNUSED(tot
);
437 void test_checkout_index__calls_progress_callback(void)
439 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
442 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
443 opts
.progress_cb
= checkout_progress_counter
;
444 opts
.progress_payload
= &calls
;
446 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
447 cl_assert(calls
> 0);
450 void test_checkout_index__can_overcome_name_clashes(void)
452 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
455 cl_git_pass(git_repository_index(&index
, g_repo
));
456 git_index_clear(index
);
458 cl_git_mkfile("./testrepo/path0", "content\r\n");
459 cl_git_pass(p_mkdir("./testrepo/path1", 0777));
460 cl_git_mkfile("./testrepo/path1/file1", "content\r\n");
462 cl_git_pass(git_index_add_bypath(index
, "path0"));
463 cl_git_pass(git_index_add_bypath(index
, "path1/file1"));
465 cl_git_pass(p_unlink("./testrepo/path0"));
466 cl_git_pass(git_futils_rmdir_r(
467 "./testrepo/path1", NULL
, GIT_RMDIR_REMOVE_FILES
));
469 cl_git_mkfile("./testrepo/path1", "content\r\n");
470 cl_git_pass(p_mkdir("./testrepo/path0", 0777));
471 cl_git_mkfile("./testrepo/path0/file0", "content\r\n");
473 cl_assert(git_path_isfile("./testrepo/path1"));
474 cl_assert(git_path_isfile("./testrepo/path0/file0"));
476 opts
.checkout_strategy
=
478 GIT_CHECKOUT_RECREATE_MISSING
|
479 GIT_CHECKOUT_ALLOW_CONFLICTS
;
480 cl_git_pass(git_checkout_index(g_repo
, index
, &opts
));
482 cl_assert(git_path_isfile("./testrepo/path1"));
483 cl_assert(git_path_isfile("./testrepo/path0/file0"));
485 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
486 cl_git_pass(git_checkout_index(g_repo
, index
, &opts
));
488 cl_assert(git_path_isfile("./testrepo/path0"));
489 cl_assert(git_path_isfile("./testrepo/path1/file1"));
491 git_index_free(index
);
494 void test_checkout_index__validates_struct_version(void)
496 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
497 const git_error
*err
;
500 cl_git_fail(git_checkout_index(g_repo
, NULL
, &opts
));
503 cl_assert_equal_i(err
->klass
, GITERR_INVALID
);
507 cl_git_fail(git_checkout_index(g_repo
, NULL
, &opts
));
510 cl_assert_equal_i(err
->klass
, GITERR_INVALID
);
513 void test_checkout_index__can_update_prefixed_files(void)
515 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
517 cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
518 cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
519 cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
521 cl_git_mkfile("./testrepo/READ", "content\n");
522 cl_git_mkfile("./testrepo/README.after", "content\n");
523 cl_git_pass(p_mkdir("./testrepo/branch_file", 0777));
524 cl_git_pass(p_mkdir("./testrepo/branch_file/contained_dir", 0777));
525 cl_git_mkfile("./testrepo/branch_file/contained_file", "content\n");
526 cl_git_pass(p_mkdir("./testrepo/branch_file.txt.after", 0777));
528 opts
.checkout_strategy
=
530 GIT_CHECKOUT_RECREATE_MISSING
|
531 GIT_CHECKOUT_REMOVE_UNTRACKED
;
533 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
535 /* remove untracked will remove the .gitattributes file before the blobs
536 * were created, so they will have had crlf filtering applied on Windows
538 check_file_contents_nocr("./testrepo/README", "hey there\n");
539 check_file_contents_nocr("./testrepo/branch_file.txt", "hi\nbye!\n");
540 check_file_contents_nocr("./testrepo/new.txt", "my new file\n");
542 cl_assert(!git_path_exists("testrepo/READ"));
543 cl_assert(!git_path_exists("testrepo/README.after"));
544 cl_assert(!git_path_exists("testrepo/branch_file"));
545 cl_assert(!git_path_exists("testrepo/branch_file.txt.after"));
548 void test_checkout_index__can_checkout_a_newly_initialized_repository(void)
550 test_checkout_index__cleanup();
552 g_repo
= cl_git_sandbox_init("empty_standard_repo");
553 cl_git_remove_placeholders(git_repository_path(g_repo
), "dummy-marker.txt");
555 cl_git_pass(git_checkout_index(g_repo
, NULL
, NULL
));
558 void test_checkout_index__issue_1397(void)
560 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
562 test_checkout_index__cleanup();
564 g_repo
= cl_git_sandbox_init("issue_1397");
566 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
568 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
570 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
572 check_file_contents("./issue_1397/crlf_file.txt", "first line\r\nsecond line\r\nboth with crlf");
575 void test_checkout_index__target_directory(void)
577 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
579 memset(&cts
, 0, sizeof(cts
));
581 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|
582 GIT_CHECKOUT_RECREATE_MISSING
;
583 opts
.target_directory
= "alternative";
584 cl_assert(!git_path_isdir("alternative"));
586 opts
.notify_flags
= GIT_CHECKOUT_NOTIFY_ALL
;
587 opts
.notify_cb
= checkout_count_callback
;
588 opts
.notify_payload
= &cts
;
590 /* create some files that *would* conflict if we were using the wd */
591 cl_git_mkfile("testrepo/README", "I'm in the way!\n");
592 cl_git_mkfile("testrepo/new.txt", "my new file\n");
594 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
596 cl_assert_equal_i(0, cts
.n_untracked
);
597 cl_assert_equal_i(0, cts
.n_ignored
);
598 cl_assert_equal_i(4, cts
.n_updates
);
600 check_file_contents("./alternative/README", "hey there\n");
601 check_file_contents("./alternative/branch_file.txt", "hi\nbye!\n");
602 check_file_contents("./alternative/new.txt", "my new file\n");
604 cl_git_pass(git_futils_rmdir_r(
605 "alternative", NULL
, GIT_RMDIR_REMOVE_FILES
));
608 void test_checkout_index__target_directory_from_bare(void)
610 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
612 git_object
*head
= NULL
;
614 memset(&cts
, 0, sizeof(cts
));
616 test_checkout_index__cleanup();
618 g_repo
= cl_git_sandbox_init("testrepo.git");
619 cl_assert(git_repository_is_bare(g_repo
));
621 cl_git_pass(git_repository_index(&index
, g_repo
));
622 cl_git_pass(git_revparse_single(&head
, g_repo
, "HEAD^{tree}"));
623 cl_git_pass(git_index_read_tree(index
, (const git_tree
*)head
));
624 cl_git_pass(git_index_write(index
));
625 git_index_free(index
);
627 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|
628 GIT_CHECKOUT_RECREATE_MISSING
;
630 opts
.notify_flags
= GIT_CHECKOUT_NOTIFY_ALL
;
631 opts
.notify_cb
= checkout_count_callback
;
632 opts
.notify_payload
= &cts
;
634 /* fail to checkout a bare repo */
635 cl_git_fail(git_checkout_index(g_repo
, NULL
, &opts
));
637 opts
.target_directory
= "alternative";
638 cl_assert(!git_path_isdir("alternative"));
640 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
642 cl_assert_equal_i(0, cts
.n_untracked
);
643 cl_assert_equal_i(0, cts
.n_ignored
);
644 cl_assert_equal_i(3, cts
.n_updates
);
646 /* files will have been filtered if needed, so strip CR */
647 check_file_contents_nocr("./alternative/README", "hey there\n");
648 check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n");
649 check_file_contents_nocr("./alternative/new.txt", "my new file\n");
651 cl_git_pass(git_futils_rmdir_r(
652 "alternative", NULL
, GIT_RMDIR_REMOVE_FILES
));
654 git_object_free(head
);
657 void test_checkout_index__can_get_repo_from_index(void)
660 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
662 cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
663 cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
664 cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
666 opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
| GIT_CHECKOUT_RECREATE_MISSING
;
668 cl_git_pass(git_repository_index(&index
, g_repo
));
670 cl_git_pass(git_checkout_index(NULL
, index
, &opts
));
672 check_file_contents("./testrepo/README", "hey there\n");
673 check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
674 check_file_contents("./testrepo/new.txt", "my new file\n");
676 git_index_free(index
);
679 static void add_conflict(git_index
*index
, const char *path
)
681 git_index_entry entry
;
683 memset(&entry
, 0, sizeof(git_index_entry
));
685 entry
.mode
= 0100644;
688 git_oid_fromstr(&entry
.id
, "d427e0b2e138501a3d15cc376077a3631e15bd46");
689 GIT_IDXENTRY_STAGE_SET(&entry
, 1);
690 cl_git_pass(git_index_add(index
, &entry
));
692 git_oid_fromstr(&entry
.id
, "4e886e602529caa9ab11d71f86634bd1b6e0de10");
693 GIT_IDXENTRY_STAGE_SET(&entry
, 2);
694 cl_git_pass(git_index_add(index
, &entry
));
696 git_oid_fromstr(&entry
.id
, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
697 GIT_IDXENTRY_STAGE_SET(&entry
, 3);
698 cl_git_pass(git_index_add(index
, &entry
));
701 void test_checkout_index__writes_conflict_file(void)
704 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
705 git_buf conflicting_buf
= GIT_BUF_INIT
;
707 cl_git_pass(git_repository_index(&index
, g_repo
));
709 add_conflict(index
, "conflicting.txt");
710 cl_git_pass(git_index_write(index
));
712 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
714 cl_git_pass(git_futils_readbuffer(&conflicting_buf
, "testrepo/conflicting.txt"));
715 cl_assert(strcmp(conflicting_buf
.ptr
,
717 "this file is changed in master and branch\n"
719 "this file is changed in branch and master\n"
720 ">>>>>>> theirs\n") == 0);
721 git_buf_free(&conflicting_buf
);
723 git_index_free(index
);
726 void test_checkout_index__adding_conflict_removes_stage_0(void)
728 git_index
*new_index
, *index
;
729 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
731 cl_git_pass(git_index_new(&new_index
));
733 add_conflict(new_index
, "new.txt");
734 cl_git_pass(git_checkout_index(g_repo
, new_index
, &opts
));
736 cl_git_pass(git_repository_index(&index
, g_repo
));
738 cl_assert(git_index_get_bypath(index
, "new.txt", 0) == NULL
);
739 cl_assert(git_index_get_bypath(index
, "new.txt", 1) != NULL
);
740 cl_assert(git_index_get_bypath(index
, "new.txt", 2) != NULL
);
741 cl_assert(git_index_get_bypath(index
, "new.txt", 3) != NULL
);
743 git_index_free(index
);
744 git_index_free(new_index
);
747 void test_checkout_index__conflicts_honor_coreautocrlf(void)
751 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
752 git_buf conflicting_buf
= GIT_BUF_INIT
;
754 cl_git_pass(p_unlink("./testrepo/.gitattributes"));
755 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
757 cl_git_pass(git_repository_index(&index
, g_repo
));
759 add_conflict(index
, "conflicting.txt");
760 cl_git_pass(git_index_write(index
));
762 cl_git_pass(git_checkout_index(g_repo
, NULL
, &opts
));
764 cl_git_pass(git_futils_readbuffer(&conflicting_buf
, "testrepo/conflicting.txt"));
765 cl_assert(strcmp(conflicting_buf
.ptr
,
767 "this file is changed in master and branch\r\n"
769 "this file is changed in branch and master\r\n"
770 ">>>>>>> theirs\r\n") == 0);
771 git_buf_free(&conflicting_buf
);
773 git_index_free(index
);