show-branch.c 22.7 KB
Newer Older
J
Junio C Hamano 已提交
1 2 3
#include "cache.h"
#include "commit.h"
#include "refs.h"
P
Peter Eriksen 已提交
4
#include "builtin.h"
5
#include "color.h"
6
#include "parse-options.h"
J
Junio C Hamano 已提交
7

8
static const char* show_branch_usage[] = {
9
    "git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]",
10
    "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]",
11 12
    NULL
};
J
Junio C Hamano 已提交
13

14 15
static int showbranch_use_color = -1;

16 17 18
static int default_num;
static int default_alloc;
static const char **default_arg;
19

J
Junio C Hamano 已提交
20 21 22
#define UNINTERESTING	01

#define REV_SHIFT	 2
L
Linus Torvalds 已提交
23
#define MAX_REVS	(FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */
J
Junio C Hamano 已提交
24

25 26
#define DEFAULT_REFLOG	4

27 28 29
static const char *get_color_code(int idx)
{
	if (showbranch_use_color)
30
		return column_colors_ansi[idx % column_colors_ansi_max];
31 32 33 34 35 36 37 38 39 40
	return "";
}

static const char *get_color_reset_code(void)
{
	if (showbranch_use_color)
		return GIT_COLOR_RESET;
	return "";
}

J
Junio C Hamano 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
static struct commit *interesting(struct commit_list *list)
{
	while (list) {
		struct commit *commit = list->item;
		list = list->next;
		if (commit->object.flags & UNINTERESTING)
			continue;
		return commit;
	}
	return NULL;
}

static struct commit *pop_one_commit(struct commit_list **list_p)
{
	struct commit *commit;
	struct commit_list *list;
	list = *list_p;
	commit = list->item;
	*list_p = list->next;
	free(list);
	return commit;
}

struct commit_name {
J
Junio C Hamano 已提交
65 66
	const char *head_name; /* which head's ancestor? */
	int generation; /* how many parents away from head_name */
J
Junio C Hamano 已提交
67 68
};

J
Junio C Hamano 已提交
69
/* Name the commit as nth generation ancestor of head_name;
J
Junio C Hamano 已提交
70 71
 * we count only the first-parent relationship for naming purposes.
 */
J
Junio C Hamano 已提交
72
static void name_commit(struct commit *commit, const char *head_name, int nth)
J
Junio C Hamano 已提交
73 74
{
	struct commit_name *name;
75 76 77
	if (!commit->util)
		commit->util = xmalloc(sizeof(struct commit_name));
	name = commit->util;
J
Junio C Hamano 已提交
78
	name->head_name = head_name;
J
Junio C Hamano 已提交
79 80 81 82
	name->generation = nth;
}

/* Parent is the first parent of the commit.  We may name it
J
Junio C Hamano 已提交
83
 * as (n+1)th generation ancestor of the same head_name as
J
Junio C Hamano 已提交
84
 * commit is nth generation ancestor of, if that generation
J
Junio C Hamano 已提交
85 86 87 88
 * number is better than the name it already has.
 */
static void name_parent(struct commit *commit, struct commit *parent)
{
89 90
	struct commit_name *commit_name = commit->util;
	struct commit_name *parent_name = parent->util;
J
Junio C Hamano 已提交
91 92 93 94
	if (!commit_name)
		return;
	if (!parent_name ||
	    commit_name->generation + 1 < parent_name->generation)
J
Junio C Hamano 已提交
95
		name_commit(parent, commit_name->head_name,
J
Junio C Hamano 已提交
96 97 98
			    commit_name->generation + 1);
}

J
Junio C Hamano 已提交
99 100 101 102 103
static int name_first_parent_chain(struct commit *c)
{
	int i = 0;
	while (c) {
		struct commit *p;
104
		if (!c->util)
J
Junio C Hamano 已提交
105 106 107 108
			break;
		if (!c->parents)
			break;
		p = c->parents->item;
109
		if (!p->util) {
J
Junio C Hamano 已提交
110 111 112
			name_parent(c, p);
			i++;
		}
113 114
		else
			break;
J
Junio C Hamano 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
		c = p;
	}
	return i;
}

