646
return slop-1;
647
}
648
649
+/*
650
+ * "rev-list --ancestry-path A..B" computes commits that are ancestors
651
+ * of B but not ancestors of A but further limits the result to those
652
+ * that are descendants of A. This takes the list of bottom commits and
653
+ * the result of "A..B" without --ancestry-path, and limits the latter
654
+ * further to the ones that can reach one of the commits in "bottom".
655
+ */
656
+static void limit_to_ancestry(struct commit_list *bottom, struct commit_list *list)
657
+{
658
+ struct commit_list *p;
659
+ struct commit_list *rlist = NULL;
660
+ int made_progress;
661
+
662
+ /*
663
+ * Reverse the list so that it will be likely that we would
664
+ * process parents before children.
665
+ */
666
+ for (p = list; p; p = p->next)
667
+ commit_list_insert(p->item, &rlist);
668
+
669
+ for (p = bottom; p; p = p->next)
670
+ p->item->object.flags |= TMP_MARK;
671
+
672
+ /*
673
+ * Mark the ones that can reach bottom commits in "list",
674
+ * in a bottom-up fashion.
675
+ */
676
+ do {
677
+ made_progress = 0;
678
+ for (p = rlist; p; p = p->next) {
679
+ struct commit *c = p->item;
680
+ struct commit_list *parents;
681
+ if (c->object.flags & (TMP_MARK | UNINTERESTING))
682
+ continue;
683
+ for (parents = c->parents;
684
+ parents;
685
+ parents = parents->next) {
686
+ if (!(parents->item->object.flags & TMP_MARK))
687
+ continue;
688
+ c->object.flags |= TMP_MARK;
689
+ made_progress = 1;
690
+ break;
691
+ }
692
+ }
693
+ } while (made_progress);
694
+
695
+ /*
696
+ * NEEDSWORK: decide if we want to remove parents that are
697
+ * not marked with TMP_MARK from commit->parents for commits
698
+ * in the resulting list. We may not want to do that, though.
699
+ */
700
+
701
+ /*
702
+ * The ones that are not marked with TMP_MARK are uninteresting
703
+ */
704
+ for (p = list; p; p = p->next) {
705
+ struct commit *c = p->item;
706
+ if (c->object.flags & TMP_MARK)
707
+ continue;
708
+ c->object.flags |= UNINTERESTING;
709
+ }
710
+
711
+ /* We are done with the TMP_MARK */
712
+ for (p = list; p; p = p->next)
713
+ p->item->object.flags &= ~TMP_MARK;
714
+ for (p = bottom; p; p = p->next)
715
+ p->item->object.flags &= ~TMP_MARK;
716
+ free_commit_list(rlist);
717
+}
718
+
719
+/*
720
+ * Before walking the history, keep the set of "negative" refs the
721
+ * caller has asked to exclude.
722
+ *
723
+ * This is used to compute "rev-list --ancestry-path A..B", as we need
724
+ * to filter the result of "A..B" further to the ones that can actually
725
+ * reach A.
726
+ */
727
+static struct commit_list *collect_bottom_commits(struct commit_list *list)
728
+{
729
+ struct commit_list *elem, *bottom = NULL;
730
+ for (elem = list; elem; elem = elem->next)
731
+ if (elem->item->object.flags & UNINTERESTING)
732
+ commit_list_insert(elem->item, &bottom);
733
+ return bottom;
734
+}
735
+
736
static int limit_list(struct rev_info *revs)
737
{
738
int slop = SLOP;
740
struct commit_list *list = revs->commits;
741
struct commit_list *newlist = NULL;
742
struct commit_list **p = &newlist;
743
+ struct commit_list *bottom = NULL;
744
+
745
+ if (revs->ancestry_path) {
746
+ bottom = collect_bottom_commits(list);
747
+ if (!bottom)
748
+ die("--ancestry-path given but there is no bottom commits");
749
+ }
750
751
while (list) {
752
struct commit_list *entry = list;
788
if (revs->cherry_pick)
789
cherry_pick_list(newlist, revs);
790
791
+ if (bottom) {
792
+ limit_to_ancestry(bottom, newlist);
793
+ free_commit_list(bottom);
794
+ }
795
+
796
revs->commits = newlist;
797
return 0;
798
}
1188
revs->min_age = approxidate(arg + 8);
1189
} else if (!strcmp(arg, "--first-parent")) {
1190
revs->first_parent_only = 1;
1191
+ } else if (!strcmp(arg, "--ancestry-path")) {
1192
+ revs->ancestry_path = 1;
1193
+ revs->limited = 1;
1194
} else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
1195
init_reflog_walk(&revs->reflog_info);
1196
} else if (!strcmp(arg, "--default")) {