show-branch.c 22.9 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 10
    N_("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>)...]"),
    N_("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
static const char *get_color_code(int idx)
{
29
	if (want_color(showbranch_use_color))
30
		return column_colors_ansi[idx % column_colors_ansi_max];
31 32 33 34 35
	return "";
}

static const char *get_color_reset_code(void)
{
36
	if (want_color(showbranch_use_color))
37 38 39 40
		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
				struct strbuf newname = STRBUF_INIT;
J
Junio C Hamano 已提交
166 167
				parents = parents->next;
				nth++;
168
				if (p->util)
J
Junio C Hamano 已提交
169
					continue;
170 171
				switch (n->generation) {
				case 0:
172
					strbuf_addstr(&newname, n->head_name);
173 174
					break;
				case 1:
175
					strbuf_addf(&newname, "%s^", n->head_name);
176 177
					break;
				default:
178 179
					strbuf_addf(&newname, "%s~%d",
						    n->head_name, n->generation);
180
					break;
181
				}
182
				if (nth == 1)
183
					strbuf_addch(&newname, '^');
184
				else
185 186
					strbuf_addf(&newname, "^%d", nth);
				name_commit(p, strbuf_detach(&newname, NULL), 0);
J
Junio C Hamano 已提交
187 188 189 190 191 192 193
				i++;
				name_first_parent_chain(p);
			}
		}
	} while (i);
}

J
Junio C Hamano 已提交
194 195 196
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
	if (!commit->object.flags) {
197
		commit_list_insert(commit, seen_p);
J
Junio C Hamano 已提交
198 199 200 201 202 203 204 205 206 207 208 209 210 211
		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;
212
		int still_interesting = !!interesting(*list_p);
J
Junio C Hamano 已提交
213 214 215
		struct commit *commit = pop_one_commit(list_p);
		int flags = commit->object.flags & all_mask;

216
		if (!still_interesting && extra <= 0)
J
Junio C Hamano 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229
			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;
230 231
			if (!p->object.parsed)
				parse_commit(p);
J
Junio C Hamano 已提交
232 233 234
			if (mark_seen(p, seen_p) && !still_interesting)
				extra--;
			p->object.flags |= flags;
235
			commit_list_insert_by_date(p, list_p);
J
Junio C Hamano 已提交
236 237
		}
	}
238 239 240 241 242

	/*
	 * Postprocess to complete well-poisoning.
	 *
	 * At this point we have all the commits we have seen in
243 244
	 * seen_p list.  Mark anything that can be reached from
	 * uninteresting commits not interesting.
245 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
	 */
	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 已提交
276 277
}

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

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

	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] ",
304 305
			       find_unique_abbrev(commit->object.sha1,
						  DEFAULT_ABBREV));
J
Junio C Hamano 已提交
306
	}
307
	puts(pretty_str);
308
	strbuf_release(&pretty);
J
Junio C Hamano 已提交
309 310 311 312 313
}

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

J
Junio C Hamano 已提交
314 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
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;
	}
}

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

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

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

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

379 380 381 382 383 384
	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;
	}
385
	if (MAX_REVS <= ref_name_cnt) {
386
		warning("ignoring %s; cannot handle more than %d refs",
J
Junio C Hamano 已提交
387 388 389
			refname, MAX_REVS);
		return 0;
	}
390
	ref_name[ref_name_cnt++] = xstrdup(refname);
J
Junio C Hamano 已提交
391 392 393 394
	ref_name[ref_name_cnt] = NULL;
	return 0;
}

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

409 410 411 412
static int append_remote_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
	unsigned char tmp[20];
	int ofs = 13;
413
	if (prefixcmp(refname, "refs/remotes/"))
414 415 416 417 418 419
		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;
420
	return append_ref(refname + ofs, sha1, 0);
421 422
}

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

430 431 432 433 434 435 436 437 438 439 440
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;
}

