merge_bases_many(): split out the logic to paint history

Introduce a new helper function paint_down_to_common() that takes the same parameters as merge_bases_many(), but without the first optimization of not painting anything when "one" is one of the "twos" (or vice versa), and the last clean-up of removing the common ancestor that is known to be an ancestor of another common one. This way, the caller of the new function could tell if "one" is reachable from any of the "twos" by simply looking at the flag bits of "one". If (and only if) it is painted in PARENT2, it is reachable from one of the "twos". Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Aug 30, 2012 at 14:39 UTC da1f515641f4853a6b7c4710392796ed08efaa6f
1 file changed +28 -19
commit.c
+28 -19
@@ -581,28 +581,12 @@ static struct commit *interesting(struct commit_list *list)
581 return NULL;
582 }
583
584 -static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
584 +static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
585 {
586 struct commit_list *list = NULL;
587 struct commit_list *result = NULL;
588 int i;
589
590 - for (i = 0; i < n; i++) {
591 - if (one == twos[i])
592 - /*
593 - * We do not mark this even with RESULT so we do not
594 - * have to clean it up.
595 - */
596 - return commit_list_insert(one, &result);
597 - }
598 -
599 - if (parse_commit(one))
600 - return NULL;
601 - for (i = 0; i < n; i++) {
602 - if (parse_commit(twos[i]))
603 - return NULL;
604 - }
605 -
590 one->object.flags |= PARENT1;
591 commit_list_insert_by_date(one, &list);
592 for (i = 0; i < n; i++) {
@@ -643,9 +627,34 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
627 }
628 }
629
646 - /* Clean up the result to remove stale ones */
630 free_commit_list(list);
648 - list = result; result = NULL;
631 + return result;
632 +}
633 +
634 +static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
635 +{
636 + struct commit_list *list = NULL;
637 + struct commit_list *result = NULL;
638 + int i;
639 +
640 + for (i = 0; i < n; i++) {
641 + if (one == twos[i])
642 + /*
643 + * We do not mark this even with RESULT so we do not
644 + * have to clean it up.
645 + */
646 + return commit_list_insert(one, &result);
647 + }
648 +
649 + if (parse_commit(one))
650 + return NULL;
651 + for (i = 0; i < n; i++) {
652 + if (parse_commit(twos[i]))
653 + return NULL;
654 + }
655 +
656 + list = paint_down_to_common(one, n, twos);
657 +
658 while (list) {
659 struct commit_list *next = list->next;
660 if (!(list->item->object.flags & STALE))