Commits

Junio C Hamano  committed 6b209d4

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 <junkio@cox.net>

  • Participants
  • Parent commits 9ce7028

Comments (0)

Files changed (1)

File show-branch.c

 			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,
 	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;
 	int independent = 0;
 	int no_name = 0;
 	int sha1_name = 0;
+	int shown_merge_point = 0;
+	int topo_order = 0;
 
 	setup_git_directory();
 
 			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++;
 		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)
 
 	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++)
 			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;
 }