Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-05-24 14:30:35 +0400
committerVicent Martí <vicent@github.com>2013-05-24 14:30:35 +0400
commit26ab6284b20a3709adc7641a52250f72df9257aa (patch)
tree7b0c2888c8a0036d370f93490c240af30dd78c65
parentf7ceef06eb5a3ad5fc8d58d0c849c0de2395a7cc (diff)
parent0e0108f73f83c7cedeaafd480fdcfe3cd6b69d1f (diff)
Merge pull request #1593 from ethomson/conflict_iterator
introduce git_conflict_iterator
-rw-r--r--include/git2/index.h46
-rw-r--r--include/git2/types.h3
-rw-r--r--src/index.c148
-rw-r--r--src/index.h5
-rw-r--r--tests-clar/index/conflicts.c51
-rw-r--r--tests-clar/reset/default.c2
6 files changed, 215 insertions, 40 deletions
diff --git a/include/git2/index.h b/include/git2/index.h
index 8a1ccce55..58b0243e0 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -463,9 +463,9 @@ GIT_EXTERN(int) git_index_conflict_add(
/**
* Get the index entries that represent a conflict of a single file.
*
- * The values of this entry can be modified (except the paths)
- * and the changes will be written back to disk on the next
- * write() call.
+ * The entries are not modifiable and should not be freed. Because the
+ * `git_index_entry` struct is a publicly defined struct, you should
+ * be able to make your own permanent copy of the data if necessary.
*
* @param ancestor_out Pointer to store the ancestor 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
*/
GIT_EXTERN(int) git_index_conflict_get(
- git_index_entry **ancestor_out,
- git_index_entry **our_out,
- git_index_entry **their_out,
+ const git_index_entry **ancestor_out,
+ const git_index_entry **our_out,
+ const git_index_entry **their_out,
git_index *index,
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);
+/**
+ * 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);
+
/**@}*/
/** @} */
diff --git a/include/git2/types.h b/include/git2/types.h
index d97bbcb30..1bfa73be6 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -131,6 +131,9 @@ typedef struct git_treebuilder git_treebuilder;
/** Memory representation of an index file. */
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 */
typedef struct git_config git_config;
diff --git a/src/index.c b/src/index.c
index f7f7133d6..ec45a5c0e 100644
--- a/src/index.c
+++ b/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)
{
- git_index_entry *conflict_entries[3];
+ const git_index_entry *conflict_entries[3];
int ancestor_mode, our_mode, their_mode;
git_oid const *ancestor_oid, *our_oid, *their_oid;
int ret;
@@ -978,52 +978,80 @@ on_error:
return ret;
}
-int git_index_conflict_get(git_index_entry **ancestor_out,
- git_index_entry **our_out,
- git_index_entry **their_out,
- git_index *index, const char *path)
+static int index_conflict__get_byindex(
+ const git_index_entry **ancestor_out,
+ const git_index_entry **our_out,
+ const git_index_entry **their_out,
+ git_index *index,
+ size_t n)
{
- size_t pos, posmax;
- int stage;
- git_index_entry *conflict_entry;
- int error = GIT_ENOTFOUND;
-
- assert(ancestor_out && our_out && their_out && index && path);
+ const git_index_entry *conflict_entry;
+ const char *path = NULL;
+ size_t count;
+ int stage, len = 0;
+ assert(ancestor_out && our_out && their_out && index);
+
*ancestor_out = NULL;
*our_out = NULL;
*their_out = NULL;
- if (git_index_find(&pos, index, path) < 0)
- return GIT_ENOTFOUND;
+ for (count = git_index_entrycount(index); n < count; ++n) {
+ conflict_entry = git_vector_get(&index->entries, n);
- for (posmax = git_index_entrycount(index); pos < posmax; ++pos) {
- conflict_entry = git_vector_get(&index->entries, pos);
-
- if (index->entries_cmp_path(conflict_entry->path, path) != 0)
+ 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;
- error = 0;
+ len++;
break;
case 2:
*our_out = conflict_entry;
- error = 0;
+ len++;
break;
case 1:
*ancestor_out = conflict_entry;
- error = 0;
+ len++;
break;
default:
break;
};
}
- return error;
+ 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);
+
+ *ancestor_out = NULL;
+ *our_out = NULL;
+ *their_out = NULL;
+
+ if (git_index_find(&pos, index, path) < 0)
+ return GIT_ENOTFOUND;
+
+ if ((len = index_conflict__get_byindex(
+ ancestor_out, our_out, their_out, index, pos)) < 0)
+ return len;
+ else if (len == 0)
+ return GIT_ENOTFOUND;
+
+ return 0;
}
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;
}
+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)
{
assert(index);
@@ -1283,9 +1373,8 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
size_t len;
int i;
- /* If called multiple times, the vector might already be initialized */
- if (index->reuc._alloc_size == 0 &&
- git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
+ /* This gets called multiple times, the vector might already be initialized */
+ if (index->reuc._alloc_size == 0 && git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
return -1;
while (size) {
@@ -1295,9 +1384,12 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
if (size <= len)
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);
+ if (git_vector_insert(&index->reuc, lost) < 0)
+ return -1;
+
/* read NUL-terminated pathname for entry */
lost->path = git__strdup(buffer);
GITERR_CHECK_ALLOC(lost->path);
@@ -1335,10 +1427,6 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
size -= 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 */
diff --git a/src/index.h b/src/index.h
index 2ad401741..a59107a7b 100644
--- a/src/index.h
+++ b/src/index.h
@@ -42,6 +42,11 @@ struct git_index {
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 size_t git_index__prefix_position(git_index *index, const char *path);
diff --git a/tests-clar/index/conflicts.c b/tests-clar/index/conflicts.c
index 7eee496de..6311b3a75 100644
--- a/tests-clar/index/conflicts.c
+++ b/tests-clar/index/conflicts.c
@@ -65,7 +65,7 @@ void test_index_conflicts__add(void)
void test_index_conflicts__add_fixes_incorrect_stage(void)
{
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);
@@ -98,7 +98,7 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
void test_index_conflicts__get(void)
{
- git_index_entry *conflict_entry[3];
+ const git_index_entry *conflict_entry[3];
git_oid oid;
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);
}
+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)
{
const git_index_entry *entry;
@@ -218,7 +263,7 @@ void test_index_conflicts__remove_all_conflicts(void)
void test_index_conflicts__partial(void)
{
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);
diff --git a/tests-clar/reset/default.c b/tests-clar/reset/default.c
index 506d971ff..e29e63550 100644
--- a/tests-clar/reset/default.c
+++ b/tests-clar/reset/default.c
@@ -133,7 +133,7 @@ void test_reset_default__resetting_filepaths_replaces_their_corresponding_index_
*/
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;
char *paths[] = { "conflicts-one.txt" };