summaryrefslogtreecommitdiff
path: root/src/merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/merge.c')
-rw-r--r--src/merge.c116
1 files changed, 30 insertions, 86 deletions
diff --git a/src/merge.c b/src/merge.c
index 517d317de..9d6252ea8 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -1449,6 +1449,34 @@ static int merge_diff_list_insert_unmodified(
return error;
}
+struct merge_diff_find_data {
+ git_merge_diff_list *diff_list;
+ struct merge_diff_df_data df_data;
+};
+
+static int queue_difference(const git_index_entry **entries, void *data)
+{
+ struct merge_diff_find_data *find_data = data;
+ bool item_modified = false;
+ size_t i;
+
+ if (!entries[0] || !entries[1] || !entries[2]) {
+ item_modified = true;
+ } else {
+ for (i = 1; i < 3; i++) {
+ if (index_entry_cmp(entries[0], entries[i]) != 0) {
+ item_modified = true;
+ break;
+ }
+ }
+ }
+
+ return item_modified ?
+ merge_diff_list_insert_conflict(
+ find_data->diff_list, &find_data->df_data, entries) :
+ merge_diff_list_insert_unmodified(find_data->diff_list, entries);
+}
+
int git_merge_diff_list__find_differences(
git_merge_diff_list *diff_list,
git_iterator *ancestor_iter,
@@ -1456,93 +1484,9 @@ int git_merge_diff_list__find_differences(
git_iterator *their_iter)
{
git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
- const git_index_entry *items[3] = {0}, *best_cur_item, *cur_items[3];
- git_vector_cmp entry_compare = git_index_entry_cmp;
- struct merge_diff_df_data df_data = {0};
- int cur_item_modified;
- size_t i, j;
- int error = 0;
-
- assert(diff_list && (our_iter || their_iter));
-
- /* Set up the iterators */
- for (i = 0; i < 3; i++) {
- error = git_iterator_current(&items[i], iterators[i]);
-
- if (error < 0 && error != GIT_ITEROVER)
- goto done;
- }
-
- while (true) {
- for (i = 0; i < 3; i++)
- cur_items[i] = NULL;
-
- best_cur_item = NULL;
- cur_item_modified = 0;
-
- /* Find the next path(s) to consume from each iterator */
- for (i = 0; i < 3; i++) {
- if (items[i] == NULL) {
- cur_item_modified = 1;
- continue;
- }
-
- if (best_cur_item == NULL) {
- best_cur_item = items[i];
- cur_items[i] = items[i];
- } else {
- int path_diff = entry_compare(items[i], best_cur_item);
-
- if (path_diff < 0) {
- /*
- * Found an item that sorts before our current item, make
- * our current item this one.
- */
- for (j = 0; j < i; j++)
- cur_items[j] = NULL;
-
- cur_item_modified = 1;
- best_cur_item = items[i];
- cur_items[i] = items[i];
- } else if (path_diff > 0) {
- /* No entry for the current item, this is modified */
- cur_item_modified = 1;
- } else if (path_diff == 0) {
- cur_items[i] = items[i];
-
- if (!cur_item_modified)
- cur_item_modified = index_entry_cmp(best_cur_item, items[i]);
- }
- }
- }
-
- if (best_cur_item == NULL)
- break;
-
- if (cur_item_modified)
- error = merge_diff_list_insert_conflict(diff_list, &df_data, cur_items);
- else
- error = merge_diff_list_insert_unmodified(diff_list, cur_items);
- if (error < 0)
- goto done;
+ struct merge_diff_find_data find_data = { diff_list };
- /* Advance each iterator that participated */
- for (i = 0; i < 3; i++) {
- if (cur_items[i] == NULL)
- continue;
-
- error = git_iterator_advance(&items[i], iterators[i]);
-
- if (error < 0 && error != GIT_ITEROVER)
- goto done;
- }
- }
-
-done:
- if (error == GIT_ITEROVER)
- error = 0;
-
- return error;
+ return git_iterator_walk(iterators, 3, queue_difference, &find_data);
}
git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)