git-tar-tree: no more void pointer arithmetic
[git.git] / builtin-show-branch.c
1 #include <stdlib.h>
2 #include <fnmatch.h>
3 #include "cache.h"
4 #include "commit.h"
5 #include "refs.h"
6 #include "builtin.h"
7
8 static const char show_branch_usage[] =
9 "git-show-branch [--dense] [--current] [--all] [--heads] [--tags] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...]";
10
11 static int default_num = 0;
12 static int default_alloc = 0;
13 static const char **default_arg = NULL;
14
15 #define UNINTERESTING   01
16
17 #define REV_SHIFT        2
18 #define MAX_REVS        (FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */
19
20 static struct commit *interesting(struct commit_list *list)
21 {
22         while (list) {
23                 struct commit *commit = list->item;
24                 list = list->next;
25                 if (commit->object.flags & UNINTERESTING)
26                         continue;
27                 return commit;
28         }
29         return NULL;
30 }
31
32 static struct commit *pop_one_commit(struct commit_list **list_p)
33 {
34         struct commit *commit;
35         struct commit_list *list;
36         list = *list_p;
37         commit = list->item;
38         *list_p = list->next;
39         free(list);
40         return commit;
41 }
42
43 struct commit_name {
44         const char *head_name; /* which head's ancestor? */
45         int generation; /* how many parents away from head_name */
46 };
47
48 /* Name the commit as nth generation ancestor of head_name;
49  * we count only the first-parent relationship for naming purposes.
50  */
51 static void name_commit(struct commit *commit, const char *head_name, int nth)
52 {
53         struct commit_name *name;
54         if (!commit->util)
55                 commit->util = xmalloc(sizeof(struct commit_name));
56         name = commit->util;
57         name->head_name = head_name;
58         name->generation = nth;
59 }
60
61 /* Parent is the first parent of the commit.  We may name it
62  * as (n+1)th generation ancestor of the same head_name as
63  * commit is nth generation ancestor of, if that generation
64  * number is better than the name it already has.
65  */
66 static void name_parent(struct commit *commit, struct commit *parent)
67 {
68         struct commit_name *commit_name = commit->util;
69         struct commit_name *parent_name = parent->util;
70         if (!commit_name)
71                 return;
72         if (!parent_name ||
73             commit_name->generation + 1 < parent_name->generation)
74                 name_commit(parent, commit_name->head_name,
75                             commit_name->generation + 1);
76 }
77
78 static int name_first_parent_chain(struct commit *c)
79 {
80         int i = 0;
81         while (c) {
82                 struct commit *p;
83                 if (!c->util)
84                         break;
85                 if (!c->parents)
86                         break;
87                 p = c->parents->item;
88                 if (!p->util) {
89                         name_parent(c, p);
90                         i++;
91                 }
92                 c = p;
93         }
94         return i;
95 }
96
97 static void name_commits(struct commit_list *list,
98                          struct commit **rev,
99                          char **ref_name,
100                          int num_rev)
101 {
102         struct commit_list *cl;
103         struct commit *c;
104         int i;
105
106         /* First give names to the given heads */
107         for (cl = list; cl; cl = cl->next) {
108                 c = cl->item;
109                 if (c->util)
110                         continue;
111                 for (i = 0; i < num_rev; i++) {
112                         if (rev[i] == c) {
113                                 name_commit(c, ref_name[i], 0);
114                                 break;
115                         }
116                 }
117         }
118
119         /* Then commits on the first parent ancestry chain */
120         do {
121                 i = 0;
122                 for (cl = list; cl; cl = cl->next) {
123                         i += name_first_parent_chain(cl->item);
124                 }
125         } while (i);
126
127         /* Finally, any unnamed commits */
128         do {
129                 i = 0;
130                 for (cl = list; cl; cl = cl->next) {
131                         struct commit_list *parents;
132                         struct commit_name *n;
133                         int nth;
134                         c = cl->item;
135                         if (!c->util)
136                                 continue;
137                         n = c->util;
138                         parents = c->parents;
139                         nth = 0;
140                         while (parents) {
141                                 struct commit *p = parents->item;
142                                 char newname[1000], *en;
143                                 parents = parents->next;
144                                 nth++;
145                                 if (p->util)
146                                         continue;
147                                 en = newname;
148                                 switch (n->generation) {
149                                 case 0:
150                                         en += sprintf(en, "%s", n->head_name);
151                                         break;
152                                 case 1:
153                                         en += sprintf(en, "%s^", n->head_name);
154                                         break;
155                                 default:
156                                         en += sprintf(en, "%s~%d",
157                                                 n->head_name, n->generation);
158                                         break;
159                                 }
160                                 if (nth == 1)
161                                         en += sprintf(en, "^");
162                                 else
163                                         en += sprintf(en, "^%d", nth);
164                                 name_commit(p, strdup(newname), 0);
165                                 i++;
166                                 name_first_parent_chain(p);
167                         }
168                 }
169         } while (i);
170 }
171
172 static int mark_seen(struct commit *commit, struct commit_list **seen_p)
173 {
174         if (!commit->object.flags) {
175                 insert_by_date(commit, seen_p);
176                 return 1;
177         }
178         return 0;
179 }
180
181 static void join_revs(struct commit_list **list_p,
182                       struct commit_list **seen_p,
183                       int num_rev, int extra)
184 {
185         int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
186         int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
187
188         while (*list_p) {
189                 struct commit_list *parents;
190                 int still_interesting = !!interesting(*list_p);
191                 struct commit *commit = pop_one_commit(list_p);
192                 int flags = commit->object.flags & all_mask;
193
194                 if (!still_interesting && extra <= 0)
195                         break;
196
197                 mark_seen(commit, seen_p);
198                 if ((flags & all_revs) == all_revs)
199                         flags |= UNINTERESTING;
200                 parents = commit->parents;
201
202                 while (parents) {
203                         struct commit *p = parents->item;
204                         int this_flag = p->object.flags;
205                         parents = parents->next;
206                         if ((this_flag & flags) == flags)
207                                 continue;
208                         if (!p->object.parsed)
209                                 parse_commit(p);
210                         if (mark_seen(p, seen_p) && !still_interesting)
211                                 extra--;
212                         p->object.flags |= flags;
213                         insert_by_date(p, list_p);
214                 }
215         }
216
217         /*
218          * Postprocess to complete well-poisoning.
219          *
220          * At this point we have all the commits we have seen in
221          * seen_p list (which happens to be sorted chronologically but
222          * it does not really matter).  Mark anything that can be
223          * reached from uninteresting commits not interesting.
224          */
225         for (;;) {
226                 int changed = 0;
227                 struct commit_list *s;
228                 for (s = *seen_p; s; s = s->next) {
229                         struct commit *c = s->item;
230                         struct commit_list *parents;
231
232                         if (((c->object.flags & all_revs) != all_revs) &&
233                             !(c->object.flags & UNINTERESTING))
234                                 continue;
235
236                         /* The current commit is either a merge base or
237                          * already uninteresting one.  Mark its parents
238                          * as uninteresting commits _only_ if they are
239                          * already parsed.  No reason to find new ones
240                          * here.
241                          */
242                         parents = c->parents;
243                         while (parents) {
244                                 struct commit *p = parents->item;
245                                 parents = parents->next;
246                                 if (!(p->object.flags & UNINTERESTING)) {
247                                         p->object.flags |= UNINTERESTING;
248                                         changed = 1;
249                                 }
250                         }
251                 }
252                 if (!changed)
253                         break;
254         }
255 }
256
257 static void show_one_commit(struct commit *commit, int no_name)
258 {
259         char pretty[256], *cp;
260         struct commit_name *name = commit->util;
261         if (commit->object.parsed)
262                 pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
263                                     pretty, sizeof(pretty), 0, NULL, NULL);
264         else
265                 strcpy(pretty, "(unavailable)");
266         if (!strncmp(pretty, "[PATCH] ", 8))
267                 cp = pretty + 8;
268         else
269                 cp = pretty;
270
271         if (!no_name) {
272                 if (name && name->head_name) {
273                         printf("[%s", name->head_name);
274                         if (name->generation) {
275                                 if (name->generation == 1)
276                                         printf("^");
277                                 else
278                                         printf("~%d", name->generation);
279                         }
280                         printf("] ");
281                 }
282                 else
283                         printf("[%s] ",
284                                find_unique_abbrev(commit->object.sha1, 7));
285         }
286         puts(cp);
287 }
288
289 static char *ref_name[MAX_REVS + 1];
290 static int ref_name_cnt;
291
292 static const char *find_digit_prefix(const char *s, int *v)
293 {
294         const char *p;
295         int ver;
296         char ch;
297
298         for (p = s, ver = 0;
299              '0' <= (ch = *p) && ch <= '9';
300              p++)
301                 ver = ver * 10 + ch - '0';
302         *v = ver;
303         return p;
304 }
305
306
307 static int version_cmp(const char *a, const char *b)
308 {
309         while (1) {
310                 int va, vb;
311
312                 a = find_digit_prefix(a, &va);
313                 b = find_digit_prefix(b, &vb);
314                 if (va != vb)
315                         return va - vb;
316
317                 while (1) {
318                         int ca = *a;
319                         int cb = *b;
320                         if ('0' <= ca && ca <= '9')
321                                 ca = 0;
322                         if ('0' <= cb && cb <= '9')
323                                 cb = 0;
324                         if (ca != cb)
325                                 return ca - cb;
326                         if (!ca)
327                                 break;
328                         a++;
329                         b++;
330                 }
331                 if (!*a && !*b)
332                         return 0;
333         }
334 }
335
336 static int compare_ref_name(const void *a_, const void *b_)
337 {
338         const char * const*a = a_, * const*b = b_;
339         return version_cmp(*a, *b);
340 }
341
342 static void sort_ref_range(int bottom, int top)
343 {
344         qsort(ref_name + bottom, top - bottom, sizeof(ref_name[0]),
345               compare_ref_name);
346 }
347
348 static int append_ref(const char *refname, const unsigned char *sha1)
349 {
350         struct commit *commit = lookup_commit_reference_gently(sha1, 1);
351         int i;
352
353         if (!commit)
354                 return 0;
355         /* Avoid adding the same thing twice */
356         for (i = 0; i < ref_name_cnt; i++)
357                 if (!strcmp(refname, ref_name[i]))
358                         return 0;
359
360         if (MAX_REVS <= ref_name_cnt) {
361                 fprintf(stderr, "warning: ignoring %s; "
362                         "cannot handle more than %d refs\n",
363                         refname, MAX_REVS);
364                 return 0;
365         }
366         ref_name[ref_name_cnt++] = strdup(refname);
367         ref_name[ref_name_cnt] = NULL;
368         return 0;
369 }
370
371 static int append_head_ref(const char *refname, const unsigned char *sha1)
372 {
373         unsigned char tmp[20];
374         int ofs = 11;
375         if (strncmp(refname, "refs/heads/", ofs))
376                 return 0;
377         /* If both heads/foo and tags/foo exists, get_sha1 would
378          * get confused.
379          */
380         if (get_sha1(refname + ofs, tmp) || memcmp(tmp, sha1, 20))
381                 ofs = 5;
382         return append_ref(refname + ofs, sha1);
383 }
384
385 static int append_tag_ref(const char *refname, const unsigned char *sha1)
386 {
387         if (strncmp(refname, "refs/tags/", 10))
388                 return 0;
389         return append_ref(refname + 5, sha1);
390 }
391
392 static const char *match_ref_pattern = NULL;
393 static int match_ref_slash = 0;
394 static int count_slash(const char *s)
395 {
396         int cnt = 0;
397         while (*s)
398                 if (*s++ == '/')
399                         cnt++;
400         return cnt;
401 }
402
403 static int append_matching_ref(const char *refname, const unsigned char *sha1)
404 {
405         /* we want to allow pattern hold/<asterisk> to show all
406          * branches under refs/heads/hold/, and v0.99.9? to show
407          * refs/tags/v0.99.9a and friends.
408          */
409         const char *tail;
410         int slash = count_slash(refname);
411         for (tail = refname; *tail && match_ref_slash < slash; )
412                 if (*tail++ == '/')
413                         slash--;
414         if (!*tail)
415                 return 0;
416         if (fnmatch(match_ref_pattern, tail, 0))
417                 return 0;
418         if (!strncmp("refs/heads/", refname, 11))
419                 return append_head_ref(refname, sha1);
420         if (!strncmp("refs/tags/", refname, 10))
421                 return append_tag_ref(refname, sha1);
422         return append_ref(refname, sha1);
423 }
424
425 static void snarf_refs(int head, int tag)
426 {
427         if (head) {
428                 int orig_cnt = ref_name_cnt;
429                 for_each_ref(append_head_ref);
430                 sort_ref_range(orig_cnt, ref_name_cnt);
431         }
432         if (tag) {
433                 int orig_cnt = ref_name_cnt;
434                 for_each_ref(append_tag_ref);
435                 sort_ref_range(orig_cnt, ref_name_cnt);
436         }
437 }
438
439 static int rev_is_head(char *head_path, int headlen, char *name,
440                        unsigned char *head_sha1, unsigned char *sha1)
441 {
442         int namelen;
443         if ((!head_path[0]) ||
444             (head_sha1 && sha1 && memcmp(head_sha1, sha1, 20)))
445                 return 0;
446         namelen = strlen(name);
447         if ((headlen < namelen) ||
448             memcmp(head_path + headlen - namelen, name, namelen))
449                 return 0;
450         if (headlen == namelen ||
451             head_path[headlen - namelen - 1] == '/')
452                 return 1;
453         return 0;
454 }
455
456 static int show_merge_base(struct commit_list *seen, int num_rev)
457 {
458         int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
459         int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
460         int exit_status = 1;
461
462         while (seen) {
463                 struct commit *commit = pop_one_commit(&seen);
464                 int flags = commit->object.flags & all_mask;
465                 if (!(flags & UNINTERESTING) &&
466                     ((flags & all_revs) == all_revs)) {
467                         puts(sha1_to_hex(commit->object.sha1));
468                         exit_status = 0;
469                         commit->object.flags |= UNINTERESTING;
470                 }
471         }
472         return exit_status;
473 }
474
475 static int show_independent(struct commit **rev,
476                             int num_rev,
477                             char **ref_name,
478                             unsigned int *rev_mask)
479 {
480         int i;
481
482         for (i = 0; i < num_rev; i++) {
483                 struct commit *commit = rev[i];
484                 unsigned int flag = rev_mask[i];
485
486                 if (commit->object.flags == flag)
487                         puts(sha1_to_hex(commit->object.sha1));
488                 commit->object.flags |= UNINTERESTING;
489         }
490         return 0;
491 }
492
493 static void append_one_rev(const char *av)
494 {
495         unsigned char revkey[20];
496         if (!get_sha1(av, revkey)) {
497                 append_ref(av, revkey);
498                 return;
499         }
500         if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
501                 /* glob style match */
502                 int saved_matches = ref_name_cnt;
503                 match_ref_pattern = av;
504                 match_ref_slash = count_slash(av);
505                 for_each_ref(append_matching_ref);
506                 if (saved_matches == ref_name_cnt &&
507                     ref_name_cnt < MAX_REVS)
508                         error("no matching refs with %s", av);
509                 if (saved_matches + 1 < ref_name_cnt)
510                         sort_ref_range(saved_matches, ref_name_cnt);
511                 return;
512         }
513         die("bad sha1 reference %s", av);
514 }
515
516 static int git_show_branch_config(const char *var, const char *value)
517 {
518         if (!strcmp(var, "showbranch.default")) {
519                 if (default_alloc <= default_num + 1) {
520                         default_alloc = default_alloc * 3 / 2 + 20;
521                         default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc);
522                 }
523                 default_arg[default_num++] = strdup(value);
524                 default_arg[default_num] = NULL;
525                 return 0;
526         }
527
528         return git_default_config(var, value);
529 }
530
531 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
532 {
533         /* If the commit is tip of the named branches, do not
534          * omit it.
535          * Otherwise, if it is a merge that is reachable from only one
536          * tip, it is not that interesting.
537          */
538         int i, flag, count;
539         for (i = 0; i < n; i++)
540                 if (rev[i] == commit)
541                         return 0;
542         flag = commit->object.flags;
543         for (i = count = 0; i < n; i++) {
544                 if (flag & (1u << (i + REV_SHIFT)))
545                         count++;
546         }
547         if (count == 1)
548                 return 1;
549         return 0;
550 }
551
552 int cmd_show_branch(int ac, const char **av, char **envp)
553 {
554         struct commit *rev[MAX_REVS], *commit;
555         struct commit_list *list = NULL, *seen = NULL;
556         unsigned int rev_mask[MAX_REVS];
557         int num_rev, i, extra = 0;
558         int all_heads = 0, all_tags = 0;
559         int all_mask, all_revs;
560         int lifo = 1;
561         char head_path[128];
562         const char *head_path_p;
563         int head_path_len;
564         unsigned char head_sha1[20];
565         int merge_base = 0;
566         int independent = 0;
567         int no_name = 0;
568         int sha1_name = 0;
569         int shown_merge_point = 0;
570         int with_current_branch = 0;
571         int head_at = -1;
572         int topics = 0;
573         int dense = 1;
574
575         setup_git_directory();
576         git_config(git_show_branch_config);
577
578         /* If nothing is specified, try the default first */
579         if (ac == 1 && default_num) {
580                 ac = default_num + 1;
581                 av = default_arg - 1; /* ick; we would not address av[0] */
582         }
583
584         while (1 < ac && av[1][0] == '-') {
585                 const char *arg = av[1];
586                 if (!strcmp(arg, "--")) {
587                         ac--; av++;
588                         break;
589                 }
590                 else if (!strcmp(arg, "--all"))
591                         all_heads = all_tags = 1;
592                 else if (!strcmp(arg, "--heads"))
593                         all_heads = 1;
594                 else if (!strcmp(arg, "--tags"))
595                         all_tags = 1;
596                 else if (!strcmp(arg, "--more"))
597                         extra = 1;
598                 else if (!strcmp(arg, "--list"))
599                         extra = -1;
600                 else if (!strcmp(arg, "--no-name"))
601                         no_name = 1;
602                 else if (!strcmp(arg, "--current"))
603                         with_current_branch = 1;
604                 else if (!strcmp(arg, "--sha1-name"))
605                         sha1_name = 1;
606                 else if (!strncmp(arg, "--more=", 7))
607                         extra = atoi(arg + 7);
608                 else if (!strcmp(arg, "--merge-base"))
609                         merge_base = 1;
610                 else if (!strcmp(arg, "--independent"))
611                         independent = 1;
612                 else if (!strcmp(arg, "--topo-order"))
613                         lifo = 1;
614                 else if (!strcmp(arg, "--topics"))
615                         topics = 1;
616                 else if (!strcmp(arg, "--sparse"))
617                         dense = 0;
618                 else if (!strcmp(arg, "--date-order"))
619                         lifo = 0;
620                 else
621                         usage(show_branch_usage);
622                 ac--; av++;
623         }
624         ac--; av++;
625
626         /* Only one of these is allowed */
627         if (1 < independent + merge_base + (extra != 0))
628                 usage(show_branch_usage);
629
630         /* If nothing is specified, show all branches by default */
631         if (ac + all_heads + all_tags == 0)
632                 all_heads = 1;
633
634         if (all_heads + all_tags)
635                 snarf_refs(all_heads, all_tags);
636         while (0 < ac) {
637                 append_one_rev(*av);
638                 ac--; av++;
639         }
640
641         head_path_p = resolve_ref(git_path("HEAD"), head_sha1, 1);
642         if (head_path_p) {
643                 head_path_len = strlen(head_path_p);
644                 memcpy(head_path, head_path_p, head_path_len + 1);
645         }
646         else {
647                 head_path_len = 0;
648                 head_path[0] = 0;
649         }
650
651         if (with_current_branch && head_path_p) {
652                 int has_head = 0;
653                 for (i = 0; !has_head && i < ref_name_cnt; i++) {
654                         /* We are only interested in adding the branch
655                          * HEAD points at.
656                          */
657                         if (rev_is_head(head_path,
658                                         head_path_len,
659                                         ref_name[i],
660                                         head_sha1, NULL))
661                                 has_head++;
662                 }
663                 if (!has_head) {
664                         int pfxlen = strlen(git_path("refs/heads/"));
665                         append_one_rev(head_path + pfxlen);
666                 }
667         }
668
669         if (!ref_name_cnt) {
670                 fprintf(stderr, "No revs to be shown.\n");
671                 exit(0);
672         }
673
674         for (num_rev = 0; ref_name[num_rev]; num_rev++) {
675                 unsigned char revkey[20];
676                 unsigned int flag = 1u << (num_rev + REV_SHIFT);
677
678                 if (MAX_REVS <= num_rev)
679                         die("cannot handle more than %d revs.", MAX_REVS);
680                 if (get_sha1(ref_name[num_rev], revkey))
681                         die("'%s' is not a valid ref.", ref_name[num_rev]);
682                 commit = lookup_commit_reference(revkey);
683                 if (!commit)
684                         die("cannot find commit %s (%s)",
685                             ref_name[num_rev], revkey);
686                 parse_commit(commit);
687                 mark_seen(commit, &seen);
688
689                 /* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
690                  * and so on.  REV_SHIFT bits from bit 0 are used for
691                  * internal bookkeeping.
692                  */
693                 commit->object.flags |= flag;
694                 if (commit->object.flags == flag)
695                         insert_by_date(commit, &list);
696                 rev[num_rev] = commit;
697         }
698         for (i = 0; i < num_rev; i++)
699                 rev_mask[i] = rev[i]->object.flags;
700
701         if (0 <= extra)
702                 join_revs(&list, &seen, num_rev, extra);
703
704         if (merge_base)
705                 return show_merge_base(seen, num_rev);
706
707         if (independent)
708                 return show_independent(rev, num_rev, ref_name, rev_mask);
709
710         /* Show list; --more=-1 means list-only */
711         if (1 < num_rev || extra < 0) {
712                 for (i = 0; i < num_rev; i++) {
713                         int j;
714                         int is_head = rev_is_head(head_path,
715                                                   head_path_len,
716                                                   ref_name[i],
717                                                   head_sha1,
718                                                   rev[i]->object.sha1);
719                         if (extra < 0)
720                                 printf("%c [%s] ",
721                                        is_head ? '*' : ' ', ref_name[i]);
722                         else {
723                                 for (j = 0; j < i; j++)
724                                         putchar(' ');
725                                 printf("%c [%s] ",
726                                        is_head ? '*' : '!', ref_name[i]);
727                         }
728                         /* header lines never need name */
729                         show_one_commit(rev[i], 1);
730                         if (is_head)
731                                 head_at = i;
732                 }
733                 if (0 <= extra) {
734                         for (i = 0; i < num_rev; i++)
735                                 putchar('-');
736                         putchar('\n');
737                 }
738         }
739         if (extra < 0)
740                 exit(0);
741
742         /* Sort topologically */
743         sort_in_topological_order(&seen, lifo);
744
745         /* Give names to commits */
746         if (!sha1_name && !no_name)
747                 name_commits(seen, rev, ref_name, num_rev);
748
749         all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
750         all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
751
752         while (seen) {
753                 struct commit *commit = pop_one_commit(&seen);
754                 int this_flag = commit->object.flags;
755                 int is_merge_point = ((this_flag & all_revs) == all_revs);
756
757                 shown_merge_point |= is_merge_point;
758
759                 if (1 < num_rev) {
760                         int is_merge = !!(commit->parents &&
761                                           commit->parents->next);
762                         if (topics &&
763                             !is_merge_point &&
764                             (this_flag & (1u << REV_SHIFT)))
765                                 continue;
766                         if (dense && is_merge &&
767                             omit_in_dense(commit, rev, num_rev))
768                                 continue;
769                         for (i = 0; i < num_rev; i++) {
770                                 int mark;
771                                 if (!(this_flag & (1u << (i + REV_SHIFT))))
772                                         mark = ' ';
773                                 else if (is_merge)
774                                         mark = '-';
775                                 else if (i == head_at)
776                                         mark = '*';
777                                 else
778                                         mark = '+';
779                                 putchar(mark);
780                         }
781                         putchar(' ');
782                 }
783                 show_one_commit(commit, no_name);
784
785                 if (shown_merge_point && --extra < 0)
786                         break;
787         }
788         return 0;
789 }