1 #include "clar_libgit2.h"
4 #include "status_data.h"
12 * Not all of the tests in this file use the same fixtures, so we allow each
13 * test to load their fixture at the top of the test function.
15 void test_status_worktree__initialize(void)
22 * This will be called once after each test finishes, even
25 void test_status_worktree__cleanup(void)
27 cl_git_sandbox_cleanup();
31 * Tests - Status determination on a working tree
33 /* this test is equivalent to t18-status.c:statuscb0 */
34 void test_status_worktree__whole_repository(void)
36 status_entry_counts counts
;
37 git_repository
*repo
= cl_git_sandbox_init("status");
39 memset(&counts
, 0x0, sizeof(status_entry_counts
));
40 counts
.expected_entry_count
= entry_count0
;
41 counts
.expected_paths
= entry_paths0
;
42 counts
.expected_statuses
= entry_statuses0
;
45 git_status_foreach(repo
, cb_status__normal
, &counts
)
48 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
49 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
50 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
53 /* this test is equivalent to t18-status.c:statuscb1 */
54 void test_status_worktree__empty_repository(void)
57 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
59 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
61 cl_assert_equal_i(0, count
);
64 static int remove_file_cb(void *data
, git_buf
*file
)
66 const char *filename
= git_buf_cstr(file
);
70 if (git__suffixcmp(filename
, ".git") == 0)
73 if (git_path_isdir(filename
))
74 cl_git_pass(git_futils_rmdir_r(filename
, GIT_DIRREMOVAL_FILES_AND_DIRS
));
76 cl_git_pass(p_unlink(git_buf_cstr(file
)));
81 /* this test is equivalent to t18-status.c:statuscb2 */
82 void test_status_worktree__purged_worktree(void)
84 status_entry_counts counts
;
85 git_repository
*repo
= cl_git_sandbox_init("status");
86 git_buf workdir
= GIT_BUF_INIT
;
88 /* first purge the contents of the worktree */
89 cl_git_pass(git_buf_sets(&workdir
, git_repository_workdir(repo
)));
90 cl_git_pass(git_path_direach(&workdir
, remove_file_cb
, NULL
));
91 git_buf_free(&workdir
);
94 memset(&counts
, 0x0, sizeof(status_entry_counts
));
95 counts
.expected_entry_count
= entry_count2
;
96 counts
.expected_paths
= entry_paths2
;
97 counts
.expected_statuses
= entry_statuses2
;
100 git_status_foreach(repo
, cb_status__normal
, &counts
)
103 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
104 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
105 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
108 /* this test is similar to t18-status.c:statuscb3 */
109 void test_status_worktree__swap_subdir_and_file(void)
111 status_entry_counts counts
;
112 git_repository
*repo
= cl_git_sandbox_init("status");
113 git_status_options opts
;
115 /* first alter the contents of the worktree */
116 cl_git_pass(p_rename("status/current_file", "status/swap"));
117 cl_git_pass(p_rename("status/subdir", "status/current_file"));
118 cl_git_pass(p_rename("status/swap", "status/subdir"));
120 cl_git_mkfile("status/.HEADER", "dummy");
121 cl_git_mkfile("status/42-is-not-prime.sigh", "dummy");
122 cl_git_mkfile("status/README.md", "dummy");
125 memset(&counts
, 0x0, sizeof(status_entry_counts
));
126 counts
.expected_entry_count
= entry_count3
;
127 counts
.expected_paths
= entry_paths3
;
128 counts
.expected_statuses
= entry_statuses3
;
130 memset(&opts
, 0, sizeof(opts
));
131 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
132 GIT_STATUS_OPT_INCLUDE_IGNORED
;
135 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
138 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
139 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
140 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
143 void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void)
145 status_entry_counts counts
;
146 git_repository
*repo
= cl_git_sandbox_init("status");
147 git_status_options opts
;
149 /* first alter the contents of the worktree */
150 cl_git_pass(p_rename("status/current_file", "status/swap"));
151 cl_git_pass(p_rename("status/subdir", "status/current_file"));
152 cl_git_pass(p_rename("status/swap", "status/subdir"));
153 cl_git_mkfile("status/.new_file", "dummy");
154 cl_git_pass(git_futils_mkdir_r("status/zzz_new_dir", NULL
, 0777));
155 cl_git_mkfile("status/zzz_new_dir/new_file", "dummy");
156 cl_git_mkfile("status/zzz_new_file", "dummy");
159 memset(&counts
, 0x0, sizeof(status_entry_counts
));
160 counts
.expected_entry_count
= entry_count4
;
161 counts
.expected_paths
= entry_paths4
;
162 counts
.expected_statuses
= entry_statuses4
;
164 memset(&opts
, 0, sizeof(opts
));
165 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
166 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
167 /* TODO: set pathspec to "current_file" eventually */
170 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
173 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
174 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
175 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
178 /* this test is equivalent to t18-status.c:singlestatus0 */
179 void test_status_worktree__single_file(void)
182 unsigned int status_flags
;
183 git_repository
*repo
= cl_git_sandbox_init("status");
185 for (i
= 0; i
< (int)entry_count0
; i
++) {
187 git_status_file(&status_flags
, repo
, entry_paths0
[i
])
189 cl_assert(entry_statuses0
[i
] == status_flags
);
193 /* this test is equivalent to t18-status.c:singlestatus1 */
194 void test_status_worktree__single_nonexistent_file(void)
197 unsigned int status_flags
;
198 git_repository
*repo
= cl_git_sandbox_init("status");
200 error
= git_status_file(&status_flags
, repo
, "nonexistent");
202 cl_assert(error
== GIT_ENOTFOUND
);
205 /* this test is equivalent to t18-status.c:singlestatus2 */
206 void test_status_worktree__single_nonexistent_file_empty_repo(void)
209 unsigned int status_flags
;
210 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
212 error
= git_status_file(&status_flags
, repo
, "nonexistent");
214 cl_assert(error
== GIT_ENOTFOUND
);
217 /* this test is equivalent to t18-status.c:singlestatus3 */
218 void test_status_worktree__single_file_empty_repo(void)
220 unsigned int status_flags
;
221 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
223 cl_git_mkfile("empty_standard_repo/new_file", "new_file\n");
225 cl_git_pass(git_status_file(&status_flags
, repo
, "new_file"));
226 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
229 /* this test is equivalent to t18-status.c:singlestatus4 */
230 void test_status_worktree__single_folder(void)
233 unsigned int status_flags
;
234 git_repository
*repo
= cl_git_sandbox_init("status");
236 error
= git_status_file(&status_flags
, repo
, "subdir");
238 cl_assert(error
!= GIT_ENOTFOUND
);
242 void test_status_worktree__ignores(void)
245 git_repository
*repo
= cl_git_sandbox_init("status");
247 for (i
= 0; i
< (int)entry_count0
; i
++) {
249 git_status_should_ignore(&ignored
, repo
, entry_paths0
[i
])
251 cl_assert(ignored
== (entry_statuses0
[i
] == GIT_STATUS_IGNORED
));
255 git_status_should_ignore(&ignored
, repo
, "nonexistent_file")
260 git_status_should_ignore(&ignored
, repo
, "ignored_nonexistent_file")
265 static int cb_status__check_592(const char *p
, unsigned int s
, void *payload
)
269 if (s
!= GIT_STATUS_WT_DELETED
|| (payload
!= NULL
&& strcmp(p
, (const char *)payload
) != 0))
275 void test_status_worktree__issue_592(void)
277 git_repository
*repo
;
278 git_buf path
= GIT_BUF_INIT
;
280 repo
= cl_git_sandbox_init("issue_592");
281 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "l.txt"));
282 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
284 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "l.txt"));
289 void test_status_worktree__issue_592_2(void)
291 git_repository
*repo
;
292 git_buf path
= GIT_BUF_INIT
;
294 repo
= cl_git_sandbox_init("issue_592");
295 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "c/a.txt"));
296 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
298 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "c/a.txt"));
303 void test_status_worktree__issue_592_3(void)
305 git_repository
*repo
;
306 git_buf path
= GIT_BUF_INIT
;
308 repo
= cl_git_sandbox_init("issue_592");
310 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "c"));
311 cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path
), GIT_DIRREMOVAL_FILES_AND_DIRS
));
313 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "c/a.txt"));
318 void test_status_worktree__issue_592_4(void)
320 git_repository
*repo
;
321 git_buf path
= GIT_BUF_INIT
;
323 repo
= cl_git_sandbox_init("issue_592");
325 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "t/b.txt"));
326 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
328 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "t/b.txt"));
333 void test_status_worktree__issue_592_5(void)
335 git_repository
*repo
;
336 git_buf path
= GIT_BUF_INIT
;
338 repo
= cl_git_sandbox_init("issue_592");
340 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "t"));
341 cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path
), GIT_DIRREMOVAL_FILES_AND_DIRS
));
342 cl_git_pass(p_mkdir(git_buf_cstr(&path
), 0777));
344 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, NULL
));
349 void test_status_worktree__issue_592_ignores_0(void)
352 status_entry_single st
;
353 git_repository
*repo
= cl_git_sandbox_init("issue_592");
355 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
356 cl_assert_equal_i(0, count
);
358 cl_git_rewritefile("issue_592/.gitignore",
359 ".gitignore\n*.txt\nc/\n[tT]*/\n");
361 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
362 cl_assert_equal_i(1, count
);
364 /* This is a situation where the behavior of libgit2 is
365 * different from core git. Core git will show ignored.txt
366 * in the list of ignored files, even though the directory
367 * "t" is ignored and the file is untracked because we have
368 * the explicit "*.txt" ignore rule. Libgit2 just excludes
369 * all untracked files that are contained within ignored
370 * directories without explicitly listing them.
372 cl_git_rewritefile("issue_592/t/ignored.txt", "ping");
374 memset(&st
, 0, sizeof(st
));
375 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
376 cl_assert_equal_i(1, st
.count
);
377 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
379 cl_git_rewritefile("issue_592/c/ignored_by_dir", "ping");
381 memset(&st
, 0, sizeof(st
));
382 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
383 cl_assert_equal_i(1, st
.count
);
384 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
386 cl_git_rewritefile("issue_592/t/ignored_by_dir_pattern", "ping");
388 memset(&st
, 0, sizeof(st
));
389 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
390 cl_assert_equal_i(1, st
.count
);
391 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
394 void test_status_worktree__issue_592_ignored_dirs_with_tracked_content(void)
397 git_repository
*repo
= cl_git_sandbox_init("issue_592b");
399 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
400 cl_assert_equal_i(1, count
);
402 /* if we are really mimicking core git, then only ignored1.txt
403 * at the top level will show up in the ignores list here.
404 * everything else will be unmodified or skipped completely.
408 void test_status_worktree__cannot_retrieve_the_status_of_a_bare_repository(void)
410 git_repository
*repo
;
412 unsigned int status
= 0;
414 cl_git_pass(git_repository_open(&repo
, cl_fixture("testrepo.git")));
416 error
= git_status_file(&status
, repo
, "dummy");
419 cl_assert(error
!= GIT_ENOTFOUND
);
421 git_repository_free(repo
);
424 void test_status_worktree__first_commit_in_progress(void)
426 git_repository
*repo
;
428 status_entry_single result
;
430 cl_git_pass(git_repository_init(&repo
, "getting_started", 0));
431 cl_git_mkfile("getting_started/testfile.txt", "content\n");
433 memset(&result
, 0, sizeof(result
));
434 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
435 cl_assert_equal_i(1, result
.count
);
436 cl_assert(result
.status
== GIT_STATUS_WT_NEW
);
438 cl_git_pass(git_repository_index(&index
, repo
));
439 cl_git_pass(git_index_add(index
, "testfile.txt", 0));
440 cl_git_pass(git_index_write(index
));
442 memset(&result
, 0, sizeof(result
));
443 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
444 cl_assert_equal_i(1, result
.count
);
445 cl_assert(result
.status
== GIT_STATUS_INDEX_NEW
);
447 git_index_free(index
);
448 git_repository_free(repo
);
453 void test_status_worktree__status_file_without_index_or_workdir(void)
455 git_repository
*repo
;
456 unsigned int status
= 0;
459 cl_git_pass(p_mkdir("wd", 0777));
461 cl_git_pass(git_repository_open(&repo
, cl_fixture("testrepo.git")));
462 cl_git_pass(git_repository_set_workdir(repo
, "wd", false));
464 cl_git_pass(git_index_open(&index
, "empty-index"));
465 cl_assert_equal_i(0, git_index_entrycount(index
));
466 git_repository_set_index(repo
, index
);
468 cl_git_pass(git_status_file(&status
, repo
, "branch_file.txt"));
470 cl_assert_equal_i(GIT_STATUS_INDEX_DELETED
, status
);
472 git_repository_free(repo
);
473 git_index_free(index
);
474 cl_git_pass(p_rmdir("wd"));
477 static void fill_index_wth_head_entries(git_repository
*repo
, git_index
*index
)
483 cl_git_pass(git_reference_name_to_oid(&oid
, repo
, "HEAD"));
484 cl_git_pass(git_commit_lookup(&commit
, repo
, &oid
));
485 cl_git_pass(git_commit_tree(&tree
, commit
));
487 cl_git_pass(git_index_read_tree(index
, tree
, NULL
));
488 cl_git_pass(git_index_write(index
));
491 git_commit_free(commit
);
494 void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void)
496 git_repository
*repo
;
497 unsigned int status
= 0;
500 cl_git_pass(p_mkdir("wd", 0777));
502 cl_git_pass(git_repository_open(&repo
, cl_fixture("testrepo.git")));
503 cl_git_pass(git_repository_set_workdir(repo
, "wd", false));
505 cl_git_pass(git_index_open(&index
, "my-index"));
506 fill_index_wth_head_entries(repo
, index
);
508 git_repository_set_index(repo
, index
);
510 cl_git_pass(git_status_file(&status
, repo
, "branch_file.txt"));
512 cl_assert_equal_i(GIT_STATUS_WT_DELETED
, status
);
514 git_repository_free(repo
);
515 git_index_free(index
);
516 cl_git_pass(p_rmdir("wd"));
517 cl_git_pass(p_unlink("my-index"));
520 void test_status_worktree__bracket_in_filename(void)
522 git_repository
*repo
;
524 status_entry_single result
;
525 unsigned int status_flags
;
528 #define FILE_WITH_BRACKET "LICENSE[1].md"
529 #define FILE_WITHOUT_BRACKET "LICENSE1.md"
531 cl_git_pass(git_repository_init(&repo
, "with_bracket", 0));
532 cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET
, "I have a bracket in my name\n");
534 /* file is new to working directory */
536 memset(&result
, 0, sizeof(result
));
537 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
538 cl_assert_equal_i(1, result
.count
);
539 cl_assert(result
.status
== GIT_STATUS_WT_NEW
);
541 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_BRACKET
));
542 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
544 /* ignore the file */
546 cl_git_rewritefile("with_bracket/.gitignore", "*.md\n.gitignore\n");
548 memset(&result
, 0, sizeof(result
));
549 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
550 cl_assert_equal_i(2, result
.count
);
551 cl_assert(result
.status
== GIT_STATUS_IGNORED
);
553 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_BRACKET
));
554 cl_assert(status_flags
== GIT_STATUS_IGNORED
);
556 /* don't ignore the file */
558 cl_git_rewritefile("with_bracket/.gitignore", ".gitignore\n");
560 memset(&result
, 0, sizeof(result
));
561 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
562 cl_assert_equal_i(2, result
.count
);
563 cl_assert(result
.status
== GIT_STATUS_WT_NEW
);
565 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_BRACKET
));
566 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
568 /* add the file to the index */
570 cl_git_pass(git_repository_index(&index
, repo
));
571 cl_git_pass(git_index_add(index
, FILE_WITH_BRACKET
, 0));
572 cl_git_pass(git_index_write(index
));
574 memset(&result
, 0, sizeof(result
));
575 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
576 cl_assert_equal_i(2, result
.count
);
577 cl_assert(result
.status
== GIT_STATUS_INDEX_NEW
);
579 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_BRACKET
));
580 cl_assert(status_flags
== GIT_STATUS_INDEX_NEW
);
582 /* Create file without bracket */
584 cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET
, "I have no bracket in my name!\n");
586 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITHOUT_BRACKET
));
587 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
589 cl_git_pass(git_status_file(&status_flags
, repo
, "LICENSE\\[1\\].md"));
590 cl_assert(status_flags
== GIT_STATUS_INDEX_NEW
);
592 error
= git_status_file(&status_flags
, repo
, FILE_WITH_BRACKET
);
594 cl_assert_equal_i(GIT_EAMBIGUOUS
, error
);
596 git_index_free(index
);
597 git_repository_free(repo
);
600 void test_status_worktree__space_in_filename(void)
602 git_repository
*repo
;
604 status_entry_single result
;
605 unsigned int status_flags
;
607 #define FILE_WITH_SPACE "LICENSE - copy.md"
609 cl_git_pass(git_repository_init(&repo
, "with_space", 0));
610 cl_git_mkfile("with_space/" FILE_WITH_SPACE
, "I have a space in my name\n");
612 /* file is new to working directory */
614 memset(&result
, 0, sizeof(result
));
615 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
616 cl_assert_equal_i(1, result
.count
);
617 cl_assert(result
.status
== GIT_STATUS_WT_NEW
);
619 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_SPACE
));
620 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
622 /* ignore the file */
624 cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n");
626 memset(&result
, 0, sizeof(result
));
627 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
628 cl_assert_equal_i(2, result
.count
);
629 cl_assert(result
.status
== GIT_STATUS_IGNORED
);
631 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_SPACE
));
632 cl_assert(status_flags
== GIT_STATUS_IGNORED
);
634 /* don't ignore the file */
636 cl_git_rewritefile("with_space/.gitignore", ".gitignore\n");
638 memset(&result
, 0, sizeof(result
));
639 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
640 cl_assert_equal_i(2, result
.count
);
641 cl_assert(result
.status
== GIT_STATUS_WT_NEW
);
643 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_SPACE
));
644 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
646 /* add the file to the index */
648 cl_git_pass(git_repository_index(&index
, repo
));
649 cl_git_pass(git_index_add(index
, FILE_WITH_SPACE
, 0));
650 cl_git_pass(git_index_write(index
));
652 memset(&result
, 0, sizeof(result
));
653 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &result
));
654 cl_assert_equal_i(2, result
.count
);
655 cl_assert(result
.status
== GIT_STATUS_INDEX_NEW
);
657 cl_git_pass(git_status_file(&status_flags
, repo
, FILE_WITH_SPACE
));
658 cl_assert(status_flags
== GIT_STATUS_INDEX_NEW
);
660 git_index_free(index
);
661 git_repository_free(repo
);
664 static const char *filemode_paths
[] = {
666 "exec_off2on_staged",
667 "exec_off2on_workdir",
668 "exec_off_untracked",
670 "exec_on2off_staged",
671 "exec_on2off_workdir",
675 static unsigned int filemode_statuses
[] = {
677 GIT_STATUS_INDEX_MODIFIED
,
678 GIT_STATUS_WT_MODIFIED
,
681 GIT_STATUS_INDEX_MODIFIED
,
682 GIT_STATUS_WT_MODIFIED
,
686 static const int filemode_count
= 8;
688 void test_status_worktree__filemode_changes(void)
690 git_repository
*repo
= cl_git_sandbox_init("filemodes");
691 status_entry_counts counts
;
692 git_status_options opts
;
695 /* overwrite stored filemode with platform appropriate value */
696 cl_git_pass(git_repository_config(&cfg
, repo
));
697 if (cl_is_chmod_supported())
698 cl_git_pass(git_config_set_bool(cfg
, "core.filemode", true));
701 cl_git_pass(git_config_set_bool(cfg
, "core.filemode", false));
703 /* won't trust filesystem mode diffs, so these will appear unchanged */
704 for (i
= 0; i
< filemode_count
; ++i
)
705 if (filemode_statuses
[i
] == GIT_STATUS_WT_MODIFIED
)
706 filemode_statuses
[i
] = GIT_STATUS_CURRENT
;
709 memset(&opts
, 0, sizeof(opts
));
710 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
711 GIT_STATUS_OPT_INCLUDE_IGNORED
|
712 GIT_STATUS_OPT_INCLUDE_UNMODIFIED
;
714 memset(&counts
, 0, sizeof(counts
));
715 counts
.expected_entry_count
= filemode_count
;
716 counts
.expected_paths
= filemode_paths
;
717 counts
.expected_statuses
= filemode_statuses
;
720 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
723 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
724 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
725 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
727 git_config_free(cfg
);
730 static int cb_status__expected_path(const char *p
, unsigned int s
, void *payload
)
732 const char *expected_path
= (const char *)payload
;
737 cl_fail("Unexpected path");
739 cl_assert_equal_s(expected_path
, p
);
744 void test_status_worktree__disable_pathspec_match(void)
746 git_repository
*repo
;
747 git_status_options opts
;
748 char *file_with_bracket
= "LICENSE[1].md",
749 *imaginary_file_with_bracket
= "LICENSE[1-2].md";
751 cl_git_pass(git_repository_init(&repo
, "pathspec", 0));
752 cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n");
753 cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n");
755 memset(&opts
, 0, sizeof(opts
));
756 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
757 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
;
758 opts
.pathspec
.count
= 1;
759 opts
.pathspec
.strings
= &file_with_bracket
;
762 git_status_foreach_ext(repo
, &opts
, cb_status__expected_path
,
766 /* Test passing a pathspec matching files in the workdir. */
767 /* Must not match because pathspecs are disabled. */
768 opts
.pathspec
.strings
= &imaginary_file_with_bracket
;
770 git_status_foreach_ext(repo
, &opts
, cb_status__expected_path
, NULL
)
773 git_repository_free(repo
);
777 static int cb_status__interrupt(const char *p
, unsigned int s
, void *payload
)
779 volatile int *count
= (int *)payload
;
786 return (*count
== 8);
789 void test_status_worktree__interruptable_foreach(void)
792 git_repository
*repo
= cl_git_sandbox_init("status");
795 GIT_EUSER
, git_status_foreach(repo
, cb_status__interrupt
, &count
)
798 cl_assert_equal_i(8, count
);
801 void test_status_worktree__new_staged_file_must_handle_crlf(void)
803 git_repository
*repo
;
808 cl_git_pass(git_repository_init(&repo
, "getting_started", 0));
810 // Ensure that repo has core.autocrlf=true
811 cl_git_pass(git_repository_config(&config
, repo
));
812 cl_git_pass(git_config_set_bool(config
, "core.autocrlf", true));
814 cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); // Content with CRLF
816 cl_git_pass(git_repository_index(&index
, repo
));
817 cl_git_pass(git_index_add(index
, "testfile.txt", 0));
818 cl_git_pass(git_index_write(index
));
820 cl_git_pass(git_status_file(&status
, repo
, "testfile.txt"));
821 cl_assert_equal_i(GIT_STATUS_INDEX_NEW
, status
);
823 git_config_free(config
);
824 git_index_free(index
);
825 git_repository_free(repo
);