show-branch.c 16.5 KB
Newer Older
J
Junio C Hamano 已提交
1
#include <stdlib.h>
2
#include <fnmatch.h>
J
Junio C Hamano 已提交
3 4 5 6 7
#include "cache.h"
#include "commit.h"
#include "refs.h"

static const char show_branch_usage[] =
8
"git-show-branch [--all] [--heads] [--tags] [--topo-order] [--more=count | --list | --independent | --merge-base ] [<refs>...]";
J
Junio C Hamano 已提交
9

10 11 12 13
static int default_num = 0;
static int default_alloc = 0;
static char **default_arg = NULL;

J
Junio C Hamano 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#define UNINTERESTING	01

#define REV_SHIFT	 2
#define MAX_REVS	29 /* should not exceed bits_per_int - REV_SHIFT */

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 已提交
43 44
	const char *head_name; /* which head's ancestor? */
	int generation; /* how many parents away from head_name */
J
Junio C Hamano 已提交
45 46
};

J
Junio C Hamano 已提交
47
/* Name the commit as nth generation ancestor of head_name;
J
Junio C Hamano 已提交
48 49
 * we count only the first-parent relationship for naming purposes.
 */
J
Junio C Hamano 已提交
50
static void name_commit(struct commit *commit, const char *head_name, int nth)
J
Junio C Hamano 已提交
51 52 53 54 55
{
	struct commit_name *name;
	if (!commit->object.util)
		commit->object.util = xmalloc(sizeof(struct commit_name));
	name = commit->object.util;
J
Junio C Hamano 已提交
56
	name->head_name = head_name;
J
Junio C Hamano 已提交
57 58 59 60
	name->generation = nth;
}

/* Parent is the first parent of the commit.  We may name it
J
Junio C Hamano 已提交
61
 * as (n+1)th generation ancestor of the same head_name as
J
Junio C Hamano 已提交
62
 * commit is nth generation ancestor of, if that generation
J
Junio C Hamano 已提交
63 64 65 66 67 68 69 70 71 72
 * number is better than the name it already has.
 */
static void name_parent(struct commit *commit, struct commit *parent)
{
	struct commit_name *commit_name = commit->object.util;
	struct commit_name *parent_name = parent->object.util;
	if (!commit_name)
		return;
	if (!parent_name ||
	    commit_name->generation + 1 < parent_name->generation)
J
Junio C Hamano 已提交
73
		name_commit(parent, commit_name->head_name,
J
Junio C Hamano 已提交
74 75 76
			    commit_name->generation + 1);
}

J
Junio C Hamano 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
static int name_first_parent_chain(struct commit *c)
{
	int i = 0;
	while (c) {
		struct commit *p;
		if (!c->object.util)
			break;
		if (!c->parents)
			break;
		p = c->parents->item;
		if (!p->object.util) {
			name_parent(c, p);
			i++;
		}
		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;
		if (c->object.util)
			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;
			if (!c->object.util)
				continue;
			n = c->object.util;
			parents = c->parents;
			nth = 0;
			while (parents) {
				struct commit *p = parents->item;
141
				char newname[1000], *en;
J
Junio C Hamano 已提交
142 143 144 145
				parents = parents->next;
				nth++;
				if (p->object.util)
					continue;
146
				en = newname;
147 148
				switch (n->generation) {
				case 0:
149
					en += sprintf(en, "%s", n->head_name);
150 151
					break;
				case 1:
152
					en += sprintf(en, "%s^", n->head_name);
153 154
					break;
				default:
155 156 157
					en += sprintf(en, "%s~%d",
						n->head_name, n->generation);
					break;
158
				}
159 160 161 162
				if (nth == 1)
					en += sprintf(en, "^");
				else
					en += sprintf(en, "^%d", nth);
J
Junio C Hamano 已提交
163 164 165 166 167 168 169 170
				name_commit(p, strdup(newname), 0);
				i++;
				name_first_parent_chain(p);
			}
		}
	} while (i);
}

J
Junio C Hamano 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
	if (!commit->object.flags) {
		insert_by_date(commit, seen_p);
		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;
189
		int still_interesting = !!interesting(*list_p);
J
Junio C Hamano 已提交
190 191 192
		struct commit *commit = pop_one_commit(list_p);
		int flags = commit->object.flags & all_mask;

193
		if (!still_interesting && extra <= 0)
J
Junio C Hamano 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206
			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;
207 208
			if (!p->object.parsed)
				parse_commit(p);
J
Junio C Hamano 已提交
209 210 211 212 213 214
			if (mark_seen(p, seen_p) && !still_interesting)
				extra--;
			p->object.flags |= flags;
			insert_by_date(p, list_p);
		}
	}
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

	/*
	 * Postprocess to complete well-poisoning.
	 *
	 * At this point we have all the commits we have seen in
	 * seen_p list (which happens to be sorted chronologically but
	 * it does not really matter).  Mark anything that can be
	 * reached from uninteresting commits not interesting.
	 */
	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 已提交
