Commit 4ae29053 by Russell Belfer

Merge pull request #1701 from yorah/fix/gh-1698

Fix segfault in git_status_foreach_ext()
parents 6bb7bff2 9b6075b2
...@@ -1273,7 +1273,7 @@ int git_diff__paired_foreach( ...@@ -1273,7 +1273,7 @@ int git_diff__paired_foreach(
git_vector_sort(&idx2wd->deltas); 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; strcomp = git__strcasecmp;
for (i = 0, j = 0; i < i_max || j < j_max; ) { for (i = 0, j = 0; i < i_max || j < j_max; ) {
......
...@@ -257,6 +257,7 @@ int git_status_list_new( ...@@ -257,6 +257,7 @@ int git_status_list_new(
opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
int error = 0; int error = 0;
unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS;
git_diff_list *head2idx = NULL;
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
...@@ -307,8 +308,10 @@ int git_status_list_new( ...@@ -307,8 +308,10 @@ int git_status_list_new(
&status->head2idx, repo, head, NULL, &diffopt)) < 0) &status->head2idx, repo, head, NULL, &diffopt)) < 0)
goto done; goto done;
head2idx = status->head2idx;
if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && 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; goto done;
} }
...@@ -324,15 +327,14 @@ int git_status_list_new( ...@@ -324,15 +327,14 @@ int git_status_list_new(
if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) { if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
if ((error = git_diff__paired_foreach( if ((error = git_diff__paired_foreach(
status->head2idx, NULL, status_collect, status)) < 0) head2idx, NULL, status_collect, status)) < 0)
goto done; goto done;
git_diff_list_free(status->head2idx); head2idx = NULL;
status->head2idx = NULL;
} }
if ((error = git_diff__paired_foreach( if ((error = git_diff__paired_foreach(
status->head2idx, status->idx2wd, status_collect, status)) < 0) head2idx, status->idx2wd, status_collect, status)) < 0)
goto done; goto done;
if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY)
......
...@@ -250,3 +250,130 @@ static const unsigned int entry_statuses4[] = { ...@@ -250,3 +250,130 @@ static const unsigned int entry_statuses4[] = {
}; };
static const int entry_count4 = 23; 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;
...@@ -40,6 +40,54 @@ void test_status_worktree__whole_repository(void) ...@@ -40,6 +40,54 @@ void test_status_worktree__whole_repository(void)
cl_assert_equal_i(0, counts.wrong_sorted_path); 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 */ /* this test is equivalent to t18-status.c:statuscb1 */
void test_status_worktree__empty_repository(void) void test_status_worktree__empty_repository(void)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment