From 191e97a02b3360820177ed7642116796551ce1f6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 18 May 2015 18:15:17 -0400 Subject: [PATCH] diff conflicts: don't include incorrect ID Since a diff entry only concerns a single entry, zero the information for the index side of a conflict. (The index entry would otherwise erroneously include the lowest-stage index entry - generally the ancestor of a conflict.) Test that during status, the index side of the conflict is empty. --- src/diff.c | 39 +++++++++++++++++++--------------- tests/status/worktree.c | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/diff.c b/src/diff.c index c061a903b..abe0de0d4 100644 --- a/src/diff.c +++ b/src/diff.c @@ -149,9 +149,10 @@ static int diff_delta__from_two( uint32_t old_mode, const git_index_entry *new_entry, uint32_t new_mode, - git_oid *new_oid, + const git_oid *new_id, const char *matched_pathspec) { + const git_oid *old_id = &old_entry->id; git_diff_delta *delta; const char *canonical_path = old_entry->path; @@ -159,37 +160,41 @@ static int diff_delta__from_two( DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNMODIFIED)) return 0; + if (!new_id) + new_id = &new_entry->id; + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { uint32_t temp_mode = old_mode; const git_index_entry *temp_entry = old_entry; + const git_oid *temp_id = old_id; + old_entry = new_entry; new_entry = temp_entry; old_mode = new_mode; new_mode = temp_mode; + old_id = new_id; + new_id = temp_id; } delta = diff_delta__alloc(diff, status, canonical_path); GITERR_CHECK_ALLOC(delta); delta->nfiles = 2; - git_oid_cpy(&delta->old_file.id, &old_entry->id); - delta->old_file.size = old_entry->file_size; - delta->old_file.mode = old_mode; - delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; - - git_oid_cpy(&delta->new_file.id, &new_entry->id); - delta->new_file.size = new_entry->file_size; - delta->new_file.mode = new_mode; - - if (new_oid) { - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) - git_oid_cpy(&delta->old_file.id, new_oid); - else - git_oid_cpy(&delta->new_file.id, new_oid); + if (!git_index_entry_stage(old_entry)) { + delta->old_file.size = old_entry->file_size; + delta->old_file.mode = old_mode; + git_oid_cpy(&delta->old_file.id, old_id); + delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; } - if (new_oid || !git_oid_iszero(&new_entry->id)) - delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; + if (!git_index_entry_stage(new_entry)) { + git_oid_cpy(&delta->new_file.id, new_id); + delta->new_file.size = new_entry->file_size; + delta->new_file.mode = new_mode; + + if (!git_oid_iszero(&new_entry->id)) + delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; + } return diff_insert_delta(diff, delta, matched_pathspec); } diff --git a/tests/status/worktree.c b/tests/status/worktree.c index 9be0a4172..e272c0a10 100644 --- a/tests/status/worktree.c +++ b/tests/status/worktree.c @@ -645,6 +645,52 @@ void test_status_worktree__conflicted_item(void) git_index_free(index); } +void test_status_worktree__conflict_has_no_oid(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + git_index_entry entry = {0}; + git_status_list *statuslist; + const git_status_entry *status; + git_oid zero_id = {0}; + + entry.mode = 0100644; + entry.path = "modified_file"; + git_oid_fromstr(&entry.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry)); + + git_status_list_new(&statuslist, repo, NULL); + + cl_assert_equal_i(16, git_status_list_entrycount(statuslist)); + + status = git_status_byindex(statuslist, 2); + + cl_assert_equal_i(GIT_STATUS_CONFLICTED, status->status); + cl_assert_equal_s("modified_file", status->head_to_index->old_file.path); + cl_assert(!git_oid_equal(&zero_id, &status->head_to_index->old_file.id)); + cl_assert(0 != status->head_to_index->old_file.mode); + cl_assert_equal_s("modified_file", status->head_to_index->new_file.path); + cl_assert_equal_oid(&zero_id, &status->head_to_index->new_file.id); + cl_assert_equal_i(0, status->head_to_index->new_file.mode); + cl_assert_equal_i(0, status->head_to_index->new_file.size); + + cl_assert_equal_s("modified_file", status->index_to_workdir->old_file.path); + cl_assert_equal_oid(&zero_id, &status->index_to_workdir->old_file.id); + cl_assert_equal_i(0, status->index_to_workdir->old_file.mode); + cl_assert_equal_i(0, status->index_to_workdir->old_file.size); + cl_assert_equal_s("modified_file", status->index_to_workdir->new_file.path); + cl_assert( + !git_oid_equal(&zero_id, &status->index_to_workdir->new_file.id) || + !(status->index_to_workdir->new_file.flags & GIT_DIFF_FLAG_VALID_ID)); + cl_assert(0 != status->index_to_workdir->new_file.mode); + cl_assert(0 != status->index_to_workdir->new_file.size); + + git_index_free(index); + git_status_list_free(statuslist); +} + static void stage_and_commit(git_repository *repo, const char *path) { git_index *index;