builtin-log.c 34.2 KB
Newer Older
1 2 3 4 5 6 7
/*
 * Builtin "git log" and related commands (show, whatchanged)
 *
 * (C) Copyright 2006 Linus Torvalds
 *		 2006 Junio Hamano
 */
#include "cache.h"
8
#include "color.h"
9 10 11 12
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "log-tree.h"
13
#include "builtin.h"
14
#include "tag.h"
L
Linus Torvalds 已提交
15
#include "reflog-walk.h"
16
#include "patch-ids.h"
17
#include "run-command.h"
18
#include "shortlog.h"
19
#include "remote.h"
20
#include "string-list.h"
21
#include "parse-options.h"
22

H
Heikki Orsila 已提交
23 24 25
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;

26
static int default_show_root = 1;
27
static const char *fmt_patch_subject_prefix = "PATCH";
28
static const char *fmt_pretty;
29

30 31 32 33
static const char * const builtin_log_usage =
	"git log [<options>] [<since>..<until>] [[--] <path>...]\n"
	"   or: git show [options] <object>...";

34
static void cmd_log_init(int argc, const char **argv, const char *prefix,
35 36
		      struct rev_info *rev)
{
J
Junio C Hamano 已提交
37
	int i;
38
	int decoration_style = 0;
J
Junio C Hamano 已提交
39

40 41
	rev->abbrev = DEFAULT_ABBREV;
	rev->commit_format = CMIT_FMT_DEFAULT;
42
	if (fmt_pretty)
43
		get_commit_format(fmt_pretty, rev);
44
	rev->verbose_header = 1;
45
	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
46
	rev->show_root_diff = default_show_root;
47
	rev->subject_prefix = fmt_patch_subject_prefix;
J
Jeff King 已提交
48
	DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
H
Heikki Orsila 已提交
49 50 51 52

	if (default_date_mode)
		rev->date_mode = parse_date_format(default_date_mode);

53
	argc = setup_revisions(argc, argv, rev, "HEAD");
H
Heikki Orsila 已提交
54

55 56
	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
57
	if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
58 59 60 61
		rev->always_show_header = 0;
		if (rev->diffopt.nr_paths != 1)
			usage("git logs can only follow renames on one pathname at a time");
	}
J
Junio C Hamano 已提交
62 63
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];
64
		if (!strcmp(arg, "--decorate")) {
65 66 67 68 69 70 71 72 73
			decoration_style = DECORATE_SHORT_REFS;
		} else if (!prefixcmp(arg, "--decorate=")) {
			const char *v = skip_prefix(arg, "--decorate=");
			if (!strcmp(v, "full"))
				decoration_style = DECORATE_FULL_REFS;
			else if (!strcmp(v, "short"))
				decoration_style = DECORATE_SHORT_REFS;
			else
				die("invalid --decorate option: %s", arg);
74 75
		} else if (!strcmp(arg, "--source")) {
			rev->show_source = 1;
76 77
		} else if (!strcmp(arg, "-h")) {
			usage(builtin_log_usage);
78
		} else
J
Junio C Hamano 已提交
79 80
			die("unrecognized argument: %s", arg);
	}
81 82 83 84
	if (decoration_style) {
		rev->show_decorations = 1;
		load_ref_decorations(decoration_style);
	}
85 86
}

L
Linus Torvalds 已提交
87 88 89 90 91 92 93 94 95 96 97 98
/*
 * This gives a rough estimate for how many commits we
 * will print out in the list.
 */
static int estimate_commit_count(struct rev_info *rev, struct commit_list *list)
{
	int n = 0;

	while (list) {
		struct commit *commit = list->item;
		unsigned int flags = commit->object.flags;
		list = list->next;
99
		if (!(flags & (TREESAME | UNINTERESTING)))
L
Linus Torvalds 已提交
100
			n++;
L
Linus Torvalds 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114
	}
	return n;
}

static void show_early_header(struct rev_info *rev, const char *stage, int nr)
{
	if (rev->shown_one) {
		rev->shown_one = 0;
		if (rev->commit_format != CMIT_FMT_ONELINE)
			putchar(rev->diffopt.line_termination);
	}
	printf("Final output: %d %s\n", nr, stage);
}

115
static struct itimerval early_output_timer;
L
Linus Torvalds 已提交
116

117 118 119
static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
	int i = revs->early_output;
L
Linus Torvalds 已提交
120
	int show_header = 1;
121 122 123 124

	sort_in_topological_order(&list, revs->lifo);
	while (list && i) {
		struct commit *commit = list->item;
L
Linus Torvalds 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
		switch (simplify_commit(revs, commit)) {
		case commit_show:
			if (show_header) {
				int n = estimate_commit_count(revs, list);
				show_early_header(revs, "incomplete", n);
				show_header = 0;
			}
			log_tree_commit(revs, commit);
			i--;
			break;
		case commit_ignore:
			break;
		case commit_error:
			return;
		}
140 141
		list = list->next;
	}
L
Linus Torvalds 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

	/* Did we already get enough commits for the early output? */
	if (!i)
		return;

	/*
	 * ..if no, then repeat it twice a second until we
	 * do.
	 *
	 * NOTE! We don't use "it_interval", because if the
	 * reader isn't listening, we want our output to be
	 * throttled by the writing, and not have the timer
	 * trigger every second even if we're blocked on a
	 * reader!
	 */
	early_output_timer.it_value.tv_sec = 0;
	early_output_timer.it_value.tv_usec = 500000;
	setitimer(ITIMER_REAL, &early_output_timer, NULL);
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
}

static void early_output(int signal)
{
	show_early_output = log_show_early;
}

