commit: use generation number in remove_redundant()
[gitweb.git] / commit.c
index 39a3749abd71536649e91dac2eacbfcb9f00eadd..1d28677dfb701824f1afb4c51e673d57606c2d4e 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -808,11 +808,14 @@ static int queue_has_nonstale(struct prio_queue *queue)
 }
 
 /* all input commits in one and twos[] must have been parsed! */
-static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
+static struct commit_list *paint_down_to_common(struct commit *one, int n,
+                                               struct commit **twos,
+                                               int min_generation)
 {
        struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
        struct commit_list *result = NULL;
        int i;
+       uint32_t last_gen = GENERATION_NUMBER_INFINITY;
 
        one->object.flags |= PARENT1;
        if (!n) {
@@ -831,6 +834,15 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, struc
                struct commit_list *parents;
                int flags;
 
+               if (commit->generation > last_gen)
+                       BUG("bad generation skip %8x > %8x at %s",
+                           commit->generation, last_gen,
+                           oid_to_hex(&commit->object.oid));
+               last_gen = commit->generation;
+
+               if (commit->generation < min_generation)
+                       break;
+
                flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
                if (flags == (PARENT1 | PARENT2)) {
                        if (!(commit->object.flags & RESULT)) {
@@ -879,7 +891,7 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
                        return NULL;
        }
 
-       list = paint_down_to_common(one, n, twos);
+       list = paint_down_to_common(one, n, twos, 0);
 
        while (list) {
                struct commit *commit = pop_commit(&list);
@@ -937,6 +949,7 @@ static int remove_redundant(struct commit **array, int cnt)
                parse_commit(array[i]);
        for (i = 0; i < cnt; i++) {
                struct commit_list *common;
+               uint32_t min_generation = array[i]->generation;
 
                if (redundant[i])
                        continue;
@@ -945,8 +958,12 @@ static int remove_redundant(struct commit **array, int cnt)
                                continue;
                        filled_index[filled] = j;
                        work[filled++] = array[j];
+
+                       if (array[j]->generation < min_generation)
+                               min_generation = array[j]->generation;
                }
-               common = paint_down_to_common(array[i], filled, work);
+               common = paint_down_to_common(array[i], filled, work,
+                                             min_generation);
                if (array[i]->object.flags & PARENT2)
                        redundant[i] = 1;
                for (j = 0; j < filled; j++)
@@ -1056,14 +1073,21 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit *
 {
        struct commit_list *bases;
        int ret = 0, i;
+       uint32_t min_generation = GENERATION_NUMBER_INFINITY;
 
        if (parse_commit(commit))
                return ret;
-       for (i = 0; i < nr_reference; i++)
+       for (i = 0; i < nr_reference; i++) {
                if (parse_commit(reference[i]))
                        return ret;
+               if (reference[i]->generation < min_generation)
+                       min_generation = reference[i]->generation;
+       }
+
+       if (commit->generation > min_generation)
+               return ret;
 
-       bases = paint_down_to_common(commit, nr_reference, reference);
+       bases = paint_down_to_common(commit, nr_reference, reference, commit->generation);
        if (commit->object.flags & PARENT2)
                ret = 1;
        clear_commit_marks(commit, all_flags);