Merge branch 'nd/the-index' into md/list-objects-filter-by-depth
[git] / builtin / show-branch.c
1 #include "cache.h"
2 #include "config.h"
3 #include "pretty.h"
4 #include "refs.h"
5 #include "builtin.h"
6 #include "color.h"
7 #include "argv-array.h"
8 #include "parse-options.h"
9 #include "dir.h"
10 #include "commit-slab.h"
11
12 static const char* show_branch_usage[] = {
13     N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
14        "                [--current] [--color[=<when>] | --no-color] [--sparse]\n"
15        "                [--more=<n> | --list | --independent | --merge-base]\n"
16        "                [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"),
17     N_("git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"),
18     NULL
19 };
20
21 static int showbranch_use_color = -1;
22
23 static struct argv_array default_args = ARGV_ARRAY_INIT;
24
25 /*
26  * TODO: convert this use of commit->object.flags to commit-slab
27  * instead to store a pointer to ref name directly. Then use the same
28  * UNINTERESTING definition from revision.h here.
29  */
30 #define UNINTERESTING   01
31
32 #define REV_SHIFT        2
33 #define MAX_REVS        (FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */
34
35 #define DEFAULT_REFLOG  4
36
37 static const char *get_color_code(int idx)
38 {
39         if (want_color(showbranch_use_color))
40                 return column_colors_ansi[idx % column_colors_ansi_max];
41         return "";
42 }
43
44 static const char *get_color_reset_code(void)
45 {
46         if (want_color(showbranch_use_color))
47                 return GIT_COLOR_RESET;
48         return "";
49 }
50
51 static struct commit *interesting(struct commit_list *list)
52 {
53         while (list) {
54                 struct commit *commit = list->item;
55                 list = list->next;
56                 if (commit->object.flags & UNINTERESTING)
57                         continue;
58                 return commit;
59         }
60         return NULL;
61 }
62
63 struct commit_name {
64         const char *head_name; /* which head's ancestor? */
65         int generation; /* how many parents away from head_name */
66 };
67
68 define_commit_slab(commit_name_slab, struct commit_name *);
69 static struct commit_name_slab name_slab;
70
71 static struct commit_name *commit_to_name(struct commit *commit)
72 {
73         return *commit_name_slab_at(&name_slab, commit);
74 }
75
76
77 /* Name the commit as nth generation ancestor of head_name;
78  * we count only the first-parent relationship for naming purposes.
79  */
80 static void name_commit(struct commit *commit, const char *head_name, int nth)
81 {
82         struct commit_name *name;
83
84         name = *commit_name_slab_at(&name_slab, commit);
85         if (!name) {
86                 name = xmalloc(sizeof(*name));
87                 *commit_name_slab_at(&name_slab, commit) = name;
88         }
89         name->head_name = head_name;
90         name->generation = nth;
91 }
92
93 /* Parent is the first parent of the commit.  We may name it
94  * as (n+1)th generation ancestor of the same head_name as
95  * commit is nth generation ancestor of, if that generation
96  * number is better than the name it already has.
97  */
98 static void name_parent(struct commit *commit, struct commit *parent)
99 {
100         struct commit_name *commit_name = commit_to_name(commit);
101         struct commit_name *parent_name = commit_to_name(parent);
102         if (!commit_name)
103                 return;
104         if (!parent_name ||
105             commit_name->generation + 1 < parent_name->generation)
106                 name_commit(parent, commit_name->head_name,
107                             commit_name->generation + 1);
108 }
109
110 static int name_first_parent_chain(struct commit *c)
111 {
112         int i = 0;
113         while (c) {
114                 struct commit *p;
115                 if (!commit_to_name(c))
116                         break;
117                 if (!c->parents)
118                         break;
119                 p = c->parents->item;
120                 if (!commit_to_name(p)) {
121                         name_parent(c, p);
122                         i++;
123                 }
124                 else
125                         break;
126                 c = p;
127         }
128         return i;
129 }
130
131 static void name_commits(struct commit_list *list,
132                          struct commit **rev,
133                          char **ref_name,
134                          int num_rev)
135 {
136         struct commit_list *cl;
137         struct commit *c;
138         int i;
139
140         /* First give names to the given heads */
141         for (cl = list; cl; cl = cl->next) {
142                 c = cl->item;
143                 if (commit_to_name(c))
144                         continue;
145                 for (i = 0; i < num_rev; i++) {
146                         if (rev[i] == c) {
147                                 name_commit(c, ref_name[i], 0);
148                                 break;
149                         }
150                 }
151         }
152
153         /* Then commits on the first parent ancestry chain */
154         do {
155                 i = 0;
156                 for (cl = list; cl; cl = cl->next) {
157                         i += name_first_parent_chain(cl->item);
158                 }
159         } while (i);
160
161         /* Finally, any unnamed commits */
162         do {
163                 i = 0;
164                 for (cl = list; cl; cl = cl->next) {
165                         struct commit_list *parents;
166                         struct commit_name *n;
167                         int nth;
168                         c = cl->item;
169                         if (!commit_to_name(c))
170                                 continue;
171                         n = commit_to_name(c);
172                         parents = c->parents;
173                         nth = 0;
174                         while (parents) {
175                                 struct commit *p = parents->item;
176                                 struct strbuf newname = STRBUF_INIT;
177                                 parents = parents->next;
178                                 nth++;
179                                 if (commit_to_name(p))
180                                         continue;
181                                 switch (n->generation) {
182                                 case 0:
183                                         strbuf_addstr(&newname, n->head_name);
184                                         break;
185                                 case 1:
186                                         strbuf_addf(&newname, "%s^", n->head_name);
187                                         break;
188                                 default:
189                                         strbuf_addf(&newname, "%s~%d",
190                                                     n->head_name, n->generation);
191                                         break;
192                                 }
193                                 if (nth == 1)
194                                         strbuf_addch(&newname, '^');
195                                 else
196                                         strbuf_addf(&newname, "^%d", nth);
197                                 name_commit(p, strbuf_detach(&newname, NULL), 0);
198                                 i++;
199                                 name_first_parent_chain(p);
200                         }
201                 }
202         } while (i);
203 }
204
205 static int mark_seen(struct commit *commit, struct commit_list **seen_p)
206 {
207         if (!commit->object.flags) {
208                 commit_list_insert(commit, seen_p);
209                 return 1;
210         }
211         return 0;
212 }
213
214 static void join_revs(struct commit_list **list_p,
215                       struct commit_list **seen_p,
216                       int num_rev, int extra)
217 {
218         int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
219         int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
220
221         while (*list_p) {
222                 struct commit_list *parents;
223                 int still_interesting = !!interesting(*list_p);
224                 struct commit *commit = pop_commit(list_p);
225                 int flags = commit->object.flags & all_mask;
226
227                 if (!still_interesting && extra <= 0)
228                         break;
229
230                 mark_seen(commit, seen_p);
231                 if ((flags & all_revs) == all_revs)
232                         flags |= UNINTERESTING;
233                 parents = commit->parents;
234
235                 while (parents) {
236                         struct commit *p = parents->item;
237                         int this_flag = p->object.flags;
238                         parents = parents->next;
239                         if ((this_flag & flags) == flags)
240                                 continue;
241                         parse_commit(p);
242                         if (mark_seen(p, seen_p) && !still_interesting)
243                                 extra--;
244                         p->object.flags |= flags;
245                         commit_list_insert_by_date(p, list_p);
246                 }
247         }
248
249         /*
250          * Postprocess to complete well-poisoning.
251          *
252          * At this point we have all the commits we have seen in
253          * seen_p list.  Mark anything that can be reached from
254          * uninteresting commits not interesting.
255          */
256         for (;;) {
257                 int changed = 0;
258                 struct commit_list *s;
259                 for (s = *seen_p; s; s = s->next) {
260                         struct commit *c = s->item;
261                         struct commit_list *parents;
262
263                         if (((c->object.flags & all_revs) != all_revs) &&
264                             !(c->object.flags & UNINTERESTING))
265                                 continue;
266
267                         /* The current commit is either a merge base or
268                          * already uninteresting one.  Mark its parents
269                          * as uninteresting commits _only_ if they are
270                          * already parsed.  No reason to find new ones
271                          * here.
272                          */
273                         parents = c->parents;
274                         while (parents) {
275                                 struct commit *p = parents->item;
276                                 parents = parents->next;
277                                 if (!(p->object.flags & UNINTERESTING)) {
278                                         p->object.flags |= UNINTERESTING;
279                                         changed = 1;
280                                 }
281                         }
282                 }
283                 if (!changed)
284                         break;
285         }
286 }
287
288 static void show_one_commit(struct commit *commit, int no_name)
289 {
290         struct strbuf pretty = STRBUF_INIT;
291         const char *pretty_str = "(unavailable)";
292         struct commit_name *name = commit_to_name(commit);
293
294         if (commit->object.parsed) {
295                 pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
296                 pretty_str = pretty.buf;
297         }
298         skip_prefix(pretty_str, "[PATCH] ", &pretty_str);
299
300         if (!no_name) {
301                 if (name && name->head_name) {
302                         printf("[%s", name->head_name);
303                         if (name->generation) {
304                                 if (name->generation == 1)
305                                         printf("^");
306                                 else
307                                         printf("~%d", name->generation);
308                         }
309                         printf("] ");
310                 }
311                 else
312                         printf("[%s] ",
313                                find_unique_abbrev(&commit->object.oid,
314                                                   DEFAULT_ABBREV));
315         }
316         puts(pretty_str);
317         strbuf_release(&pretty);
318 }
319
320 static char *ref_name[MAX_REVS + 1];
321 static int ref_name_cnt;
322
323 static const char *find_digit_prefix(const char *s, int *v)
324 {
325         const char *p;
326         int ver;
327         char ch;
328
329         for (p = s, ver = 0;
330              '0' <= (ch = *p) && ch <= '9';
331              p++)
332                 ver = ver * 10 + ch - '0';
333         *v = ver;
334         return p;
335 }
336
337
338 static int version_cmp(const char *a, const char *b)
339 {
340         while (1) {
341                 int va, vb;
342
343                 a = find_digit_prefix(a, &va);
344                 b = find_digit_prefix(b, &vb);
345                 if (va != vb)
346                         return va - vb;
347
348                 while (1) {
349                         int ca = *a;
350                         int cb = *b;
351                         if ('0' <= ca && ca <= '9')
352                                 ca = 0;
353                         if ('0' <= cb && cb <= '9')
354                                 cb = 0;
355                         if (ca != cb)
356                                 return ca - cb;
357                         if (!ca)
358                                 break;
359                         a++;
360                         b++;
361                 }
362                 if (!*a && !*b)
363                         return 0;
364         }
365 }
366
367 static int compare_ref_name(const void *a_, const void *b_)
368 {
369         const char * const*a = a_, * const*b = b_;
370         return version_cmp(*a, *b);
371 }
372
373 static void sort_ref_range(int bottom, int top)
374 {
375         QSORT(ref_name + bottom, top - bottom, compare_ref_name);
376 }
377
378 static int append_ref(const char *refname, const struct object_id *oid,
379                       int allow_dups)
380 {
381         struct commit *commit = lookup_commit_reference_gently(the_repository,
382                                                                oid, 1);
383         int i;
384
385         if (!commit)
386                 return 0;
387
388         if (!allow_dups) {
389                 /* Avoid adding the same thing twice */
390                 for (i = 0; i < ref_name_cnt; i++)
391                         if (!strcmp(refname, ref_name[i]))
392                                 return 0;
393         }
394         if (MAX_REVS <= ref_name_cnt) {
395                 warning(Q_("ignoring %s; cannot handle more than %d ref",
396                            "ignoring %s; cannot handle more than %d refs",
397                            MAX_REVS), refname, MAX_REVS);
398                 return 0;
399         }
400         ref_name[ref_name_cnt++] = xstrdup(refname);
401         ref_name[ref_name_cnt] = NULL;
402         return 0;
403 }
404
405 static int append_head_ref(const char *refname, const struct object_id *oid,
406                            int flag, void *cb_data)
407 {
408         struct object_id tmp;
409         int ofs = 11;
410         if (!starts_with(refname, "refs/heads/"))
411                 return 0;
412         /* If both heads/foo and tags/foo exists, get_sha1 would
413          * get confused.
414          */
415         if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
416                 ofs = 5;
417         return append_ref(refname + ofs, oid, 0);
418 }
419
420 static int append_remote_ref(const char *refname, const struct object_id *oid,
421                              int flag, void *cb_data)
422 {
423         struct object_id tmp;
424         int ofs = 13;
425         if (!starts_with(refname, "refs/remotes/"))
426                 return 0;
427         /* If both heads/foo and tags/foo exists, get_sha1 would
428          * get confused.
429          */
430         if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
431                 ofs = 5;
432         return append_ref(refname + ofs, oid, 0);
433 }
434
435 static int append_tag_ref(const char *refname, const struct object_id *oid,
436                           int flag, void *cb_data)
437 {
438         if (!starts_with(refname, "refs/tags/"))
439                 return 0;
440         return append_ref(refname + 5, oid, 0);
441 }
442
443 static const char *match_ref_pattern = NULL;
444 static int match_ref_slash = 0;
445
446 static int append_matching_ref(const char *refname, const struct object_id *oid,
447                                int flag, void *cb_data)
448 {
449         /* we want to allow pattern hold/<asterisk> to show all
450          * branches under refs/heads/hold/, and v0.99.9? to show
451          * refs/tags/v0.99.9a and friends.
452          */
453         const char *tail;
454         int slash = count_slashes(refname);
455         for (tail = refname; *tail && match_ref_slash < slash; )
456                 if (*tail++ == '/')
457                         slash--;
458         if (!*tail)
459                 return 0;
460         if (wildmatch(match_ref_pattern, tail, 0))
461                 return 0;
462         if (starts_with(refname, "refs/heads/"))
463                 return append_head_ref(refname, oid, flag, cb_data);
464         if (starts_with(refname, "refs/tags/"))
465                 return append_tag_ref(refname, oid, flag, cb_data);
466         return append_ref(refname, oid, 0);
467 }
468
469 static void snarf_refs(int head, int remotes)
470 {
471         if (head) {
472                 int orig_cnt = ref_name_cnt;
473
474                 for_each_ref(append_head_ref, NULL);
475                 sort_ref_range(orig_cnt, ref_name_cnt);
476         }
477         if (remotes) {
478                 int orig_cnt = ref_name_cnt;
479
480                 for_each_ref(append_remote_ref, NULL);
481                 sort_ref_range(orig_cnt, ref_name_cnt);
482         }
483 }
484
485 static int rev_is_head(const char *head, const char *name,
486                        unsigned char *head_sha1, unsigned char *sha1)
487 {
488         if (!head || (head_sha1 && sha1 && !hasheq(head_sha1, sha1)))
489                 return 0;
490         skip_prefix(head, "refs/heads/", &head);
491         if (!skip_prefix(name, "refs/heads/", &name))
492                 skip_prefix(name, "heads/", &name);
493         return !strcmp(head, name);
494 }
495
496 static int show_merge_base(struct commit_list *seen, int num_rev)
497 {
498         int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
499         int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
500         int exit_status = 1;
501
502         while (seen) {
503                 struct commit *commit = pop_commit(&seen);
504                 int flags = commit->object.flags & all_mask;
505                 if (!(flags & UNINTERESTING) &&
506                     ((flags & all_revs) == all_revs)) {
507                         puts(oid_to_hex(&commit->object.oid));
508                         exit_status = 0;
509                         commit->object.flags |= UNINTERESTING;
510                 }
511         }
512         return exit_status;
513 }
514
515 static int show_independent(struct commit **rev,
516                             int num_rev,
517                             char **ref_name,
518                             unsigned int *rev_mask)
519 {
520         int i;
521
522         for (i = 0; i < num_rev; i++) {
523                 struct commit *commit = rev[i];
524                 unsigned int flag = rev_mask[i];
525
526                 if (commit->object.flags == flag)
527                         puts(oid_to_hex(&commit->object.oid));
528                 commit->object.flags |= UNINTERESTING;
529         }
530         return 0;
531 }
532
533 static void append_one_rev(const char *av)
534 {
535         struct object_id revkey;
536         if (!get_oid(av, &revkey)) {
537                 append_ref(av, &revkey, 0);
538                 return;
539         }
540         if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
541                 /* glob style match */
542                 int saved_matches = ref_name_cnt;
543
544                 match_ref_pattern = av;
545                 match_ref_slash = count_slashes(av);
546                 for_each_ref(append_matching_ref, NULL);
547                 if (saved_matches == ref_name_cnt &&
548                     ref_name_cnt < MAX_REVS)
549                         error(_("no matching refs with %s"), av);
550                 sort_ref_range(saved_matches, ref_name_cnt);
551                 return;
552         }
553         die("bad sha1 reference %s", av);
554 }
555
556 static int git_show_branch_config(const char *var, const char *value, void *cb)
557 {
558         if (!strcmp(var, "showbranch.default")) {
559                 if (!value)
560                         return config_error_nonbool(var);
561                 /*
562                  * default_arg is now passed to parse_options(), so we need to
563                  * mimic the real argv a bit better.
564                  */
565                 if (!default_args.argc)
566                         argv_array_push(&default_args, "show-branch");
567                 argv_array_push(&default_args, value);
568                 return 0;
569         }
570
571         if (!strcmp(var, "color.showbranch")) {
572                 showbranch_use_color = git_config_colorbool(var, value);
573                 return 0;
574         }
575
576         return git_color_default_config(var, value, cb);
577 }
578
579 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
580 {
581         /* If the commit is tip of the named branches, do not
582          * omit it.
583          * Otherwise, if it is a merge that is reachable from only one
584          * tip, it is not that interesting.
585          */
586         int i, flag, count;
587         for (i = 0; i < n; i++)
588                 if (rev[i] == commit)
589                         return 0;
590         flag = commit->object.flags;
591         for (i = count = 0; i < n; i++) {
592                 if (flag & (1u << (i + REV_SHIFT)))
593                         count++;
594         }
595         if (count == 1)
596                 return 1;
597         return 0;
598 }
599
600 static int reflog = 0;
601
602 static int parse_reflog_param(const struct option *opt, const char *arg,
603                               int unset)
604 {
605         char *ep;
606         const char **base = (const char **)opt->value;
607         BUG_ON_OPT_NEG(unset);
608         if (!arg)
609                 arg = "";
610         reflog = strtoul(arg, &ep, 10);
611         if (*ep == ',')
612                 *base = ep + 1;
613         else if (*ep)
614                 return error("unrecognized reflog param '%s'", arg);
615         else
616                 *base = NULL;
617         if (reflog <= 0)
618                 reflog = DEFAULT_REFLOG;
619         return 0;
620 }
621
622 int cmd_show_branch(int ac, const char **av, const char *prefix)
623 {
624         struct commit *rev[MAX_REVS], *commit;
625         char *reflog_msg[MAX_REVS];
626         struct commit_list *list = NULL, *seen = NULL;
627         unsigned int rev_mask[MAX_REVS];
628         int num_rev, i, extra = 0;
629         int all_heads = 0, all_remotes = 0;
630         int all_mask, all_revs;
631         enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
632         char *head;
633         struct object_id head_oid;
634         int merge_base = 0;
635         int independent = 0;
636         int no_name = 0;
637         int sha1_name = 0;
638         int shown_merge_point = 0;
639         int with_current_branch = 0;
640         int head_at = -1;
641         int topics = 0;
642         int dense = 1;
643         const char *reflog_base = NULL;
644         struct option builtin_show_branch_options[] = {
645                 OPT_BOOL('a', "all", &all_heads,
646                          N_("show remote-tracking and local branches")),
647                 OPT_BOOL('r', "remotes", &all_remotes,
648                          N_("show remote-tracking branches")),
649                 OPT__COLOR(&showbranch_use_color,
650                             N_("color '*!+-' corresponding to the branch")),
651                 { OPTION_INTEGER, 0, "more", &extra, N_("n"),
652                             N_("show <n> more commits after the common ancestor"),
653                             PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
654                 OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
655                 OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
656                 OPT_BOOL(0, "current", &with_current_branch,
657                          N_("include the current branch")),
658                 OPT_BOOL(0, "sha1-name", &sha1_name,
659                          N_("name commits with their object names")),
660                 OPT_BOOL(0, "merge-base", &merge_base,
661                          N_("show possible merge bases")),
662                 OPT_BOOL(0, "independent", &independent,
663                             N_("show refs unreachable from any other ref")),
664                 OPT_SET_INT(0, "topo-order", &sort_order,
665                             N_("show commits in topological order"),
666                             REV_SORT_IN_GRAPH_ORDER),
667                 OPT_BOOL(0, "topics", &topics,
668                          N_("show only commits not on the first branch")),
669                 OPT_SET_INT(0, "sparse", &dense,
670                             N_("show merges reachable from only one tip"), 0),
671                 OPT_SET_INT(0, "date-order", &sort_order,
672                             N_("topologically sort, maintaining date order "
673                                "where possible"),
674                             REV_SORT_BY_COMMIT_DATE),
675                 { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
676                             N_("show <n> most recent ref-log entries starting at "
677                                "base"),
678                             PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
679                             parse_reflog_param },
680                 OPT_END()
681         };
682
683         init_commit_name_slab(&name_slab);
684
685         git_config(git_show_branch_config, NULL);
686
687         /* If nothing is specified, try the default first */
688         if (ac == 1 && default_args.argc) {
689                 ac = default_args.argc;
690                 av = default_args.argv;
691         }
692
693         ac = parse_options(ac, av, prefix, builtin_show_branch_options,
694                            show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
695         if (all_heads)
696                 all_remotes = 1;
697
698         if (extra || reflog) {
699                 /* "listing" mode is incompatible with
700                  * independent nor merge-base modes.
701                  */
702                 if (independent || merge_base)
703                         usage_with_options(show_branch_usage,
704                                            builtin_show_branch_options);
705                 if (reflog && ((0 < extra) || all_heads || all_remotes))
706                         /*
707                          * Asking for --more in reflog mode does not
708                          * make sense.  --list is Ok.
709                          *
710                          * Also --all and --remotes do not make sense either.
711                          */
712                         die(_("--reflog is incompatible with --all, --remotes, "
713                               "--independent or --merge-base"));
714         }
715
716         /* If nothing is specified, show all branches by default */
717         if (ac <= topics && all_heads + all_remotes == 0)
718                 all_heads = 1;
719
720         if (reflog) {
721                 struct object_id oid;
722                 char *ref;
723                 int base = 0;
724                 unsigned int flags = 0;
725
726                 if (ac == 0) {
727                         static const char *fake_av[2];
728
729                         fake_av[0] = resolve_refdup("HEAD",
730                                                     RESOLVE_REF_READING, &oid,
731                                                     NULL);
732                         fake_av[1] = NULL;
733                         av = fake_av;
734                         ac = 1;
735                         if (!*av)
736                                 die(_("no branches given, and HEAD is not valid"));
737                 }
738                 if (ac != 1)
739                         die(_("--reflog option needs one branch name"));
740
741                 if (MAX_REVS < reflog)
742                         die(Q_("only %d entry can be shown at one time.",
743                                "only %d entries can be shown at one time.",
744                                MAX_REVS), MAX_REVS);
745                 if (!dwim_ref(*av, strlen(*av), &oid, &ref))
746                         die(_("no such ref %s"), *av);
747
748                 /* Has the base been specified? */
749                 if (reflog_base) {
750                         char *ep;
751                         base = strtoul(reflog_base, &ep, 10);
752                         if (*ep) {
753                                 /* Ah, that is a date spec... */
754                                 timestamp_t at;
755                                 at = approxidate(reflog_base);
756                                 read_ref_at(ref, flags, at, -1, &oid, NULL,
757                                             NULL, NULL, &base);
758                         }
759                 }
760
761                 for (i = 0; i < reflog; i++) {
762                         char *logmsg;
763                         char *nth_desc;
764                         const char *msg;
765                         timestamp_t timestamp;
766                         int tz;
767
768                         if (read_ref_at(ref, flags, 0, base + i, &oid, &logmsg,
769                                         &timestamp, &tz, NULL)) {
770                                 reflog = i;
771                                 break;
772                         }
773                         msg = strchr(logmsg, '\t');
774                         if (!msg)
775                                 msg = "(none)";
776                         else
777                                 msg++;
778                         reflog_msg[i] = xstrfmt("(%s) %s",
779                                                 show_date(timestamp, tz,
780                                                           DATE_MODE(RELATIVE)),
781                                                 msg);
782                         free(logmsg);
783
784                         nth_desc = xstrfmt("%s@{%d}", *av, base+i);
785                         append_ref(nth_desc, &oid, 1);
786                         free(nth_desc);
787                 }
788                 free(ref);
789         }
790         else {
791                 while (0 < ac) {
792                         append_one_rev(*av);
793                         ac--; av++;
794                 }
795                 if (all_heads + all_remotes)
796                         snarf_refs(all_heads, all_remotes);
797         }
798
799         head = resolve_refdup("HEAD", RESOLVE_REF_READING,
800                               &head_oid, NULL);
801
802         if (with_current_branch && head) {
803                 int has_head = 0;
804                 for (i = 0; !has_head && i < ref_name_cnt; i++) {
805                         /* We are only interested in adding the branch
806                          * HEAD points at.
807                          */
808                         if (rev_is_head(head,
809                                         ref_name[i],
810                                         head_oid.hash, NULL))
811                                 has_head++;
812                 }
813                 if (!has_head) {
814                         const char *name = head;
815                         skip_prefix(name, "refs/heads/", &name);
816                         append_one_rev(name);
817                 }
818         }
819
820         if (!ref_name_cnt) {
821                 fprintf(stderr, "No revs to be shown.\n");
822                 exit(0);
823         }
824
825         for (num_rev = 0; ref_name[num_rev]; num_rev++) {
826                 struct object_id revkey;
827                 unsigned int flag = 1u << (num_rev + REV_SHIFT);
828
829                 if (MAX_REVS <= num_rev)
830                         die(Q_("cannot handle more than %d rev.",
831                                "cannot handle more than %d revs.",
832                                MAX_REVS), MAX_REVS);
833                 if (get_oid(ref_name[num_rev], &revkey))
834                         die(_("'%s' is not a valid ref."), ref_name[num_rev]);
835                 commit = lookup_commit_reference(the_repository, &revkey);
836                 if (!commit)
837                         die(_("cannot find commit %s (%s)"),
838                             ref_name[num_rev], oid_to_hex(&revkey));
839                 parse_commit(commit);
840                 mark_seen(commit, &seen);
841
842                 /* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
843                  * and so on.  REV_SHIFT bits from bit 0 are used for
844                  * internal bookkeeping.
845                  */
846                 commit->object.flags |= flag;
847                 if (commit->object.flags == flag)
848                         commit_list_insert_by_date(commit, &list);
849                 rev[num_rev] = commit;
850         }
851         for (i = 0; i < num_rev; i++)
852                 rev_mask[i] = rev[i]->object.flags;
853
854         if (0 <= extra)
855                 join_revs(&list, &seen, num_rev, extra);
856
857         commit_list_sort_by_date(&seen);
858
859         if (merge_base)
860                 return show_merge_base(seen, num_rev);
861
862         if (independent)
863                 return show_independent(rev, num_rev, ref_name, rev_mask);
864
865         /* Show list; --more=-1 means list-only */
866         if (1 < num_rev || extra < 0) {
867                 for (i = 0; i < num_rev; i++) {
868                         int j;
869                         int is_head = rev_is_head(head,
870                                                   ref_name[i],
871                                                   head_oid.hash,
872                                                   rev[i]->object.oid.hash);
873                         if (extra < 0)
874                                 printf("%c [%s] ",
875                                        is_head ? '*' : ' ', ref_name[i]);
876                         else {
877                                 for (j = 0; j < i; j++)
878                                         putchar(' ');
879                                 printf("%s%c%s [%s] ",
880                                        get_color_code(i),
881                                        is_head ? '*' : '!',
882                                        get_color_reset_code(), ref_name[i]);
883                         }
884
885                         if (!reflog) {
886                                 /* header lines never need name */
887                                 show_one_commit(rev[i], 1);
888                         }
889                         else
890                                 puts(reflog_msg[i]);
891
892                         if (is_head)
893                                 head_at = i;
894                 }
895                 if (0 <= extra) {
896                         for (i = 0; i < num_rev; i++)
897                                 putchar('-');
898                         putchar('\n');
899                 }
900         }
901         if (extra < 0)
902                 exit(0);
903
904         /* Sort topologically */
905         sort_in_topological_order(&seen, sort_order);
906
907         /* Give names to commits */
908         if (!sha1_name && !no_name)
909                 name_commits(seen, rev, ref_name, num_rev);
910
911         all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
912         all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
913
914         while (seen) {
915                 struct commit *commit = pop_commit(&seen);
916                 int this_flag = commit->object.flags;
917                 int is_merge_point = ((this_flag & all_revs) == all_revs);
918
919                 shown_merge_point |= is_merge_point;
920
921                 if (1 < num_rev) {
922                         int is_merge = !!(commit->parents &&
923                                           commit->parents->next);
924                         if (topics &&
925                             !is_merge_point &&
926                             (this_flag & (1u << REV_SHIFT)))
927                                 continue;
928                         if (dense && is_merge &&
929                             omit_in_dense(commit, rev, num_rev))
930                                 continue;
931                         for (i = 0; i < num_rev; i++) {
932                                 int mark;
933                                 if (!(this_flag & (1u << (i + REV_SHIFT))))
934                                         mark = ' ';
935                                 else if (is_merge)
936                                         mark = '-';
937                                 else if (i == head_at)
938                                         mark = '*';
939                                 else
940                                         mark = '+';
941                                 printf("%s%c%s",
942                                        get_color_code(i),
943                                        mark, get_color_reset_code());
944                         }
945                         putchar(' ');
946                 }
947                 show_one_commit(commit, no_name);
948
949                 if (shown_merge_point && --extra < 0)
950                         break;
951         }
952         return 0;
953 }