254 255
}

256
static void show_one_commit(struct commit *commit, int no_name)
J
Junio C Hamano 已提交
257
{
258
	char pretty[256], *cp;
J
Junio C Hamano 已提交
259
	struct commit_name *name = commit->object.util;
260 261 262 263 264
	if (commit->object.parsed)
		pretty_print_commit(CMIT_FMT_ONELINE, commit->buffer, ~0,
				    pretty, sizeof(pretty));
	else
		strcpy(pretty, "(unavailable)");
J
Junio C Hamano 已提交
265 266 267 268
	if (!strncmp(pretty, "[PATCH] ", 8))
		cp = pretty + 8;
	else
		cp = pretty;
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

	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] ",
			       find_unique_abbrev(commit->object.sha1, 7));
J
Junio C Hamano 已提交
284 285 286 287 288 289 290
	}
	puts(cp);
}

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

J
Junio C Hamano 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
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;
	}
}

335 336 337
static int compare_ref_name(const void *a_, const void *b_)
{
	const char * const*a = a_, * const*b = b_;
J
Junio C Hamano 已提交
338
	return version_cmp(*a, *b);
339 340 341 342 343 344 345 346
}

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

J
Junio C Hamano 已提交
347 348 349
static int append_ref(const char *refname, const unsigned char *sha1)
{
	struct commit *commit = lookup_commit_reference_gently(sha1, 1);
J
Junio C Hamano 已提交
350 351
	int i;

J
Junio C Hamano 已提交
352 353
	if (!commit)
		return 0;
J
Junio C Hamano 已提交
354 355 356 357 358
	/* Avoid adding the same thing twice */
	for (i = 0; i < ref_name_cnt; i++)
		if (!strcmp(refname, ref_name[i]))
			return 0;

359
	if (MAX_REVS <= ref_name_cnt) {
J
Junio C Hamano 已提交
360
		fprintf(stderr, "warning: ignoring %s; "
A
Alex Riesen 已提交
361
			"cannot handle more than %d refs\n",
J
Junio C Hamano 已提交
362 363 364 365 366 367 368 369 370 371
			refname, MAX_REVS);
		return 0;
	}
	ref_name[ref_name_cnt++] = strdup(refname);
	ref_name[ref_name_cnt] = NULL;
	return 0;
}

static int append_head_ref(const char *refname, const unsigned char *sha1)
{
372 373 374
	unsigned char tmp[20];
	int ofs = 11;
	if (strncmp(refname, "refs/heads/", ofs))
J
Junio C Hamano 已提交
375
		return 0;
376 377 378 379 380 381
	/* If both heads/foo and tags/foo exists, get_sha1 would
	 * get confused.
	 */
	if (get_sha1(refname + ofs, tmp) || memcmp(tmp, sha1, 20))
		ofs = 5;
	return append_ref(refname + ofs, sha1);
J
Junio C Hamano 已提交
382 383 384 385 386 387 388 389 390
}

static int append_tag_ref(const char *refname, const unsigned char *sha1)
{
	if (strncmp(refname, "refs/tags/", 10))
		return 0;
	return append_ref(refname + 5, sha1);
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
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;
}

