builtin-log.c 29.0 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

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

23
static int default_show_root = 1;
24
static const char *fmt_patch_subject_prefix = "PATCH";
25
static const char *fmt_pretty;
26

27
static void cmd_log_init(int argc, const char **argv, const char *prefix,
28 29
		      struct rev_info *rev)
{
J
Junio C Hamano 已提交
30 31
	int i;

32 33
	rev->abbrev = DEFAULT_ABBREV;
	rev->commit_format = CMIT_FMT_DEFAULT;
34
	if (fmt_pretty)
35
		get_commit_format(fmt_pretty, rev);
36
	rev->verbose_header = 1;
37
	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
38
	rev->show_root_diff = default_show_root;
39
	rev->subject_prefix = fmt_patch_subject_prefix;
H
Heikki Orsila 已提交
40 41 42 43

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

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

46 47
	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
48
	if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
49 50 51 52
		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 已提交
53 54
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];
55
		if (!strcmp(arg, "--decorate")) {
R
René Scharfe 已提交
56
			load_ref_decorations();
57
			rev->show_decorations = 1;
58 59
		} else if (!strcmp(arg, "--source")) {
			rev->show_source = 1;
60
		} else
J
Junio C Hamano 已提交
61 62
			die("unrecognized argument: %s", arg);
	}
63
	DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
64 65
}

L
Linus Torvalds 已提交
66 67 68 69 70 71 72 73 74 75 76 77
/*
 * 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;
78
		if (!(flags & (TREESAME | UNINTERESTING)))
L
Linus Torvalds 已提交
79
			n++;
L
Linus Torvalds 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
	}
	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);
}

struct itimerval early_output_timer;

96 97 98
static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
	int i = revs->early_output;
L
Linus Torvalds 已提交
99
	int show_header = 1;
100 101 102 103

	sort_in_topological_order(&list, revs->lifo);
	while (list && i) {
		struct commit *commit = list->item;
L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
		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;
		}
119 120
		list = list->next;
	}
L
Linus Torvalds 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

	/* 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);
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
}

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 已提交
170 171 172
	early_output_timer.it_value.tv_sec = 0;
	early_output_timer.it_value.tv_usec = 100000;
	setitimer(ITIMER_REAL, &early_output_timer, NULL);
173 174 175 176
}

static void finish_early_output(struct rev_info *rev)
{
L
Linus Torvalds 已提交
177
	int n = estimate_commit_count(rev, rev->commits);
178
	signal(SIGALRM, SIG_IGN);
L
Linus Torvalds 已提交
179
	show_early_header(rev, "done", n);
180 181
}

182 183 184
static int cmd_log_walk(struct rev_info *rev)
{
	struct commit *commit;
185

186 187 188
	if (rev->early_output)
		setup_early_output(rev);

189 190
	if (prepare_revision_walk(rev))
		die("revision walk setup failed");
191 192 193 194

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

195
	/*
196 197 198
	 * 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
199
	 */
200 201
	while ((commit = get_revision(rev)) != NULL) {
		log_tree_commit(rev, commit);
202 203 204 205 206
		if (!rev->reflog_info) {
			/* we allow cycles in reflog ancestry */
			free(commit->buffer);
			commit->buffer = NULL;
		}
L
Linus Torvalds 已提交
207 208
		free_commit_list(commit->parents);
		commit->parents = NULL;
209
	}
210 211 212 213
	if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
	    DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
		return 02;
	}
214
	return diff_result_code(&rev->diffopt, 0);
215 216
}

217
static int git_log_config(const char *var, const char *value, void *cb)
218
{
219 220
	if (!strcmp(var, "format.pretty"))
		return git_config_string(&fmt_pretty, var, value);
221 222
	if (!strcmp(var, "format.subjectprefix"))
		return git_config_string(&fmt_patch_subject_prefix, var, value);
H
Heikki Orsila 已提交
223 224
	if (!strcmp(var, "log.date"))
		return git_config_string(&default_date_mode, var, value);
225 226 227 228
	if (!strcmp(var, "log.showroot")) {
		default_show_root = git_config_bool(var, value);
		return 0;
	}
229
	return git_diff_ui_config(var, value, cb);
230 231
}