static void setup_early_output(struct rev_info *rev)
{
	struct sigaction sa;

	/*
	 * Set up the signal handler, minimally intrusively:
	 * we only set a single volatile integer word (not
	 * using sigatomic_t - trying to avoid unnecessary
	 * system dependencies and headers), and using
	 * SA_RESTART.
	 */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = early_output;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sigaction(SIGALRM, &sa, NULL);

	/*
	 * If we can get the whole output in less than a
	 * tenth of a second, don't even bother doing the
	 * early-output thing..
	 *
	 * This is a one-time-only trigger.
	 */
L
Linus Torvalds 已提交
191 192 193
	early_output_timer.it_value.tv_sec = 0;
	early_output_timer.it_value.tv_usec = 100000;
	setitimer(ITIMER_REAL, &early_output_timer, NULL);
194 195 196 197
}

static void finish_early_output(struct rev_info *rev)
{
L
Linus Torvalds 已提交
198
	int n = estimate_commit_count(rev, rev->commits);
199
	signal(SIGALRM, SIG_IGN);
L
Linus Torvalds 已提交
200
	show_early_header(rev, "done", n);
201 202
}

203 204 205
static int cmd_log_walk(struct rev_info *rev)
{
	struct commit *commit;
206

207 208 209
	if (rev->early_output)
		setup_early_output(rev);

210 211
	if (prepare_revision_walk(rev))
		die("revision walk setup failed");
212 213 214 215

	if (rev->early_output)
		finish_early_output(rev);

216
	/*
217 218 219
	 * For --check and --exit-code, the exit code is based on CHECK_FAILED
	 * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
	 * retain that state information if replacing rev->diffopt in this loop
220
	 */
221 222
	while ((commit = get_revision(rev)) != NULL) {
		log_tree_commit(rev, commit);
223 224 225 226 227
		if (!rev->reflog_info) {
			/* we allow cycles in reflog ancestry */
			free(commit->buffer);
			commit->buffer = NULL;
		}
L
Linus Torvalds 已提交
228 229
		free_commit_list(commit->parents);
		commit->parents = NULL;
230
	}
231 232 233 234
	if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
	    DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
		return 02;
	}
235
	return diff_result_code(&rev->diffopt, 0);
236 237
}

238
static int git_log_config(const char *var, const char *value, void *cb)
239
{
240 241
	if (!strcmp(var, "format.pretty"))
		return git_config_string(&fmt_pretty, var, value);
242 243
	if (!strcmp(var, "format.subjectprefix"))
		return git_config_string(&fmt_patch_subject_prefix, var, value);
H
Heikki Orsila 已提交
244 245
	if (!strcmp(var, "log.date"))
		return git_config_string(&default_date_mode, var, value);
246 247 248 249
	if (!strcmp(var, "log.showroot")) {
		default_show_root = git_config_bool(var, value);
		return 0;
	}
250
	return git_diff_ui_config(var, value, cb);
251 252
}

253
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
254 255 256
{
	struct rev_info rev;

257
	git_config(git_log_config, NULL);
258 259 260 261

	if (diff_use_color_default == -1)
		diff_use_color_default = git_use_color_default;

262
	init_revisions(&rev, prefix);
263
	rev.diff = 1;
L
Linus Torvalds 已提交
264
	rev.simplify_history = 0;
265
	cmd_log_init(argc, argv, prefix, &rev);
266 267 268
	if (!rev.diffopt.output_format)
		rev.diffopt.output_format = DIFF_FORMAT_RAW;
	return cmd_log_walk(&rev);
269 270
}

271 272
static void show_tagger(char *buf, int len, struct rev_info *rev)
{
273
	struct strbuf out = STRBUF_INIT;
274

275 276 277
	pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode,
		git_log_output_encoding ?
		git_log_output_encoding: git_commit_encoding);
278
	printf("%s", out.buf);
279
	strbuf_release(&out);
280 281 282 283
}

static int show_object(const unsigned char *sha1, int show_tag_object,
	struct rev_info *rev)
284 285
{
	unsigned long size;
286 287
	enum object_type type;
	char *buf = read_sha1_file(sha1, &type, &size);
288 289 290 291 292
	int offset = 0;

	if (!buf)
		return error("Could not read object %s", sha1_to_hex(sha1));

293 294 295
	if (show_tag_object)
		while (offset < size && buf[offset] != '\n') {
			int new_offset = offset + 1;
296 297
			while (new_offset < size && buf[new_offset++] != '\n')
				; /* do nothing */
298 299 300
			if (!prefixcmp(buf + offset, "tagger "))
				show_tagger(buf + offset + 7,
					    new_offset - offset - 7, rev);
301 302 303 304 305 306 307 308 309 310 311
			offset = new_offset;
		}

	if (offset < size)
		fwrite(buf + offset, size - offset, 1, stdout);
	free(buf);
	return 0;
}

static int show_tree_object(const unsigned char *sha1,
		const char *base, int baselen,
312
		const char *pathname, unsigned mode, int stage, void *context)
313 314 315 316 317
{
	printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
	return 0;
}

318
int cmd_show(int argc, const char **argv, const char *prefix)
319 320
{
	struct rev_info rev;
321 322
	struct object_array_entry *objects;
	int i, count, ret = 0;
323

324
	git_config(git_log_config, NULL);
325 326 327 328

	if (diff_use_color_default == -1)
		diff_use_color_default = git_use_color_default;

329
	init_revisions(&rev, prefix);
330 331 332 333 334 335
	rev.diff = 1;
	rev.combine_merges = 1;
	rev.dense_combined_merges = 1;
	rev.always_show_header = 1;
	rev.ignore_merges = 0;
	rev.no_walk = 1;
336
	cmd_log_init(argc, argv, prefix, &rev);
337 338 339 340 341 342 343 344

	count = rev.pending.nr;
	objects = rev.pending.objects;
	for (i = 0; i < count && !ret; i++) {
		struct object *o = objects[i].item;
		const char *name = objects[i].name;
		switch (o->type) {
		case OBJ_BLOB:
345
			ret = show_object(o->sha1, 0, NULL);
346 347 348 349
			break;
		case OBJ_TAG: {
			struct tag *t = (struct tag *)o;

350 351
			if (rev.shown_one)
				putchar('\n');
352
			printf("%stag %s%s\n",
353
					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
354
					t->tag,
355
					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
356
			ret = show_object(o->sha1, 1, &rev);
357
			rev.shown_one = 1;
358 359 360 361 362 363 364
			if (ret)
				break;
			o = parse_object(t->tagged->sha1);
			if (!o)
				ret = error("Could not read object %s",
					    sha1_to_hex(t->tagged->sha1));
			objects[i].item = o;
365 366 367 368
			i--;
			break;
		}
		case OBJ_TREE:
369 370
			if (rev.shown_one)
				putchar('\n');
371
			printf("%stree %s%s\n\n",
372
					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
373
					name,
374
					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
375
			read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
376
					show_tree_object, NULL);
377
			rev.shown_one = 1;
378 379 380 381 382 383 384 385 386 387 388 389 390
			break;
		case OBJ_COMMIT:
			rev.pending.nr = rev.pending.alloc = 0;
			rev.pending.objects = NULL;
			add_object_array(o, name, &rev.pending);
			ret = cmd_log_walk(&rev);
			break;
		default:
			ret = error("Unknown type: %d", o->type);
		}
	}
	free(objects);
	return ret;
391 392
}

L
Linus Torvalds 已提交
393 394 395 396 397 398 399
/*
 * This is equivalent to "git log -g --abbrev-commit --pretty=oneline"
 */
int cmd_log_reflog(int argc, const char **argv, const char *prefix)
{
	struct rev_info rev;

400
	git_config(git_log_config, NULL);
401 402 403 404

	if (diff_use_color_default == -1)
		diff_use_color_default = git_use_color_default;

L
Linus Torvalds 已提交
405 406 407 408 409 410 411 412 413 414 415 416
	init_revisions(&rev, prefix);
	init_reflog_walk(&rev.reflog_info);
	rev.abbrev_commit = 1;
	rev.verbose_header = 1;
	cmd_log_init(argc, argv, prefix, &rev);

	/*
	 * This means that we override whatever commit format the user gave
	 * on the cmd line.  Sad, but cmd_log_init() currently doesn't
	 * allow us to set a different default.
	 */
	rev.commit_format = CMIT_FMT_ONELINE;
417
	rev.use_terminator = 1;
L
Linus Torvalds 已提交
418 419 420 421 422 423 424 425 426 427 428
	rev.always_show_header = 1;

	/*
	 * We get called through "git reflog", so unlike the other log
	 * routines, we need to set up our pager manually..
	 */
	setup_pager();

	return cmd_log_walk(&rev);
}

429
int cmd_log(int argc, const char **argv, const char *prefix)
430 431 432
{
	struct rev_info rev;

433
	git_config(git_log_config, NULL);
434 435 436 437

	if (diff_use_color_default == -1)
		diff_use_color_default = git_use_color_default;

438
	init_revisions(&rev, prefix);
439
	rev.always_show_header = 1;
440
	cmd_log_init(argc, argv, prefix, &rev);
441
	return cmd_log_walk(&rev);
442
}
443

444
/* format-patch */
445

446
static const char *fmt_patch_suffix = ".patch";
447
static int numbered = 0;
448
static int auto_number = 1;
449

450 451
static char *default_attach = NULL;

D
Daniel Barkalow 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
static char **extra_hdr;
static int extra_hdr_nr;
static int extra_hdr_alloc;

static char **extra_to;
static int extra_to_nr;
static int extra_to_alloc;

static char **extra_cc;
static int extra_cc_nr;
static int extra_cc_alloc;

static void add_header(const char *value)
{
	int len = strlen(value);
467
	while (len && value[len - 1] == '\n')
D
Daniel Barkalow 已提交
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
		len--;
	if (!strncasecmp(value, "to: ", 4)) {
		ALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc);
		extra_to[extra_to_nr++] = xstrndup(value + 4, len - 4);
		return;
	}
	if (!strncasecmp(value, "cc: ", 4)) {
		ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
		extra_cc[extra_cc_nr++] = xstrndup(value + 4, len - 4);
		return;
	}
	ALLOC_GROW(extra_hdr, extra_hdr_nr + 1, extra_hdr_alloc);
	extra_hdr[extra_hdr_nr++] = xstrndup(value, len);
}

483 484 485
#define THREAD_SHALLOW 1
#define THREAD_DEEP 2
static int thread = 0;
486
static int do_signoff = 0;
487

488
static int git_format_config(const char *var, const char *value, void *cb)
489 490
{
	if (!strcmp(var, "format.headers")) {
491 492
		if (!value)
			die("format.headers without value");
D
Daniel Barkalow 已提交
493
		add_header(value);
494 495
		return 0;
	}
496 497
	if (!strcmp(var, "format.suffix"))
		return git_config_string(&fmt_patch_suffix, var, value);
498 499 500 501 502 503 504
	if (!strcmp(var, "format.cc")) {
		if (!value)
			return config_error_nonbool(var);
		ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
		extra_cc[extra_cc_nr++] = xstrdup(value);
		return 0;
	}
505
	if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
506 507
		return 0;
	}
508
	if (!strcmp(var, "format.numbered")) {
509
		if (value && !strcasecmp(value, "auto")) {
510 511 512 513
			auto_number = 1;
			return 0;
		}
		numbered = git_config_bool(var, value);
514
		auto_number = auto_number && numbered;
515 516
		return 0;
	}
517 518 519 520 521 522 523
	if (!strcmp(var, "format.attach")) {
		if (value && *value)
			default_attach = xstrdup(value);
		else
			default_attach = xstrdup(git_version_string);
		return 0;
	}
524 525 526 527 528 529 530 531 532 533 534 535
	if (!strcmp(var, "format.thread")) {
		if (value && !strcasecmp(value, "deep")) {
			thread = THREAD_DEEP;
			return 0;
		}
		if (value && !strcasecmp(value, "shallow")) {
			thread = THREAD_SHALLOW;
			return 0;
		}
		thread = git_config_bool(var, value) && THREAD_SHALLOW;
		return 0;
	}
536 537 538 539
	if (!strcmp(var, "format.signoff")) {
		do_signoff = git_config_bool(var, value);
		return 0;
	}
540

541
	return git_log_config(var, value, cb);
542 543
}

544
static FILE *realstdout = NULL;
545
static const char *output_directory = NULL;
546
static int outdir_offset;
547

548
static int reopen_stdout(struct commit *commit, struct rev_info *rev)
549
{
550
	struct strbuf filename = STRBUF_INIT;
551
	int suffix_len = strlen(fmt_patch_suffix) + 1;
552

553
	if (output_directory) {
554 555 556
		strbuf_addstr(&filename, output_directory);
		if (filename.len >=
		    PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
557
			return error("name of output directory is too long");
558 559
		if (filename.buf[filename.len - 1] != '/')
			strbuf_addch(&filename, '/');
560
	}
561

562
	get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
563

N
Nate Case 已提交
564
	if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
565
		fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
N
Nate Case 已提交
566

567 568
	if (freopen(filename.buf, "w", stdout) == NULL)
		return error("Cannot open patch file %s", filename.buf);
569

570
	strbuf_release(&filename);
571
	return 0;
572 573
}

574
static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix)
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
{
	struct rev_info check_rev;
	struct commit *commit;
	struct object *o1, *o2;
	unsigned flags1, flags2;

	if (rev->pending.nr != 2)
		die("Need exactly one range.");

	o1 = rev->pending.objects[0].item;
	flags1 = o1->flags;
	o2 = rev->pending.objects[1].item;
	flags2 = o2->flags;

	if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
		die("Not a range.");

592
	init_patch_ids(ids);
593 594

	/* given a range a..b get all patch ids for b..a */
595
	init_revisions(&check_rev, prefix);
596 597 598 599
	o1->flags ^= UNINTERESTING;
	o2->flags ^= UNINTERESTING;
	add_pending_object(&check_rev, o1, "o1");
	add_pending_object(&check_rev, o2, "o2");
600 601
	if (prepare_revision_walk(&check_rev))
		die("revision walk setup failed");
602 603 604 605 606 607

	while ((commit = get_revision(&check_rev)) != NULL) {
		/* ignore merges */
		if (commit->parents && commit->parents->next)
			continue;

608
		add_commit_patch_id(commit, ids);
609 610 611
	}

	/* reset for next revision walk */
612 613 614 615
	clear_commit_marks((struct commit *)o1,
			SEEN | UNINTERESTING | SHOWN | ADDED);
	clear_commit_marks((struct commit *)o2,
			SEEN | UNINTERESTING | SHOWN | ADDED);
616 617 618 619
	o1->flags = flags1;
	o2->flags = flags2;
}

620
static void gen_message_id(struct rev_info *info, char *base)
621
{
622
	const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME);
623 624
	const char *email_start = strrchr(committer, '<');
	const char *email_end = strrchr(committer, '>');
625
	struct strbuf buf = STRBUF_INIT;
626
	if (!email_start || !email_end || email_start > email_end - 1)
627
		die("Could not extract email from committer identity.");
628 629 630 631
	strbuf_addf(&buf, "%s.%lu.git.%.*s", base,
		    (unsigned long) time(NULL),
		    (int)(email_end - email_start - 1), email_start + 1);
	info->message_id = strbuf_detach(&buf, NULL);
632 633
}

634 635 636 637
static void make_cover_letter(struct rev_info *rev, int use_stdout,
			      int numbered, int numbered_files,
			      struct commit *origin,
			      int nr, struct commit **list, struct commit *head)
638 639 640 641 642 643
{
	const char *committer;
	const char *subject_start = NULL;
	const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
	const char *msg;
	const char *extra_headers = rev->extra_headers;
644
	struct shortlog log;
645
	struct strbuf sb = STRBUF_INIT;
646
	int i;
647
	const char *encoding = "UTF-8";
648
	struct diff_options opts;
J
Junio C Hamano 已提交
649
	int need_8bit_cte = 0;
650
	struct commit *commit = NULL;
651 652 653 654

	if (rev->commit_format != CMIT_FMT_EMAIL)
		die("Cover letter needs email format");

655
	committer = git_committer_info(0);
656

657 658 659 660 661 662 663 664 665 666 667 668 669
	if (!numbered_files) {
		/*
		 * We fake a commit for the cover letter so we get the filename
		 * desired.
		 */
		commit = xcalloc(1, sizeof(*commit));
		commit->buffer = xmalloc(400);
		snprintf(commit->buffer, 400,
			"tree 0000000000000000000000000000000000000000\n"
			"parent %s\n"
			"author %s\n"
			"committer %s\n\n"
			"cover letter\n",
670
			sha1_to_hex(head->object.sha1), committer, committer);
671 672 673
	}

	if (!use_stdout && reopen_stdout(commit, rev))
674 675
		return;

676
	if (commit) {
677

678 679 680
		free(commit->buffer);
		free(commit);
	}
681

682
	log_write_email_headers(rev, head, &subject_start, &extra_headers,
J
Junio C Hamano 已提交
683
				&need_8bit_cte);
684

685 686 687 688
	for (i = 0; !need_8bit_cte && i < nr; i++)
		if (has_non_ascii(list[i]->buffer))
			need_8bit_cte = 1;

689 690 691 692
	msg = body;
	pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822,
		     encoding);
	pp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers,
J
Junio C Hamano 已提交
693
		      encoding, need_8bit_cte);
694 695 696 697 698
	pp_remainder(CMIT_FMT_EMAIL, &msg, &sb, 0);
	printf("%s\n", sb.buf);

	strbuf_release(&sb);

699
	shortlog_init(&log);
700 701 702 703
	log.wrap_lines = 1;
	log.wrap = 72;
	log.in1 = 2;
	log.in2 = 4;
704 705 706 707 708
	for (i = 0; i < nr; i++)
		shortlog_add_commit(&log, list[i]);

	shortlog_output(&log);

709
	/*
710
	 * We can only do diffstat with a unique reference point
711 712 713 714
	 */
	if (!origin)
		return;

715 716
	memcpy(&opts, &rev->diffopt, sizeof(opts));
	opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
717

718 719 720 721 722 723 724
	diff_setup_done(&opts);

	diff_tree_sha1(origin->tree->object.sha1,
		       head->tree->object.sha1,
		       "", &opts);
	diffcore_std(&opts);
	diff_flush(&opts);
725 726

	printf("\n");
727 728
}

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
static const char *clean_message_id(const char *msg_id)
{
	char ch;
	const char *a, *z, *m;

	m = msg_id;
	while ((ch = *m) && (isspace(ch) || (ch == '<')))
		m++;
	a = m;
	z = NULL;
	while ((ch = *m)) {
		if (!isspace(ch) && (ch != '>'))
			z = m;
		m++;
	}
	if (!z)
		die("insane in-reply-to: %s", msg_id);
	if (++z == m)
		return a;
P
Pierre Habouzit 已提交
748
	return xmemdupz(a, z - a);
749 750
}

751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
static const char *set_outdir(const char *prefix, const char *output_directory)
{
	if (output_directory && is_absolute_path(output_directory))
		return output_directory;

	if (!prefix || !*prefix) {
		if (output_directory)
			return output_directory;
		/* The user did not explicitly ask for "./" */
		outdir_offset = 2;
		return "./";
	}

	outdir_offset = strlen(prefix);
	if (!output_directory)
		return prefix;

	return xstrdup(prefix_filename(prefix, outdir_offset,
				       output_directory));
}

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
static const char * const builtin_format_patch_usage[] = {
	"git format-patch [options] [<since> | <revision range>]",
	NULL
};

static int keep_subject = 0;

static int keep_callback(const struct option *opt, const char *arg, int unset)
{
	((struct rev_info *)opt->value)->total = -1;
	keep_subject = 1;
	return 0;
}

static int subject_prefix = 0;

static int subject_prefix_callback(const struct option *opt, const char *arg,
			    int unset)
{
	subject_prefix = 1;
	((struct rev_info *)opt->value)->subject_prefix = arg;
	return 0;
}

796 797
static int numbered_cmdline_opt = 0;

798 799 800
static int numbered_callback(const struct option *opt, const char *arg,
			     int unset)
{
801
	*(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
	if (unset)
		auto_number =  0;
	return 0;
}

static int no_numbered_callback(const struct option *opt, const char *arg,
				int unset)
{
	return numbered_callback(opt, arg, 1);
}

static int output_directory_callback(const struct option *opt, const char *arg,
			      int unset)
{
	const char **dir = (const char **)opt->value;
	if (*dir)
		die("Two output directories?");
	*dir = arg;
	return 0;
}

static int thread_callback(const struct option *opt, const char *arg, int unset)
{
	int *thread = (int *)opt->value;
	if (unset)
		*thread = 0;
	else if (!arg || !strcmp(arg, "shallow"))
		*thread = THREAD_SHALLOW;
	else if (!strcmp(arg, "deep"))
		*thread = THREAD_DEEP;
	else
		return 1;
	return 0;
}

static int attach_callback(const struct option *opt, const char *arg, int unset)
{
	struct rev_info *rev = (struct rev_info *)opt->value;
	if (unset)
		rev->mime_boundary = NULL;
	else if (arg)
		rev->mime_boundary = arg;
	else
		rev->mime_boundary = git_version_string;
	rev->no_inline = unset ? 0 : 1;
	return 0;
}

static int inline_callback(const struct option *opt, const char *arg, int unset)
{
	struct rev_info *rev = (struct rev_info *)opt->value;
	if (unset)
		rev->mime_boundary = NULL;
	else if (arg)
		rev->mime_boundary = arg;
	else
		rev->mime_boundary = git_version_string;
	rev->no_inline = 0;
	return 0;
}

static int header_callback(const struct option *opt, const char *arg, int unset)
{
	add_header(arg);
	return 0;
}

static int cc_callback(const struct option *opt, const char *arg, int unset)
{
	ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
	extra_cc[extra_cc_nr++] = xstrdup(arg);
	return 0;
}

876
int cmd_format_patch(int argc, const char **argv, const char *prefix)
877 878 879 880
{
	struct commit *commit;
	struct commit **list = NULL;
	struct rev_info rev;
881
	int nr = 0, total, i;
882
	int use_stdout = 0;
883
	int start_number = -1;
884
	int numbered_files = 0;		/* _just_ numbers */
885
	int ignore_if_in_upstream = 0;
886
	int cover_letter = 0;
887
	int boundary_count = 0;
888
	int no_binary_diff = 0;
889
	struct commit *origin = NULL, *head = NULL;
890
	const char *in_reply_to = NULL;
891
	struct patch_ids ids;
J
Junio C Hamano 已提交
892
	char *add_signoff = NULL;
893
	struct strbuf buf = STRBUF_INIT;
894
	int use_patch_format = 0;
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
	const struct option builtin_format_patch_options[] = {
		{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
			    "use [PATCH n/m] even with a single patch",
			    PARSE_OPT_NOARG, numbered_callback },
		{ OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
			    "use [PATCH] even with multiple patches",
			    PARSE_OPT_NOARG, no_numbered_callback },
		OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
		OPT_BOOLEAN(0, "stdout", &use_stdout,
			    "print patches to standard out"),
		OPT_BOOLEAN(0, "cover-letter", &cover_letter,
			    "generate a cover letter"),
		OPT_BOOLEAN(0, "numbered-files", &numbered_files,
			    "use simple number sequence for output file names"),
		OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
			    "use <sfx> instead of '.patch'"),
		OPT_INTEGER(0, "start-number", &start_number,
			    "start numbering patches at <n> instead of 1"),
		{ OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
			    "Use [<prefix>] instead of [PATCH]",
			    PARSE_OPT_NONEG, subject_prefix_callback },
		{ OPTION_CALLBACK, 'o', "output-directory", &output_directory,
			    "dir", "store resulting files in <dir>",
			    PARSE_OPT_NONEG, output_directory_callback },
		{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
			    "don't strip/add [PATCH]",
			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
		OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
			    "don't output binary diffs"),
924 925
		OPT_BOOLEAN('p', NULL, &use_patch_format,
			"show patch format instead of default (patch + stat)"),
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
		OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
			    "don't include a patch matching a commit upstream"),
		OPT_GROUP("Messaging"),
		{ OPTION_CALLBACK, 0, "add-header", NULL, "header",
			    "add email header", PARSE_OPT_NONEG,
			    header_callback },
		{ OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
			    PARSE_OPT_NONEG, cc_callback },
		OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
			    "make first mail a reply to <message-id>"),
		{ OPTION_CALLBACK, 0, "attach", &rev, "boundary",
			    "attach the patch", PARSE_OPT_OPTARG,
			    attach_callback },
		{ OPTION_CALLBACK, 0, "inline", &rev, "boundary",
			    "inline the patch",
			    PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
			    inline_callback },
		{ OPTION_CALLBACK, 0, "thread", &thread, "style",
			    "enable message threading, styles: shallow, deep",
			    PARSE_OPT_OPTARG, thread_callback },
		OPT_END()
	};
948

949
	git_config(git_format_config, NULL);
950
	init_revisions(&rev, prefix);
951 952 953 954 955
	rev.commit_format = CMIT_FMT_EMAIL;
	rev.verbose_header = 1;
	rev.diff = 1;
	rev.combine_merges = 0;
	rev.ignore_merges = 1;
956
	DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
957

958
	rev.subject_prefix = fmt_patch_subject_prefix;
959

960 961 962 963 964
	if (default_attach) {
		rev.mime_boundary = default_attach;
		rev.no_inline = 1;
	}

965 966
	/*
	 * Parse the arguments before setup_revisions(), or something
967
	 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
968 969
	 * possibly a valid SHA1.
	 */
970
	argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
971 972
			     builtin_format_patch_usage,
			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
973

974 975 976 977 978 979 980 981 982 983
	if (do_signoff) {
		const char *committer;
		const char *endpos;
		committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
		endpos = strchr(committer, '>');
		if (!endpos)
			die("bogus committer info %s", committer);
		add_signoff = xmemdupz(committer, endpos - committer + 1);
	}

D
Daniel Barkalow 已提交
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
	for (i = 0; i < extra_hdr_nr; i++) {
		strbuf_addstr(&buf, extra_hdr[i]);
		strbuf_addch(&buf, '\n');
	}

	if (extra_to_nr)
		strbuf_addstr(&buf, "To: ");
	for (i = 0; i < extra_to_nr; i++) {
		if (i)
			strbuf_addstr(&buf, "    ");
		strbuf_addstr(&buf, extra_to[i]);
		if (i + 1 < extra_to_nr)
			strbuf_addch(&buf, ',');
		strbuf_addch(&buf, '\n');
	}

	if (extra_cc_nr)
		strbuf_addstr(&buf, "Cc: ");
	for (i = 0; i < extra_cc_nr; i++) {
		if (i)
			strbuf_addstr(&buf, "    ");
		strbuf_addstr(&buf, extra_cc[i]);
		if (i + 1 < extra_cc_nr)
			strbuf_addch(&buf, ',');
		strbuf_addch(&buf, '\n');
	}

1011
	rev.extra_headers = strbuf_detach(&buf, NULL);
D
Daniel Barkalow 已提交
1012

1013
	if (start_number < 0)
1014
		start_number = 1;
1015 1016 1017 1018 1019 1020 1021 1022 1023

	/*
	 * If numbered is set solely due to format.numbered in config,
	 * and it would conflict with --keep-subject (-k) from the
	 * command line, reset "numbered".
	 */
	if (numbered && keep_subject && !numbered_cmdline_opt)
		numbered = 0;

1024
	if (numbered && keep_subject)
1025
		die ("-n and -k are mutually exclusive.");
1026 1027
	if (keep_subject && subject_prefix)
		die ("--subject-prefix and -k are mutually exclusive.");
1028

1029 1030 1031
	argc = setup_revisions(argc, argv, &rev, "HEAD");
	if (argc > 1)
		die ("unrecognized argument: %s", argv[1]);
1032

1033 1034 1035 1036
	if (use_patch_format)
		rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
	else if (!rev.diffopt.output_format ||
		  rev.diffopt.output_format == DIFF_FORMAT_PATCH)
1037
		rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
1038

1039
	if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
1040
		DIFF_OPT_SET(&rev.diffopt, BINARY);
1041

1042 1043
	if (!use_stdout)
		output_directory = set_outdir(prefix, output_directory);
1044

1045 1046 1047 1048
	if (output_directory) {
		if (use_stdout)
			die("standard output, or directory, which one?");
		if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
1049 1050
			die_errno("Could not create directory '%s'",
				  output_directory);
1051 1052
	}

1053
	if (rev.pending.nr == 1) {
1054 1055 1056 1057 1058 1059
		if (rev.max_count < 0 && !rev.show_root_diff) {
			/*
			 * This is traditional behaviour of "git format-patch
			 * origin" that prepares what the origin side still
			 * does not have.
			 */
J
Junio C Hamano 已提交
1060
			rev.pending.objects[0].item->flags |= UNINTERESTING;
1061
			add_head_to_pending(&rev);
J
Junio C Hamano 已提交
1062
		}
1063 1064 1065 1066
		/*
		 * Otherwise, it is "format-patch -22 HEAD", and/or
		 * "format-patch --root HEAD".  The user wants
		 * get_revision() to do the usual traversal.
J
Junio C Hamano 已提交
1067
		 */
1068
	}
1069 1070 1071 1072 1073 1074 1075

	/*
	 * We cannot move this anywhere earlier because we do want to
	 * know if --root was given explicitly from the comand line.
	 */
	rev.show_root_diff = 1;

1076 1077 1078 1079 1080
	if (cover_letter) {
		/* remember the range */
		int i;
		for (i = 0; i < rev.pending.nr; i++) {
			struct object *o = rev.pending.objects[i].item;
1081
			if (!(o->flags & UNINTERESTING))
1082 1083 1084 1085 1086 1087
				head = (struct commit *)o;
		}
		/* We can't generate a cover letter without any patches */
		if (!head)
			return 0;
	}
1088

1089
	if (ignore_if_in_upstream)
1090
		get_patch_ids(&rev, &ids, prefix);
1091

1092
	if (!use_stdout)
1093
		realstdout = xfdopen(xdup(1), "w");
1094

1095 1096
	if (prepare_revision_walk(&rev))
		die("revision walk setup failed");
1097
	rev.boundary = 1;
1098
	while ((commit = get_revision(&rev)) != NULL) {
1099 1100 1101 1102 1103 1104
		if (commit->object.flags & BOUNDARY) {
			boundary_count++;
			origin = (boundary_count == 1) ? commit : NULL;
			continue;
		}

1105 1106 1107
		/* ignore merges */
		if (commit->parents && commit->parents->next)
			continue;
1108 1109

		if (ignore_if_in_upstream &&
1110
				has_commit_patch_id(commit, &ids))
1111 1112
			continue;

1113
		nr++;
J
Jonas Fonseca 已提交
1114
		list = xrealloc(list, nr * sizeof(list[0]));
1115 1116
		list[nr - 1] = commit;
	}
1117
	total = nr;
1118 1119
	if (!keep_subject && auto_number && total > 1)
		numbered = 1;
1120
	if (numbered)
1121
		rev.total = total + start_number - 1;
1122 1123 1124 1125 1126 1127
	if (in_reply_to || thread || cover_letter)
		rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
	if (in_reply_to) {
		const char *msgid = clean_message_id(in_reply_to);
		string_list_append(msgid, rev.ref_message_ids);
	}
1128 1129
	rev.numbered_files = numbered_files;
	rev.patch_suffix = fmt_patch_suffix;
1130 1131 1132 1133
	if (cover_letter) {
		if (thread)
			gen_message_id(&rev, "cover");
		make_cover_letter(&rev, use_stdout, numbered, numbered_files,
1134
				  origin, nr, list, head);
1135 1136 1137 1138
		total++;
		start_number--;
	}
	rev.add_signoff = add_signoff;
