mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 19:46:59 +00:00
introduce git_conflict_iterator
This commit is contained in:
parent
5b3d52ce37
commit
0e0108f73f
@ -463,9 +463,9 @@ GIT_EXTERN(int) git_index_conflict_add(
|
|||||||
/**
|
/**
|
||||||
* Get the index entries that represent a conflict of a single file.
|
* Get the index entries that represent a conflict of a single file.
|
||||||
*
|
*
|
||||||
* The values of this entry can be modified (except the paths)
|
* The entries are not modifiable and should not be freed. Because the
|
||||||
* and the changes will be written back to disk on the next
|
* `git_index_entry` struct is a publicly defined struct, you should
|
||||||
* write() call.
|
* be able to make your own permanent copy of the data if necessary.
|
||||||
*
|
*
|
||||||
* @param ancestor_out Pointer to store the ancestor entry
|
* @param ancestor_out Pointer to store the ancestor entry
|
||||||
* @param our_out Pointer to store the our entry
|
* @param our_out Pointer to store the our entry
|
||||||
@ -474,9 +474,9 @@ GIT_EXTERN(int) git_index_conflict_add(
|
|||||||
* @param path path to search
|
* @param path path to search
|
||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_index_conflict_get(
|
GIT_EXTERN(int) git_index_conflict_get(
|
||||||
git_index_entry **ancestor_out,
|
const git_index_entry **ancestor_out,
|
||||||
git_index_entry **our_out,
|
const git_index_entry **our_out,
|
||||||
git_index_entry **their_out,
|
const git_index_entry **their_out,
|
||||||
git_index *index,
|
git_index *index,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
@ -502,6 +502,40 @@ GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index);
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_index_has_conflicts(const git_index *index);
|
GIT_EXTERN(int) git_index_has_conflicts(const git_index *index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an iterator for the conflicts in the index. You may not modify the
|
||||||
|
* index while iterating, the results are undefined.
|
||||||
|
*
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_index_conflict_iterator_new(
|
||||||
|
git_index_conflict_iterator **iterator_out,
|
||||||
|
git_index *index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current conflict (ancestor, ours and theirs entry) and
|
||||||
|
* advance the iterator internally to the next value.
|
||||||
|
*
|
||||||
|
* @param ancestor_out Pointer to store the ancestor side of the conflict
|
||||||
|
* @param our_out Pointer to store our side of the conflict
|
||||||
|
* @param their_out Pointer to store their side of the conflict
|
||||||
|
* @return 0 (no error), GIT_ITEROVER (iteration is done) or an error code
|
||||||
|
* (negative value)
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_index_conflict_next(
|
||||||
|
const git_index_entry **ancestor_out,
|
||||||
|
const git_index_entry **our_out,
|
||||||
|
const git_index_entry **their_out,
|
||||||
|
git_index_conflict_iterator *iterator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a `git_index_conflict_iterator`.
|
||||||
|
*
|
||||||
|
* @param it pointer to the iterator
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(void) git_index_conflict_iterator_free(
|
||||||
|
git_index_conflict_iterator *iterator);
|
||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -131,6 +131,9 @@ typedef struct git_treebuilder git_treebuilder;
|
|||||||
/** Memory representation of an index file. */
|
/** Memory representation of an index file. */
|
||||||
typedef struct git_index git_index;
|
typedef struct git_index git_index;
|
||||||
|
|
||||||
|
/** An interator for conflicts in the index. */
|
||||||
|
typedef struct git_index_conflict_iterator git_index_conflict_iterator;
|
||||||
|
|
||||||
/** Memory representation of a set of config files */
|
/** Memory representation of a set of config files */
|
||||||
typedef struct git_config git_config;
|
typedef struct git_config git_config;
|
||||||
|
|
||||||
|
174
src/index.c
174
src/index.c
@ -739,7 +739,7 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
|
|||||||
|
|
||||||
static int index_conflict_to_reuc(git_index *index, const char *path)
|
static int index_conflict_to_reuc(git_index *index, const char *path)
|
||||||
{
|
{
|
||||||
git_index_entry *conflict_entries[3];
|
const git_index_entry *conflict_entries[3];
|
||||||
int ancestor_mode, our_mode, their_mode;
|
int ancestor_mode, our_mode, their_mode;
|
||||||
git_oid const *ancestor_oid, *our_oid, *their_oid;
|
git_oid const *ancestor_oid, *our_oid, *their_oid;
|
||||||
int ret;
|
int ret;
|
||||||
@ -978,15 +978,63 @@ on_error:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_index_conflict_get(git_index_entry **ancestor_out,
|
static int index_conflict__get_byindex(
|
||||||
git_index_entry **our_out,
|
const git_index_entry **ancestor_out,
|
||||||
git_index_entry **their_out,
|
const git_index_entry **our_out,
|
||||||
git_index *index, const char *path)
|
const git_index_entry **their_out,
|
||||||
|
git_index *index,
|
||||||
|
size_t n)
|
||||||
{
|
{
|
||||||
size_t pos, posmax;
|
const git_index_entry *conflict_entry;
|
||||||
int stage;
|
const char *path = NULL;
|
||||||
git_index_entry *conflict_entry;
|
size_t count;
|
||||||
int error = GIT_ENOTFOUND;
|
int stage, len = 0;
|
||||||
|
|
||||||
|
assert(ancestor_out && our_out && their_out && index);
|
||||||
|
|
||||||
|
*ancestor_out = NULL;
|
||||||
|
*our_out = NULL;
|
||||||
|
*their_out = NULL;
|
||||||
|
|
||||||
|
for (count = git_index_entrycount(index); n < count; ++n) {
|
||||||
|
conflict_entry = git_vector_get(&index->entries, n);
|
||||||
|
|
||||||
|
if (path && index->entries_cmp_path(conflict_entry->path, path) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
stage = GIT_IDXENTRY_STAGE(conflict_entry);
|
||||||
|
path = conflict_entry->path;
|
||||||
|
|
||||||
|
switch (stage) {
|
||||||
|
case 3:
|
||||||
|
*their_out = conflict_entry;
|
||||||
|
len++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*our_out = conflict_entry;
|
||||||
|
len++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
*ancestor_out = conflict_entry;
|
||||||
|
len++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_index_conflict_get(
|
||||||
|
const git_index_entry **ancestor_out,
|
||||||
|
const git_index_entry **our_out,
|
||||||
|
const git_index_entry **their_out,
|
||||||
|
git_index *index,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
size_t pos;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
assert(ancestor_out && our_out && their_out && index && path);
|
assert(ancestor_out && our_out && their_out && index && path);
|
||||||
|
|
||||||
@ -997,33 +1045,13 @@ int git_index_conflict_get(git_index_entry **ancestor_out,
|
|||||||
if (git_index_find(&pos, index, path) < 0)
|
if (git_index_find(&pos, index, path) < 0)
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
for (posmax = git_index_entrycount(index); pos < posmax; ++pos) {
|
if ((len = index_conflict__get_byindex(
|
||||||
conflict_entry = git_vector_get(&index->entries, pos);
|
ancestor_out, our_out, their_out, index, pos)) < 0)
|
||||||
|
return len;
|
||||||
|
else if (len == 0)
|
||||||
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
if (index->entries_cmp_path(conflict_entry->path, path) != 0)
|
return 0;
|
||||||
break;
|
|
||||||
|
|
||||||
stage = GIT_IDXENTRY_STAGE(conflict_entry);
|
|
||||||
|
|
||||||
switch (stage) {
|
|
||||||
case 3:
|
|
||||||
*their_out = conflict_entry;
|
|
||||||
error = 0;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*our_out = conflict_entry;
|
|
||||||
error = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*ancestor_out = conflict_entry;
|
|
||||||
error = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_index_conflict_remove(git_index *index, const char *path)
|
int git_index_conflict_remove(git_index *index, const char *path)
|
||||||
@ -1093,6 +1121,68 @@ int git_index_has_conflicts(const git_index *index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_index_conflict_iterator_new(
|
||||||
|
git_index_conflict_iterator **iterator_out,
|
||||||
|
git_index *index)
|
||||||
|
{
|
||||||
|
git_index_conflict_iterator *it = NULL;
|
||||||
|
|
||||||
|
assert(iterator_out && index);
|
||||||
|
|
||||||
|
it = git__calloc(1, sizeof(git_index_conflict_iterator));
|
||||||
|
GITERR_CHECK_ALLOC(it);
|
||||||
|
|
||||||
|
it->index = index;
|
||||||
|
|
||||||
|
*iterator_out = it;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_index_conflict_next(
|
||||||
|
const git_index_entry **ancestor_out,
|
||||||
|
const git_index_entry **our_out,
|
||||||
|
const git_index_entry **their_out,
|
||||||
|
git_index_conflict_iterator *iterator)
|
||||||
|
{
|
||||||
|
const git_index_entry *entry;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
assert(ancestor_out && our_out && their_out && iterator);
|
||||||
|
|
||||||
|
*ancestor_out = NULL;
|
||||||
|
*our_out = NULL;
|
||||||
|
*their_out = NULL;
|
||||||
|
|
||||||
|
while (iterator->cur < iterator->index->entries.length) {
|
||||||
|
entry = git_index_get_byindex(iterator->index, iterator->cur);
|
||||||
|
|
||||||
|
if (git_index_entry_stage(entry) > 0) {
|
||||||
|
if ((len = index_conflict__get_byindex(
|
||||||
|
ancestor_out,
|
||||||
|
our_out,
|
||||||
|
their_out,
|
||||||
|
iterator->index,
|
||||||
|
iterator->cur)) < 0)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
iterator->cur += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator->cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GIT_ITEROVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator)
|
||||||
|
{
|
||||||
|
if (iterator == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
git__free(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int git_index_name_entrycount(git_index *index)
|
unsigned int git_index_name_entrycount(git_index *index)
|
||||||
{
|
{
|
||||||
assert(index);
|
assert(index);
|
||||||
@ -1283,9 +1373,8 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|||||||
size_t len;
|
size_t len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* If called multiple times, the vector might already be initialized */
|
/* This gets called multiple times, the vector might already be initialized */
|
||||||
if (index->reuc._alloc_size == 0 &&
|
if (index->reuc._alloc_size == 0 && git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
|
||||||
git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (size) {
|
while (size) {
|
||||||
@ -1295,9 +1384,12 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|||||||
if (size <= len)
|
if (size <= len)
|
||||||
return index_error_invalid("reading reuc entries");
|
return index_error_invalid("reading reuc entries");
|
||||||
|
|
||||||
lost = git__calloc(1, sizeof(git_index_reuc_entry));
|
lost = git__malloc(sizeof(git_index_reuc_entry));
|
||||||
GITERR_CHECK_ALLOC(lost);
|
GITERR_CHECK_ALLOC(lost);
|
||||||
|
|
||||||
|
if (git_vector_insert(&index->reuc, lost) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* read NUL-terminated pathname for entry */
|
/* read NUL-terminated pathname for entry */
|
||||||
lost->path = git__strdup(buffer);
|
lost->path = git__strdup(buffer);
|
||||||
GITERR_CHECK_ALLOC(lost->path);
|
GITERR_CHECK_ALLOC(lost->path);
|
||||||
@ -1335,10 +1427,6 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|||||||
size -= 20;
|
size -= 20;
|
||||||
buffer += 20;
|
buffer += 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* entry was read successfully - insert into reuc vector */
|
|
||||||
if (git_vector_insert(&index->reuc, lost) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* entries are guaranteed to be sorted on-disk */
|
/* entries are guaranteed to be sorted on-disk */
|
||||||
|
@ -42,6 +42,11 @@ struct git_index {
|
|||||||
git_vector_cmp reuc_search;
|
git_vector_cmp reuc_search;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct git_index_conflict_iterator {
|
||||||
|
git_index *index;
|
||||||
|
size_t cur;
|
||||||
|
};
|
||||||
|
|
||||||
extern void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st);
|
extern void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st);
|
||||||
|
|
||||||
extern size_t git_index__prefix_position(git_index *index, const char *path);
|
extern size_t git_index__prefix_position(git_index *index, const char *path);
|
||||||
|
@ -65,7 +65,7 @@ void test_index_conflicts__add(void)
|
|||||||
void test_index_conflicts__add_fixes_incorrect_stage(void)
|
void test_index_conflicts__add_fixes_incorrect_stage(void)
|
||||||
{
|
{
|
||||||
git_index_entry ancestor_entry, our_entry, their_entry;
|
git_index_entry ancestor_entry, our_entry, their_entry;
|
||||||
git_index_entry *conflict_entry[3];
|
const git_index_entry *conflict_entry[3];
|
||||||
|
|
||||||
cl_assert(git_index_entrycount(repo_index) == 8);
|
cl_assert(git_index_entrycount(repo_index) == 8);
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
|
|||||||
|
|
||||||
void test_index_conflicts__get(void)
|
void test_index_conflicts__get(void)
|
||||||
{
|
{
|
||||||
git_index_entry *conflict_entry[3];
|
const git_index_entry *conflict_entry[3];
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
|
|
||||||
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
|
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
|
||||||
@ -130,6 +130,51 @@ void test_index_conflicts__get(void)
|
|||||||
cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
|
cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_index_conflicts__iterate(void)
|
||||||
|
{
|
||||||
|
git_index_conflict_iterator *iterator;
|
||||||
|
const git_index_entry *conflict_entry[3];
|
||||||
|
git_oid oid;
|
||||||
|
|
||||||
|
cl_git_pass(git_index_conflict_iterator_new(&iterator, repo_index));
|
||||||
|
|
||||||
|
cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
|
||||||
|
|
||||||
|
cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
|
||||||
|
|
||||||
|
git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
|
||||||
|
cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
|
||||||
|
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
|
||||||
|
|
||||||
|
cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER);
|
||||||
|
|
||||||
|
cl_assert(conflict_entry[0] == NULL);
|
||||||
|
cl_assert(conflict_entry[2] == NULL);
|
||||||
|
cl_assert(conflict_entry[2] == NULL);
|
||||||
|
|
||||||
|
git_index_conflict_iterator_free(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
void test_index_conflicts__remove(void)
|
void test_index_conflicts__remove(void)
|
||||||
{
|
{
|
||||||
const git_index_entry *entry;
|
const git_index_entry *entry;
|
||||||
@ -218,7 +263,7 @@ void test_index_conflicts__remove_all_conflicts(void)
|
|||||||
void test_index_conflicts__partial(void)
|
void test_index_conflicts__partial(void)
|
||||||
{
|
{
|
||||||
git_index_entry ancestor_entry, our_entry, their_entry;
|
git_index_entry ancestor_entry, our_entry, their_entry;
|
||||||
git_index_entry *conflict_entry[3];
|
const git_index_entry *conflict_entry[3];
|
||||||
|
|
||||||
cl_assert(git_index_entrycount(repo_index) == 8);
|
cl_assert(git_index_entrycount(repo_index) == 8);
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ void test_reset_default__resetting_filepaths_replaces_their_corresponding_index_
|
|||||||
*/
|
*/
|
||||||
void test_reset_default__resetting_filepaths_clears_previous_conflicts(void)
|
void test_reset_default__resetting_filepaths_clears_previous_conflicts(void)
|
||||||
{
|
{
|
||||||
git_index_entry *conflict_entry[3];
|
const git_index_entry *conflict_entry[3];
|
||||||
git_strarray after;
|
git_strarray after;
|
||||||
|
|
||||||
char *paths[] = { "conflicts-one.txt" };
|
char *paths[] = { "conflicts-one.txt" };
|
||||||
|
Loading…
Reference in New Issue
Block a user