From 6b209d473378cc25708ab9839d0edd493afc1e8f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 10 Nov 2005 15:47:58 -0800 Subject: [PATCH] Fully detect uninteresting commits. With the change in the previous round, we are guaranteed to come up with the list of all relevant merge bases, but sometimes we do not fully mark unintersting ones due to a horizon effect. Add a phase to postprocess, so that we mark all ancestor of "interesting" commit. This also changes the default ordering of shown commits back to chronological order, and adds --topo-order flag to show them in topological order. Signed-off-by: Junio C Hamano --- show-branch.c | 64 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/show-branch.c b/show-branch.c index 714e7f8ca..631336cd9 100644 --- a/show-branch.c +++ b/show-branch.c @@ -199,18 +199,58 @@ static void join_revs(struct commit_list **list_p, parents = parents->next; if ((this_flag & flags) == flags) continue; - parse_commit(p); + if (!p->object.parsed) + parse_commit(p); if (mark_seen(p, seen_p) && !still_interesting) extra--; p->object.flags |= flags; insert_by_date(p, list_p); } } + + /* + * Postprocess to complete well-poisoning. + * + * At this point we have all the commits we have seen in + * seen_p list (which happens to be sorted chronologically but + * it does not really matter). Mark anything that can be + * reached from uninteresting commits not interesting. + */ + for (;;) { + int changed = 0; + struct commit_list *s; + for (s = *seen_p; s; s = s->next) { + struct commit *c = s->item; + struct commit_list *parents; + + if (((c->object.flags & all_revs) != all_revs) && + !(c->object.flags & UNINTERESTING)) + continue; + + /* The current commit is either a merge base or + * already uninteresting one. Mark its parents + * as uninteresting commits _only_ if they are + * already parsed. No reason to find new ones + * here. + */ + parents = c->parents; + while (parents) { + struct commit *p = parents->item; + parents = parents->next; + if (!(p->object.flags & UNINTERESTING)) { + p->object.flags |= UNINTERESTING; + changed = 1; + } + } + } + if (!changed) + break; + } } static void show_one_commit(struct commit *commit, int no_name) { - char pretty[128], *cp; + char pretty[256], *cp; struct commit_name *name = commit->object.util; if (commit->object.parsed) pretty_print_commit(CMIT_FMT_ONELINE, commit->buffer, ~0, @@ -360,7 +400,7 @@ int main(int ac, char **av) unsigned int rev_mask[MAX_REVS]; int num_rev, i, extra = 0; int all_heads = 0, all_tags = 0; - int all_mask, all_revs, shown_merge_point; + int all_mask, all_revs; char head_path[128]; const char *head_path_p; int head_path_len; @@ -369,6 +409,8 @@ int main(int ac, char **av) int independent = 0; int no_name = 0; int sha1_name = 0; + int shown_merge_point = 0; + int topo_order = 0; setup_git_directory(); @@ -394,6 +436,8 @@ int main(int ac, char **av) merge_base = 1; else if (!strcmp(arg, "--independent")) independent = 1; + else if (!strcmp(arg, "--topo-order")) + topo_order = 1; else usage(show_branch_usage); ac--; av++; @@ -496,7 +540,8 @@ int main(int ac, char **av) exit(0); /* Sort topologically */ - sort_in_topological_order(&seen); + if (topo_order) + sort_in_topological_order(&seen); /* Give names to commits */ if (!sha1_name && !no_name) @@ -504,15 +549,12 @@ int main(int ac, char **av) all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); - shown_merge_point = 0; while (seen) { struct commit *commit = pop_one_commit(&seen); int this_flag = commit->object.flags; - int is_merge_point = (this_flag & all_revs) == all_revs; - if (is_merge_point) - shown_merge_point = 1; + shown_merge_point |= ((this_flag & all_revs) == all_revs); if (1 < num_rev) { for (i = 0; i < num_rev; i++) @@ -521,9 +563,9 @@ int main(int ac, char **av) putchar(' '); } show_one_commit(commit, no_name); - if (shown_merge_point && is_merge_point) - if (--extra < 0) - break; + + if (shown_merge_point && --extra < 0) + break; } return 0; } -- 2.30.2