441
static int append_matching_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
442 443 444 445 446 447 448 449 450 451 452 453 454 455
{
	/* 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;
456
	if (!prefixcmp(refname, "refs/heads/"))
457
		return append_head_ref(refname, sha1, flag, cb_data);
458
	if (!prefixcmp(refname, "refs/tags/"))
459
		return append_tag_ref(refname, sha1, flag, cb_data);
460
	return append_ref(refname, sha1, 0);
461 462
}

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

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

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);
496
	int exit_status = 1;
J
Junio C Hamano 已提交
497 498 499 500 501 502 503

	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));
504 505
			exit_status = 0;
			commit->object.flags |= UNINTERESTING;
J
Junio C Hamano 已提交
506 507
		}
	}
508
	return exit_status;
J
Junio C Hamano 已提交
509 510
}

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
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;
}

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

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

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

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

582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
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;
}

603 604 605 606
static int reflog = 0;

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

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

687
	git_config(git_show_branch_config, NULL);
688

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

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

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

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

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

		if (ac == 0) {
			static const char *fake_av[2];
730

731
			fake_av[0] = resolve_refdup("HEAD", sha1, 1, NULL);
J
Junio C Hamano 已提交
732 733 734 735
			fake_av[1] = NULL;
			av = fake_av;
			ac = 1;
		}
736
		if (ac != 1)
737
			die("--reflog option needs one branch name");
J
Junio C Hamano 已提交
738

739 740 741
		if (MAX_REVS < reflog)
			die("Only %d entries can be shown at one time.",
			    MAX_REVS);
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
		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);
			}
		}

758
		for (i = 0; i < reflog; i++) {
759 760
			char *logmsg, *m;
			const char *msg;
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
			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",
776
				show_date(timestamp, tz, 1),
777 778 779 780 781
				msg);
			reflog_msg[i] = m;
			free(logmsg);
			sprintf(nth_desc, "%s@{%d}", *av, base+i);
			append_ref(nth_desc, sha1, 1);
782 783
		}
	}
J
Junio C Hamano 已提交
784 785
	else if (all_heads + all_remotes)
		snarf_refs(all_heads, all_remotes);
786 787 788 789 790
	else {
		while (0 < ac) {
			append_one_rev(*av);
			ac--; av++;
		}
791
	}
J
Junio C Hamano 已提交
792

793
	head_p = resolve_ref_unsafe("HEAD", head_sha1, 1, NULL);
L
Linus Torvalds 已提交
794 795 796
	if (head_p) {
		head_len = strlen(head_p);
		memcpy(head, head_p, head_len + 1);
797 798
	}
	else {
L
Linus Torvalds 已提交
799 800
		head_len = 0;
		head[0] = 0;
801 802
	}

L
Linus Torvalds 已提交
803
	if (with_current_branch && head_p) {
804 805 806 807 808
		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 已提交
809 810
			if (rev_is_head(head,
					head_len,
811 812 813 814 815
					ref_name[i],
					head_sha1, NULL))
				has_head++;
		}
		if (!has_head) {
816 817
			int offset = !prefixcmp(head, "refs/heads/") ? 11 : 0;
			append_one_rev(head + offset);
818 819 820
		}
	}

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

	for (num_rev = 0; ref_name[num_rev]; num_rev++) {
		unsigned char revkey[20];
828
		unsigned int flag = 1u << (num_rev + REV_SHIFT);
J
Junio C Hamano 已提交
829 830 831 832

		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 已提交
833
			die("'%s' is not a valid ref.", ref_name[num_rev]);
J
Junio C Hamano 已提交
834 835 836 837 838 839 840 841 842 843 844
		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.
		 */
845 846
		commit->object.flags |= flag;
		if (commit->object.flags == flag)
847
			commit_list_insert_by_date(commit, &list);
J
Junio C Hamano 已提交
848 849
		rev[num_rev] = commit;
	}
850 851 852 853 854
	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 已提交
855

856
	commit_list_sort_by_date(&seen);
857

J
Junio C Hamano 已提交
858 859 860
	if (merge_base)
		return show_merge_base(seen, num_rev);

861 862 863 864
	if (independent)
		return show_independent(rev, num_rev, ref_name, rev_mask);

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

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

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

J
Junio C Hamano 已提交
904
	/* Sort topologically */
J
Junio C Hamano 已提交
905
	sort_in_topological_order(&seen, sort_order);
J
Junio C Hamano 已提交
906 907

	/* Give names to commits */
908 909
	if (!sha1_name && !no_name)
		name_commits(seen, rev, ref_name, num_rev);
J
Junio C Hamano 已提交
910 911 912 913

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

J
Junio C Hamano 已提交
914 915 916
	while (seen) {
		struct commit *commit = pop_one_commit(&seen);
		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;
J
Junio C Hamano 已提交
920

921
		if (1 < num_rev) {
922 923
			int is_merge = !!(commit->parents &&
					  commit->parents->next);
924 925 926 927
			if (topics &&
			    !is_merge_point &&
			    (this_flag & (1u << REV_SHIFT)))
				continue;
928 929 930
			if (dense && is_merge &&
			    omit_in_dense(commit, rev, num_rev))
				continue;
931 932 933 934 935 936 937 938 939 940
			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 = '+';
941
				printf("%s%c%s",
942
				       get_color_code(i),
943
				       mark, get_color_reset_code());
944
			}
945 946
			putchar(' ');
		}
947
		show_one_commit(commit, no_name);
948 949 950

		if (shown_merge_point && --extra < 0)
			break;
J
Junio C Hamano 已提交
951 952 953
	}
	return 0;
}