static int append_matching_ref(const char *refname, const unsigned char *sha1)
{
	/* 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;
	if (!strncmp("refs/heads/", refname, 11))
		return append_head_ref(refname, sha1);
	if (!strncmp("refs/tags/", refname, 10))
		return append_tag_ref(refname, sha1);
	return append_ref(refname, sha1);
}

J
Junio C Hamano 已提交
424 425
static void snarf_refs(int head, int tag)
{
426 427
	if (head) {
		int orig_cnt = ref_name_cnt;
J
Junio C Hamano 已提交
428
		for_each_ref(append_head_ref);
429 430 431 432
		sort_ref_range(orig_cnt, ref_name_cnt);
	}
	if (tag) {
		int orig_cnt = ref_name_cnt;
J
Junio C Hamano 已提交
433
		for_each_ref(append_tag_ref);
434 435
		sort_ref_range(orig_cnt, ref_name_cnt);
	}
J
Junio C Hamano 已提交
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
}

static int rev_is_head(char *head_path, int headlen,
		       char *name,
		       unsigned char *head_sha1, unsigned char *sha1)
{
	int namelen;
	if ((!head_path[0]) || memcmp(head_sha1, sha1, 20))
		return 0;
	namelen = strlen(name);
	if ((headlen < namelen) ||
	    memcmp(head_path + headlen - namelen, name, namelen))
		return 0;
	if (headlen == namelen ||
	    head_path[headlen - namelen - 1] == '/')
		return 1;
	return 0;
}

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);
459
	int exit_status = 1;
J
Junio C Hamano 已提交
460 461 462 463 464 465 466

	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));
467 468
			exit_status = 0;
			commit->object.flags |= UNINTERESTING;
J
Junio C Hamano 已提交
469 470
		}
	}
471
	return exit_status;
J
Junio C Hamano 已提交
472 473
}

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
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;
}

492 493 494 495 496 497 498
static void append_one_rev(const char *av)
{
	unsigned char revkey[20];
	if (!get_sha1(av, revkey)) {
		append_ref(av, revkey);
		return;
	}
499
	if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
500 501 502 503 504 505 506 507
		/* glob style match */
		int saved_matches = ref_name_cnt;
		match_ref_pattern = av;
		match_ref_slash = count_slash(av);
		for_each_ref(append_matching_ref);
		if (saved_matches == ref_name_cnt &&
		    ref_name_cnt < MAX_REVS)
			error("no matching refs with %s", av);
508 509
		if (saved_matches + 1 < ref_name_cnt)
			sort_ref_range(saved_matches, ref_name_cnt);
510 511 512 513 514
		return;
	}
	die("bad sha1 reference %s", av);
}

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
static int git_show_branch_config(const char *var, const char *value)
{
	if (!strcmp(var, "showbranch.default")) {
		if (default_alloc <= default_num + 1) {
			default_alloc = default_alloc * 3 / 2 + 20;
			default_arg = xrealloc(default_arg, sizeof *default_arg * default_alloc);
		}
		default_arg[default_num++] = strdup(value);
		default_arg[default_num] = NULL;
		return 0;
	}

	return git_default_config(var, value);
}

