@@ -199,18 +199,58 @@ static void join_revs(struct commit_list **list_p,
199199 parents = parents -> next ;
200200 if ((this_flag & flags ) == flags )
201201 continue ;
202- parse_commit (p );
202+ if (!p -> object .parsed )
203+ parse_commit (p );
203204 if (mark_seen (p , seen_p ) && !still_interesting )
204205 extra -- ;
205206 p -> object .flags |= flags ;
206207 insert_by_date (p , list_p );
207208 }
208209 }
210+
211+ /*
212+ * Postprocess to complete well-poisoning.
213+ *
214+ * At this point we have all the commits we have seen in
215+ * seen_p list (which happens to be sorted chronologically but
216+ * it does not really matter). Mark anything that can be
217+ * reached from uninteresting commits not interesting.
218+ */
219+ for (;;) {
220+ int changed = 0 ;
221+ struct commit_list * s ;
222+ for (s = * seen_p ; s ; s = s -> next ) {
223+ struct commit * c = s -> item ;
224+ struct commit_list * parents ;
225+
226+ if (((c -> object .flags & all_revs ) != all_revs ) &&
227+ !(c -> object .flags & UNINTERESTING ))
228+ continue ;
229+
230+ /* The current commit is either a merge base or
231+ * already uninteresting one. Mark its parents
232+ * as uninteresting commits _only_ if they are
233+ * already parsed. No reason to find new ones
234+ * here.
235+ */
236+ parents = c -> parents ;
237+ while (parents ) {
238+ struct commit * p = parents -> item ;
239+ parents = parents -> next ;
240+ if (!(p -> object .flags & UNINTERESTING )) {
241+ p -> object .flags |= UNINTERESTING ;
242+ changed = 1 ;
243+ }
244+ }
245+ }
246+ if (!changed )
247+ break ;
248+ }
209249}
210250
211251static void show_one_commit (struct commit * commit , int no_name )
212252{
213- char pretty [128 ], * cp ;
253+ char pretty [256 ], * cp ;
214254 struct commit_name * name = commit -> object .util ;
215255 if (commit -> object .parsed )
216256 pretty_print_commit (CMIT_FMT_ONELINE , commit -> buffer , ~0 ,
@@ -360,7 +400,7 @@ int main(int ac, char **av)
360400 unsigned int rev_mask [MAX_REVS ];
361401 int num_rev , i , extra = 0 ;
362402 int all_heads = 0 , all_tags = 0 ;
363- int all_mask , all_revs , shown_merge_point ;
403+ int all_mask , all_revs ;
364404 char head_path [128 ];
365405 const char * head_path_p ;
366406 int head_path_len ;
@@ -369,6 +409,8 @@ int main(int ac, char **av)
369409 int independent = 0 ;
370410 int no_name = 0 ;
371411 int sha1_name = 0 ;
412+ int shown_merge_point = 0 ;
413+ int topo_order = 0 ;
372414
373415 setup_git_directory ();
374416
@@ -394,6 +436,8 @@ int main(int ac, char **av)
394436 merge_base = 1 ;
395437 else if (!strcmp (arg , "--independent" ))
396438 independent = 1 ;
439+ else if (!strcmp (arg , "--topo-order" ))
440+ topo_order = 1 ;
397441 else
398442 usage (show_branch_usage );
399443 ac -- ; av ++ ;
@@ -496,23 +540,21 @@ int main(int ac, char **av)
496540 exit (0 );
497541
498542 /* Sort topologically */
499- sort_in_topological_order (& seen );
543+ if (topo_order )
544+ sort_in_topological_order (& seen );
500545
501546 /* Give names to commits */
502547 if (!sha1_name && !no_name )
503548 name_commits (seen , rev , ref_name , num_rev );
504549
505550 all_mask = ((1u << (REV_SHIFT + num_rev )) - 1 );
506551 all_revs = all_mask & ~((1u << REV_SHIFT ) - 1 );
507- shown_merge_point = 0 ;
508552
509553 while (seen ) {
510554 struct commit * commit = pop_one_commit (& seen );
511555 int this_flag = commit -> object .flags ;
512- int is_merge_point = (this_flag & all_revs ) == all_revs ;
513556
514- if (is_merge_point )
515- shown_merge_point = 1 ;
557+ shown_merge_point |= ((this_flag & all_revs ) == all_revs );
516558
517559 if (1 < num_rev ) {
518560 for (i = 0 ; i < num_rev ; i ++ )
@@ -521,9 +563,9 @@ int main(int ac, char **av)
521563 putchar (' ' );
522564 }
523565 show_one_commit (commit , no_name );
524- if ( shown_merge_point && is_merge_point )
525- if (-- extra < 0 )
526- break ;
566+
567+ if (shown_merge_point && -- extra < 0 )
568+ break ;
527569 }
528570 return 0 ;
529571}
0 commit comments