static void name_commits(struct commit_list *list,
			 struct commit **rev,
			 char **ref_name,
			 int num_rev)
{
	struct commit_list *cl;
	struct commit *c;
	int i;

	/* First give names to the given heads */
	for (cl = list; cl; cl = cl->next) {
		c = cl->item;
132
		if (c->util)
J
Junio C Hamano 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
			continue;
		for (i = 0; i < num_rev; i++) {
			if (rev[i] == c) {
				name_commit(c, ref_name[i], 0);
				break;
			}
		}
	}

	/* Then commits on the first parent ancestry chain */
	do {
		i = 0;
		for (cl = list; cl; cl = cl->next) {
			i += name_first_parent_chain(cl->item);
		}
	} while (i);

	/* Finally, any unnamed commits */
	do {
		i = 0;
		for (cl = list; cl; cl = cl->next) {
			struct commit_list *parents;
			struct commit_name *n;
			int nth;
			c = cl->item;
158
			if (!c->util)
J
Junio C Hamano 已提交
159
				continue;
160
			n = c->util;
J
Junio C Hamano 已提交
161 162 163 164
			parents = c->parents;
			nth = 0;
			while (parents) {
				struct commit *p = parents->item;
165
				char newname[1000], *en;
J
Junio C Hamano 已提交
166 167
				parents = parents->next;
				nth++;
168
				if (p->util)
J
Junio C Hamano 已提交
169
					continue;
170
				en = newname;
171 172
				switch (n->generation) {
				case 0:
173
					en += sprintf(en, "%s", n->head_name);
174 175
					break;
				case 1:
176
					en += sprintf(en, "%s^", n->head_name);
177 178
					break;
				default:
179 180 181
					en += sprintf(en, "%s~%d",
						n->head_name, n->generation);
					break;
182
				}
183 184 185 186
				if (nth == 1)
					en += sprintf(en, "^");
				else
					en += sprintf(en, "^%d", nth);
187
				name_commit(p, xstrdup(newname), 0);
J
Junio C Hamano 已提交
188 189 190 191 192 193 194
				i++;
				name_first_parent_chain(p);
			}
		}
	} while (i);
}

J
Junio C Hamano 已提交
195 196 197
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
	if (!commit->object.flags) {
198
		commit_list_insert(commit, seen_p);
J
Junio C Hamano 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212
		return 1;
	}
	return 0;
}

static void join_revs(struct commit_list **list_p,
		      struct commit_list **seen_p,
		      int num_rev, int extra)
{
	int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
	int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);

	while (*list_p) {
		struct commit_list *parents;
213
		int still_interesting = !!interesting(*list_p);
J
Junio C Hamano 已提交
214 215 216
		struct commit *commit = pop_one_commit(list_p);
		int flags = commit->object.flags & all_mask;

217
		if (!still_interesting && extra <= 0)
J
Junio C Hamano 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230
			break;

		mark_seen(commit, seen_p);
		if ((flags & all_revs) == all_revs)
			flags |= UNINTERESTING;
		parents = commit->parents;

		while (parents) {
			struct commit *p = parents->item;
			int this_flag = p->object.flags;
			parents = parents->next;
			if ((this_flag & flags) == flags)
				continue;
231 232
			if (!p->object.parsed)
				parse_commit(p);
J
Junio C Hamano 已提交
233 234 235
			if (mark_seen(p, seen_p) && !still_interesting)
				extra--;
			p->object.flags |= flags;
236
			commit_list_insert_by_date(p, list_p);
J
Junio C Hamano 已提交
237 238
		}
	}
239 240 241 242 243

	/*
	 * Postprocess to complete well-poisoning.
	 *
	 * At this point we have all the commits we have seen in
244 245
	 * seen_p list.  Mark anything that can be reached from
	 * uninteresting commits not interesting.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
	 */
	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;
	}
J
Junio C Hamano 已提交
277 278
}