J
Junio C Hamano 已提交
530 531 532 533
int main(int ac, char **av)
{
	struct commit *rev[MAX_REVS], *commit;
	struct commit_list *list = NULL, *seen = NULL;
534
	unsigned int rev_mask[MAX_REVS];
J
Junio C Hamano 已提交
535 536
	int num_rev, i, extra = 0;
	int all_heads = 0, all_tags = 0;
537
	int all_mask, all_revs;
J
Junio C Hamano 已提交
538
	char head_path[128];
J
Junio C Hamano 已提交
539
	const char *head_path_p;
J
Junio C Hamano 已提交
540 541 542
	int head_path_len;
	unsigned char head_sha1[20];
	int merge_base = 0;
543
	int independent = 0;
544 545
	int no_name = 0;
	int sha1_name = 0;
546 547
	int shown_merge_point = 0;
	int topo_order = 0;
J
Junio C Hamano 已提交
548

549
	git_config(git_show_branch_config);
550 551
	setup_git_directory();

552 553 554 555 556 557
	/* If nothing is specified, try the default first */
	if (ac == 1 && default_num) {
		ac = default_num + 1;
		av = default_arg - 1; /* ick; we would not address av[0] */
	}

J
Junio C Hamano 已提交
558 559
	while (1 < ac && av[1][0] == '-') {
		char *arg = av[1];
560 561 562 563 564
		if (!strcmp(arg, "--")) {
			ac--; av++;
			break;
		}
		else if (!strcmp(arg, "--all"))
J
Junio C Hamano 已提交
565 566 567 568 569 570 571
			all_heads = all_tags = 1;
		else if (!strcmp(arg, "--heads"))
			all_heads = 1;
		else if (!strcmp(arg, "--tags"))
			all_tags = 1;
		else if (!strcmp(arg, "--more"))
			extra = 1;
572 573
		else if (!strcmp(arg, "--list"))
			extra = -1;
574 575 576 577
		else if (!strcmp(arg, "--no-name"))
			no_name = 1;
		else if (!strcmp(arg, "--sha1-name"))
			sha1_name = 1;
578
		else if (!strncmp(arg, "--more=", 7))
J
Junio C Hamano 已提交
579 580 581
			extra = atoi(arg + 7);
		else if (!strcmp(arg, "--merge-base"))
			merge_base = 1;
582 583
		else if (!strcmp(arg, "--independent"))
			independent = 1;
584 585
		else if (!strcmp(arg, "--topo-order"))
			topo_order = 1;
J
Junio C Hamano 已提交
586 587 588 589 590 591
		else
			usage(show_branch_usage);
		ac--; av++;
	}
	ac--; av++;

592 593 594 595
	/* Only one of these is allowed */
	if (1 < independent + merge_base + (extra != 0))
		usage(show_branch_usage);

J
Junio C Hamano 已提交
596 597 598 599
	/* If nothing is specified, show all branches by default */
	if (ac + all_heads + all_tags == 0)
		all_heads = 1;

J
Junio C Hamano 已提交
600 601
	if (all_heads + all_tags)
		snarf_refs(all_heads, all_tags);
J
Junio C Hamano 已提交
602 603 604
	while (0 < ac) {
		append_one_rev(*av);
		ac--; av++;
605
	}
J
Junio C Hamano 已提交
606

607 608 609 610
	if (!ref_name_cnt) {
		fprintf(stderr, "No revs to be shown.\n");
		exit(0);
	}
J
Junio C Hamano 已提交
611 612 613

	for (num_rev = 0; ref_name[num_rev]; num_rev++) {
		unsigned char revkey[20];
614
		unsigned int flag = 1u << (num_rev + REV_SHIFT);
J
Junio C Hamano 已提交
615 616 617 618

		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 已提交
619
			die("'%s' is not a valid ref.", ref_name[num_rev]);
J
Junio C Hamano 已提交
620 621 622 623 624 625 626 627 628 629 630
		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.
		 */
631 632 633
		commit->object.flags |= flag;
		if (commit->object.flags == flag)
			insert_by_date(commit, &list);
J
Junio C Hamano 已提交
634 635
		rev[num_rev] = commit;
	}
636 637 638 639 640
	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 已提交
641

J
Junio C Hamano 已提交
642 643 644 645 646 647 648
	head_path_p = resolve_ref(git_path("HEAD"), head_sha1, 1);
	if (head_path_p) {
		head_path_len = strlen(head_path_p);
		memcpy(head_path, head_path_p, head_path_len + 1);
	}
	else {
		head_path_len = 0;
J
Junio C Hamano 已提交
649
		head_path[0] = 0;
J
Junio C Hamano 已提交
650
	}
J
Junio C Hamano 已提交
651 652 653 654

	if (merge_base)
		return show_merge_base(seen, num_rev);

655 656 657 658
	if (independent)
		return show_independent(rev, num_rev, ref_name, rev_mask);

	/* Show list; --more=-1 means list-only */
659
	if (1 < num_rev || extra < 0) {
J
Junio C Hamano 已提交
660 661 662 663 664 665 666
		for (i = 0; i < num_rev; i++) {
			int j;
			int is_head = rev_is_head(head_path,
						  head_path_len,
						  ref_name[i],
						  head_sha1,
						  rev[i]->object.sha1);
667 668 669 670 671 672 673 674 675
			if (extra < 0)
				printf("%c [%s] ",
				       is_head ? '*' : ' ', ref_name[i]);
			else {
				for (j = 0; j < i; j++)
					putchar(' ');
				printf("%c [%s] ",
				       is_head ? '*' : '!', ref_name[i]);
			}
676 677
			/* header lines never need name */
			show_one_commit(rev[i], 1);
J
Junio C Hamano 已提交
678
		}
679 680 681 682 683
		if (0 <= extra) {
			for (i = 0; i < num_rev; i++)
				putchar('-');
			putchar('\n');
		}
684
	}
685 686
	if (extra < 0)
		exit(0);
687

J
Junio C Hamano 已提交
688
	/* Sort topologically */
689 690
	if (topo_order)
		sort_in_topological_order(&seen);
J
Junio C Hamano 已提交
691 692

	/* Give names to commits */
693 694
	if (!sha1_name && !no_name)
		name_commits(seen, rev, ref_name, num_rev);
J
Junio C Hamano 已提交
695 696 697 698

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

J
Junio C Hamano 已提交
699 700 701
	while (seen) {
		struct commit *commit = pop_one_commit(&seen);
		int this_flag = commit->object.flags;
702

703
		shown_merge_point |= ((this_flag & all_revs) == all_revs);
J
Junio C Hamano 已提交
704

705 706 707 708 709 710
		if (1 < num_rev) {
			for (i = 0; i < num_rev; i++)
				putchar((this_flag & (1u << (i + REV_SHIFT)))
					? '+' : ' ');
			putchar(' ');
		}
711
		show_one_commit(commit, no_name);
712 713 714

		if (shown_merge_point && --extra < 0)
			break;
J
Junio C Hamano 已提交
715 716 717
	}
	return 0;
}