diff --git a/src/diff.c b/src/diff.c index 26e117402..9e9528ef9 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1273,7 +1273,7 @@ int git_diff__paired_foreach( git_vector_sort(&idx2wd->deltas); } } - else if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) + else if (head2idx != NULL && head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) strcomp = git__strcasecmp; for (i = 0, j = 0; i < i_max || j < j_max; ) { diff --git a/src/status.c b/src/status.c index e520c1017..7da94edc1 100644 --- a/src/status.c +++ b/src/status.c @@ -257,6 +257,7 @@ int git_status_list_new( opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; int error = 0; unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; + git_diff_list *head2idx = NULL; assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); @@ -307,8 +308,10 @@ int git_status_list_new( &status->head2idx, repo, head, NULL, &diffopt)) < 0) goto done; + head2idx = status->head2idx; + if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && - (error = git_diff_find_similar(status->head2idx, NULL)) < 0) + (error = git_diff_find_similar(head2idx, NULL)) < 0) goto done; } @@ -324,15 +327,14 @@ int git_status_list_new( if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) { if ((error = git_diff__paired_foreach( - status->head2idx, NULL, status_collect, status)) < 0) + head2idx, NULL, status_collect, status)) < 0) goto done; - git_diff_list_free(status->head2idx); - status->head2idx = NULL; + head2idx = NULL; } if ((error = git_diff__paired_foreach( - status->head2idx, status->idx2wd, status_collect, status)) < 0) + head2idx, status->idx2wd, status_collect, status)) < 0) goto done; if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index a41bde7c2..27587843b 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -250,3 +250,130 @@ static const unsigned int entry_statuses4[] = { }; static const int entry_count4 = 23; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the HEAD and the index (changes to be committed) + */ + +static const char *entry_paths5[] = { + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", +}; + +static const unsigned int entry_statuses5[] = { + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, +}; + +static const int entry_count5 = 8; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the workdir and the index (changes not staged, untracked files) + */ + +static const char *entry_paths6[] = { + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses6[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count6 = 13; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to get the differences + * between the HEAD and the index and then between the workdir + * and the index. + */ + +static const char *entry_paths7[] = { + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses7[] = { + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count7 = 21; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 920671e13..ac993767a 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -40,6 +40,54 @@ void test_status_worktree__whole_repository(void) cl_assert_equal_i(0, counts.wrong_sorted_path); } +void assert_show(const int entry_counts, const char *entry_paths[], + const unsigned int entry_statuses[], git_status_show_t show) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_counts; + counts.expected_paths = entry_paths; + counts.expected_statuses = entry_statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + opts.show = show; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_worktree__show_index_and_workdir(void) +{ + assert_show(entry_count0, entry_paths0, entry_statuses0, + GIT_STATUS_SHOW_INDEX_AND_WORKDIR); +} + +void test_status_worktree__show_index_only(void) +{ + assert_show(entry_count5, entry_paths5, entry_statuses5, + GIT_STATUS_SHOW_INDEX_ONLY); +} + +void test_status_worktree__show_workdir_only(void) +{ + assert_show(entry_count6, entry_paths6, entry_statuses6, + GIT_STATUS_SHOW_WORKDIR_ONLY); +} + +void test_status_worktree__show_index_then_workdir_only(void) +{ + assert_show(entry_count7, entry_paths7, entry_statuses7, + GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); +} + /* this test is equivalent to t18-status.c:statuscb1 */ void test_status_worktree__empty_repository(void) {