279
static void show_one_commit(struct commit *commit, int no_name)
J
Junio C Hamano 已提交
280
{
281
	struct strbuf pretty = STRBUF_INIT;
282
	const char *pretty_str = "(unavailable)";
283
	struct commit_name *name = commit->util;
284 285

	if (commit->object.parsed) {
286
		pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
287
		pretty_str = pretty.buf;
288 289 290
	}
	if (!prefixcmp(pretty_str, "[PATCH] "))
		pretty_str += 8;
291 292 293 294 295 296 297 298 299 300 301 302 303 304

	if (!no_name) {
		if (name && name->head_name) {
			printf("[%s", name->head_name);
			if (name->generation) {
				if (name->generation == 1)
					printf("^");
				else
					printf("~%d", name->generation);
			}
			printf("] ");
		}
		else
			printf("[%s] ",
305 306
			       find_unique_abbrev(commit->object.sha1,
						  DEFAULT_ABBREV));
J
Junio C Hamano 已提交
307
	}
308
	puts(pretty_str);
309
	strbuf_release(&pretty);
J
Junio C Hamano 已提交
310 311 312 313 314
}

static char *ref_name[MAX_REVS + 1];
static int ref_name_cnt;

J
Junio C Hamano 已提交
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
static const char *find_digit_prefix(const char *s, int *v)
{
	const char *p;
	int ver;
	char ch;

	for (p = s, ver = 0;
	     '0' <= (ch = *p) && ch <= '9';
	     p++)
		ver = ver * 10 + ch - '0';
	*v = ver;
	return p;
}


static int version_cmp(const char *a, const char *b)
{
	while (1) {
		int va, vb;

		a = find_digit_prefix(a, &va);
		b = find_digit_prefix(b, &vb);
		if (va != vb)
			return va - vb;

		while (1) {
			int ca = *a;
			int cb = *b;
			if ('0' <= ca && ca <= '9')
				ca = 0;
			if ('0' <= cb && cb <= '9')
				cb = 0;
			if (ca != cb)
				return ca - cb;
			if (!ca)
				break;
			a++;
			b++;
		}
		if (!*a && !*b)
			return 0;
	}
}

359 360 361
static int compare_ref_name(const void *a_, const void *b_)
{
	const char * const*a = a_, * const*b = b_;
J
Junio C Hamano 已提交
362
	return version_cmp(*a, *b);
363 364 365 366 367 368 369 370
}

static void sort_ref_range(int bottom, int top)
{
	qsort(ref_name + bottom, top - bottom, sizeof(ref_name[0]),
	      compare_ref_name);
}

371 372
static int append_ref(const char *refname, const unsigned char *sha1,
		      int allow_dups)
J
Junio C Hamano 已提交
373 374
{
	struct commit *commit = lookup_commit_reference_gently(sha1, 1);
J
Junio C Hamano 已提交
375 376
	int i;

J
Junio C Hamano 已提交
377 378
	if (!commit)
		return 0;
J
Junio C Hamano 已提交
379

380 381 382 383 384 385
	if (!allow_dups) {
		/* Avoid adding the same thing twice */
		for (i = 0; i < ref_name_cnt; i++)
			if (!strcmp(refname, ref_name[i]))
				return 0;
	}
386
	if (MAX_REVS <= ref_name_cnt) {
387
		warning("ignoring %s; cannot handle more than %d refs",
J
Junio C Hamano 已提交
388 389 390
			refname, MAX_REVS);
		return 0;
	}
391
	ref_name[ref_name_cnt++] = xstrdup(refname);
J
Junio C Hamano 已提交
392 393 394 395
	ref_name[ref_name_cnt] = NULL;
	return 0;
}

396
static int append_head_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
J
Junio C Hamano 已提交
397
{
398 399
	unsigned char tmp[20];
	int ofs = 11;
400
	if (prefixcmp(refname, "refs/heads/"))
J
Junio C Hamano 已提交
401
		return 0;
402 403 404
	/* If both heads/foo and tags/foo exists, get_sha1 would
	 * get confused.
	 */
405
	if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
406
		ofs = 5;
407
	return append_ref(refname + ofs, sha1, 0);
J
Junio C Hamano 已提交
408 409
}

