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
			parse_commit(p);
J
Junio C Hamano 已提交
231 232 233
			if (mark_seen(p, seen_p) && !still_interesting)
				extra--;
			p->object.flags |= flags;
234
			commit_list_insert_by_date(p, list_p);
J
Junio C Hamano 已提交
235 236
		}
	}
237 238 239 240 241

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

602 603 604 605
static int reflog = 0;

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

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

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

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

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

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

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

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

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

759
		for (i = 0; i < reflog; i++) {
760
			char *logmsg;
761
			char *nth_desc;
762
			const char *msg;
763 764 765
			unsigned long timestamp;
			int tz;

766
			if (read_ref_at(ref, flags, 0, base+i, sha1, &logmsg,
767 768 769 770 771 772 773 774 775
					&timestamp, &tz, NULL)) {
				reflog = i;
				break;
			}
			msg = strchr(logmsg, '\t');
			if (!msg)
				msg = "(none)";
			else
				msg++;
776 777 778
			reflog_msg[i] = xstrfmt("(%s) %s",
						show_date(timestamp, tz, 1),
						msg);
779
			free(logmsg);
780 781

			nth_desc = xstrfmt("%s@{%d}", *av, base+i);
782
			append_ref(nth_desc, sha1, 1);
783
			free(nth_desc);
784
		}
J
Jeff King 已提交
785
		free(ref);
786
	}
J
Junio C Hamano 已提交
787 788
	else if (all_heads + all_remotes)
		snarf_refs(all_heads, all_remotes);
789 790 791 792 793
	else {
		while (0 < ac) {
			append_one_rev(*av);
			ac--; av++;
		}
794
	}
J
Junio C Hamano 已提交
795

796 797
	head_p = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
				    head_sha1, 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
			int offset = starts_with(head, "refs/heads/") ? 11 : 0;
821
			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 */
J
Junio C Hamano 已提交
909
	sort_in_topological_order(&seen, sort_order);
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;
}