1 #include "clar_libgit2.h"
4 #include "status_data.h"
8 #include "../diff/diff_helpers.h"
9 #include "../checkout/checkout_helpers.h"
10 #include "git2/sys/diff.h"
15 * This will be called once after each test finishes, even
18 void test_status_worktree__cleanup(void)
20 cl_git_sandbox_cleanup();
24 * Tests - Status determination on a working tree
26 /* this test is equivalent to t18-status.c:statuscb0 */
27 void test_status_worktree__whole_repository(void)
29 status_entry_counts counts
;
30 git_repository
*repo
= cl_git_sandbox_init("status");
32 memset(&counts
, 0x0, sizeof(status_entry_counts
));
33 counts
.expected_entry_count
= entry_count0
;
34 counts
.expected_paths
= entry_paths0
;
35 counts
.expected_statuses
= entry_statuses0
;
38 git_status_foreach(repo
, cb_status__normal
, &counts
)
41 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
42 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
43 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
47 const int entry_counts
,
48 const char *entry_paths
[],
49 const unsigned int entry_statuses
[],
51 git_status_show_t show
,
52 unsigned int extra_flags
)
54 status_entry_counts counts
;
55 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
57 memset(&counts
, 0x0, sizeof(status_entry_counts
));
58 counts
.expected_entry_count
= entry_counts
;
59 counts
.expected_paths
= entry_paths
;
60 counts
.expected_statuses
= entry_statuses
;
62 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
| extra_flags
;
66 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
69 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
70 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
71 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
74 void test_status_worktree__show_index_and_workdir(void)
76 assert_show(entry_count0
, entry_paths0
, entry_statuses0
,
77 cl_git_sandbox_init("status"), GIT_STATUS_SHOW_INDEX_AND_WORKDIR
, 0);
80 void test_status_worktree__show_index_only(void)
82 assert_show(entry_count5
, entry_paths5
, entry_statuses5
,
83 cl_git_sandbox_init("status"), GIT_STATUS_SHOW_INDEX_ONLY
, 0);
86 void test_status_worktree__show_workdir_only(void)
88 assert_show(entry_count6
, entry_paths6
, entry_statuses6
,
89 cl_git_sandbox_init("status"), GIT_STATUS_SHOW_WORKDIR_ONLY
, 0);
92 /* this test is equivalent to t18-status.c:statuscb1 */
93 void test_status_worktree__empty_repository(void)
96 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
98 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
100 cl_assert_equal_i(0, count
);
103 static int remove_file_cb(void *data
, git_buf
*file
)
105 const char *filename
= git_buf_cstr(file
);
109 if (git__suffixcmp(filename
, ".git") == 0)
112 if (git_path_isdir(filename
))
113 cl_git_pass(git_futils_rmdir_r(filename
, NULL
, GIT_RMDIR_REMOVE_FILES
));
115 cl_git_pass(p_unlink(git_buf_cstr(file
)));
120 /* this test is equivalent to t18-status.c:statuscb2 */
121 void test_status_worktree__purged_worktree(void)
123 status_entry_counts counts
;
124 git_repository
*repo
= cl_git_sandbox_init("status");
125 git_buf workdir
= GIT_BUF_INIT
;
127 /* first purge the contents of the worktree */
128 cl_git_pass(git_buf_sets(&workdir
, git_repository_workdir(repo
)));
129 cl_git_pass(git_path_direach(&workdir
, 0, remove_file_cb
, NULL
));
130 git_buf_free(&workdir
);
133 memset(&counts
, 0x0, sizeof(status_entry_counts
));
134 counts
.expected_entry_count
= entry_count2
;
135 counts
.expected_paths
= entry_paths2
;
136 counts
.expected_statuses
= entry_statuses2
;
139 git_status_foreach(repo
, cb_status__normal
, &counts
)
142 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
143 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
144 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
147 /* this test is similar to t18-status.c:statuscb3 */
148 void test_status_worktree__swap_subdir_and_file(void)
150 status_entry_counts counts
;
151 git_repository
*repo
= cl_git_sandbox_init("status");
153 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
156 cl_git_pass(git_repository_index(&index
, repo
));
157 ignore_case
= (git_index_caps(index
) & GIT_INDEXCAP_IGNORE_CASE
) != 0;
158 git_index_free(index
);
160 /* first alter the contents of the worktree */
161 cl_git_pass(p_rename("status/current_file", "status/swap"));
162 cl_git_pass(p_rename("status/subdir", "status/current_file"));
163 cl_git_pass(p_rename("status/swap", "status/subdir"));
165 cl_git_mkfile("status/.HEADER", "dummy");
166 cl_git_mkfile("status/42-is-not-prime.sigh", "dummy");
167 cl_git_mkfile("status/README.md", "dummy");
170 memset(&counts
, 0x0, sizeof(status_entry_counts
));
171 counts
.expected_entry_count
= entry_count3
;
172 counts
.expected_paths
= ignore_case
? entry_paths3_icase
: entry_paths3
;
173 counts
.expected_statuses
= ignore_case
? entry_statuses3_icase
: entry_statuses3
;
175 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
176 GIT_STATUS_OPT_INCLUDE_IGNORED
;
179 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
182 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
183 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
184 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
187 void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void)
189 status_entry_counts counts
;
190 git_repository
*repo
= cl_git_sandbox_init("status");
191 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
193 /* first alter the contents of the worktree */
194 cl_git_pass(p_rename("status/current_file", "status/swap"));
195 cl_git_pass(p_rename("status/subdir", "status/current_file"));
196 cl_git_pass(p_rename("status/swap", "status/subdir"));
197 cl_git_mkfile("status/.new_file", "dummy");
198 cl_git_pass(git_futils_mkdir_r("status/zzz_new_dir", 0777));
199 cl_git_mkfile("status/zzz_new_dir/new_file", "dummy");
200 cl_git_mkfile("status/zzz_new_file", "dummy");
203 memset(&counts
, 0x0, sizeof(status_entry_counts
));
204 counts
.expected_entry_count
= entry_count4
;
205 counts
.expected_paths
= entry_paths4
;
206 counts
.expected_statuses
= entry_statuses4
;
208 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
209 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
210 /* TODO: set pathspec to "current_file" eventually */
213 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
216 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
217 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
218 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
221 static void stage_and_commit(git_repository
*repo
, const char *path
)
225 cl_git_pass(git_repository_index(&index
, repo
));
226 cl_git_pass(git_index_add_bypath(index
, path
));
227 cl_repo_commit_from_index(NULL
, repo
, NULL
, 1323847743, "Initial commit\n");
228 git_index_free(index
);
231 void test_status_worktree__within_subdir(void)
233 status_entry_counts counts
;
234 git_repository
*repo
= cl_git_sandbox_init("status");
235 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
236 char *paths
[] = { "zzz_new_dir" };
237 git_strarray pathsArray
;
239 /* first alter the contents of the worktree */
240 cl_git_mkfile("status/.new_file", "dummy");
241 cl_git_pass(git_futils_mkdir_r("status/zzz_new_dir", 0777));
242 cl_git_mkfile("status/zzz_new_dir/new_file", "dummy");
243 cl_git_mkfile("status/zzz_new_file", "dummy");
244 cl_git_mkfile("status/wut", "dummy");
246 stage_and_commit(repo
, "zzz_new_dir/new_file");
249 memset(&counts
, 0x0, sizeof(status_entry_counts
));
250 counts
.expected_entry_count
= entry_count4
;
251 counts
.expected_paths
= entry_paths4
;
252 counts
.expected_statuses
= entry_statuses4
;
255 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
256 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
|
257 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
;
259 pathsArray
.count
= 1;
260 pathsArray
.strings
= paths
;
261 opts
.pathspec
= pathsArray
;
263 // We committed zzz_new_dir/new_file above. It shouldn't be reported.
265 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
268 cl_assert_equal_i(0, counts
.entry_count
);
269 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
270 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
273 /* this test is equivalent to t18-status.c:singlestatus0 */
274 void test_status_worktree__single_file(void)
277 unsigned int status_flags
;
278 git_repository
*repo
= cl_git_sandbox_init("status");
280 for (i
= 0; i
< (int)entry_count0
; i
++) {
282 git_status_file(&status_flags
, repo
, entry_paths0
[i
])
284 cl_assert(entry_statuses0
[i
] == status_flags
);
288 /* this test is equivalent to t18-status.c:singlestatus1 */
289 void test_status_worktree__single_nonexistent_file(void)
292 unsigned int status_flags
;
293 git_repository
*repo
= cl_git_sandbox_init("status");
295 error
= git_status_file(&status_flags
, repo
, "nonexistent");
297 cl_assert(error
== GIT_ENOTFOUND
);
300 /* this test is equivalent to t18-status.c:singlestatus2 */
301 void test_status_worktree__single_nonexistent_file_empty_repo(void)
304 unsigned int status_flags
;
305 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
307 error
= git_status_file(&status_flags
, repo
, "nonexistent");
309 cl_assert(error
== GIT_ENOTFOUND
);
312 /* this test is equivalent to t18-status.c:singlestatus3 */
313 void test_status_worktree__single_file_empty_repo(void)
315 unsigned int status_flags
;
316 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
318 cl_git_mkfile("empty_standard_repo/new_file", "new_file\n");
320 cl_git_pass(git_status_file(&status_flags
, repo
, "new_file"));
321 cl_assert(status_flags
== GIT_STATUS_WT_NEW
);
324 /* this test is equivalent to t18-status.c:singlestatus4 */
325 void test_status_worktree__single_folder(void)
328 unsigned int status_flags
;
329 git_repository
*repo
= cl_git_sandbox_init("status");
331 error
= git_status_file(&status_flags
, repo
, "subdir");
333 cl_assert(error
!= GIT_ENOTFOUND
);
337 void test_status_worktree__ignores(void)
340 git_repository
*repo
= cl_git_sandbox_init("status");
342 for (i
= 0; i
< (int)entry_count0
; i
++) {
344 git_status_should_ignore(&ignored
, repo
, entry_paths0
[i
])
346 cl_assert(ignored
== (entry_statuses0
[i
] == GIT_STATUS_IGNORED
));
350 git_status_should_ignore(&ignored
, repo
, "nonexistent_file")
355 git_status_should_ignore(&ignored
, repo
, "ignored_nonexistent_file")
360 static int cb_status__check_592(const char *p
, unsigned int s
, void *payload
)
362 if (s
!= GIT_STATUS_WT_DELETED
||
363 (payload
!= NULL
&& strcmp(p
, (const char *)payload
) != 0))
369 void test_status_worktree__issue_592(void)
371 git_repository
*repo
;
372 git_buf path
= GIT_BUF_INIT
;
374 repo
= cl_git_sandbox_init("issue_592");
375 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "l.txt"));
376 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
377 cl_assert(!git_path_exists("issue_592/l.txt"));
379 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "l.txt"));
384 void test_status_worktree__issue_592_2(void)
386 git_repository
*repo
;
387 git_buf path
= GIT_BUF_INIT
;
389 repo
= cl_git_sandbox_init("issue_592");
390 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "c/a.txt"));
391 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
392 cl_assert(!git_path_exists("issue_592/c/a.txt"));
394 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "c/a.txt"));
399 void test_status_worktree__issue_592_3(void)
401 git_repository
*repo
;
402 git_buf path
= GIT_BUF_INIT
;
404 repo
= cl_git_sandbox_init("issue_592");
406 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "c"));
407 cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path
), NULL
, GIT_RMDIR_REMOVE_FILES
));
408 cl_assert(!git_path_exists("issue_592/c/a.txt"));
410 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "c/a.txt"));
415 void test_status_worktree__issue_592_4(void)
417 git_repository
*repo
;
418 git_buf path
= GIT_BUF_INIT
;
420 repo
= cl_git_sandbox_init("issue_592");
422 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "t/b.txt"));
423 cl_git_pass(p_unlink(git_buf_cstr(&path
)));
425 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, "t/b.txt"));
430 void test_status_worktree__issue_592_5(void)
432 git_repository
*repo
;
433 git_buf path
= GIT_BUF_INIT
;
435 repo
= cl_git_sandbox_init("issue_592");
437 cl_git_pass(git_buf_joinpath(&path
, git_repository_workdir(repo
), "t"));
438 cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path
), NULL
, GIT_RMDIR_REMOVE_FILES
));
439 cl_git_pass(p_mkdir(git_buf_cstr(&path
), 0777));
441 cl_git_pass(git_status_foreach(repo
, cb_status__check_592
, NULL
));
446 void test_status_worktree__issue_592_ignores_0(void)
449 status_entry_single st
;
450 git_repository
*repo
= cl_git_sandbox_init("issue_592");
452 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
453 cl_assert_equal_i(0, count
);
455 cl_git_rewritefile("issue_592/.gitignore",
456 ".gitignore\n*.txt\nc/\n[tT]*/\n");
458 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
459 cl_assert_equal_i(1, count
);
461 /* This is a situation where the behavior of libgit2 is
462 * different from core git. Core git will show ignored.txt
463 * in the list of ignored files, even though the directory
464 * "t" is ignored and the file is untracked because we have
465 * the explicit "*.txt" ignore rule. Libgit2 just excludes
466 * all untracked files that are contained within ignored
467 * directories without explicitly listing them.
469 cl_git_rewritefile("issue_592/t/ignored.txt", "ping");
471 memset(&st
, 0, sizeof(st
));
472 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
473 cl_assert_equal_i(1, st
.count
);
474 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
476 cl_git_rewritefile("issue_592/c/ignored_by_dir", "ping");
478 memset(&st
, 0, sizeof(st
));
479 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
480 cl_assert_equal_i(1, st
.count
);
481 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
483 cl_git_rewritefile("issue_592/t/ignored_by_dir_pattern", "ping");
485 memset(&st
, 0, sizeof(st
));
486 cl_git_pass(git_status_foreach(repo
, cb_status__single
, &st
));
487 cl_assert_equal_i(1, st
.count
);
488 cl_assert(st
.status
== GIT_STATUS_IGNORED
);
491 void test_status_worktree__issue_592_ignored_dirs_with_tracked_content(void)
494 git_repository
*repo
= cl_git_sandbox_init("issue_592b");
496 cl_git_pass(git_status_foreach(repo
, cb_status__count
, &count
));
497 cl_assert_equal_i(1, count
);
499 /* if we are really mimicking core git, then only ignored1.txt
500 * at the top level will show up in the ignores list here.
501 * everything else will be unmodified or skipped completely.
505 void test_status_worktree__conflict_with_diff3(void)
507 git_repository
*repo
= cl_git_sandbox_init("status");
510 git_index_entry ancestor_entry
, our_entry
, their_entry
;
512 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
513 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
514 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
516 ancestor_entry
.path
= "modified_file";
517 ancestor_entry
.mode
= 0100644;
518 git_oid_fromstr(&ancestor_entry
.id
,
519 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
521 our_entry
.path
= "modified_file";
522 our_entry
.mode
= 0100644;
523 git_oid_fromstr(&our_entry
.id
,
524 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
526 their_entry
.path
= "modified_file";
527 their_entry
.mode
= 0100644;
528 git_oid_fromstr(&their_entry
.id
,
529 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
531 cl_git_pass(git_status_file(&status
, repo
, "modified_file"));
532 cl_assert_equal_i(GIT_STATUS_WT_MODIFIED
, status
);
534 cl_git_pass(git_repository_index(&index
, repo
));
535 cl_git_pass(git_index_remove(index
, "modified_file", 0));
536 cl_git_pass(git_index_conflict_add(
537 index
, &ancestor_entry
, &our_entry
, &their_entry
));
538 cl_git_pass(git_index_write(index
));
539 git_index_free(index
);
541 cl_git_pass(git_status_file(&status
, repo
, "modified_file"));
543 cl_assert_equal_i(GIT_STATUS_CONFLICTED
, status
);
546 static const char *filemode_paths
[] = {
548 "exec_off2on_staged",
549 "exec_off2on_workdir",
550 "exec_off_untracked",
552 "exec_on2off_staged",
553 "exec_on2off_workdir",
557 static unsigned int filemode_statuses
[] = {
559 GIT_STATUS_INDEX_MODIFIED
,
560 GIT_STATUS_WT_MODIFIED
,
563 GIT_STATUS_INDEX_MODIFIED
,
564 GIT_STATUS_WT_MODIFIED
,
568 static const int filemode_count
= 8;
570 void test_status_worktree__filemode_changes(void)
572 git_repository
*repo
= cl_git_sandbox_init("filemodes");
573 status_entry_counts counts
;
574 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
576 /* overwrite stored filemode with platform appropriate value */
577 if (cl_is_chmod_supported())
578 cl_repo_set_bool(repo
, "core.filemode", true);
582 cl_repo_set_bool(repo
, "core.filemode", false);
584 /* won't trust filesystem mode diffs, so these will appear unchanged */
585 for (i
= 0; i
< filemode_count
; ++i
)
586 if (filemode_statuses
[i
] == GIT_STATUS_WT_MODIFIED
)
587 filemode_statuses
[i
] = GIT_STATUS_CURRENT
;
590 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
591 GIT_STATUS_OPT_INCLUDE_IGNORED
|
592 GIT_STATUS_OPT_INCLUDE_UNMODIFIED
;
594 memset(&counts
, 0, sizeof(counts
));
595 counts
.expected_entry_count
= filemode_count
;
596 counts
.expected_paths
= filemode_paths
;
597 counts
.expected_statuses
= filemode_statuses
;
600 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
)
603 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
604 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
605 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
608 static int cb_status__interrupt(const char *p
, unsigned int s
, void *payload
)
610 volatile int *count
= (int *)payload
;
617 return (*count
== 8) ? -111 : 0;
620 void test_status_worktree__interruptable_foreach(void)
623 git_repository
*repo
= cl_git_sandbox_init("status");
626 -111, git_status_foreach(repo
, cb_status__interrupt
, &count
)
629 cl_assert_equal_i(8, count
);
632 void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void)
634 git_repository
*repo
= cl_git_sandbox_init("status");
637 cl_repo_set_bool(repo
, "core.autocrlf", true);
639 cl_git_rewritefile("status/current_file", "current_file\r\n");
641 cl_git_pass(git_status_file(&status
, repo
, "current_file"));
643 /* stat data on file should no longer match stat cache, even though
644 * file diff will be empty because of line-ending conversion - matches
645 * the Git command-line behavior here.
647 cl_assert_equal_i(GIT_STATUS_WT_MODIFIED
, status
);
650 void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf_issue_1397(void)
652 git_repository
*repo
= cl_git_sandbox_init("issue_1397");
655 cl_repo_set_bool(repo
, "core.autocrlf", true);
657 cl_git_pass(git_status_file(&status
, repo
, "crlf_file.txt"));
659 cl_assert_equal_i(GIT_STATUS_CURRENT
, status
);
662 void test_status_worktree__conflicted_item(void)
664 git_repository
*repo
= cl_git_sandbox_init("status");
667 git_index_entry ancestor_entry
, our_entry
, their_entry
;
669 memset(&ancestor_entry
, 0x0, sizeof(git_index_entry
));
670 memset(&our_entry
, 0x0, sizeof(git_index_entry
));
671 memset(&their_entry
, 0x0, sizeof(git_index_entry
));
673 ancestor_entry
.mode
= 0100644;
674 ancestor_entry
.path
= "modified_file";
675 git_oid_fromstr(&ancestor_entry
.id
,
676 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
678 our_entry
.mode
= 0100644;
679 our_entry
.path
= "modified_file";
680 git_oid_fromstr(&our_entry
.id
,
681 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
683 their_entry
.mode
= 0100644;
684 their_entry
.path
= "modified_file";
685 git_oid_fromstr(&their_entry
.id
,
686 "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
688 cl_git_pass(git_status_file(&status
, repo
, "modified_file"));
689 cl_assert_equal_i(GIT_STATUS_WT_MODIFIED
, status
);
691 cl_git_pass(git_repository_index(&index
, repo
));
692 cl_git_pass(git_index_conflict_add(index
, &ancestor_entry
,
693 &our_entry
, &their_entry
));
695 cl_git_pass(git_status_file(&status
, repo
, "modified_file"));
696 cl_assert_equal_i(GIT_STATUS_CONFLICTED
, status
);
698 git_index_free(index
);
701 void test_status_worktree__conflict_has_no_oid(void)
703 git_repository
*repo
= cl_git_sandbox_init("status");
705 git_index_entry entry
= {{0}};
706 git_status_list
*statuslist
;
707 const git_status_entry
*status
;
708 git_oid zero_id
= {{0}};
710 entry
.mode
= 0100644;
711 entry
.path
= "modified_file";
712 git_oid_fromstr(&entry
.id
, "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
714 cl_git_pass(git_repository_index(&index
, repo
));
715 cl_git_pass(git_index_conflict_add(index
, &entry
, &entry
, &entry
));
717 git_status_list_new(&statuslist
, repo
, NULL
);
719 cl_assert_equal_i(16, git_status_list_entrycount(statuslist
));
721 status
= git_status_byindex(statuslist
, 2);
723 cl_assert_equal_i(GIT_STATUS_CONFLICTED
, status
->status
);
724 cl_assert_equal_s("modified_file", status
->head_to_index
->old_file
.path
);
725 cl_assert(!git_oid_equal(&zero_id
, &status
->head_to_index
->old_file
.id
));
726 cl_assert(0 != status
->head_to_index
->old_file
.mode
);
727 cl_assert_equal_s("modified_file", status
->head_to_index
->new_file
.path
);
728 cl_assert_equal_oid(&zero_id
, &status
->head_to_index
->new_file
.id
);
729 cl_assert_equal_i(0, status
->head_to_index
->new_file
.mode
);
730 cl_assert_equal_i(0, status
->head_to_index
->new_file
.size
);
732 cl_assert_equal_s("modified_file", status
->index_to_workdir
->old_file
.path
);
733 cl_assert_equal_oid(&zero_id
, &status
->index_to_workdir
->old_file
.id
);
734 cl_assert_equal_i(0, status
->index_to_workdir
->old_file
.mode
);
735 cl_assert_equal_i(0, status
->index_to_workdir
->old_file
.size
);
736 cl_assert_equal_s("modified_file", status
->index_to_workdir
->new_file
.path
);
738 !git_oid_equal(&zero_id
, &status
->index_to_workdir
->new_file
.id
) ||
739 !(status
->index_to_workdir
->new_file
.flags
& GIT_DIFF_FLAG_VALID_ID
));
740 cl_assert(0 != status
->index_to_workdir
->new_file
.mode
);
741 cl_assert(0 != status
->index_to_workdir
->new_file
.size
);
743 git_index_free(index
);
744 git_status_list_free(statuslist
);
747 static void assert_ignore_case(
748 bool should_ignore_case
,
749 int expected_lower_cased_file_status
,
750 int expected_camel_cased_file_status
)
753 git_buf lower_case_path
= GIT_BUF_INIT
, camel_case_path
= GIT_BUF_INIT
;
754 git_repository
*repo
, *repo2
;
756 repo
= cl_git_sandbox_init("empty_standard_repo");
757 cl_git_remove_placeholders(git_repository_path(repo
), "dummy-marker.txt");
759 cl_repo_set_bool(repo
, "core.ignorecase", should_ignore_case
);
761 cl_git_pass(git_buf_joinpath(&lower_case_path
,
762 git_repository_workdir(repo
), "plop"));
764 cl_git_mkfile(git_buf_cstr(&lower_case_path
), "");
766 stage_and_commit(repo
, "plop");
768 cl_git_pass(git_repository_open(&repo2
, "./empty_standard_repo"));
770 cl_git_pass(git_status_file(&status
, repo2
, "plop"));
771 cl_assert_equal_i(GIT_STATUS_CURRENT
, status
);
773 cl_git_pass(git_buf_joinpath(&camel_case_path
,
774 git_repository_workdir(repo
), "Plop"));
776 cl_git_pass(p_rename(git_buf_cstr(&lower_case_path
), git_buf_cstr(&camel_case_path
)));
778 cl_git_pass(git_status_file(&status
, repo2
, "plop"));
779 cl_assert_equal_i(expected_lower_cased_file_status
, status
);
781 cl_git_pass(git_status_file(&status
, repo2
, "Plop"));
782 cl_assert_equal_i(expected_camel_cased_file_status
, status
);
784 git_repository_free(repo2
);
785 git_buf_free(&lower_case_path
);
786 git_buf_free(&camel_case_path
);
789 void test_status_worktree__file_status_honors_core_ignorecase_true(void)
791 assert_ignore_case(true, GIT_STATUS_CURRENT
, GIT_STATUS_CURRENT
);
794 void test_status_worktree__file_status_honors_core_ignorecase_false(void)
796 assert_ignore_case(false, GIT_STATUS_WT_DELETED
, GIT_STATUS_WT_NEW
);
799 void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void)
801 git_repository
*repo
= cl_git_sandbox_init("status");
805 cl_repo_set_bool(repo
, "core.ignorecase", false);
807 repo
= cl_git_sandbox_reopen();
809 /* Actually returns GIT_STATUS_IGNORED on Windows */
810 cl_git_fail_with(git_status_file(&status
, repo
, "NEW_FILE"), GIT_ENOTFOUND
);
812 cl_git_pass(git_repository_index(&index
, repo
));
814 cl_git_pass(git_index_add_bypath(index
, "new_file"));
815 cl_git_pass(git_index_write(index
));
816 git_index_free(index
);
818 /* Actually returns GIT_STATUS_IGNORED on Windows */
819 cl_git_fail_with(git_status_file(&status
, repo
, "NEW_FILE"), GIT_ENOTFOUND
);
822 void test_status_worktree__simple_delete(void)
824 git_repository
*repo
= cl_git_sandbox_init("renames");
825 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
828 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
829 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
|
830 GIT_STATUS_OPT_EXCLUDE_SUBMODULES
|
831 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
835 git_status_foreach_ext(repo
, &opts
, cb_status__count
, &count
) );
836 cl_assert_equal_i(0, count
);
838 cl_must_pass(p_unlink("renames/untimely.txt"));
842 git_status_foreach_ext(repo
, &opts
, cb_status__count
, &count
) );
843 cl_assert_equal_i(1, count
);
846 void test_status_worktree__simple_delete_indexed(void)
848 git_repository
*repo
= cl_git_sandbox_init("renames");
849 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
850 git_status_list
*status
;
852 opts
.flags
= GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
853 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
|
854 GIT_STATUS_OPT_EXCLUDE_SUBMODULES
|
855 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
857 cl_git_pass(git_status_list_new(&status
, repo
, &opts
));
858 cl_assert_equal_sz(0, git_status_list_entrycount(status
));
859 git_status_list_free(status
);
861 cl_must_pass(p_unlink("renames/untimely.txt"));
863 cl_git_pass(git_status_list_new(&status
, repo
, &opts
));
864 cl_assert_equal_sz(1, git_status_list_entrycount(status
));
866 GIT_STATUS_WT_DELETED
, git_status_byindex(status
, 0)->status
);
867 git_status_list_free(status
);
870 static const char *icase_paths
[] = { "B", "c", "g", "H" };
871 static unsigned int icase_statuses
[] = {
872 GIT_STATUS_WT_MODIFIED
, GIT_STATUS_WT_DELETED
,
873 GIT_STATUS_WT_MODIFIED
, GIT_STATUS_WT_DELETED
,
876 static const char *case_paths
[] = { "B", "H", "c", "g" };
877 static unsigned int case_statuses
[] = {
878 GIT_STATUS_WT_MODIFIED
, GIT_STATUS_WT_DELETED
,
879 GIT_STATUS_WT_DELETED
, GIT_STATUS_WT_MODIFIED
,
882 void test_status_worktree__sorting_by_case(void)
884 git_repository
*repo
= cl_git_sandbox_init("icase");
886 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
887 bool native_ignore_case
;
888 status_entry_counts counts
;
890 cl_git_pass(git_repository_index(&index
, repo
));
892 (git_index_caps(index
) & GIT_INDEXCAP_IGNORE_CASE
) != 0;
893 git_index_free(index
);
895 memset(&counts
, 0, sizeof(counts
));
896 counts
.expected_entry_count
= 0;
897 counts
.expected_paths
= NULL
;
898 counts
.expected_statuses
= NULL
;
900 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
));
901 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
902 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
903 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
905 cl_git_rewritefile("icase/B", "new stuff");
906 cl_must_pass(p_unlink("icase/c"));
907 cl_git_rewritefile("icase/g", "new stuff");
908 cl_must_pass(p_unlink("icase/H"));
910 memset(&counts
, 0, sizeof(counts
));
911 counts
.expected_entry_count
= 4;
912 if (native_ignore_case
) {
913 counts
.expected_paths
= icase_paths
;
914 counts
.expected_statuses
= icase_statuses
;
916 counts
.expected_paths
= case_paths
;
917 counts
.expected_statuses
= case_statuses
;
920 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
));
921 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
922 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
923 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
925 opts
.flags
= GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
;
927 memset(&counts
, 0, sizeof(counts
));
928 counts
.expected_entry_count
= 4;
929 counts
.expected_paths
= case_paths
;
930 counts
.expected_statuses
= case_statuses
;
932 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
));
933 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
934 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
935 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
937 opts
.flags
= GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
;
939 memset(&counts
, 0, sizeof(counts
));
940 counts
.expected_entry_count
= 4;
941 counts
.expected_paths
= icase_paths
;
942 counts
.expected_statuses
= icase_statuses
;
944 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
));
945 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
946 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
947 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
950 void test_status_worktree__long_filenames(void)
953 const char *expected_paths
[] = {path
};
954 const unsigned int expected_statuses
[] = {GIT_STATUS_WT_NEW
};
956 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
957 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
958 status_entry_counts counts
= {0};
960 // Create directory with amazingly long filename
961 sprintf(path
, "empty_standard_repo/%s", longname
);
962 cl_git_pass(git_futils_mkdir_r(path
, 0777));
963 sprintf(path
, "empty_standard_repo/%s/foo", longname
);
964 cl_git_mkfile(path
, "dummy");
966 sprintf(path
, "%s/foo", longname
);
967 counts
.expected_entry_count
= 1;
968 counts
.expected_paths
= expected_paths
;
969 counts
.expected_statuses
= expected_statuses
;
971 opts
.show
= GIT_STATUS_SHOW_WORKDIR_ONLY
;
972 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
;
975 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
) );
976 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
977 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
978 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
981 /* The update stat cache tests mostly just mirror other tests and try
982 * to make sure that updating the stat cache doesn't change the results
983 * while reducing the amount of work that needs to be done
986 static void check_status0(git_status_list
*status
)
988 size_t i
, max_i
= git_status_list_entrycount(status
);
989 cl_assert_equal_sz(entry_count0
, max_i
);
990 for (i
= 0; i
< max_i
; ++i
) {
991 const git_status_entry
*entry
= git_status_byindex(status
, i
);
992 cl_assert_equal_i(entry_statuses0
[i
], entry
->status
);
996 void test_status_worktree__update_stat_cache_0(void)
998 git_repository
*repo
= cl_git_sandbox_init("status");
999 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1000 git_status_list
*status
;
1001 git_diff_perfdata perf
= GIT_DIFF_PERFDATA_INIT
;
1004 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
;
1006 cl_git_pass(git_status_list_new(&status
, repo
, &opts
));
1007 check_status0(status
);
1008 cl_git_pass(git_status_list_get_perfdata(&perf
, status
));
1009 cl_assert_equal_sz(13 + 3, perf
.stat_calls
);
1010 cl_assert_equal_sz(5, perf
.oid_calculations
);
1012 git_status_list_free(status
);
1014 /* tick the index so we avoid recalculating racily-clean entries */
1015 cl_git_pass(git_repository_index__weakptr(&index
, repo
));
1018 opts
.flags
|= GIT_STATUS_OPT_UPDATE_INDEX
;
1020 cl_git_pass(git_status_list_new(&status
, repo
, &opts
));
1021 check_status0(status
);
1022 cl_git_pass(git_status_list_get_perfdata(&perf
, status
));
1023 cl_assert_equal_sz(13 + 3, perf
.stat_calls
);
1024 cl_assert_equal_sz(5, perf
.oid_calculations
);
1026 git_status_list_free(status
);
1028 opts
.flags
&= ~GIT_STATUS_OPT_UPDATE_INDEX
;
1030 /* tick again as the index updating from the previous diff might have reset the timestamp */
1032 cl_git_pass(git_status_list_new(&status
, repo
, &opts
));
1033 check_status0(status
);
1034 cl_git_pass(git_status_list_get_perfdata(&perf
, status
));
1035 cl_assert_equal_sz(13 + 3, perf
.stat_calls
);
1036 cl_assert_equal_sz(0, perf
.oid_calculations
);
1038 git_status_list_free(status
);
1041 void test_status_worktree__unreadable(void)
1044 const char *expected_paths
[] = { "no_permission/foo" };
1045 const unsigned int expected_statuses
[] = {GIT_STATUS_WT_UNREADABLE
};
1047 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
1048 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1049 status_entry_counts counts
= {0};
1054 /* Create directory with no read permission */
1055 cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777));
1056 cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy");
1057 p_chmod("empty_standard_repo/no_permission", 0644);
1059 counts
.expected_entry_count
= 1;
1060 counts
.expected_paths
= expected_paths
;
1061 counts
.expected_statuses
= expected_statuses
;
1063 opts
.show
= GIT_STATUS_SHOW_WORKDIR_ONLY
;
1064 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
| GIT_STATUS_OPT_INCLUDE_UNREADABLE
;
1067 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
) );
1069 /* Restore permissions so we can cleanup :) */
1070 p_chmod("empty_standard_repo/no_permission", 0777);
1072 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
1073 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
1074 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
1080 void test_status_worktree__unreadable_not_included(void)
1083 const char *expected_paths
[] = { "no_permission/" };
1084 const unsigned int expected_statuses
[] = {GIT_STATUS_WT_NEW
};
1086 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
1087 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1088 status_entry_counts counts
= {0};
1090 /* Create directory with no read permission */
1091 cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777));
1092 cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy");
1093 p_chmod("empty_standard_repo/no_permission", 0644);
1095 counts
.expected_entry_count
= 1;
1096 counts
.expected_paths
= expected_paths
;
1097 counts
.expected_statuses
= expected_statuses
;
1099 opts
.show
= GIT_STATUS_SHOW_WORKDIR_ONLY
;
1100 opts
.flags
= (GIT_STATUS_OPT_INCLUDE_IGNORED
| GIT_STATUS_OPT_INCLUDE_UNTRACKED
);
1103 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
) );
1105 /* Restore permissions so we can cleanup :) */
1106 p_chmod("empty_standard_repo/no_permission", 0777);
1108 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
1109 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
1110 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
1116 void test_status_worktree__unreadable_as_untracked(void)
1118 const char *expected_paths
[] = { "no_permission/foo" };
1119 const unsigned int expected_statuses
[] = {GIT_STATUS_WT_NEW
};
1121 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
1122 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1123 status_entry_counts counts
= {0};
1125 /* Create directory with no read permission */
1126 cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777));
1127 cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy");
1128 p_chmod("empty_standard_repo/no_permission", 0644);
1130 counts
.expected_entry_count
= 1;
1131 counts
.expected_paths
= expected_paths
;
1132 counts
.expected_statuses
= expected_statuses
;
1134 opts
.show
= GIT_STATUS_SHOW_WORKDIR_ONLY
;
1135 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
|
1136 GIT_STATUS_OPT_INCLUDE_UNREADABLE
|
1137 GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED
;
1140 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
) );
1142 /* Restore permissions so we can cleanup :) */
1143 p_chmod("empty_standard_repo/no_permission", 0777);
1145 cl_assert_equal_i(counts
.expected_entry_count
, counts
.entry_count
);
1146 cl_assert_equal_i(0, counts
.wrong_status_flags_count
);
1147 cl_assert_equal_i(0, counts
.wrong_sorted_path
);
1150 void test_status_worktree__update_index_with_symlink_doesnt_change_mode(void)
1152 git_repository
*repo
= cl_git_sandbox_init("testrepo");
1153 git_reference
*head
;
1154 git_object
*head_object
;
1156 const git_index_entry
*idx_entry
;
1157 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1158 status_entry_counts counts
= {0};
1159 const char *expected_paths
[] = { "README" };
1160 const unsigned int expected_statuses
[] = {GIT_STATUS_WT_NEW
};
1162 opts
.show
= GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
1163 opts
.flags
= GIT_STATUS_OPT_DEFAULTS
| GIT_STATUS_OPT_UPDATE_INDEX
;
1165 cl_git_pass(git_repository_head(&head
, repo
));
1166 cl_git_pass(git_reference_peel(&head_object
, head
, GIT_OBJ_COMMIT
));
1168 cl_git_pass(git_reset(repo
, head_object
, GIT_RESET_HARD
, NULL
));
1170 cl_git_rewritefile("testrepo/README", "This was rewritten.");
1172 /* this status rewrites the index because we have changed the
1173 * contents of a tracked file
1175 counts
.expected_entry_count
= 1;
1176 counts
.expected_paths
= expected_paths
;
1177 counts
.expected_statuses
= expected_statuses
;
1180 git_status_foreach_ext(repo
, &opts
, cb_status__normal
, &counts
));
1181 cl_assert_equal_i(1, counts
.entry_count
);
1183 /* now ensure that the status's rewrite of the index did not screw
1184 * up the mode of the symlink `link_to_new.txt`, particularly
1185 * on platforms that don't support symlinks
1187 cl_git_pass(git_repository_index(&index
, repo
));
1188 cl_git_pass(git_index_read(index
, true));
1190 cl_assert(idx_entry
= git_index_get_bypath(index
, "link_to_new.txt", 0));
1191 cl_assert(S_ISLNK(idx_entry
->mode
));
1193 git_index_free(index
);
1194 git_object_free(head_object
);
1195 git_reference_free(head
);
1198 static const char *testrepo2_subdir_paths
[] = {
1201 "subdir/subdir2/README",
1202 "subdir/subdir2/new.txt",
1205 static const char *testrepo2_subdir_paths_icase
[] = {
1208 "subdir/subdir2/new.txt",
1209 "subdir/subdir2/README"
1212 void test_status_worktree__with_directory_in_pathlist(void)
1214 git_repository
*repo
= cl_git_sandbox_init("testrepo2");
1216 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1217 git_status_list
*statuslist
;
1218 const git_status_entry
*status
;
1219 size_t i
, entrycount
;
1220 bool native_ignore_case
;
1221 char *subdir_path
= "subdir";
1223 cl_git_pass(git_repository_index(&index
, repo
));
1224 native_ignore_case
=
1225 (git_index_caps(index
) & GIT_INDEXCAP_IGNORE_CASE
) != 0;
1226 git_index_free(index
);
1228 opts
.pathspec
.strings
= &subdir_path
;
1229 opts
.pathspec
.count
= 1;
1231 GIT_STATUS_OPT_DEFAULTS
|
1232 GIT_STATUS_OPT_INCLUDE_UNMODIFIED
|
1233 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
;
1235 opts
.show
= GIT_STATUS_SHOW_WORKDIR_ONLY
;
1236 git_status_list_new(&statuslist
, repo
, &opts
);
1238 entrycount
= git_status_list_entrycount(statuslist
);
1239 cl_assert_equal_i(4, entrycount
);
1241 for (i
= 0; i
< entrycount
; i
++) {
1242 status
= git_status_byindex(statuslist
, i
);
1243 cl_assert_equal_i(0, status
->status
);
1244 cl_assert_equal_s(native_ignore_case
?
1245 testrepo2_subdir_paths_icase
[i
] :
1246 testrepo2_subdir_paths
[i
],
1247 status
->index_to_workdir
->old_file
.path
);
1250 git_status_list_free(statuslist
);
1252 opts
.show
= GIT_STATUS_SHOW_INDEX_ONLY
;
1253 git_status_list_new(&statuslist
, repo
, &opts
);
1255 entrycount
= git_status_list_entrycount(statuslist
);
1256 cl_assert_equal_i(4, entrycount
);
1258 for (i
= 0; i
< entrycount
; i
++) {
1259 status
= git_status_byindex(statuslist
, i
);
1260 cl_assert_equal_i(0, status
->status
);
1261 cl_assert_equal_s(native_ignore_case
?
1262 testrepo2_subdir_paths_icase
[i
] :
1263 testrepo2_subdir_paths
[i
],
1264 status
->head_to_index
->old_file
.path
);
1267 git_status_list_free(statuslist
);
1269 opts
.show
= GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
1270 git_status_list_new(&statuslist
, repo
, &opts
);
1272 entrycount
= git_status_list_entrycount(statuslist
);
1273 cl_assert_equal_i(4, entrycount
);
1275 for (i
= 0; i
< entrycount
; i
++) {
1276 status
= git_status_byindex(statuslist
, i
);
1277 cl_assert_equal_i(0, status
->status
);
1278 cl_assert_equal_s(native_ignore_case
?
1279 testrepo2_subdir_paths_icase
[i
] :
1280 testrepo2_subdir_paths
[i
],
1281 status
->index_to_workdir
->old_file
.path
);
1284 git_status_list_free(statuslist
);
1287 void test_status_worktree__at_head_parent(void)
1289 git_repository
*repo
= cl_git_sandbox_init("empty_standard_repo");
1290 git_status_options opts
= GIT_STATUS_OPTIONS_INIT
;
1291 git_status_list
*statuslist
;
1292 git_tree
*parent_tree
;
1293 const git_status_entry
*status
;
1295 cl_git_mkfile("empty_standard_repo/file1", "ping");
1296 stage_and_commit(repo
, "file1");
1298 cl_git_pass(git_repository_head_tree(&parent_tree
, repo
));
1300 cl_git_mkfile("empty_standard_repo/file2", "pong");
1301 stage_and_commit(repo
, "file2");
1303 cl_git_rewritefile("empty_standard_repo/file2", "pyng");
1305 opts
.show
= GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
1306 opts
.baseline
= parent_tree
;
1307 cl_git_pass(git_status_list_new(&statuslist
, repo
, &opts
));
1309 cl_assert_equal_sz(1, git_status_list_entrycount(statuslist
));
1310 status
= git_status_byindex(statuslist
, 0);
1311 cl_assert(status
!= NULL
);
1312 cl_assert_equal_s("file2", status
->index_to_workdir
->old_file
.path
);
1313 cl_assert_equal_i(GIT_STATUS_WT_MODIFIED
| GIT_STATUS_INDEX_NEW
, status
->status
);
1315 git_tree_free(parent_tree
);
1316 git_status_list_free(statuslist
);