410 411 412 413
static int append_remote_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
	unsigned char tmp[20];
	int ofs = 13;
414
	if (prefixcmp(refname, "refs/remotes/"))
415 416 417 418 419 420
		return 0;
	/* If both heads/foo and tags/foo exists, get_sha1 would
	 * get confused.
	 */
	if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
		ofs = 5;
421
	return append_ref(refname + ofs, sha1, 0);
422 423
}

424
static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
J
Junio C Hamano 已提交
425
{
426
	if (prefixcmp(refname, "refs/tags/"))
J
Junio C Hamano 已提交
427
		return 0;
428
	return append_ref(refname + 5, sha1, 0);
J
Junio C Hamano 已提交
429 430
}

431 432 433 434 435 436 437 438 439 440 441
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
static int count_slash(const char *s)
{
	int cnt = 0;
	while (*s)
		if (*s++ == '/')
			cnt++;
	return cnt;
}

442
static int append_matching_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
443 444 445 446 447 448 449 450 451 452 453 454 455 456
{
	/* we want to allow pattern hold/<asterisk> to show all
	 * branches under refs/heads/hold/, and v0.99.9? to show
	 * refs/tags/v0.99.9a and friends.
	 */
	const char *tail;
	int slash = count_slash(refname);
	for (tail = refname; *tail && match_ref_slash < slash; )
		if (*tail++ == '/')
			slash--;
	if (!*tail)
		return 0;
	if (fnmatch(match_ref_pattern, tail, 0))
		return 0;
457
	if (!prefixcmp(refname, "refs/heads/"))
458
		return append_head_ref(refname, sha1, flag, cb_data);
459
	if (!prefixcmp(refname, "refs/tags/"))
460
		return append_tag_ref(refname, sha1, flag, cb_data);
461
	return append_ref(refname, sha1, 0);
462 463
}

464
static void snarf_refs(int head, int remotes)
J
Junio C Hamano 已提交
465
{
466 467
	if (head) {
		int orig_cnt = ref_name_cnt;
468
		for_each_ref(append_head_ref, NULL);
469 470
		sort_ref_range(orig_cnt, ref_name_cnt);
	}
471
	if (remotes) {
472
		int orig_cnt = ref_name_cnt;
473
		for_each_ref(append_remote_ref, NULL);
474 475
		sort_ref_range(orig_cnt, ref_name_cnt);
	}
J
Junio C Hamano 已提交
476 477
}

L
Linus Torvalds 已提交
478
static int rev_is_head(char *head, int headlen, char *name,
J
Junio C Hamano 已提交
479 480
		       unsigned char *head_sha1, unsigned char *sha1)
{
L
Linus Torvalds 已提交
481
	if ((!head[0]) ||
482
	    (head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
J
Junio C Hamano 已提交
483
		return 0;
484
	if (!prefixcmp(head, "refs/heads/"))
485
		head += 11;
486
	if (!prefixcmp(name, "refs/heads/"))
487
		name += 11;
488
	else if (!prefixcmp(name, "heads/"))
489
		name += 6;
L
Linus Torvalds 已提交
490
	return !strcmp(head, name);
J
Junio C Hamano 已提交
491 492 493 494 495 496
}

static int show_merge_base(struct commit_list *seen, int num_rev)
{
	int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
	int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
497
	int exit_status = 1;
J
Junio C Hamano 已提交
498 499 500 501 502 503 504

	while (seen) {
		struct commit *commit = pop_one_commit(&seen);
		int flags = commit->object.flags & all_mask;
		if (!(flags & UNINTERESTING) &&
		    ((flags & all_revs) == all_revs)) {
			puts(sha1_to_hex(commit->object.sha1));
505 506
			exit_status = 0;
			commit->object.flags |= UNINTERESTING;
J
Junio C Hamano 已提交
507 508
		}
	}
509
	return exit_status;
J
Junio C Hamano 已提交
510 511
}

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
static int show_independent(struct commit **rev,
			    int num_rev,
			    char **ref_name,
			    unsigned int *rev_mask)
{
	int i;

	for (i = 0; i < num_rev; i++) {
		struct commit *commit = rev[i];
		unsigned int flag = rev_mask[i];

		if (commit->object.flags == flag)
			puts(sha1_to_hex(commit->object.sha1));
		commit->object.flags |= UNINTERESTING;
	}
	return 0;
}

530 531 532 533
static void append_one_rev(const char *av)
{
	unsigned char revkey[20];
	if (!get_sha1(av, revkey)) {
534
		append_ref(av, revkey, 0);
535 536
		return;
	}
537
	if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
538 539 540 541
		/* glob style match */
		int saved_matches = ref_name_cnt;
		match_ref_pattern = av;
		match_ref_slash = count_slash(av);
542
		for_each_ref(append_matching_ref, NULL);
543 544 545
		if (saved_matches == ref_name_cnt &&
		    ref_name_cnt < MAX_REVS)
			error("no matching refs with %s", av);
546 547
		if (saved_matches + 1 < ref_name_cnt)
			sort_ref_range(saved_matches, ref_name_cnt);
548 549 550 551 552
		return;
	}
	die("bad sha1 reference %s", av);
}

553
static int git_show_branch_config(const char *var, const char *value, void *cb)
554 555
{
	if (!strcmp(var, "showbranch.default")) {
556 557
		if (!value)
			return config_error_nonbool(var);
558 559
		/*
		 * default_arg is now passed to parse_options(), so we need to
560
		 * mimic the real argv a bit better.
561 562 563 564 565 566
		 */
		if (!default_num) {
			default_alloc = 20;
			default_arg = xcalloc(default_alloc, sizeof(*default_arg));
			default_arg[default_num++] = "show-branch";
		} else if (default_alloc <= default_num + 1) {
567 568 569
			default_alloc = default_alloc * 3 / 2 + 20;
			default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc);
		}
570
		default_arg[default_num++] = xstrdup(value);
571 572 573 574
		default_arg[default_num] = NULL;
		return 0;
	}

575
	if (!strcmp(var, "color.showbranch")) {
576
		showbranch_use_color = git_config_colorbool(var, value);
577 578 579 580
		return 0;
	}

	return git_color_default_config(var, value, cb);
581 582
}

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
{
	/* If the commit is tip of the named branches, do not
	 * omit it.
	 * Otherwise, if it is a merge that is reachable from only one
	 * tip, it is not that interesting.
	 */
	int i, flag, count;
	for (i = 0; i < n; i++)
		if (rev[i] == commit)
			return 0;
	flag = commit->object.flags;
	for (i = count = 0; i < n; i++) {
		if (flag & (1u << (i + REV_SHIFT)))
			count++;
	}
	if (count == 1)
		return 1;
	return 0;
}

604 605 606 607
static int reflog = 0;

static int parse_reflog_param(const struct option *opt, const char *arg,
			      int unset)
608 609
{
	char *ep;
610 611 612 613
	const char **base = (const char **)opt->value;
	if (!arg)
		arg = "";
	reflog = strtoul(arg, &ep, 10);
614 615 616
	if (*ep == ',')
		*base = ep + 1;
	else if (*ep)
617
		return error("unrecognized reflog param '%s'", arg);
618 619
	else
		*base = NULL;
620 621 622
	if (reflog <= 0)
		reflog = DEFAULT_REFLOG;
	return 0;
623 624
}