232
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
233 234 235
{
	struct rev_info rev;

236
	git_config(git_log_config, NULL);
237 238 239 240

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

241
	init_revisions(&rev, prefix);
242
	rev.diff = 1;
L
Linus Torvalds 已提交
243
	rev.simplify_history = 0;
244
	cmd_log_init(argc, argv, prefix, &rev);
245 246 247
	if (!rev.diffopt.output_format)
		rev.diffopt.output_format = DIFF_FORMAT_RAW;
	return cmd_log_walk(&rev);
248 249
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
static void show_tagger(char *buf, int len, struct rev_info *rev)
{
	char *email_end, *p;
	unsigned long date;
	int tz;

	email_end = memchr(buf, '>', len);
	if (!email_end)
		return;
	p = ++email_end;
	while (isspace(*p))
		p++;
	date = strtoul(p, &p, 10);
	while (isspace(*p))
		p++;
	tz = (int)strtol(p, NULL, 10);
	printf("Tagger: %.*s\nDate:   %s\n", (int)(email_end - buf), buf,
	       show_date(date, tz, rev->date_mode));
}

static int show_object(const unsigned char *sha1, int show_tag_object,
	struct rev_info *rev)
272 273
{
	unsigned long size;
274 275
	enum object_type type;
	char *buf = read_sha1_file(sha1, &type, &size);
276 277 278 279 280
	int offset = 0;

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

281 282 283
	if (show_tag_object)
		while (offset < size && buf[offset] != '\n') {
			int new_offset = offset + 1;
284 285
			while (new_offset < size && buf[new_offset++] != '\n')
				; /* do nothing */
286 287 288
			if (!prefixcmp(buf + offset, "tagger "))
				show_tagger(buf + offset + 7,
					    new_offset - offset - 7, rev);
289 290 291 292 293 294 295 296 297 298 299
			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,
300
		const char *pathname, unsigned mode, int stage, void *context)
301 302 303 304 305
{
	printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
	return 0;
}

306
int cmd_show(int argc, const char **argv, const char *prefix)
307 308
{
	struct rev_info rev;
309 310
	struct object_array_entry *objects;
	int i, count, ret = 0;
311

312
	git_config(git_log_config, NULL);
313 314 315 316

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

317
	init_revisions(&rev, prefix);
318 319 320 321 322 323
	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;
324
	cmd_log_init(argc, argv, prefix, &rev);
325 326 327 328 329 330 331 332

	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:
333
			ret = show_object(o->sha1, 0, NULL);
334 335 336 337
			break;
		case OBJ_TAG: {
			struct tag *t = (struct tag *)o;

338
			printf("%stag %s%s\n",
339
					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
340
					t->tag,
341
					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
342
			ret = show_object(o->sha1, 1, &rev);
343
			objects[i].item = parse_object(t->tagged->sha1);
344 345 346 347 348
			i--;
			break;
		}
		case OBJ_TREE:
			printf("%stree %s%s\n\n",
349
					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
350
					name,
351
					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
352
			read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
353
					show_tree_object, NULL);
354 355 356 357 358 359 360 361 362 363 364 365 366
			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;
367 368
}

L
Linus Torvalds 已提交
369 370 371 372 373 374 375
/*
 * 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;

376
	git_config(git_log_config, NULL);
377 378 379 380

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

L
Linus Torvalds 已提交
381 382 383 384 385 386 387 388 389 390 391 392
	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;
393
	rev.use_terminator = 1;
L
Linus Torvalds 已提交
394 395 396 397 398 399 400 401 402 403 404
	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);
}

405
int cmd_log(int argc, const char **argv, const char *prefix)
406 407 408
{
	struct rev_info rev;

409
	git_config(git_log_config, NULL);
410 411 412 413

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

414
	init_revisions(&rev, prefix);
415
	rev.always_show_header = 1;
416
	cmd_log_init(argc, argv, prefix, &rev);
417
	return cmd_log_walk(&rev);
418
}
419

420 421 422
/* format-patch */
#define FORMAT_PATCH_NAME_MAX 64

423 424 425 426 427 428
static int istitlechar(char c)
{
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
		(c >= '0' && c <= '9') || c == '.' || c == '_';
}

429
static const char *fmt_patch_suffix = ".patch";
430
static int numbered = 0;
431
static int auto_number = 1;
432

D
Daniel Barkalow 已提交
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
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);
448
	while (len && value[len - 1] == '\n')
D
Daniel Barkalow 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
		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);
}

464
static int git_format_config(const char *var, const char *value, void *cb)
465 466
{
	if (!strcmp(var, "format.headers")) {
467 468
		if (!value)
			die("format.headers without value");
D
Daniel Barkalow 已提交
469
		add_header(value);
470 471
		return 0;
	}
472 473
	if (!strcmp(var, "format.suffix"))
		return git_config_string(&fmt_patch_suffix, var, value);
474 475 476 477 478 479 480
	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;
	}
481
	if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
482 483
		return 0;
	}
484
	if (!strcmp(var, "format.numbered")) {
485
		if (value && !strcasecmp(value, "auto")) {
486 487 488 489
			auto_number = 1;
			return 0;
		}
		numbered = git_config_bool(var, value);
490
		auto_number = auto_number && numbered;
491 492
		return 0;
	}
493

494
	return git_log_config(var, value, cb);
495 496 497
}


498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
static const char *get_oneline_for_filename(struct commit *commit,
					    int keep_subject)
{
	static char filename[PATH_MAX];
	char *sol;
	int len = 0;
	int suffix_len = strlen(fmt_patch_suffix) + 1;

	sol = strstr(commit->buffer, "\n\n");
	if (!sol)
		filename[0] = '\0';
	else {
		int j, space = 0;

		sol += 2;
		/* strip [PATCH] or [PATCH blabla] */
		if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
			char *eos = strchr(sol + 6, ']');
			if (eos) {
				while (isspace(*eos))
					eos++;
				sol = eos;
			}
		}

		for (j = 0;
		     j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 &&
			     len < sizeof(filename) - suffix_len &&
			     sol[j] && sol[j] != '\n';
		     j++) {
			if (istitlechar(sol[j])) {
				if (space) {
					filename[len++] = '-';
					space = 0;
				}
				filename[len++] = sol[j];
				if (sol[j] == '.')
					while (sol[j + 1] == '.')
						j++;
			} else
				space = 1;
		}
		while (filename[len - 1] == '.'
		       || filename[len - 1] == '-')
			len--;
		filename[len] = '\0';
	}
	return filename;
}

548
static FILE *realstdout = NULL;
549
static const char *output_directory = NULL;
550

551
static int reopen_stdout(const char *oneline, int nr, int total)
552
{
553
	char filename[PATH_MAX];
554
	int len = 0;
555
	int suffix_len = strlen(fmt_patch_suffix) + 1;
556

557
	if (output_directory) {
558 559 560
		len = snprintf(filename, sizeof(filename), "%s",
				output_directory);
		if (len >=
561 562
		    sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len)
			return error("name of output directory is too long");
563 564 565
		if (filename[len - 1] != '/')
			filename[len++] = '/';
	}
566

567 568 569 570 571 572
	if (!oneline)
		len += sprintf(filename + len, "%d", nr);
	else {
		len += sprintf(filename + len, "%04d-", nr);
		len += snprintf(filename + len, sizeof(filename) - len - 1
				- suffix_len, "%s", oneline);
573
		strcpy(filename + len, fmt_patch_suffix);
574
	}
575

576
	fprintf(realstdout, "%s\n", filename);
577 578 579
	if (freopen(filename, "w", stdout) == NULL)
		return error("Cannot open patch file %s",filename);

580
	return 0;
581 582
}

583
static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix)
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
{
	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.");

601
	init_patch_ids(ids);
602 603

	/* given a range a..b get all patch ids for b..a */
604
	init_revisions(&check_rev, prefix);
605 606 607 608
	o1->flags ^= UNINTERESTING;
	o2->flags ^= UNINTERESTING;
	add_pending_object(&check_rev, o1, "o1");
	add_pending_object(&check_rev, o2, "o2");
609 610
	if (prepare_revision_walk(&check_rev))
		die("revision walk setup failed");
611 612 613 614 615 616

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

617
		add_commit_patch_id(commit, ids);
618 619 620
	}

	/* reset for next revision walk */
621 622 623 624
	clear_commit_marks((struct commit *)o1,
			SEEN | UNINTERESTING | SHOWN | ADDED);
	clear_commit_marks((struct commit *)o2,
			SEEN | UNINTERESTING | SHOWN | ADDED);
625 626 627 628
	o1->flags = flags1;
	o2->flags = flags2;
}

629
static void gen_message_id(struct rev_info *info, char *base)
630
{
631
	const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME);
632 633
	const char *email_start = strrchr(committer, '<');
	const char *email_end = strrchr(committer, '>');
634
	struct strbuf buf = STRBUF_INIT;
635
	if (!email_start || !email_end || email_start > email_end - 1)
636
		die("Could not extract email from committer identity.");
637 638 639 640
	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);
641 642
}

643 644 645 646
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)
647 648
{
	const char *committer;
649
	char *head_sha1;
650 651 652 653
	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;
654
	struct shortlog log;
655
	struct strbuf sb = STRBUF_INIT;
656
	int i;
657
	const char *encoding = "utf-8";
658
	struct diff_options opts;
J
Junio C Hamano 已提交
659
	int need_8bit_cte = 0;
660 661 662 663 664 665 666 667 668 669

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

	if (!use_stdout && reopen_stdout(numbered_files ?
				NULL : "cover-letter", 0, rev->total))
		return;

	head_sha1 = sha1_to_hex(head->object.sha1);

J
Junio C Hamano 已提交
670 671
	log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers,
				&need_8bit_cte);
672 673 674 675 676 677 678

	committer = git_committer_info(0);

	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 已提交
679
		      encoding, need_8bit_cte);
680 681 682 683 684
	pp_remainder(CMIT_FMT_EMAIL, &msg, &sb, 0);
	printf("%s\n", sb.buf);

	strbuf_release(&sb);

685
	shortlog_init(&log);
686 687 688 689
	log.wrap_lines = 1;
	log.wrap = 72;
	log.in1 = 2;
	log.in2 = 4;
690 691 692 693 694
	for (i = 0; i < nr; i++)
		shortlog_add_commit(&log, list[i]);

	shortlog_output(&log);

695
	/*
696
	 * We can only do diffstat with a unique reference point
697 698 699 700
	 */
	if (!origin)
		return;

701 702
	memcpy(&opts, &rev->diffopt, sizeof(opts));
	opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
703

704 705 706 707 708 709 710
	diff_setup_done(&opts);

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

	printf("\n");
713 714
}

715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
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 已提交
734
	return xmemdupz(a, z - a);
735 736
}

737
int cmd_format_patch(int argc, const char **argv, const char *prefix)
738 739 740 741
{
	struct commit *commit;
	struct commit **list = NULL;
	struct rev_info rev;
742
	int nr = 0, total, i, j;
743
	int use_stdout = 0;
744
	int start_number = -1;
745
	int keep_subject = 0;
746
	int numbered_files = 0;		/* _just_ numbers */
747
	int subject_prefix = 0;
748
	int ignore_if_in_upstream = 0;
749
	int thread = 0;
750
	int cover_letter = 0;
751
	int boundary_count = 0;
752
	int no_binary_diff = 0;
753
	struct commit *origin = NULL, *head = NULL;
754
	const char *in_reply_to = NULL;
755
	struct patch_ids ids;
J
Junio C Hamano 已提交
756
	char *add_signoff = NULL;
757
	struct strbuf buf = STRBUF_INIT;
758

759
	git_config(git_format_config, NULL);
760
	init_revisions(&rev, prefix);
761 762 763 764 765
	rev.commit_format = CMIT_FMT_EMAIL;
	rev.verbose_header = 1;
	rev.diff = 1;
	rev.combine_merges = 0;
	rev.ignore_merges = 1;
766
	DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
767

768
	rev.subject_prefix = fmt_patch_subject_prefix;
769

770 771
	/*
	 * Parse the arguments before setup_revisions(), or something
772
	 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
773 774 775 776
	 * possibly a valid SHA1.
	 */
	for (i = 1, j = 1; i < argc; i++) {
		if (!strcmp(argv[i], "--stdout"))
777
			use_stdout = 1;
778 779 780
		else if (!strcmp(argv[i], "-n") ||
				!strcmp(argv[i], "--numbered"))
			numbered = 1;
781 782 783 784 785
		else if (!strcmp(argv[i], "-N") ||
				!strcmp(argv[i], "--no-numbered")) {
			numbered = 0;
			auto_number = 0;
		}
786
		else if (!prefixcmp(argv[i], "--start-number="))
787
			start_number = strtol(argv[i] + 15, NULL, 10);
788 789
		else if (!strcmp(argv[i], "--numbered-files"))
			numbered_files = 1;
790 791 792 793 794
		else if (!strcmp(argv[i], "--start-number")) {
			i++;
			if (i == argc)
				die("Need a number for --start-number");
			start_number = strtol(argv[i], NULL, 10);
J
Junio C Hamano 已提交
795
		}
796 797 798 799
		else if (!prefixcmp(argv[i], "--cc=")) {
			ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
			extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5);
		}
J
Junio C Hamano 已提交
800
		else if (!strcmp(argv[i], "-k") ||
801 802 803
				!strcmp(argv[i], "--keep-subject")) {
			keep_subject = 1;
			rev.total = -1;
J
Junio C Hamano 已提交
804
		}
805 806
		else if (!strcmp(argv[i], "--output-directory") ||
			 !strcmp(argv[i], "-o")) {
807
			i++;
808 809 810 811 812
			if (argc <= i)
				die("Which directory?");
			if (output_directory)
				die("Two output directories?");
			output_directory = argv[i];
813
		}
J
Junio C Hamano 已提交
814 815
		else if (!strcmp(argv[i], "--signoff") ||
			 !strcmp(argv[i], "-s")) {
E
Eric W. Biederman 已提交
816 817
			const char *committer;
			const char *endpos;
818
			committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
E
Eric W. Biederman 已提交
819
			endpos = strchr(committer, '>');
J
Junio C Hamano 已提交
820
			if (!endpos)
821
				die("bogus committer info %s\n", committer);
P
Pierre Habouzit 已提交
822
			add_signoff = xmemdupz(committer, endpos - committer + 1);
J
Junio C Hamano 已提交
823
		}
824
		else if (!strcmp(argv[i], "--attach")) {
825
			rev.mime_boundary = git_version_string;
826 827 828 829 830 831 832 833 834 835 836
			rev.no_inline = 1;
		}
		else if (!prefixcmp(argv[i], "--attach=")) {
			rev.mime_boundary = argv[i] + 9;
			rev.no_inline = 1;
		}
		else if (!strcmp(argv[i], "--inline")) {
			rev.mime_boundary = git_version_string;
			rev.no_inline = 0;
		}
		else if (!prefixcmp(argv[i], "--inline=")) {
837
			rev.mime_boundary = argv[i] + 9;
838 839
			rev.no_inline = 0;
		}
840 841
		else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
			ignore_if_in_upstream = 1;
842 843
		else if (!strcmp(argv[i], "--thread"))
			thread = 1;
844
		else if (!prefixcmp(argv[i], "--in-reply-to="))
845 846 847 848 849 850
			in_reply_to = argv[i] + 14;
		else if (!strcmp(argv[i], "--in-reply-to")) {
			i++;
			if (i == argc)
				die("Need a Message-Id for --in-reply-to");
			in_reply_to = argv[i];
851 852 853 854
		} else if (!prefixcmp(argv[i], "--subject-prefix=")) {
			subject_prefix = 1;
			rev.subject_prefix = argv[i] + 17;
		} else if (!prefixcmp(argv[i], "--suffix="))
855
			fmt_patch_suffix = argv[i] + 9;
856 857
		else if (!strcmp(argv[i], "--cover-letter"))
			cover_letter = 1;
858 859
		else if (!strcmp(argv[i], "--no-binary"))
			no_binary_diff = 1;
860
		else
861
			argv[j++] = argv[i];
862
	}
863 864
	argc = j;

D
Daniel Barkalow 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	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');
	}

	rev.extra_headers = strbuf_detach(&buf, 0);

894
	if (start_number < 0)
895
		start_number = 1;
896
	if (numbered && keep_subject)
897
		die ("-n and -k are mutually exclusive.");
898 899
	if (keep_subject && subject_prefix)
		die ("--subject-prefix and -k are mutually exclusive.");
900 901
	if (numbered_files && use_stdout)
		die ("--numbered-files and --stdout are mutually exclusive.");
902

903 904 905
	argc = setup_revisions(argc, argv, &rev, "HEAD");
	if (argc > 1)
		die ("unrecognized argument: %s", argv[1]);
906

907 908
	if (!rev.diffopt.output_format
		|| rev.diffopt.output_format == DIFF_FORMAT_PATCH)
909
		rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
910

911
	if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
912
		DIFF_OPT_SET(&rev.diffopt, BINARY);
913

914
	if (!output_directory && !use_stdout)
915 916
		output_directory = prefix;

917 918 919 920 921 922 923 924
	if (output_directory) {
		if (use_stdout)
			die("standard output, or directory, which one?");
		if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
			die("Could not create directory %s",
			    output_directory);
	}

925
	if (rev.pending.nr == 1) {
926 927 928 929 930 931
		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 已提交
932
			rev.pending.objects[0].item->flags |= UNINTERESTING;
933
			add_head_to_pending(&rev);
J
Junio C Hamano 已提交
934
		}
935 936 937 938
		/*
		 * 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 已提交
939
		 */
940
	}
941 942 943 944 945
	if (cover_letter) {
		/* remember the range */
		int i;
		for (i = 0; i < rev.pending.nr; i++) {
			struct object *o = rev.pending.objects[i].item;
946
			if (!(o->flags & UNINTERESTING))
947 948 949 950 951 952
				head = (struct commit *)o;
		}
		/* We can't generate a cover letter without any patches */
		if (!head)
			return 0;
	}
953

954
	if (ignore_if_in_upstream)
955
		get_patch_ids(&rev, &ids, prefix);
956

957
	if (!use_stdout)
958
		realstdout = xfdopen(xdup(1), "w");
959

960 961
	if (prepare_revision_walk(&rev))
		die("revision walk setup failed");
962
	rev.boundary = 1;
963
	while ((commit = get_revision(&rev)) != NULL) {
964 965 966 967 968 969
		if (commit->object.flags & BOUNDARY) {
			boundary_count++;
			origin = (boundary_count == 1) ? commit : NULL;
			continue;
		}

970 971 972
		/* ignore merges */
		if (commit->parents && commit->parents->next)
			continue;
973 974

		if (ignore_if_in_upstream &&
975
				has_commit_patch_id(commit, &ids))
976 977
			continue;

978
		nr++;
J
Jonas Fonseca 已提交
979
		list = xrealloc(list, nr * sizeof(list[0]));
980 981
		list[nr - 1] = commit;
	}
982
	total = nr;
983 984
	if (!keep_subject && auto_number && total > 1)
		numbered = 1;
