diff --git a/src/iterator.c b/src/iterator.c index bd586ce99..0fdf0c69d 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -340,14 +340,6 @@ static int index_iterator__current( index_iterator *ii = (index_iterator *)self; const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current); - if (ie != NULL && - ii->base.end != NULL && - ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0) - { - ii->current = git_index_entrycount(ii->index); - ie = NULL; - } - if (entry) *entry = ie; @@ -360,6 +352,29 @@ static int index_iterator__at_end(git_iterator *self) return (ii->current >= git_index_entrycount(ii->index)); } +static void index_iterator__skip_conflicts( + index_iterator *ii) +{ + size_t entrycount = git_index_entrycount(ii->index); + const git_index_entry *ie; + + while (ii->current < entrycount) { + ie = git_index_get_byindex(ii->index, ii->current); + + if (ie == NULL || + (ii->base.end != NULL && + ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)) { + ii->current = entrycount; + break; + } + + if (git_index_entry_stage(ie) == 0) + break; + + ii->current++; + } +} + static int index_iterator__advance( git_iterator *self, const git_index_entry **entry) { @@ -368,6 +383,8 @@ static int index_iterator__advance( if (ii->current < git_index_entrycount(ii->index)) ii->current++; + index_iterator__skip_conflicts(ii); + return index_iterator__current(self, entry); } @@ -382,7 +399,9 @@ static int index_iterator__seek(git_iterator *self, const char *prefix) static int index_iterator__reset(git_iterator *self) { index_iterator *ii = (index_iterator *)self; - ii->current = 0; + ii->current = ii->base.start ? + git_index__prefix_position(ii->index, ii->base.start) : 0; + index_iterator__skip_conflicts(ii); return 0; } @@ -406,7 +425,8 @@ int git_iterator_for_index_range( ii->index = index; ii->base.ignore_case = ii->index->ignore_case; - ii->current = start ? git_index__prefix_position(ii->index, start) : 0; + + index_iterator__reset((git_iterator *)ii); *iter = (git_iterator *)ii; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 838a04377..7ae1883b9 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -843,3 +843,79 @@ void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void cl_assert_equal_i(GIT_STATUS_CURRENT, status); } + +void test_status_worktree__conflicted_item(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + unsigned int status; + git_index_entry ancestor_entry, our_entry, their_entry; + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "modified_file"; + git_oid_fromstr(&ancestor_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + our_entry.path = "modified_file"; + git_oid_fromstr(&our_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + their_entry.path = "modified_file"; + git_oid_fromstr(&their_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_conflict_add(index, &ancestor_entry, + &our_entry, &their_entry)); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + git_index_free(index); +} + +void test_status_worktree__conflict_with_diff3(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + unsigned int status; + git_index_entry ancestor_entry, our_entry, their_entry; + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "modified_file"; + git_oid_fromstr(&ancestor_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + our_entry.path = "modified_file"; + git_oid_fromstr(&our_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + their_entry.path = "modified_file"; + git_oid_fromstr(&their_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_pass(git_index_remove(index, "modified_file", 0)); + cl_git_pass(git_index_conflict_add(index, &ancestor_entry, + &our_entry, &their_entry)); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + + cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); + + git_index_free(index); +} +