625
int cmd_show_branch(int ac, const char **av, const char *prefix)
J
Junio C Hamano 已提交
626 627
{
	struct commit *rev[MAX_REVS], *commit;
628
	char *reflog_msg[MAX_REVS];
J
Junio C Hamano 已提交
629
	struct commit_list *list = NULL, *seen = NULL;
630
	unsigned int rev_mask[MAX_REVS];
J
Junio C Hamano 已提交
631
	int num_rev, i, extra = 0;
632
	int all_heads = 0, all_remotes = 0;
633
	int all_mask, all_revs;
634
	int lifo = 1;
L
Linus Torvalds 已提交
635 636 637
	char head[128];
	const char *head_p;
	int head_len;
J
Junio C Hamano 已提交
638 639
	unsigned char head_sha1[20];
	int merge_base = 0;
640
	int independent = 0;
641 642
	int no_name = 0;
	int sha1_name = 0;
643
	int shown_merge_point = 0;
644
	int with_current_branch = 0;
645
	int head_at = -1;
J
Junio C Hamano 已提交
646
	int topics = 0;
647
	int dense = 1;
648
	const char *reflog_base = NULL;
649 650 651 652 653
	struct option builtin_show_branch_options[] = {
		OPT_BOOLEAN('a', "all", &all_heads,
			    "show remote-tracking and local branches"),
		OPT_BOOLEAN('r', "remotes", &all_remotes,
			    "show remote-tracking branches"),
654
		OPT__COLOR(&showbranch_use_color,
655 656 657
			    "color '*!+-' corresponding to the branch"),
		{ OPTION_INTEGER, 0, "more", &extra, "n",
			    "show <n> more commits after the common ancestor",
658
			    PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
659 660 661 662 663 664 665
		OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
		OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
		OPT_BOOLEAN(0, "current", &with_current_branch,
			    "include the current branch"),
		OPT_BOOLEAN(0, "sha1-name", &sha1_name,
			    "name commits with their object names"),
		OPT_BOOLEAN(0, "merge-base", &merge_base,
666
			    "show possible merge bases"),
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
		OPT_BOOLEAN(0, "independent", &independent,
			    "show refs unreachable from any other ref"),
		OPT_BOOLEAN(0, "topo-order", &lifo,
			    "show commits in topological order"),
		OPT_BOOLEAN(0, "topics", &topics,
			    "show only commits not on the first branch"),
		OPT_SET_INT(0, "sparse", &dense,
			    "show merges reachable from only one tip", 0),
		OPT_SET_INT(0, "date-order", &lifo,
			    "show commits where no parent comes before its "
			    "children", 0),
		{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
			    "show <n> most recent ref-log entries starting at "
			    "base",
			    PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
			    parse_reflog_param },
		OPT_END()
	};
J
Junio C Hamano 已提交
685

686
	git_config(git_show_branch_config, NULL);
687

688 689 690
	if (showbranch_use_color == -1)
		showbranch_use_color = git_use_color_default;

691 692
	/* If nothing is specified, try the default first */
	if (ac == 1 && default_num) {
693 694
		ac = default_num;
		av = default_arg;
695 696
	}

697
	ac = parse_options(ac, av, prefix, builtin_show_branch_options,
698 699 700
			   show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
	if (all_heads)
		all_remotes = 1;
J
Junio C Hamano 已提交
701

J
Junio C Hamano 已提交
702
	if (extra || reflog) {
703 704 705 706
		/* "listing" mode is incompatible with
		 * independent nor merge-base modes.
		 */
		if (independent || merge_base)
707 708
			usage_with_options(show_branch_usage,
					   builtin_show_branch_options);
J
Junio C Hamano 已提交
709
		if (reflog && ((0 < extra) || all_heads || all_remotes))
710 711
			/*
			 * Asking for --more in reflog mode does not
712 713 714
			 * make sense.  --list is Ok.
			 *
			 * Also --all and --remotes do not make sense either.
715
			 */
716 717
			die("--reflog is incompatible with --all, --remotes, "
			    "--independent or --merge-base");
718
	}
719

J
Junio C Hamano 已提交
720
	/* If nothing is specified, show all branches by default */
721
	if (ac + all_heads + all_remotes == 0)
J
Junio C Hamano 已提交
722 723
		all_heads = 1;

724
	if (reflog) {
725 726 727 728
		unsigned char sha1[20];
		char nth_desc[256];
		char *ref;
		int base = 0;
J
Junio C Hamano 已提交
729 730 731

		if (ac == 0) {
			static const char *fake_av[2];
732 733 734 735
			const char *refname;

			refname = resolve_ref("HEAD", sha1, 1, NULL);
			fake_av[0] = xstrdup(refname);
J
Junio C Hamano 已提交
736 737 738 739
			fake_av[1] = NULL;
			av = fake_av;
			ac = 1;
		}
740
		if (ac != 1)
741
			die("--reflog option needs one branch name");
J
Junio C Hamano 已提交
742

743 744 745
		if (MAX_REVS < reflog)
			die("Only %d entries can be shown at one time.",
			    MAX_REVS);
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
		if (!dwim_ref(*av, strlen(*av), sha1, &ref))
			die("No such ref %s", *av);

		/* Has the base been specified? */
		if (reflog_base) {
			char *ep;
			base = strtoul(reflog_base, &ep, 10);
			if (*ep) {
				/* Ah, that is a date spec... */
				unsigned long at;
				at = approxidate(reflog_base);
				read_ref_at(ref, at, -1, sha1, NULL,
					    NULL, NULL, &base);
			}
		}

762
		for (i = 0; i < reflog; i++) {
763 764
			char *logmsg, *m;
			const char *msg;
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
			unsigned long timestamp;
			int tz;

			if (read_ref_at(ref, 0, base+i, sha1, &logmsg,
					&timestamp, &tz, NULL)) {
				reflog = i;
				break;
			}
			msg = strchr(logmsg, '\t');
			if (!msg)
				msg = "(none)";
			else
				msg++;
			m = xmalloc(strlen(msg) + 200);
			sprintf(m, "(%s) %s",
780
				show_date(timestamp, tz, 1),
781 782 783 784 785
				msg);
			reflog_msg[i] = m;
			free(logmsg);
			sprintf(nth_desc, "%s@{%d}", *av, base+i);
			append_ref(nth_desc, sha1, 1);
786 787
		}
	}
J
Junio C Hamano 已提交
788 789
	else if (all_heads + all_remotes)
		snarf_refs(all_heads, all_remotes);
790 791 792 793 794
	else {
		while (0 < ac) {
			append_one_rev(*av);
			ac--; av++;
		}
795
	}
J
Junio C Hamano 已提交
796

797
	head_p = resolve_ref("HEAD", head_sha1, 1, NULL);
L
Linus Torvalds 已提交
798 799 800
	if (head_p) {
		head_len = strlen(head_p);
		memcpy(head, head_p, head_len + 1);
801 802
	}
	else {
L
Linus Torvalds 已提交
803 804
		head_len = 0;
		head[0] = 0;
805 806
	}

L
Linus Torvalds 已提交
807
	if (with_current_branch && head_p) {
808 809 810 811 812
		int has_head = 0;
		for (i = 0; !has_head && i < ref_name_cnt; i++) {
			/* We are only interested in adding the branch
			 * HEAD points at.
			 */
L
Linus Torvalds 已提交
813 814
			if (rev_is_head(head,
					head_len,
815 816 817 818 819
					ref_name[i],
					head_sha1, NULL))
				has_head++;
		}
		if (!has_head) {
820 821
			int offset = !prefixcmp(head, "refs/heads/") ? 11 : 0;
			append_one_rev(head + offset);
822 823 824
		}
	}

825 826 827 828
	if (!ref_name_cnt) {
		fprintf(stderr, "No revs to be shown.\n");
		exit(0);
	}
J
Junio C Hamano 已提交
829 830 831

	for (num_rev = 0; ref_name[num_rev]; num_rev++) {
		unsigned char revkey[20];
832
		unsigned int flag = 1u << (num_rev + REV_SHIFT);
J
Junio C Hamano 已提交
833 834 835 836

		if (MAX_REVS <= num_rev)
			die("cannot handle more than %d revs.", MAX_REVS);
		if (get_sha1(ref_name[num_rev], revkey))
A
Alex Riesen 已提交
837
			die("'%s' is not a valid ref.", ref_name[num_rev]);
J
Junio C Hamano 已提交
838 839 840 841 842 843 844 845 846 847 848
		commit = lookup_commit_reference(revkey);
		if (!commit)
			die("cannot find commit %s (%s)",
			    ref_name[num_rev], revkey);
		parse_commit(commit);
		mark_seen(commit, &seen);

		/* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
		 * and so on.  REV_SHIFT bits from bit 0 are used for
		 * internal bookkeeping.
		 */
849 850
		commit->object.flags |= flag;
		if (commit->object.flags == flag)
851
			commit_list_insert_by_date(commit, &list);
J
Junio C Hamano 已提交
852 853
		rev[num_rev] = commit;
	}
854 855 856 857 858
	for (i = 0; i < num_rev; i++)
		rev_mask[i] = rev[i]->object.flags;

	if (0 <= extra)
		join_revs(&list, &seen, num_rev, extra);
J
Junio C Hamano 已提交
859

860
	commit_list_sort_by_date(&seen);
861

J
Junio C Hamano 已提交
862 863 864
	if (merge_base)
		return show_merge_base(seen, num_rev);

865 866 867 868
	if (independent)
		return show_independent(rev, num_rev, ref_name, rev_mask);

	/* Show list; --more=-1 means list-only */
869
	if (1 < num_rev || extra < 0) {
J
Junio C Hamano 已提交
870 871
		for (i = 0; i < num_rev; i++) {
			int j;
L
Linus Torvalds 已提交
872 873
			int is_head = rev_is_head(head,
						  head_len,
J
Junio C Hamano 已提交
874 875 876
						  ref_name[i],
						  head_sha1,
						  rev[i]->object.sha1);
877 878 879 880 881 882
			if (extra < 0)
				printf("%c [%s] ",
				       is_head ? '*' : ' ', ref_name[i]);
			else {
				for (j = 0; j < i; j++)
					putchar(' ');
883
				printf("%s%c%s [%s] ",
884
				       get_color_code(i),
885 886
				       is_head ? '*' : '!',
				       get_color_reset_code(), ref_name[i]);
887
			}
888 889 890 891 892 893 894 895

			if (!reflog) {
				/* header lines never need name */
				show_one_commit(rev[i], 1);
			}
			else
				puts(reflog_msg[i]);

896 897
			if (is_head)
				head_at = i;
J
Junio C Hamano 已提交
898
		}
899 900 901 902 903
		if (0 <= extra) {
			for (i = 0; i < num_rev; i++)
				putchar('-');
			putchar('\n');
		}
904
	}
905 906
	if (extra < 0)
		exit(0);
907

J
Junio C Hamano 已提交
908
	/* Sort topologically */
909
	sort_in_topological_order(&seen, lifo);
J
Junio C Hamano 已提交
910 911

	/* Give names to commits */
912 913
	if (!sha1_name && !no_name)
		name_commits(seen, rev, ref_name, num_rev);
J
Junio C Hamano 已提交
914 915 916 917

	all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
	all_revs = all_mask & ~((1u << REV_SHIFT) - 1);

J
Junio C Hamano 已提交
918 919 920
	while (seen) {
		struct commit *commit = pop_one_commit(&seen);
		int this_flag = commit->object.flags;
921
		int is_merge_point = ((this_flag & all_revs) == all_revs);
922

923
		shown_merge_point |= is_merge_point;
J
Junio C Hamano 已提交
924

925
		if (1 < num_rev) {
926 927
			int is_merge = !!(commit->parents &&
					  commit->parents->next);
928 929 930 931
			if (topics &&
			    !is_merge_point &&
			    (this_flag & (1u << REV_SHIFT)))
				continue;
932 933 934
			if (dense && is_merge &&
			    omit_in_dense(commit, rev, num_rev))
				continue;
935 936 937 938 939 940 941 942 943 944
			for (i = 0; i < num_rev; i++) {
				int mark;
				if (!(this_flag & (1u << (i + REV_SHIFT))))
					mark = ' ';
				else if (is_merge)
					mark = '-';
				else if (i == head_at)
					mark = '*';
				else
					mark = '+';
945
				printf("%s%c%s",
946
				       get_color_code(i),
947
				       mark, get_color_reset_code());
948
			}
949 950
			putchar(' ');
		}
951
		show_one_commit(commit, no_name);
952 953 954

		if (shown_merge_point && --extra < 0)
			break;
J
Junio C Hamano 已提交
955 956 957
	}
	return 0;
}