985
	if (numbered)
986
		rev.total = total + start_number - 1;
987 988
	if (in_reply_to)
		rev.ref_message_id = clean_message_id(in_reply_to);
989 990 991 992
	if (cover_letter) {
		if (thread)
			gen_message_id(&rev, "cover");
		make_cover_letter(&rev, use_stdout, numbered, numbered_files,
993
				  origin, nr, list, head);
994 995 996 997
		total++;
		start_number--;
	}
	rev.add_signoff = add_signoff;
998 999 1000
	while (0 <= --nr) {
		int shown;
		commit = list[nr];
1001
		rev.nr = total - nr + (start_number - 1);
1002
		/* Make the second and subsequent mails replies to the first */
1003
		if (thread) {
1004
			/* Have we already had a message ID? */
1005
			if (rev.message_id) {
1006 1007 1008 1009 1010 1011
				/*
				 * If we've got the ID to be a reply
				 * to, discard the current ID;
				 * otherwise, make everything a reply
				 * to that.
				 */
1012 1013 1014 1015
				if (rev.ref_message_id)
					free(rev.message_id);
				else
					rev.ref_message_id = rev.message_id;
1016
			}
1017
			gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
1018
		}
1019 1020 1021 1022
		if (!use_stdout && reopen_stdout(numbered_files ? NULL :
				get_oneline_for_filename(commit, keep_subject),
				rev.nr, rev.total))
			die("Failed to create output files");
1023 1024 1025
		shown = log_tree_commit(&rev, commit);
		free(commit->buffer);
		commit->buffer = NULL;
1026 1027 1028 1029 1030 1031 1032 1033 1034

		/* 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;
1035 1036 1037 1038 1039 1040 1041 1042
		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);
		}
1043 1044
		if (!use_stdout)
			fclose(stdout);
1045 1046
	}
	free(list);
1047 1048
	if (ignore_if_in_upstream)
		free_patch_ids(&ids);
1049 1050 1051
	return 0;
}

R
Rene Scharfe 已提交
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
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[] =
S
Stephan Beyer 已提交
1067
"git cherry [-v] <upstream> [<head>] [<limit>]";
R
Rene Scharfe 已提交
1068 1069 1070
int cmd_cherry(int argc, const char **argv, const char *prefix)
{
	struct rev_info revs;
1071
	struct patch_ids ids;
R
Rene Scharfe 已提交
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
	struct commit *commit;
	struct commit_list *list = NULL;
	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:
		usage(cherry_usage);
	}

	init_revisions(&revs, prefix);
	revs.diff = 1;
	revs.combine_merges = 0;
	revs.ignore_merges = 1;
1103
	DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
R
Rene Scharfe 已提交
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116

	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;
	}

1117
	get_patch_ids(&revs, &ids, prefix);
R
Rene Scharfe 已提交
1118 1119 1120 1121 1122

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

	/* reverse the list of commits */
1123 1124
	if (prepare_revision_walk(&revs))
		die("revision walk setup failed");
R
Rene Scharfe 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
	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;
1137
		if (has_commit_patch_id(commit, &ids))
R
Rene Scharfe 已提交
1138 1139 1140
			sign = '-';

		if (verbose) {
1141
			struct strbuf buf = STRBUF_INIT;
1142
			pretty_print_commit(CMIT_FMT_ONELINE, commit,
1143
			                    &buf, 0, NULL, NULL, 0, 0);
R
Rene Scharfe 已提交
1144
			printf("%c %s %s\n", sign,
1145 1146
			       sha1_to_hex(commit->object.sha1), buf.buf);
			strbuf_release(&buf);
R
Rene Scharfe 已提交
1147 1148 1149 1150 1151 1152 1153 1154 1155
		}
		else {
			printf("%c %s\n", sign,
			       sha1_to_hex(commit->object.sha1));
		}

		list = list->next;
	}

1156
	free_patch_ids(&ids);
R
Rene Scharfe 已提交
1157 1158
	return 0;
}