reduce_heads(): reimplement on top of remove_redundant()
This is used by "git merge" and "git merge-base --independent" but used to use a similar N*(N-1) traversals to reject commits that are ancestors of other commits. Reimplement it on top of remove_redundant(). Note that the callers of this function are allowed to pass the same commit more than once, but remove_redundant() is designed to be fed each commit only once. The function removes duplicates before calling remove_redundant(). Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Aug 30, 2012 at 23:20 UTC
f37d3c755209234acfc2ca280027ebdab8e9ea8a
1 file changed
+18
-38
commit.c
+18
-38
@@ -842,51 +842,31 @@ struct commit_list *reduce_heads(struct commit_list *heads)
842
{
843
struct commit_list *p;
844
struct commit_list *result = NULL, **tail = &result;
845
- struct commit **other;
846
- size_t num_head, num_other;
845
+ struct commit **array;
846
+ int num_head, i;
847
848
if (!heads)
849
return NULL;
850
851
- /* Avoid unnecessary reallocations */
852
- for (p = heads, num_head = 0; p; p = p->next)
853
- num_head++;
854
- other = xcalloc(sizeof(*other), num_head);
855
-
856
- /* For each commit, see if it can be reached by others */
857
- for (p = heads; p; p = p->next) {
858
- struct commit_list *q, *base;
859
-
860
- /* Do we already have this in the result? */
861
- for (q = result; q; q = q->next)
862
- if (p->item == q->item)
863
- break;
864
- if (q)
851
+ /* Uniquify */
852
+ for (p = heads; p; p = p->next)
853
+ p->item->object.flags &= ~STALE;
854
+ for (p = heads, num_head = 0; p; p = p->next) {
855
+ if (p->item->object.flags & STALE)
856
continue;
866
-
867
- num_other = 0;
868
- for (q = heads; q; q = q->next) {
869
- if (p->item == q->item)
870
- continue;
871
- other[num_other++] = q->item;
857
+ p->item->object.flags |= STALE;
858
+ num_head++;
859
+ }
860
+ array = xcalloc(sizeof(*array), num_head);
861
+ for (p = heads, i = 0; p; p = p->next) {
862
+ if (p->item->object.flags & STALE) {
863
+ array[i++] = p->item;
864
+ p->item->object.flags &= ~STALE;
865
}
873
- if (num_other)
874
- base = get_merge_bases_many(p->item, num_other, other, 1);
875
- else
876
- base = NULL;
877
- /*
878
- * If p->item does not have anything common with other
879
- * commits, there won't be any merge base. If it is
880
- * reachable from some of the others, p->item will be
881
- * the merge base. If its history is connected with
882
- * others, but p->item is not reachable by others, we
883
- * will get something other than p->item back.
884
- */
885
- if (!base || (base->item != p->item))
886
- tail = &(commit_list_insert(p->item, tail)->next);
887
- free_commit_list(base);
866
}
889
- free(other);
867
+ num_head = remove_redundant(array, num_head);
868
+ for (i = 0; i < num_head; i++)
869
+ tail = &commit_list_insert(array[i], tail)->next;
870
return result;
871
}
872