1139 1140 1141
	while (0 <= --nr) {
		int shown;
		commit = list[nr];
1142
		rev.nr = total - nr + (start_number - 1);
1143
		/* Make the second and subsequent mails replies to the first */
1144
		if (thread) {
1145
			/* Have we already had a message ID? */
1146
			if (rev.message_id) {
1147
				/*
1148 1149 1150 1151 1152 1153
				 * For deep threading: make every mail
				 * a reply to the previous one, no
				 * matter what other options are set.
				 *
				 * For shallow threading:
				 *
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
				 * Without --cover-letter and
				 * --in-reply-to, make every mail a
				 * reply to the one before.
				 *
				 * With --in-reply-to but no
				 * --cover-letter, make every mail a
				 * reply to the <reply-to>.
				 *
				 * With --cover-letter, make every
				 * mail but the cover letter a reply
				 * to the cover letter.  The cover
				 * letter is a reply to the
				 * --in-reply-to, if specified.
1167
				 */
1168 1169
				if (thread == THREAD_SHALLOW
				    && rev.ref_message_ids->nr > 0
1170
				    && (!cover_letter || rev.nr > 1))
1171 1172
					free(rev.message_id);
				else
1173 1174
					string_list_append(rev.message_id,
							   rev.ref_message_ids);
1175
			}
1176
			gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
1177
		}
1178

1179 1180
		if (!use_stdout && reopen_stdout(numbered_files ? NULL : commit,
						 &rev))
1181
			die("Failed to create output files");
1182 1183 1184
		shown = log_tree_commit(&rev, commit);
		free(commit->buffer);
		commit->buffer = NULL;
1185 1186 1187 1188 1189 1190 1191 1192 1193

		/* We put one extra blank line between formatted
		 * patches and this flag is used by log-tree code
		 * to see if it needs to emit a LF before showing
		 * the log; when using one file per patch, we do
		 * not want the extra blank line.
		 */
		if (!use_stdout)
			rev.shown_one = 0;
1194 1195 1196 1197 1198 1199 1200 1201
		if (shown) {
			if (rev.mime_boundary)
				printf("\n--%s%s--\n\n\n",
				       mime_boundary_leader,
				       rev.mime_boundary);
			else
				printf("-- \n%s\n\n", git_version_string);
		}
1202 1203
		if (!use_stdout)
			fclose(stdout);
1204 1205
	}
	free(list);
1206 1207
	if (ignore_if_in_upstream)
		free_patch_ids(&ids);
1208 1209 1210
	return 0;
}

R
Rene Scharfe 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
{
	unsigned char sha1[20];
	if (get_sha1(arg, sha1) == 0) {
		struct commit *commit = lookup_commit_reference(sha1);
		if (commit) {
			commit->object.flags |= flags;
			add_pending_object(revs, &commit->object, arg);
			return 0;
		}
	}
	return -1;
}

static const char cherry_usage[] =
1226
"git cherry [-v] [<upstream> [<head> [<limit>]]]";
R
Rene Scharfe 已提交
1227 1228 1229
int cmd_cherry(int argc, const char **argv, const char *prefix)
{
	struct rev_info revs;
1230
	struct patch_ids ids;
R
Rene Scharfe 已提交
1231 1232
	struct commit *commit;
	struct commit_list *list = NULL;
1233
	struct branch *current_branch;
R
Rene Scharfe 已提交
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
	const char *upstream;
	const char *head = "HEAD";
	const char *limit = NULL;
	int verbose = 0;

	if (argc > 1 && !strcmp(argv[1], "-v")) {
		verbose = 1;
		argc--;
		argv++;
	}

	switch (argc) {
	case 4:
		limit = argv[3];
		/* FALLTHROUGH */
	case 3:
		head = argv[2];
		/* FALLTHROUGH */
	case 2:
		upstream = argv[1];
		break;
	default:
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
		current_branch = branch_get(NULL);
		if (!current_branch || !current_branch->merge
					|| !current_branch->merge[0]
					|| !current_branch->merge[0]->dst) {
			fprintf(stderr, "Could not find a tracked"
					" remote branch, please"
					" specify <upstream> manually.\n");
			usage(cherry_usage);
		}

		upstream = current_branch->merge[0]->dst;
R
Rene Scharfe 已提交
1267 1268 1269 1270 1271 1272
	}

	init_revisions(&revs, prefix);
	revs.diff = 1;
	revs.combine_merges = 0;
	revs.ignore_merges = 1;
1273
	DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
R
Rene Scharfe 已提交
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286

	if (add_pending_commit(head, &revs, 0))
		die("Unknown commit %s", head);
	if (add_pending_commit(upstream, &revs, UNINTERESTING))
		die("Unknown commit %s", upstream);

	/* Don't say anything if head and upstream are the same. */
	if (revs.pending.nr == 2) {
		struct object_array_entry *o = revs.pending.objects;
		if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0)
			return 0;
	}

1287
	get_patch_ids(&revs, &ids, prefix);
R
Rene Scharfe 已提交
1288 1289 1290 1291 1292

	if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
		die("Unknown commit %s", limit);

	/* reverse the list of commits */
1293 1294
	if (prepare_revision_walk(&revs))
		die("revision walk setup failed");
R
Rene Scharfe 已提交
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
	while ((commit = get_revision(&revs)) != NULL) {
		/* ignore merges */
		if (commit->parents && commit->parents->next)
			continue;

		commit_list_insert(commit, &list);
	}

	while (list) {
		char sign = '+';

		commit = list->item;
1307
		if (has_commit_patch_id(commit, &ids))
R
Rene Scharfe 已提交
1308 1309 1310
			sign = '-';

		if (verbose) {
1311
			struct strbuf buf = STRBUF_INIT;
1312
			pretty_print_commit(CMIT_FMT_ONELINE, commit,
1313
			                    &buf, 0, NULL, NULL, 0, 0);
R
Rene Scharfe 已提交
1314
			printf("%c %s %s\n", sign,
1315 1316
			       sha1_to_hex(commit->object.sha1), buf.buf);
			strbuf_release(&buf);
R
Rene Scharfe 已提交
1317 1318 1319 1320 1321 1322 1323 1324 1325
		}
		else {
			printf("%c %s\n", sign,
			       sha1_to_hex(commit->object.sha1));
		}

		list = list->next;
	}

1326
	free_patch_ids(&ids);
R
Rene Scharfe 已提交
1327 1328
	return 0;
}