conflicts: when adding conflicts, remove staged

When adding a conflict for some path, remove the staged entry.
Otherwise, an illegal index (with both stage 0 and high-stage
entries) would result.
This commit is contained in:
Edward Thomson 2015-05-14 11:52:48 -04:00
parent 1b6c26db97
commit ecd60a56eb
5 changed files with 71 additions and 3 deletions

View File

@ -49,6 +49,8 @@ support for HTTPS connections insead of OpenSSL.
the error message, which allows you to get the "repository not the error message, which allows you to get the "repository not
found" messages. found" messages.
* `git_index_conflict_add()` will remove staged entries that exist for
conflicted paths.
### API additions ### API additions

View File

@ -631,7 +631,8 @@ GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *pat
/**@{*/ /**@{*/
/** /**
* Add or update index entries to represent a conflict * Add or update index entries to represent a conflict. Any staged
* entries that exist at the given paths will be removed.
* *
* The entries are the entries from the tree included in the merge. Any * The entries are the entries from the tree included in the merge. Any
* entry may be null to indicate that that file was not present in the * entry may be null to indicate that that file was not present in the

View File

@ -1314,6 +1314,21 @@ int git_index_conflict_add(git_index *index,
(ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0) (ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0)
goto on_error; goto on_error;
/* Remove existing index entries for each path */
for (i = 0; i < 3; i++) {
if (entries[i] == NULL)
continue;
if ((ret = git_index_remove(index, entries[i]->path, 0)) != 0) {
if (ret != GIT_ENOTFOUND)
goto on_error;
giterr_clear();
ret = 0;
}
}
/* Add the conflict entries */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (entries[i] == NULL) if (entries[i] == NULL)
continue; continue;
@ -1321,7 +1336,7 @@ int git_index_conflict_add(git_index *index,
/* Make sure stage is correct */ /* Make sure stage is correct */
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1); GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
if ((ret = index_insert(index, &entries[i], 1, true)) < 0) if ((ret = index_insert(index, &entries[i], 0, true)) < 0)
goto on_error; goto on_error;
entries[i] = NULL; /* don't free if later entry fails */ entries[i] = NULL; /* don't free if later entry fails */

View File

@ -16,6 +16,7 @@ static git_index *repo_index;
#define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2" #define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2"
#define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e" #define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e"
#define TEST_STAGED_OID "beefdadafeedabedcafedeedbabedeadbeaddeaf"
#define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f" #define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f"
#define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b" #define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b"
#define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567" #define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567"
@ -96,6 +97,55 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
cl_assert(git_index_entry_stage(conflict_entry[2]) == 3); cl_assert(git_index_entry_stage(conflict_entry[2]) == 3);
} }
void test_index_conflicts__add_removes_stage_zero(void)
{
git_index_entry staged, ancestor_entry, our_entry, their_entry;
const git_index_entry *conflict_entry[3];
cl_assert(git_index_entrycount(repo_index) == 8);
memset(&staged, 0x0, sizeof(git_index_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));
staged.mode = 0100644;
staged.path = "test-one.txt";
git_oid_fromstr(&staged.id, TEST_STAGED_OID);
cl_git_pass(git_index_add(repo_index, &staged));
cl_assert(git_index_entrycount(repo_index) == 9);
ancestor_entry.path = "test-one.txt";
ancestor_entry.mode = 0100644;
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT);
git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt";
our_entry.mode = 0100644;
our_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT);
git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt";
their_entry.mode = 0100644;
their_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT);
git_oid_fromstr(&their_entry.id, TEST_THEIR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
cl_assert(git_index_entrycount(repo_index) == 11);
cl_assert_equal_p(NULL, git_index_get_bypath(repo_index, "test-one.txt", 0));
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt"));
cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id);
cl_assert_equal_i(1, git_index_entry_stage(conflict_entry[0]));
cl_assert_equal_oid(&our_entry.id, &conflict_entry[1]->id);
cl_assert_equal_i(2, git_index_entry_stage(conflict_entry[1]));
cl_assert_equal_oid(&their_entry.id, &conflict_entry[2]->id);
cl_assert_equal_i(3, git_index_entry_stage(conflict_entry[2]));
}
void test_index_conflicts__get(void) void test_index_conflicts__get(void)
{ {
const git_index_entry *conflict_entry[3]; const git_index_entry *conflict_entry[3];

View File

@ -634,7 +634,7 @@ void test_status_worktree__conflicted_item(void)
&our_entry, &their_entry)); &our_entry, &their_entry));
cl_git_pass(git_status_file(&status, repo, "modified_file")); cl_git_pass(git_status_file(&status, repo, "modified_file"));
cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); cl_assert_equal_i(GIT_STATUS_INDEX_DELETED|GIT_STATUS_WT_NEW, status);
git_index_free(index); git_index_free(index);
} }