git

Форк
0
/
pretty.c 
2363 строки · 57.7 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "config.h"
5
#include "commit.h"
6
#include "environment.h"
7
#include "gettext.h"
8
#include "hash.h"
9
#include "hex.h"
10
#include "utf8.h"
11
#include "diff.h"
12
#include "pager.h"
13
#include "revision.h"
14
#include "string-list.h"
15
#include "mailmap.h"
16
#include "log-tree.h"
17
#include "notes.h"
18
#include "color.h"
19
#include "reflog-walk.h"
20
#include "gpg-interface.h"
21
#include "trailer.h"
22
#include "run-command.h"
23
#include "object-name.h"
24

25
/*
26
 * The limit for formatting directives, which enable the caller to append
27
 * arbitrarily many bytes to the formatted buffer. This includes padding
28
 * and wrapping formatters.
29
 */
30
#define FORMATTING_LIMIT (16 * 1024)
31

32
static char *user_format;
33
static struct cmt_fmt_map {
34
	const char *name;
35
	enum cmit_fmt format;
36
	int is_tformat;
37
	int expand_tabs_in_log;
38
	int is_alias;
39
	enum date_mode_type default_date_mode_type;
40
	const char *user_format;
41
} *commit_formats;
42
static size_t builtin_formats_len;
43
static size_t commit_formats_len;
44
static size_t commit_formats_alloc;
45
static struct cmt_fmt_map *find_commit_format(const char *sought);
46

47
int commit_format_is_empty(enum cmit_fmt fmt)
48
{
49
	return fmt == CMIT_FMT_USERFORMAT && !*user_format;
50
}
51

52
static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
53
{
54
	free(user_format);
55
	user_format = xstrdup(cp);
56
	if (is_tformat)
57
		rev->use_terminator = 1;
58
	rev->commit_format = CMIT_FMT_USERFORMAT;
59
}
60

61
static int git_pretty_formats_config(const char *var, const char *value,
62
				     const struct config_context *ctx UNUSED,
63
				     void *cb UNUSED)
64
{
65
	struct cmt_fmt_map *commit_format = NULL;
66
	const char *name;
67
	char *fmt;
68
	int i;
69

70
	if (!skip_prefix(var, "pretty.", &name))
71
		return 0;
72

73
	for (i = 0; i < builtin_formats_len; i++) {
74
		if (!strcmp(commit_formats[i].name, name))
75
			return 0;
76
	}
77

78
	for (i = builtin_formats_len; i < commit_formats_len; i++) {
79
		if (!strcmp(commit_formats[i].name, name)) {
80
			commit_format = &commit_formats[i];
81
			break;
82
		}
83
	}
84

85
	if (!commit_format) {
86
		ALLOC_GROW(commit_formats, commit_formats_len+1,
87
			   commit_formats_alloc);
88
		commit_format = &commit_formats[commit_formats_len];
89
		memset(commit_format, 0, sizeof(*commit_format));
90
		commit_formats_len++;
91
	}
92

93
	commit_format->name = xstrdup(name);
94
	commit_format->format = CMIT_FMT_USERFORMAT;
95
	if (git_config_string(&fmt, var, value))
96
		return -1;
97

98
	if (skip_prefix(fmt, "format:", &commit_format->user_format)) {
99
		commit_format->is_tformat = 0;
100
	} else if (skip_prefix(fmt, "tformat:", &commit_format->user_format)) {
101
		commit_format->is_tformat = 1;
102
	} else if (strchr(fmt, '%')) {
103
		commit_format->is_tformat = 1;
104
		commit_format->user_format = fmt;
105
	} else {
106
		commit_format->is_alias = 1;
107
		commit_format->user_format = fmt;
108
	}
109

110
	return 0;
111
}
112

113
static void setup_commit_formats(void)
114
{
115
	struct cmt_fmt_map builtin_formats[] = {
116
		{ "raw",	CMIT_FMT_RAW,		0,	0 },
117
		{ "medium",	CMIT_FMT_MEDIUM,	0,	8 },
118
		{ "short",	CMIT_FMT_SHORT,		0,	0 },
119
		{ "email",	CMIT_FMT_EMAIL,		0,	0 },
120
		{ "mboxrd",	CMIT_FMT_MBOXRD,	0,	0 },
121
		{ "fuller",	CMIT_FMT_FULLER,	0,	8 },
122
		{ "full",	CMIT_FMT_FULL,		0,	8 },
123
		{ "oneline",	CMIT_FMT_ONELINE,	1,	0 },
124
		{ "reference",	CMIT_FMT_USERFORMAT,	1,	0,
125
			0, DATE_SHORT, "%C(auto)%h (%s, %ad)" },
126
		/*
127
		 * Please update $__git_log_pretty_formats in
128
		 * git-completion.bash when you add new formats.
129
		 */
130
	};
131
	commit_formats_len = ARRAY_SIZE(builtin_formats);
132
	builtin_formats_len = commit_formats_len;
133
	ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
134
	COPY_ARRAY(commit_formats, builtin_formats,
135
		   ARRAY_SIZE(builtin_formats));
136

137
	git_config(git_pretty_formats_config, NULL);
138
}
139

140
static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
141
							const char *original,
142
							int num_redirections)
143
{
144
	struct cmt_fmt_map *found = NULL;
145
	size_t found_match_len = 0;
146
	int i;
147

148
	if (num_redirections >= commit_formats_len)
149
		die("invalid --pretty format: "
150
		    "'%s' references an alias which points to itself",
151
		    original);
152

153
	for (i = 0; i < commit_formats_len; i++) {
154
		size_t match_len;
155

156
		if (!istarts_with(commit_formats[i].name, sought))
157
			continue;
158

159
		match_len = strlen(commit_formats[i].name);
160
		if (found == NULL || found_match_len > match_len) {
161
			found = &commit_formats[i];
162
			found_match_len = match_len;
163
		}
164
	}
165

166
	if (found && found->is_alias) {
167
		found = find_commit_format_recursive(found->user_format,
168
						     original,
169
						     num_redirections+1);
170
	}
171

172
	return found;
173
}
174

175
static struct cmt_fmt_map *find_commit_format(const char *sought)
176
{
177
	if (!commit_formats)
178
		setup_commit_formats();
179

180
	return find_commit_format_recursive(sought, sought, 0);
181
}
182

183
void get_commit_format(const char *arg, struct rev_info *rev)
184
{
185
	struct cmt_fmt_map *commit_format;
186

187
	rev->use_terminator = 0;
188
	if (!arg) {
189
		rev->commit_format = CMIT_FMT_DEFAULT;
190
		return;
191
	}
192
	if (skip_prefix(arg, "format:", &arg)) {
193
		save_user_format(rev, arg, 0);
194
		return;
195
	}
196

197
	if (!*arg || skip_prefix(arg, "tformat:", &arg) || strchr(arg, '%')) {
198
		save_user_format(rev, arg, 1);
199
		return;
200
	}
201

202
	commit_format = find_commit_format(arg);
203
	if (!commit_format)
204
		die("invalid --pretty format: %s", arg);
205

206
	rev->commit_format = commit_format->format;
207
	rev->use_terminator = commit_format->is_tformat;
208
	rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
209
	if (!rev->date_mode_explicit && commit_format->default_date_mode_type)
210
		rev->date_mode.type = commit_format->default_date_mode_type;
211
	if (commit_format->format == CMIT_FMT_USERFORMAT) {
212
		save_user_format(rev, commit_format->user_format,
213
				 commit_format->is_tformat);
214
	}
215
}
216

217
/*
218
 * Generic support for pretty-printing the header
219
 */
220
static int get_one_line(const char *msg)
221
{
222
	int ret = 0;
223

224
	for (;;) {
225
		char c = *msg++;
226
		if (!c)
227
			break;
228
		ret++;
229
		if (c == '\n')
230
			break;
231
	}
232
	return ret;
233
}
234

235
/* High bit set, or ISO-2022-INT */
236
static int non_ascii(int ch)
237
{
238
	return !isascii(ch) || ch == '\033';
239
}
240

241
int has_non_ascii(const char *s)
242
{
243
	int ch;
244
	if (!s)
245
		return 0;
246
	while ((ch = *s++) != '\0') {
247
		if (non_ascii(ch))
248
			return 1;
249
	}
250
	return 0;
251
}
252

253
static int is_rfc822_special(char ch)
254
{
255
	switch (ch) {
256
	case '(':
257
	case ')':
258
	case '<':
259
	case '>':
260
	case '[':
261
	case ']':
262
	case ':':
263
	case ';':
264
	case '@':
265
	case ',':
266
	case '.':
267
	case '"':
268
	case '\\':
269
		return 1;
270
	default:
271
		return 0;
272
	}
273
}
274

275
static int needs_rfc822_quoting(const char *s, int len)
276
{
277
	int i;
278
	for (i = 0; i < len; i++)
279
		if (is_rfc822_special(s[i]))
280
			return 1;
281
	return 0;
282
}
283

284
static int last_line_length(struct strbuf *sb)
285
{
286
	int i;
287

288
	/* How many bytes are already used on the last line? */
289
	for (i = sb->len - 1; i >= 0; i--)
290
		if (sb->buf[i] == '\n')
291
			break;
292
	return sb->len - (i + 1);
293
}
294

295
static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
296
{
297
	int i;
298

299
	/* just a guess, we may have to also backslash-quote */
300
	strbuf_grow(out, len + 2);
301

302
	strbuf_addch(out, '"');
303
	for (i = 0; i < len; i++) {
304
		switch (s[i]) {
305
		case '"':
306
		case '\\':
307
			strbuf_addch(out, '\\');
308
			/* fall through */
309
		default:
310
			strbuf_addch(out, s[i]);
311
		}
312
	}
313
	strbuf_addch(out, '"');
314
}
315

316
enum rfc2047_type {
317
	RFC2047_SUBJECT,
318
	RFC2047_ADDRESS
319
};
320

321
static int is_rfc2047_special(char ch, enum rfc2047_type type)
322
{
323
	/*
324
	 * rfc2047, section 4.2:
325
	 *
326
	 *    8-bit values which correspond to printable ASCII characters other
327
	 *    than "=", "?", and "_" (underscore), MAY be represented as those
328
	 *    characters.  (But see section 5 for restrictions.)  In
329
	 *    particular, SPACE and TAB MUST NOT be represented as themselves
330
	 *    within encoded words.
331
	 */
332

333
	/*
334
	 * rule out non-ASCII characters and non-printable characters (the
335
	 * non-ASCII check should be redundant as isprint() is not localized
336
	 * and only knows about ASCII, but be defensive about that)
337
	 */
338
	if (non_ascii(ch) || !isprint(ch))
339
		return 1;
340

341
	/*
342
	 * rule out special printable characters (' ' should be the only
343
	 * whitespace character considered printable, but be defensive and use
344
	 * isspace())
345
	 */
346
	if (isspace(ch) || ch == '=' || ch == '?' || ch == '_')
347
		return 1;
348

349
	/*
350
	 * rfc2047, section 5.3:
351
	 *
352
	 *    As a replacement for a 'word' entity within a 'phrase', for example,
353
	 *    one that precedes an address in a From, To, or Cc header.  The ABNF
354
	 *    definition for 'phrase' from RFC 822 thus becomes:
355
	 *
356
	 *    phrase = 1*( encoded-word / word )
357
	 *
358
	 *    In this case the set of characters that may be used in a "Q"-encoded
359
	 *    'encoded-word' is restricted to: <upper and lower case ASCII
360
	 *    letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
361
	 *    (underscore, ASCII 95.)>.  An 'encoded-word' that appears within a
362
	 *    'phrase' MUST be separated from any adjacent 'word', 'text' or
363
	 *    'special' by 'linear-white-space'.
364
	 */
365

366
	if (type != RFC2047_ADDRESS)
367
		return 0;
368

369
	/* '=' and '_' are special cases and have been checked above */
370
	return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
371
}
372

373
static int needs_rfc2047_encoding(const char *line, int len)
374
{
375
	int i;
376

377
	for (i = 0; i < len; i++) {
378
		int ch = line[i];
379
		if (non_ascii(ch) || ch == '\n')
380
			return 1;
381
		if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
382
			return 1;
383
	}
384

385
	return 0;
386
}
387

388
static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
389
		       const char *encoding, enum rfc2047_type type)
390
{
391
	static const int max_encoded_length = 76; /* per rfc2047 */
392
	int i;
393
	int line_len = last_line_length(sb);
394

395
	strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
396
	strbuf_addf(sb, "=?%s?q?", encoding);
397
	line_len += strlen(encoding) + 5; /* 5 for =??q? */
398

399
	while (len) {
400
		/*
401
		 * RFC 2047, section 5 (3):
402
		 *
403
		 * Each 'encoded-word' MUST represent an integral number of
404
		 * characters.  A multi-octet character may not be split across
405
		 * adjacent 'encoded- word's.
406
		 */
407
		const unsigned char *p = (const unsigned char *)line;
408
		int chrlen = mbs_chrlen(&line, &len, encoding);
409
		int is_special = (chrlen > 1) || is_rfc2047_special(*p, type);
410

411
		/* "=%02X" * chrlen, or the byte itself */
412
		const char *encoded_fmt = is_special ? "=%02X"    : "%c";
413
		int	    encoded_len = is_special ? 3 * chrlen : 1;
414

415
		/*
416
		 * According to RFC 2047, we could encode the special character
417
		 * ' ' (space) with '_' (underscore) for readability. But many
418
		 * programs do not understand this and just leave the
419
		 * underscore in place. Thus, we do nothing special here, which
420
		 * causes ' ' to be encoded as '=20', avoiding this problem.
421
		 */
422

423
		if (line_len + encoded_len + 2 > max_encoded_length) {
424
			/* It won't fit with trailing "?=" --- break the line */
425
			strbuf_addf(sb, "?=\n =?%s?q?", encoding);
426
			line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
427
		}
428

429
		for (i = 0; i < chrlen; i++)
430
			strbuf_addf(sb, encoded_fmt, p[i]);
431
		line_len += encoded_len;
432
	}
433
	strbuf_addstr(sb, "?=");
434
}
435

436
const char *show_ident_date(const struct ident_split *ident,
437
			    struct date_mode mode)
438
{
439
	timestamp_t date = 0;
440
	long tz = 0;
441

442
	if (ident->date_begin && ident->date_end)
443
		date = parse_timestamp(ident->date_begin, NULL, 10);
444
	if (date_overflows(date))
445
		date = 0;
446
	else {
447
		if (ident->tz_begin && ident->tz_end)
448
			tz = strtol(ident->tz_begin, NULL, 10);
449
		if (tz >= INT_MAX || tz <= INT_MIN)
450
			tz = 0;
451
	}
452
	return show_date(date, tz, mode);
453
}
454

455
static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,
456
					 const char *buf, size_t buflen)
457
{
458
	strbuf_addstr(sb, color);
459
	strbuf_add(sb, buf, buflen);
460
	if (*color)
461
		strbuf_addstr(sb, GIT_COLOR_RESET);
462
}
463

464
static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt,
465
				   const char *line, size_t linelen,
466
				   int color, enum grep_context ctx,
467
				   enum grep_header_field field)
468
{
469
	const char *buf, *eol, *line_color, *match_color;
470
	regmatch_t match;
471
	int eflags = 0;
472

473
	buf = line;
474
	eol = buf + linelen;
475

476
	if (!opt || !want_color(color) || opt->invert)
477
		goto end;
478

479
	line_color = opt->colors[GREP_COLOR_SELECTED];
480
	match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
481

482
	while (grep_next_match(opt, buf, eol, ctx, &match, field, eflags)) {
483
		if (match.rm_so == match.rm_eo)
484
			break;
485

486
		strbuf_add_with_color(sb, line_color, buf, match.rm_so);
487
		strbuf_add_with_color(sb, match_color, buf + match.rm_so,
488
				      match.rm_eo - match.rm_so);
489
		buf += match.rm_eo;
490
		eflags = REG_NOTBOL;
491
	}
492

493
	if (eflags)
494
		strbuf_add_with_color(sb, line_color, buf, eol - buf);
495
	else {
496
end:
497
		strbuf_add(sb, buf, eol - buf);
498
	}
499
}
500

501
static int use_in_body_from(const struct pretty_print_context *pp,
502
			    const struct ident_split *ident)
503
{
504
	if (pp->rev && pp->rev->force_in_body_from)
505
		return 1;
506
	if (ident_cmp(pp->from_ident, ident))
507
		return 1;
508
	return 0;
509
}
510

511
void pp_user_info(struct pretty_print_context *pp,
512
		  const char *what, struct strbuf *sb,
513
		  const char *line, const char *encoding)
514
{
515
	struct ident_split ident;
516
	char *line_end;
517
	const char *mailbuf, *namebuf;
518
	size_t namelen, maillen;
519
	int max_length = 78; /* per rfc2822 */
520

521
	if (pp->fmt == CMIT_FMT_ONELINE)
522
		return;
523

524
	line_end = strchrnul(line, '\n');
525
	if (split_ident_line(&ident, line, line_end - line))
526
		return;
527

528
	mailbuf = ident.mail_begin;
529
	maillen = ident.mail_end - ident.mail_begin;
530
	namebuf = ident.name_begin;
531
	namelen = ident.name_end - ident.name_begin;
532

533
	if (pp->mailmap)
534
		map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
535

536
	if (cmit_fmt_is_mail(pp->fmt)) {
537
		if (pp->from_ident && use_in_body_from(pp, &ident)) {
538
			struct strbuf buf = STRBUF_INIT;
539

540
			strbuf_addstr(&buf, "From: ");
541
			strbuf_add(&buf, namebuf, namelen);
542
			strbuf_addstr(&buf, " <");
543
			strbuf_add(&buf, mailbuf, maillen);
544
			strbuf_addstr(&buf, ">\n");
545
			string_list_append(&pp->in_body_headers,
546
					   strbuf_detach(&buf, NULL));
547

548
			mailbuf = pp->from_ident->mail_begin;
549
			maillen = pp->from_ident->mail_end - mailbuf;
550
			namebuf = pp->from_ident->name_begin;
551
			namelen = pp->from_ident->name_end - namebuf;
552
		}
553

554
		strbuf_addstr(sb, "From: ");
555
		if (pp->encode_email_headers &&
556
		    needs_rfc2047_encoding(namebuf, namelen)) {
557
			add_rfc2047(sb, namebuf, namelen,
558
				    encoding, RFC2047_ADDRESS);
559
			max_length = 76; /* per rfc2047 */
560
		} else if (needs_rfc822_quoting(namebuf, namelen)) {
561
			struct strbuf quoted = STRBUF_INIT;
562
			add_rfc822_quoted(&quoted, namebuf, namelen);
563
			strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
564
							-6, 1, max_length);
565
			strbuf_release(&quoted);
566
		} else {
567
			strbuf_add_wrapped_bytes(sb, namebuf, namelen,
568
						 -6, 1, max_length);
569
		}
570

571
		if (max_length <
572
		    last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
573
			strbuf_addch(sb, '\n');
574
		strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
575
	} else {
576
		struct strbuf id = STRBUF_INIT;
577
		enum grep_header_field field = GREP_HEADER_FIELD_MAX;
578
		struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
579

580
		if (!strcmp(what, "Author"))
581
			field = GREP_HEADER_AUTHOR;
582
		else if (!strcmp(what, "Commit"))
583
			field = GREP_HEADER_COMMITTER;
584

585
		strbuf_addf(sb, "%s: ", what);
586
		if (pp->fmt == CMIT_FMT_FULLER)
587
			strbuf_addchars(sb, ' ', 4);
588

589
		strbuf_addf(&id, "%.*s <%.*s>", (int)namelen, namebuf,
590
			    (int)maillen, mailbuf);
591

592
		append_line_with_color(sb, opt, id.buf, id.len, pp->color,
593
				       GREP_CONTEXT_HEAD, field);
594
		strbuf_addch(sb, '\n');
595
		strbuf_release(&id);
596
	}
597

598
	switch (pp->fmt) {
599
	case CMIT_FMT_MEDIUM:
600
		strbuf_addf(sb, "Date:   %s\n",
601
			    show_ident_date(&ident, pp->date_mode));
602
		break;
603
	case CMIT_FMT_EMAIL:
604
	case CMIT_FMT_MBOXRD:
605
		strbuf_addf(sb, "Date: %s\n",
606
			    show_ident_date(&ident, DATE_MODE(RFC2822)));
607
		break;
608
	case CMIT_FMT_FULLER:
609
		strbuf_addf(sb, "%sDate: %s\n", what,
610
			    show_ident_date(&ident, pp->date_mode));
611
		break;
612
	default:
613
		/* notin' */
614
		break;
615
	}
616
}
617

618
static int is_blank_line(const char *line, int *len_p)
619
{
620
	int len = *len_p;
621
	while (len && isspace(line[len - 1]))
622
		len--;
623
	*len_p = len;
624
	return !len;
625
}
626

627
const char *skip_blank_lines(const char *msg)
628
{
629
	for (;;) {
630
		int linelen = get_one_line(msg);
631
		int ll = linelen;
632
		if (!linelen)
633
			break;
634
		if (!is_blank_line(msg, &ll))
635
			break;
636
		msg += linelen;
637
	}
638
	return msg;
639
}
640

641
static void add_merge_info(const struct pretty_print_context *pp,
642
			   struct strbuf *sb, const struct commit *commit)
643
{
644
	struct commit_list *parent = commit->parents;
645

646
	if ((pp->fmt == CMIT_FMT_ONELINE) || (cmit_fmt_is_mail(pp->fmt)) ||
647
	    !parent || !parent->next)
648
		return;
649

650
	strbuf_addstr(sb, "Merge:");
651

652
	while (parent) {
653
		struct object_id *oidp = &parent->item->object.oid;
654
		strbuf_addch(sb, ' ');
655
		if (pp->abbrev)
656
			strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
657
		else
658
			strbuf_addstr(sb, oid_to_hex(oidp));
659
		parent = parent->next;
660
	}
661
	strbuf_addch(sb, '\n');
662
}
663

664
static char *get_header(const char *msg, const char *key)
665
{
666
	size_t len;
667
	const char *v = find_commit_header(msg, key, &len);
668
	return v ? xmemdupz(v, len) : NULL;
669
}
670

671
static char *replace_encoding_header(char *buf, const char *encoding)
672
{
673
	struct strbuf tmp = STRBUF_INIT;
674
	size_t start, len;
675
	char *cp = buf;
676

677
	/* guess if there is an encoding header before a \n\n */
678
	while (!starts_with(cp, "encoding ")) {
679
		cp = strchr(cp, '\n');
680
		if (!cp || *++cp == '\n')
681
			return buf;
682
	}
683
	start = cp - buf;
684
	cp = strchr(cp, '\n');
685
	if (!cp)
686
		return buf; /* should not happen but be defensive */
687
	len = cp + 1 - (buf + start);
688

689
	strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
690
	if (is_encoding_utf8(encoding)) {
691
		/* we have re-coded to UTF-8; drop the header */
692
		strbuf_remove(&tmp, start, len);
693
	} else {
694
		/* just replaces XXXX in 'encoding XXXX\n' */
695
		strbuf_splice(&tmp, start + strlen("encoding "),
696
					  len - strlen("encoding \n"),
697
					  encoding, strlen(encoding));
698
	}
699
	return strbuf_detach(&tmp, NULL);
700
}
701

702
const char *repo_logmsg_reencode(struct repository *r,
703
				 const struct commit *commit,
704
				 char **commit_encoding,
705
				 const char *output_encoding)
706
{
707
	static const char *utf8 = "UTF-8";
708
	const char *use_encoding;
709
	char *encoding;
710
	const char *msg = repo_get_commit_buffer(r, commit, NULL);
711
	char *out;
712

713
	if (!output_encoding || !*output_encoding) {
714
		if (commit_encoding)
715
			*commit_encoding = get_header(msg, "encoding");
716
		return msg;
717
	}
718
	encoding = get_header(msg, "encoding");
719
	if (commit_encoding)
720
		*commit_encoding = encoding;
721
	use_encoding = encoding ? encoding : utf8;
722
	if (same_encoding(use_encoding, output_encoding)) {
723
		/*
724
		 * No encoding work to be done. If we have no encoding header
725
		 * at all, then there's nothing to do, and we can return the
726
		 * message verbatim (whether newly allocated or not).
727
		 */
728
		if (!encoding)
729
			return msg;
730

731
		/*
732
		 * Otherwise, we still want to munge the encoding header in the
733
		 * result, which will be done by modifying the buffer. If we
734
		 * are using a fresh copy, we can reuse it. But if we are using
735
		 * the cached copy from repo_get_commit_buffer, we need to duplicate it
736
		 * to avoid munging the cached copy.
737
		 */
738
		if (msg == get_cached_commit_buffer(r, commit, NULL))
739
			out = xstrdup(msg);
740
		else
741
			out = (char *)msg;
742
	}
743
	else {
744
		/*
745
		 * There's actual encoding work to do. Do the reencoding, which
746
		 * still leaves the header to be replaced in the next step. At
747
		 * this point, we are done with msg. If we allocated a fresh
748
		 * copy, we can free it.
749
		 */
750
		out = reencode_string(msg, output_encoding, use_encoding);
751
		if (out)
752
			repo_unuse_commit_buffer(r, commit, msg);
753
	}
754

755
	/*
756
	 * This replacement actually consumes the buffer we hand it, so we do
757
	 * not have to worry about freeing the old "out" here.
758
	 */
759
	if (out)
760
		out = replace_encoding_header(out, output_encoding);
761

762
	if (!commit_encoding)
763
		free(encoding);
764
	/*
765
	 * If the re-encoding failed, out might be NULL here; in that
766
	 * case we just return the commit message verbatim.
767
	 */
768
	return out ? out : msg;
769
}
770

771
static int mailmap_name(const char **email, size_t *email_len,
772
			const char **name, size_t *name_len)
773
{
774
	static struct string_list *mail_map;
775
	if (!mail_map) {
776
		CALLOC_ARRAY(mail_map, 1);
777
		read_mailmap(mail_map);
778
	}
779
	return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
780
}
781

782
static size_t format_person_part(struct strbuf *sb, char part,
783
				 const char *msg, int len,
784
				 struct date_mode dmode)
785
{
786
	/* currently all placeholders have same length */
787
	const int placeholder_len = 2;
788
	struct ident_split s;
789
	const char *name, *mail;
790
	size_t maillen, namelen;
791

792
	if (split_ident_line(&s, msg, len) < 0)
793
		goto skip;
794

795
	name = s.name_begin;
796
	namelen = s.name_end - s.name_begin;
797
	mail = s.mail_begin;
798
	maillen = s.mail_end - s.mail_begin;
799

800
	if (part == 'N' || part == 'E' || part == 'L') /* mailmap lookup */
801
		mailmap_name(&mail, &maillen, &name, &namelen);
802
	if (part == 'n' || part == 'N') {	/* name */
803
		strbuf_add(sb, name, namelen);
804
		return placeholder_len;
805
	}
806
	if (part == 'e' || part == 'E') {	/* email */
807
		strbuf_add(sb, mail, maillen);
808
		return placeholder_len;
809
	}
810
	if (part == 'l' || part == 'L') {	/* local-part */
811
		const char *at = memchr(mail, '@', maillen);
812
		if (at)
813
			maillen = at - mail;
814
		strbuf_add(sb, mail, maillen);
815
		return placeholder_len;
816
	}
817

818
	if (!s.date_begin)
819
		goto skip;
820

821
	if (part == 't') {	/* date, UNIX timestamp */
822
		strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
823
		return placeholder_len;
824
	}
825

826
	switch (part) {
827
	case 'd':	/* date */
828
		strbuf_addstr(sb, show_ident_date(&s, dmode));
829
		return placeholder_len;
830
	case 'D':	/* date, RFC2822 style */
831
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RFC2822)));
832
		return placeholder_len;
833
	case 'r':	/* date, relative */
834
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RELATIVE)));
835
		return placeholder_len;
836
	case 'i':	/* date, ISO 8601-like */
837
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601)));
838
		return placeholder_len;
839
	case 'I':	/* date, ISO 8601 strict */
840
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
841
		return placeholder_len;
842
	case 'h':	/* date, human */
843
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(HUMAN)));
844
		return placeholder_len;
845
	case 's':
846
		strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(SHORT)));
847
		return placeholder_len;
848
	}
849

850
skip:
851
	/*
852
	 * reading from either a bogus commit, or a reflog entry with
853
	 * %gn, %ge, etc.; 'sb' cannot be updated, but we still need
854
	 * to compute a valid return value.
855
	 */
856
	if (part == 'n' || part == 'e' || part == 't' || part == 'd'
857
	    || part == 'D' || part == 'r' || part == 'i')
858
		return placeholder_len;
859

860
	return 0; /* unknown placeholder */
861
}
862

863
struct chunk {
864
	size_t off;
865
	size_t len;
866
};
867

868
enum flush_type {
869
	no_flush,
870
	flush_right,
871
	flush_left,
872
	flush_left_and_steal,
873
	flush_both
874
};
875

876
enum trunc_type {
877
	trunc_none,
878
	trunc_left,
879
	trunc_middle,
880
	trunc_right
881
};
882

883
struct format_commit_context {
884
	struct repository *repository;
885
	const struct commit *commit;
886
	const struct pretty_print_context *pretty_ctx;
887
	unsigned commit_header_parsed:1;
888
	unsigned commit_message_parsed:1;
889
	struct signature_check signature_check;
890
	enum flush_type flush_type;
891
	enum trunc_type truncate;
892
	const char *message;
893
	char *commit_encoding;
894
	size_t width, indent1, indent2;
895
	int auto_color;
896
	int padding;
897

898
	/* These offsets are relative to the start of the commit message. */
899
	struct chunk author;
900
	struct chunk committer;
901
	size_t message_off;
902
	size_t subject_off;
903
	size_t body_off;
904

905
	/* The following ones are relative to the result struct strbuf. */
906
	size_t wrap_start;
907
};
908

909
static void parse_commit_header(struct format_commit_context *context)
910
{
911
	const char *msg = context->message;
912
	int i;
913

914
	for (i = 0; msg[i]; i++) {
915
		const char *name;
916
		int eol;
917
		for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
918
			; /* do nothing */
919

920
		if (i == eol) {
921
			break;
922
		} else if (skip_prefix(msg + i, "author ", &name)) {
923
			context->author.off = name - msg;
924
			context->author.len = msg + eol - name;
925
		} else if (skip_prefix(msg + i, "committer ", &name)) {
926
			context->committer.off = name - msg;
927
			context->committer.len = msg + eol - name;
928
		}
929
		i = eol;
930
	}
931
	context->message_off = i;
932
	context->commit_header_parsed = 1;
933
}
934

935
static int istitlechar(char c)
936
{
937
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
938
		(c >= '0' && c <= '9') || c == '.' || c == '_';
939
}
940

941
void format_sanitized_subject(struct strbuf *sb, const char *msg, size_t len)
942
{
943
	size_t trimlen;
944
	size_t start_len = sb->len;
945
	int space = 2;
946
	int i;
947

948
	for (i = 0; i < len; i++) {
949
		if (istitlechar(msg[i])) {
950
			if (space == 1)
951
				strbuf_addch(sb, '-');
952
			space = 0;
953
			strbuf_addch(sb, msg[i]);
954
			if (msg[i] == '.')
955
				while (msg[i+1] == '.')
956
					i++;
957
		} else
958
			space |= 1;
959
	}
960

961
	/* trim any trailing '.' or '-' characters */
962
	trimlen = 0;
963
	while (sb->len - trimlen > start_len &&
964
		(sb->buf[sb->len - 1 - trimlen] == '.'
965
		|| sb->buf[sb->len - 1 - trimlen] == '-'))
966
		trimlen++;
967
	strbuf_remove(sb, sb->len - trimlen, trimlen);
968
}
969

970
const char *format_subject(struct strbuf *sb, const char *msg,
971
			   const char *line_separator)
972
{
973
	int first = 1;
974

975
	for (;;) {
976
		const char *line = msg;
977
		int linelen = get_one_line(line);
978

979
		msg += linelen;
980
		if (!linelen || is_blank_line(line, &linelen))
981
			break;
982

983
		if (!sb)
984
			continue;
985
		strbuf_grow(sb, linelen + 2);
986
		if (!first)
987
			strbuf_addstr(sb, line_separator);
988
		strbuf_add(sb, line, linelen);
989
		first = 0;
990
	}
991
	return msg;
992
}
993

994
static void parse_commit_message(struct format_commit_context *c)
995
{
996
	const char *msg = c->message + c->message_off;
997
	const char *start = c->message;
998

999
	msg = skip_blank_lines(msg);
1000
	c->subject_off = msg - start;
1001

1002
	msg = format_subject(NULL, msg, NULL);
1003
	msg = skip_blank_lines(msg);
1004
	c->body_off = msg - start;
1005

1006
	c->commit_message_parsed = 1;
1007
}
1008

1009
static void strbuf_wrap(struct strbuf *sb, size_t pos,
1010
			size_t width, size_t indent1, size_t indent2)
1011
{
1012
	struct strbuf tmp = STRBUF_INIT;
1013

1014
	if (pos)
1015
		strbuf_add(&tmp, sb->buf, pos);
1016
	strbuf_add_wrapped_text(&tmp, sb->buf + pos,
1017
				cast_size_t_to_int(indent1),
1018
				cast_size_t_to_int(indent2),
1019
				cast_size_t_to_int(width));
1020
	strbuf_swap(&tmp, sb);
1021
	strbuf_release(&tmp);
1022
}
1023

1024
static void rewrap_message_tail(struct strbuf *sb,
1025
				struct format_commit_context *c,
1026
				size_t new_width, size_t new_indent1,
1027
				size_t new_indent2)
1028
{
1029
	if (c->width == new_width && c->indent1 == new_indent1 &&
1030
	    c->indent2 == new_indent2)
1031
		return;
1032
	if (c->wrap_start < sb->len)
1033
		strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
1034
	c->wrap_start = sb->len;
1035
	c->width = new_width;
1036
	c->indent1 = new_indent1;
1037
	c->indent2 = new_indent2;
1038
}
1039

1040
static int format_reflog_person(struct strbuf *sb,
1041
				char part,
1042
				struct reflog_walk_info *log,
1043
				struct date_mode dmode)
1044
{
1045
	const char *ident;
1046

1047
	if (!log)
1048
		return 2;
1049

1050
	ident = get_reflog_ident(log);
1051
	if (!ident)
1052
		return 2;
1053

1054
	return format_person_part(sb, part, ident, strlen(ident), dmode);
1055
}
1056

1057
static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
1058
			  const char *placeholder,
1059
			  struct format_commit_context *c)
1060
{
1061
	const char *rest = placeholder;
1062
	const char *basic_color = NULL;
1063

1064
	if (placeholder[1] == '(') {
1065
		const char *begin = placeholder + 2;
1066
		const char *end = strchr(begin, ')');
1067
		char color[COLOR_MAXLEN];
1068

1069
		if (!end)
1070
			return 0;
1071

1072
		if (skip_prefix(begin, "auto,", &begin)) {
1073
			if (!want_color(c->pretty_ctx->color))
1074
				return end - placeholder + 1;
1075
		} else if (skip_prefix(begin, "always,", &begin)) {
1076
			/* nothing to do; we do not respect want_color at all */
1077
		} else {
1078
			/* the default is the same as "auto" */
1079
			if (!want_color(c->pretty_ctx->color))
1080
				return end - placeholder + 1;
1081
		}
1082

1083
		if (color_parse_mem(begin, end - begin, color) < 0)
1084
			die(_("unable to parse --pretty format"));
1085
		strbuf_addstr(sb, color);
1086
		return end - placeholder + 1;
1087
	}
1088

1089
	/*
1090
	 * We handle things like "%C(red)" above; for historical reasons, there
1091
	 * are a few colors that can be specified without parentheses (and
1092
	 * they cannot support things like "auto" or "always" at all).
1093
	 */
1094
	if (skip_prefix(placeholder + 1, "red", &rest))
1095
		basic_color = GIT_COLOR_RED;
1096
	else if (skip_prefix(placeholder + 1, "green", &rest))
1097
		basic_color = GIT_COLOR_GREEN;
1098
	else if (skip_prefix(placeholder + 1, "blue", &rest))
1099
		basic_color = GIT_COLOR_BLUE;
1100
	else if (skip_prefix(placeholder + 1, "reset", &rest))
1101
		basic_color = GIT_COLOR_RESET;
1102

1103
	if (basic_color && want_color(c->pretty_ctx->color))
1104
		strbuf_addstr(sb, basic_color);
1105

1106
	return rest - placeholder;
1107
}
1108

1109
static size_t parse_padding_placeholder(const char *placeholder,
1110
					struct format_commit_context *c)
1111
{
1112
	const char *ch = placeholder;
1113
	enum flush_type flush_type;
1114
	int to_column = 0;
1115

1116
	switch (*ch++) {
1117
	case '<':
1118
		flush_type = flush_right;
1119
		break;
1120
	case '>':
1121
		if (*ch == '<') {
1122
			flush_type = flush_both;
1123
			ch++;
1124
		} else if (*ch == '>') {
1125
			flush_type = flush_left_and_steal;
1126
			ch++;
1127
		} else
1128
			flush_type = flush_left;
1129
		break;
1130
	default:
1131
		return 0;
1132
	}
1133

1134
	/* the next value means "wide enough to that column" */
1135
	if (*ch == '|') {
1136
		to_column = 1;
1137
		ch++;
1138
	}
1139

1140
	if (*ch == '(') {
1141
		const char *start = ch + 1;
1142
		const char *end = start + strcspn(start, ",)");
1143
		char *next;
1144
		int width;
1145
		if (!*end || end == start)
1146
			return 0;
1147
		width = strtol(start, &next, 10);
1148

1149
		/*
1150
		 * We need to limit the amount of padding, or otherwise this
1151
		 * would allow the user to pad the buffer by arbitrarily many
1152
		 * bytes and thus cause resource exhaustion.
1153
		 */
1154
		if (width < -FORMATTING_LIMIT || width > FORMATTING_LIMIT)
1155
			return 0;
1156

1157
		if (next == start || width == 0)
1158
			return 0;
1159
		if (width < 0) {
1160
			if (to_column)
1161
				width += term_columns();
1162
			if (width < 0)
1163
				return 0;
1164
		}
1165
		c->padding = to_column ? -width : width;
1166
		c->flush_type = flush_type;
1167

1168
		if (*end == ',') {
1169
			start = end + 1;
1170
			end = strchr(start, ')');
1171
			if (!end || end == start)
1172
				return 0;
1173
			if (starts_with(start, "trunc)"))
1174
				c->truncate = trunc_right;
1175
			else if (starts_with(start, "ltrunc)"))
1176
				c->truncate = trunc_left;
1177
			else if (starts_with(start, "mtrunc)"))
1178
				c->truncate = trunc_middle;
1179
			else
1180
				return 0;
1181
		} else
1182
			c->truncate = trunc_none;
1183

1184
		return end - placeholder + 1;
1185
	}
1186
	return 0;
1187
}
1188

1189
static int match_placeholder_arg_value(const char *to_parse, const char *candidate,
1190
				       const char **end, const char **valuestart,
1191
				       size_t *valuelen)
1192
{
1193
	const char *p;
1194

1195
	if (!(skip_prefix(to_parse, candidate, &p)))
1196
		return 0;
1197
	if (valuestart) {
1198
		if (*p == '=') {
1199
			*valuestart = p + 1;
1200
			*valuelen = strcspn(*valuestart, ",)");
1201
			p = *valuestart + *valuelen;
1202
		} else {
1203
			if (*p != ',' && *p != ')')
1204
				return 0;
1205
			*valuestart = NULL;
1206
			*valuelen = 0;
1207
		}
1208
	}
1209
	if (*p == ',') {
1210
		*end = p + 1;
1211
		return 1;
1212
	}
1213
	if (*p == ')') {
1214
		*end = p;
1215
		return 1;
1216
	}
1217
	return 0;
1218
}
1219

1220
static int match_placeholder_bool_arg(const char *to_parse, const char *candidate,
1221
				      const char **end, int *val)
1222
{
1223
	const char *argval;
1224
	char *strval;
1225
	size_t arglen;
1226
	int v;
1227

1228
	if (!match_placeholder_arg_value(to_parse, candidate, end, &argval, &arglen))
1229
		return 0;
1230

1231
	if (!argval) {
1232
		*val = 1;
1233
		return 1;
1234
	}
1235

1236
	strval = xstrndup(argval, arglen);
1237
	v = git_parse_maybe_bool(strval);
1238
	free(strval);
1239

1240
	if (v == -1)
1241
		return 0;
1242

1243
	*val = v;
1244

1245
	return 1;
1246
}
1247

1248
static int format_trailer_match_cb(const struct strbuf *key, void *ud)
1249
{
1250
	const struct string_list *list = ud;
1251
	const struct string_list_item *item;
1252

1253
	for_each_string_list_item (item, list) {
1254
		if (key->len == (uintptr_t)item->util &&
1255
		    !strncasecmp(item->string, key->buf, key->len))
1256
			return 1;
1257
	}
1258
	return 0;
1259
}
1260

1261
static struct strbuf *expand_string_arg(struct strbuf *sb,
1262
					const char *argval, size_t arglen)
1263
{
1264
	char *fmt = xstrndup(argval, arglen);
1265
	const char *format = fmt;
1266

1267
	strbuf_reset(sb);
1268
	while (strbuf_expand_step(sb, &format)) {
1269
		size_t len;
1270

1271
		if (skip_prefix(format, "%", &format))
1272
			strbuf_addch(sb, '%');
1273
		else if ((len = strbuf_expand_literal(sb, format)))
1274
			format += len;
1275
		else
1276
			strbuf_addch(sb, '%');
1277
	}
1278
	free(fmt);
1279
	return sb;
1280
}
1281

1282
int format_set_trailers_options(struct process_trailer_options *opts,
1283
				struct string_list *filter_list,
1284
				struct strbuf *sepbuf,
1285
				struct strbuf *kvsepbuf,
1286
				const char **arg,
1287
				char **invalid_arg)
1288
{
1289
	for (;;) {
1290
		const char *argval;
1291
		size_t arglen;
1292

1293
		if (**arg == ')')
1294
			break;
1295

1296
		if (match_placeholder_arg_value(*arg, "key", arg, &argval, &arglen)) {
1297
			uintptr_t len = arglen;
1298

1299
			if (!argval)
1300
				return -1;
1301

1302
			if (len && argval[len - 1] == ':')
1303
				len--;
1304
			string_list_append(filter_list, argval)->util = (char *)len;
1305

1306
			opts->filter = format_trailer_match_cb;
1307
			opts->filter_data = filter_list;
1308
			opts->only_trailers = 1;
1309
		} else if (match_placeholder_arg_value(*arg, "separator", arg, &argval, &arglen)) {
1310
			opts->separator = expand_string_arg(sepbuf, argval, arglen);
1311
		} else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) {
1312
			opts->key_value_separator = expand_string_arg(kvsepbuf, argval, arglen);
1313
		} else if (!match_placeholder_bool_arg(*arg, "only", arg, &opts->only_trailers) &&
1314
			   !match_placeholder_bool_arg(*arg, "unfold", arg, &opts->unfold) &&
1315
			   !match_placeholder_bool_arg(*arg, "keyonly", arg, &opts->key_only) &&
1316
			   !match_placeholder_bool_arg(*arg, "valueonly", arg, &opts->value_only)) {
1317
			if (invalid_arg) {
1318
				size_t len = strcspn(*arg, ",)");
1319
				*invalid_arg = xstrndup(*arg, len);
1320
			}
1321
			return -1;
1322
		}
1323
	}
1324
	return 0;
1325
}
1326

1327
static size_t parse_describe_args(const char *start, struct strvec *args)
1328
{
1329
	struct {
1330
		const char *name;
1331
		enum {
1332
			DESCRIBE_ARG_BOOL,
1333
			DESCRIBE_ARG_INTEGER,
1334
			DESCRIBE_ARG_STRING,
1335
		} type;
1336
	}  option[] = {
1337
		{ "tags", DESCRIBE_ARG_BOOL},
1338
		{ "abbrev", DESCRIBE_ARG_INTEGER },
1339
		{ "exclude", DESCRIBE_ARG_STRING },
1340
		{ "match", DESCRIBE_ARG_STRING },
1341
	};
1342
	const char *arg = start;
1343

1344
	for (;;) {
1345
		int found = 0;
1346
		const char *argval;
1347
		size_t arglen = 0;
1348
		int optval = 0;
1349
		int i;
1350

1351
		for (i = 0; !found && i < ARRAY_SIZE(option); i++) {
1352
			switch (option[i].type) {
1353
			case DESCRIBE_ARG_BOOL:
1354
				if (match_placeholder_bool_arg(arg, option[i].name, &arg, &optval)) {
1355
					if (optval)
1356
						strvec_pushf(args, "--%s", option[i].name);
1357
					else
1358
						strvec_pushf(args, "--no-%s", option[i].name);
1359
					found = 1;
1360
				}
1361
				break;
1362
			case DESCRIBE_ARG_INTEGER:
1363
				if (match_placeholder_arg_value(arg, option[i].name, &arg,
1364
								&argval, &arglen)) {
1365
					char *endptr;
1366
					if (!arglen)
1367
						return 0;
1368
					strtol(argval, &endptr, 10);
1369
					if (endptr - argval != arglen)
1370
						return 0;
1371
					strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
1372
					found = 1;
1373
				}
1374
				break;
1375
			case DESCRIBE_ARG_STRING:
1376
				if (match_placeholder_arg_value(arg, option[i].name, &arg,
1377
								&argval, &arglen)) {
1378
					if (!arglen)
1379
						return 0;
1380
					strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
1381
					found = 1;
1382
				}
1383
				break;
1384
			}
1385
		}
1386
		if (!found)
1387
			break;
1388

1389
	}
1390
	return arg - start;
1391
}
1392

1393

1394
static int parse_decoration_option(const char **arg,
1395
				   const char *name,
1396
				   char **opt)
1397
{
1398
	const char *argval;
1399
	size_t arglen;
1400

1401
	if (match_placeholder_arg_value(*arg, name, arg, &argval, &arglen)) {
1402
		struct strbuf sb = STRBUF_INIT;
1403

1404
		expand_string_arg(&sb, argval, arglen);
1405
		*opt = strbuf_detach(&sb, NULL);
1406
		return 1;
1407
	}
1408
	return 0;
1409
}
1410

1411
static void parse_decoration_options(const char **arg,
1412
				     struct decoration_options *opts)
1413
{
1414
	while (parse_decoration_option(arg, "prefix", &opts->prefix) ||
1415
	       parse_decoration_option(arg, "suffix", &opts->suffix) ||
1416
	       parse_decoration_option(arg, "separator", &opts->separator) ||
1417
	       parse_decoration_option(arg, "pointer", &opts->pointer) ||
1418
	       parse_decoration_option(arg, "tag", &opts->tag))
1419
		;
1420
}
1421

1422
static void free_decoration_options(const struct decoration_options *opts)
1423
{
1424
	free(opts->prefix);
1425
	free(opts->suffix);
1426
	free(opts->separator);
1427
	free(opts->pointer);
1428
	free(opts->tag);
1429
}
1430

1431
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1432
				const char *placeholder,
1433
				void *context)
1434
{
1435
	struct format_commit_context *c = context;
1436
	const struct commit *commit = c->commit;
1437
	const char *msg = c->message;
1438
	struct commit_list *p;
1439
	const char *arg, *eol;
1440
	size_t res;
1441
	char **slot;
1442

1443
	/* these are independent of the commit */
1444
	res = strbuf_expand_literal(sb, placeholder);
1445
	if (res)
1446
		return res;
1447

1448
	switch (placeholder[0]) {
1449
	case 'C':
1450
		if (starts_with(placeholder + 1, "(auto)")) {
1451
			c->auto_color = want_color(c->pretty_ctx->color);
1452
			if (c->auto_color && sb->len)
1453
				strbuf_addstr(sb, GIT_COLOR_RESET);
1454
			return 7; /* consumed 7 bytes, "C(auto)" */
1455
		} else {
1456
			int ret = parse_color(sb, placeholder, c);
1457
			if (ret)
1458
				c->auto_color = 0;
1459
			/*
1460
			 * Otherwise, we decided to treat %C<unknown>
1461
			 * as a literal string, and the previous
1462
			 * %C(auto) is still valid.
1463
			 */
1464
			return ret;
1465
		}
1466
	case 'w':
1467
		if (placeholder[1] == '(') {
1468
			unsigned long width = 0, indent1 = 0, indent2 = 0;
1469
			char *next;
1470
			const char *start = placeholder + 2;
1471
			const char *end = strchr(start, ')');
1472
			if (!end)
1473
				return 0;
1474
			if (end > start) {
1475
				width = strtoul(start, &next, 10);
1476
				if (*next == ',') {
1477
					indent1 = strtoul(next + 1, &next, 10);
1478
					if (*next == ',') {
1479
						indent2 = strtoul(next + 1,
1480
								 &next, 10);
1481
					}
1482
				}
1483
				if (*next != ')')
1484
					return 0;
1485
			}
1486

1487
			/*
1488
			 * We need to limit the format here as it allows the
1489
			 * user to prepend arbitrarily many bytes to the buffer
1490
			 * when rewrapping.
1491
			 */
1492
			if (width > FORMATTING_LIMIT ||
1493
			    indent1 > FORMATTING_LIMIT ||
1494
			    indent2 > FORMATTING_LIMIT)
1495
				return 0;
1496
			rewrap_message_tail(sb, c, width, indent1, indent2);
1497
			return end - placeholder + 1;
1498
		} else
1499
			return 0;
1500

1501
	case '<':
1502
	case '>':
1503
		return parse_padding_placeholder(placeholder, c);
1504
	}
1505

1506
	if (skip_prefix(placeholder, "(describe", &arg)) {
1507
		struct child_process cmd = CHILD_PROCESS_INIT;
1508
		struct strbuf out = STRBUF_INIT;
1509
		struct strbuf err = STRBUF_INIT;
1510
		struct pretty_print_describe_status *describe_status;
1511

1512
		describe_status = c->pretty_ctx->describe_status;
1513
		if (describe_status) {
1514
			if (!describe_status->max_invocations)
1515
				return 0;
1516
			describe_status->max_invocations--;
1517
		}
1518

1519
		cmd.git_cmd = 1;
1520
		strvec_push(&cmd.args, "describe");
1521

1522
		if (*arg == ':') {
1523
			arg++;
1524
			arg += parse_describe_args(arg, &cmd.args);
1525
		}
1526

1527
		if (*arg != ')') {
1528
			child_process_clear(&cmd);
1529
			return 0;
1530
		}
1531

1532
		strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
1533
		pipe_command(&cmd, NULL, 0, &out, 0, &err, 0);
1534
		strbuf_rtrim(&out);
1535
		strbuf_addbuf(sb, &out);
1536
		strbuf_release(&out);
1537
		strbuf_release(&err);
1538
		return arg - placeholder + 1;
1539
	}
1540

1541
	/* these depend on the commit */
1542
	if (!commit->object.parsed)
1543
		parse_object(the_repository, &commit->object.oid);
1544

1545
	switch (placeholder[0]) {
1546
	case 'H':		/* commit hash */
1547
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1548
		strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
1549
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1550
		return 1;
1551
	case 'h':		/* abbreviated commit hash */
1552
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1553
		strbuf_add_unique_abbrev(sb, &commit->object.oid,
1554
					 c->pretty_ctx->abbrev);
1555
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1556
		return 1;
1557
	case 'T':		/* tree hash */
1558
		strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit)));
1559
		return 1;
1560
	case 't':		/* abbreviated tree hash */
1561
		strbuf_add_unique_abbrev(sb,
1562
					 get_commit_tree_oid(commit),
1563
					 c->pretty_ctx->abbrev);
1564
		return 1;
1565
	case 'P':		/* parent hashes */
1566
		for (p = commit->parents; p; p = p->next) {
1567
			if (p != commit->parents)
1568
				strbuf_addch(sb, ' ');
1569
			strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
1570
		}
1571
		return 1;
1572
	case 'p':		/* abbreviated parent hashes */
1573
		for (p = commit->parents; p; p = p->next) {
1574
			if (p != commit->parents)
1575
				strbuf_addch(sb, ' ');
1576
			strbuf_add_unique_abbrev(sb, &p->item->object.oid,
1577
						 c->pretty_ctx->abbrev);
1578
		}
1579
		return 1;
1580
	case 'm':		/* left/right/bottom */
1581
		strbuf_addstr(sb, get_revision_mark(NULL, commit));
1582
		return 1;
1583
	case 'd':
1584
		format_decorations(sb, commit, c->auto_color, NULL);
1585
		return 1;
1586
	case 'D':
1587
		{
1588
			const struct decoration_options opts = {
1589
				.prefix = (char *) "",
1590
				.suffix = (char *) "",
1591
			};
1592

1593
			format_decorations(sb, commit, c->auto_color, &opts);
1594
			return 1;
1595
		}
1596
	case 'S':		/* tag/branch like --source */
1597
		if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
1598
			return 0;
1599
		slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
1600
		if (!(slot && *slot))
1601
			return 0;
1602
		strbuf_addstr(sb, *slot);
1603
		return 1;
1604
	case 'g':		/* reflog info */
1605
		switch(placeholder[1]) {
1606
		case 'd':	/* reflog selector */
1607
		case 'D':
1608
			if (c->pretty_ctx->reflog_info)
1609
				get_reflog_selector(sb,
1610
						    c->pretty_ctx->reflog_info,
1611
						    c->pretty_ctx->date_mode,
1612
						    c->pretty_ctx->date_mode_explicit,
1613
						    (placeholder[1] == 'd'));
1614
			return 2;
1615
		case 's':	/* reflog message */
1616
			if (c->pretty_ctx->reflog_info)
1617
				get_reflog_message(sb, c->pretty_ctx->reflog_info);
1618
			return 2;
1619
		case 'n':
1620
		case 'N':
1621
		case 'e':
1622
		case 'E':
1623
			return format_reflog_person(sb,
1624
						    placeholder[1],
1625
						    c->pretty_ctx->reflog_info,
1626
						    c->pretty_ctx->date_mode);
1627
		}
1628
		return 0;	/* unknown %g placeholder */
1629
	case 'N':
1630
		if (c->pretty_ctx->notes_message) {
1631
			strbuf_addstr(sb, c->pretty_ctx->notes_message);
1632
			return 1;
1633
		}
1634
		return 0;
1635
	}
1636

1637
	if (placeholder[0] == 'G') {
1638
		if (!c->signature_check.result)
1639
			check_commit_signature(c->commit, &(c->signature_check));
1640
		switch (placeholder[1]) {
1641
		case 'G':
1642
			if (c->signature_check.output)
1643
				strbuf_addstr(sb, c->signature_check.output);
1644
			break;
1645
		case '?':
1646
			switch (c->signature_check.result) {
1647
			case 'G':
1648
				switch (c->signature_check.trust_level) {
1649
				case TRUST_UNDEFINED:
1650
				case TRUST_NEVER:
1651
					strbuf_addch(sb, 'U');
1652
					break;
1653
				default:
1654
					strbuf_addch(sb, 'G');
1655
					break;
1656
				}
1657
				break;
1658
			case 'B':
1659
			case 'E':
1660
			case 'N':
1661
			case 'X':
1662
			case 'Y':
1663
			case 'R':
1664
				strbuf_addch(sb, c->signature_check.result);
1665
			}
1666
			break;
1667
		case 'S':
1668
			if (c->signature_check.signer)
1669
				strbuf_addstr(sb, c->signature_check.signer);
1670
			break;
1671
		case 'K':
1672
			if (c->signature_check.key)
1673
				strbuf_addstr(sb, c->signature_check.key);
1674
			break;
1675
		case 'F':
1676
			if (c->signature_check.fingerprint)
1677
				strbuf_addstr(sb, c->signature_check.fingerprint);
1678
			break;
1679
		case 'P':
1680
			if (c->signature_check.primary_key_fingerprint)
1681
				strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
1682
			break;
1683
		case 'T':
1684
			strbuf_addstr(sb, gpg_trust_level_to_str(c->signature_check.trust_level));
1685
			break;
1686
		default:
1687
			return 0;
1688
		}
1689
		return 2;
1690
	}
1691

1692
	if (skip_prefix(placeholder, "(decorate", &arg)) {
1693
		struct decoration_options opts = { NULL };
1694
		size_t ret = 0;
1695

1696
		if (*arg == ':') {
1697
			arg++;
1698
			parse_decoration_options(&arg, &opts);
1699
		}
1700
		if (*arg == ')') {
1701
			format_decorations(sb, commit, c->auto_color, &opts);
1702
			ret = arg - placeholder + 1;
1703
		}
1704

1705
		free_decoration_options(&opts);
1706
		return ret;
1707
	}
1708

1709
	/* For the rest we have to parse the commit header. */
1710
	if (!c->commit_header_parsed) {
1711
		msg = c->message =
1712
			repo_logmsg_reencode(c->repository, commit,
1713
					     &c->commit_encoding, "UTF-8");
1714
		parse_commit_header(c);
1715
	}
1716

1717
	switch (placeholder[0]) {
1718
	case 'a':	/* author ... */
1719
		return format_person_part(sb, placeholder[1],
1720
				   msg + c->author.off, c->author.len,
1721
				   c->pretty_ctx->date_mode);
1722
	case 'c':	/* committer ... */
1723
		return format_person_part(sb, placeholder[1],
1724
				   msg + c->committer.off, c->committer.len,
1725
				   c->pretty_ctx->date_mode);
1726
	case 'e':	/* encoding */
1727
		if (c->commit_encoding)
1728
			strbuf_addstr(sb, c->commit_encoding);
1729
		return 1;
1730
	case 'B':	/* raw body */
1731
		/* message_off is always left at the initial newline */
1732
		strbuf_addstr(sb, msg + c->message_off + 1);
1733
		return 1;
1734
	}
1735

1736
	/* Now we need to parse the commit message. */
1737
	if (!c->commit_message_parsed)
1738
		parse_commit_message(c);
1739

1740
	switch (placeholder[0]) {
1741
	case 's':	/* subject */
1742
		format_subject(sb, msg + c->subject_off, " ");
1743
		return 1;
1744
	case 'f':	/* sanitized subject */
1745
		eol = strchrnul(msg + c->subject_off, '\n');
1746
		format_sanitized_subject(sb, msg + c->subject_off, eol - (msg + c->subject_off));
1747
		return 1;
1748
	case 'b':	/* body */
1749
		strbuf_addstr(sb, msg + c->body_off);
1750
		return 1;
1751
	}
1752

1753
	if (skip_prefix(placeholder, "(trailers", &arg)) {
1754
		struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1755
		struct string_list filter_list = STRING_LIST_INIT_NODUP;
1756
		struct strbuf sepbuf = STRBUF_INIT;
1757
		struct strbuf kvsepbuf = STRBUF_INIT;
1758
		size_t ret = 0;
1759

1760
		opts.no_divider = 1;
1761

1762
		if (*arg == ':') {
1763
			arg++;
1764
			if (format_set_trailers_options(&opts, &filter_list, &sepbuf, &kvsepbuf, &arg, NULL))
1765
				goto trailer_out;
1766
		}
1767
		if (*arg == ')') {
1768
			format_trailers_from_commit(&opts, msg + c->subject_off, sb);
1769
			ret = arg - placeholder + 1;
1770
		}
1771
	trailer_out:
1772
		string_list_clear(&filter_list, 0);
1773
		strbuf_release(&sepbuf);
1774
		return ret;
1775
	}
1776

1777
	return 0;	/* unknown placeholder */
1778
}
1779

1780
static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
1781
				    const char *placeholder,
1782
				    struct format_commit_context *c)
1783
{
1784
	struct strbuf local_sb = STRBUF_INIT;
1785
	size_t total_consumed = 0;
1786
	int len, padding = c->padding;
1787

1788
	if (padding < 0) {
1789
		const char *start = strrchr(sb->buf, '\n');
1790
		int occupied;
1791
		if (!start)
1792
			start = sb->buf;
1793
		occupied = utf8_strnwidth(start, strlen(start), 1);
1794
		occupied += c->pretty_ctx->graph_width;
1795
		padding = (-padding) - occupied;
1796
	}
1797
	while (1) {
1798
		int modifier = *placeholder == 'C';
1799
		size_t consumed = format_commit_one(&local_sb, placeholder, c);
1800
		total_consumed += consumed;
1801

1802
		if (!modifier)
1803
			break;
1804

1805
		placeholder += consumed;
1806
		if (*placeholder != '%')
1807
			break;
1808
		placeholder++;
1809
		total_consumed++;
1810
	}
1811
	len = utf8_strnwidth(local_sb.buf, local_sb.len, 1);
1812

1813
	if (c->flush_type == flush_left_and_steal) {
1814
		const char *ch = sb->buf + sb->len - 1;
1815
		while (len > padding && ch > sb->buf) {
1816
			const char *p;
1817
			if (*ch == ' ') {
1818
				ch--;
1819
				padding++;
1820
				continue;
1821
			}
1822
			/* check for trailing ansi sequences */
1823
			if (*ch != 'm')
1824
				break;
1825
			p = ch - 1;
1826
			while (p > sb->buf && ch - p < 10 && *p != '\033')
1827
				p--;
1828
			if (*p != '\033' ||
1829
			    ch + 1 - p != display_mode_esc_sequence_len(p))
1830
				break;
1831
			/*
1832
			 * got a good ansi sequence, put it back to
1833
			 * local_sb as we're cutting sb
1834
			 */
1835
			strbuf_insert(&local_sb, 0, p, ch + 1 - p);
1836
			ch = p - 1;
1837
		}
1838
		strbuf_setlen(sb, ch + 1 - sb->buf);
1839
		c->flush_type = flush_left;
1840
	}
1841

1842
	if (len > padding) {
1843
		switch (c->truncate) {
1844
		case trunc_left:
1845
			strbuf_utf8_replace(&local_sb,
1846
					    0, len - (padding - 2),
1847
					    "..");
1848
			break;
1849
		case trunc_middle:
1850
			strbuf_utf8_replace(&local_sb,
1851
					    padding / 2 - 1,
1852
					    len - (padding - 2),
1853
					    "..");
1854
			break;
1855
		case trunc_right:
1856
			strbuf_utf8_replace(&local_sb,
1857
					    padding - 2, len - (padding - 2),
1858
					    "..");
1859
			break;
1860
		case trunc_none:
1861
			break;
1862
		}
1863
		strbuf_addbuf(sb, &local_sb);
1864
	} else {
1865
		size_t sb_len = sb->len, offset = 0;
1866
		if (c->flush_type == flush_left)
1867
			offset = padding - len;
1868
		else if (c->flush_type == flush_both)
1869
			offset = (padding - len) / 2;
1870
		/*
1871
		 * we calculate padding in columns, now
1872
		 * convert it back to chars
1873
		 */
1874
		padding = padding - len + local_sb.len;
1875
		strbuf_addchars(sb, ' ', padding);
1876
		memcpy(sb->buf + sb_len + offset, local_sb.buf,
1877
		       local_sb.len);
1878
	}
1879
	strbuf_release(&local_sb);
1880
	c->flush_type = no_flush;
1881
	return total_consumed;
1882
}
1883

1884
static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
1885
				 const char *placeholder,
1886
				 struct format_commit_context *context)
1887
{
1888
	size_t consumed, orig_len;
1889
	enum {
1890
		NO_MAGIC,
1891
		ADD_LF_BEFORE_NON_EMPTY,
1892
		DEL_LF_BEFORE_EMPTY,
1893
		ADD_SP_BEFORE_NON_EMPTY
1894
	} magic = NO_MAGIC;
1895

1896
	switch (placeholder[0]) {
1897
	case '-':
1898
		magic = DEL_LF_BEFORE_EMPTY;
1899
		break;
1900
	case '+':
1901
		magic = ADD_LF_BEFORE_NON_EMPTY;
1902
		break;
1903
	case ' ':
1904
		magic = ADD_SP_BEFORE_NON_EMPTY;
1905
		break;
1906
	default:
1907
		break;
1908
	}
1909
	if (magic != NO_MAGIC) {
1910
		placeholder++;
1911

1912
		switch (placeholder[0]) {
1913
		case 'w':
1914
			/*
1915
			 * `%+w()` cannot ever expand to a non-empty string,
1916
			 * and it potentially changes the layout of preceding
1917
			 * contents. We're thus not able to handle the magic in
1918
			 * this combination and refuse the pattern.
1919
			 */
1920
			return 0;
1921
		};
1922
	}
1923

1924
	orig_len = sb->len;
1925
	if (context->flush_type == no_flush)
1926
		consumed = format_commit_one(sb, placeholder, context);
1927
	else
1928
		consumed = format_and_pad_commit(sb, placeholder, context);
1929
	if (magic == NO_MAGIC)
1930
		return consumed;
1931

1932
	if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
1933
		while (sb->len && sb->buf[sb->len - 1] == '\n')
1934
			strbuf_setlen(sb, sb->len - 1);
1935
	} else if (orig_len != sb->len) {
1936
		if (magic == ADD_LF_BEFORE_NON_EMPTY)
1937
			strbuf_insertstr(sb, orig_len, "\n");
1938
		else if (magic == ADD_SP_BEFORE_NON_EMPTY)
1939
			strbuf_insertstr(sb, orig_len, " ");
1940
	}
1941
	return consumed + 1;
1942
}
1943

1944
void userformat_find_requirements(const char *fmt, struct userformat_want *w)
1945
{
1946
	if (!fmt) {
1947
		if (!user_format)
1948
			return;
1949
		fmt = user_format;
1950
	}
1951
	while ((fmt = strchr(fmt, '%'))) {
1952
		fmt++;
1953
		if (skip_prefix(fmt, "%", &fmt))
1954
			continue;
1955

1956
		if (*fmt == '+' || *fmt == '-' || *fmt == ' ')
1957
			fmt++;
1958

1959
		switch (*fmt) {
1960
		case 'N':
1961
			w->notes = 1;
1962
			break;
1963
		case 'S':
1964
			w->source = 1;
1965
			break;
1966
		case 'd':
1967
		case 'D':
1968
			w->decorate = 1;
1969
			break;
1970
		case '(':
1971
			if (starts_with(fmt + 1, "decorate"))
1972
				w->decorate = 1;
1973
			break;
1974
		}
1975
	}
1976
}
1977

1978
void repo_format_commit_message(struct repository *r,
1979
				const struct commit *commit,
1980
				const char *format, struct strbuf *sb,
1981
				const struct pretty_print_context *pretty_ctx)
1982
{
1983
	struct format_commit_context context = {
1984
		.repository = r,
1985
		.commit = commit,
1986
		.pretty_ctx = pretty_ctx,
1987
		.wrap_start = sb->len
1988
	};
1989
	const char *output_enc = pretty_ctx->output_encoding;
1990
	const char *utf8 = "UTF-8";
1991

1992
	while (strbuf_expand_step(sb, &format)) {
1993
		size_t len;
1994

1995
		if (skip_prefix(format, "%", &format))
1996
			strbuf_addch(sb, '%');
1997
		else if ((len = format_commit_item(sb, format, &context)))
1998
			format += len;
1999
		else
2000
			strbuf_addch(sb, '%');
2001
	}
2002
	rewrap_message_tail(sb, &context, 0, 0, 0);
2003

2004
	/*
2005
	 * Convert output to an actual output encoding; note that
2006
	 * format_commit_item() will always use UTF-8, so we don't
2007
	 * have to bother if that's what the output wants.
2008
	 */
2009
	if (output_enc) {
2010
		if (same_encoding(utf8, output_enc))
2011
			output_enc = NULL;
2012
	} else {
2013
		if (context.commit_encoding &&
2014
		    !same_encoding(context.commit_encoding, utf8))
2015
			output_enc = context.commit_encoding;
2016
	}
2017

2018
	if (output_enc) {
2019
		size_t outsz;
2020
		char *out = reencode_string_len(sb->buf, sb->len,
2021
						output_enc, utf8, &outsz);
2022
		if (out)
2023
			strbuf_attach(sb, out, outsz, outsz + 1);
2024
	}
2025

2026
	free(context.commit_encoding);
2027
	repo_unuse_commit_buffer(r, commit, context.message);
2028
}
2029

2030
static void pp_header(struct pretty_print_context *pp,
2031
		      const char *encoding,
2032
		      const struct commit *commit,
2033
		      const char **msg_p,
2034
		      struct strbuf *sb)
2035
{
2036
	int parents_shown = 0;
2037

2038
	for (;;) {
2039
		const char *name, *line = *msg_p;
2040
		int linelen = get_one_line(*msg_p);
2041

2042
		if (!linelen)
2043
			return;
2044
		*msg_p += linelen;
2045

2046
		if (linelen == 1)
2047
			/* End of header */
2048
			return;
2049

2050
		if (pp->fmt == CMIT_FMT_RAW) {
2051
			strbuf_add(sb, line, linelen);
2052
			continue;
2053
		}
2054

2055
		if (starts_with(line, "parent ")) {
2056
			if (linelen != the_hash_algo->hexsz + 8)
2057
				die("bad parent line in commit");
2058
			continue;
2059
		}
2060

2061
		if (!parents_shown) {
2062
			unsigned num = commit_list_count(commit->parents);
2063
			/* with enough slop */
2064
			strbuf_grow(sb, num * (GIT_MAX_HEXSZ + 10) + 20);
2065
			add_merge_info(pp, sb, commit);
2066
			parents_shown = 1;
2067
		}
2068

2069
		/*
2070
		 * MEDIUM == DEFAULT shows only author with dates.
2071
		 * FULL shows both authors but not dates.
2072
		 * FULLER shows both authors and dates.
2073
		 */
2074
		if (skip_prefix(line, "author ", &name)) {
2075
			strbuf_grow(sb, linelen + 80);
2076
			pp_user_info(pp, "Author", sb, name, encoding);
2077
		}
2078
		if (skip_prefix(line, "committer ", &name) &&
2079
		    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
2080
			strbuf_grow(sb, linelen + 80);
2081
			pp_user_info(pp, "Commit", sb, name, encoding);
2082
		}
2083
	}
2084
}
2085

2086
void pp_email_subject(struct pretty_print_context *pp,
2087
		      const char **msg_p,
2088
		      struct strbuf *sb,
2089
		      const char *encoding,
2090
		      int need_8bit_cte)
2091
{
2092
	static const int max_length = 78; /* per rfc2047 */
2093
	struct strbuf title;
2094

2095
	strbuf_init(&title, 80);
2096
	*msg_p = format_subject(&title, *msg_p,
2097
				pp->preserve_subject ? "\n" : " ");
2098

2099
	strbuf_grow(sb, title.len + 1024);
2100
	fmt_output_email_subject(sb, pp->rev);
2101
	if (pp->encode_email_headers &&
2102
	    needs_rfc2047_encoding(title.buf, title.len))
2103
		add_rfc2047(sb, title.buf, title.len,
2104
			    encoding, RFC2047_SUBJECT);
2105
	else
2106
		strbuf_add_wrapped_bytes(sb, title.buf, title.len,
2107
					 -last_line_length(sb), 1, max_length);
2108
	strbuf_addch(sb, '\n');
2109

2110
	if (need_8bit_cte == 0) {
2111
		int i;
2112
		for (i = 0; i < pp->in_body_headers.nr; i++) {
2113
			if (has_non_ascii(pp->in_body_headers.items[i].string)) {
2114
				need_8bit_cte = 1;
2115
				break;
2116
			}
2117
		}
2118
	}
2119

2120
	if (need_8bit_cte > 0) {
2121
		const char *header_fmt =
2122
			"MIME-Version: 1.0\n"
2123
			"Content-Type: text/plain; charset=%s\n"
2124
			"Content-Transfer-Encoding: 8bit\n";
2125
		strbuf_addf(sb, header_fmt, encoding);
2126
	}
2127
	if (pp->after_subject) {
2128
		strbuf_addstr(sb, pp->after_subject);
2129
	}
2130

2131
	strbuf_addch(sb, '\n');
2132

2133
	if (pp->in_body_headers.nr) {
2134
		int i;
2135
		for (i = 0; i < pp->in_body_headers.nr; i++) {
2136
			strbuf_addstr(sb, pp->in_body_headers.items[i].string);
2137
			free(pp->in_body_headers.items[i].string);
2138
		}
2139
		string_list_clear(&pp->in_body_headers, 0);
2140
		strbuf_addch(sb, '\n');
2141
	}
2142

2143
	strbuf_release(&title);
2144
}
2145

2146
static int pp_utf8_width(const char *start, const char *end)
2147
{
2148
	int width = 0;
2149
	size_t remain = end - start;
2150

2151
	while (remain) {
2152
		int n = utf8_width(&start, &remain);
2153
		if (n < 0 || !start)
2154
			return -1;
2155
		width += n;
2156
	}
2157
	return width;
2158
}
2159

2160
static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
2161
				 int color, int tabwidth, const char *line,
2162
				 int linelen)
2163
{
2164
	const char *tab;
2165

2166
	while ((tab = memchr(line, '\t', linelen)) != NULL) {
2167
		int width = pp_utf8_width(line, tab);
2168

2169
		/*
2170
		 * If it wasn't well-formed utf8, or it
2171
		 * had characters with badly defined
2172
		 * width (control characters etc), just
2173
		 * give up on trying to align things.
2174
		 */
2175
		if (width < 0)
2176
			break;
2177

2178
		/* Output the data .. */
2179
		append_line_with_color(sb, opt, line, tab - line, color,
2180
				       GREP_CONTEXT_BODY,
2181
				       GREP_HEADER_FIELD_MAX);
2182

2183
		/* .. and the de-tabified tab */
2184
		strbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));
2185

2186
		/* Skip over the printed part .. */
2187
		linelen -= tab + 1 - line;
2188
		line = tab + 1;
2189
	}
2190

2191
	/*
2192
	 * Print out everything after the last tab without
2193
	 * worrying about width - there's nothing more to
2194
	 * align.
2195
	 */
2196
	append_line_with_color(sb, opt, line, linelen, color, GREP_CONTEXT_BODY,
2197
			       GREP_HEADER_FIELD_MAX);
2198
}
2199

2200
/*
2201
 * pp_handle_indent() prints out the intendation, and
2202
 * the whole line (without the final newline), after
2203
 * de-tabifying.
2204
 */
2205
static void pp_handle_indent(struct pretty_print_context *pp,
2206
			     struct strbuf *sb, int indent,
2207
			     const char *line, int linelen)
2208
{
2209
	struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
2210

2211
	strbuf_addchars(sb, ' ', indent);
2212
	if (pp->expand_tabs_in_log)
2213
		strbuf_add_tabexpand(sb, opt, pp->color, pp->expand_tabs_in_log,
2214
				     line, linelen);
2215
	else
2216
		append_line_with_color(sb, opt, line, linelen, pp->color,
2217
				       GREP_CONTEXT_BODY,
2218
				       GREP_HEADER_FIELD_MAX);
2219
}
2220

2221
static int is_mboxrd_from(const char *line, int len)
2222
{
2223
	/*
2224
	 * a line matching /^From $/ here would only have len == 4
2225
	 * at this point because is_empty_line would've trimmed all
2226
	 * trailing space
2227
	 */
2228
	return len > 4 && starts_with(line + strspn(line, ">"), "From ");
2229
}
2230

2231
void pp_remainder(struct pretty_print_context *pp,
2232
		  const char **msg_p,
2233
		  struct strbuf *sb,
2234
		  int indent)
2235
{
2236
	struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
2237
	int first = 1;
2238

2239
	for (;;) {
2240
		const char *line = *msg_p;
2241
		int linelen = get_one_line(line);
2242
		*msg_p += linelen;
2243

2244
		if (!linelen)
2245
			break;
2246

2247
		if (is_blank_line(line, &linelen)) {
2248
			if (first)
2249
				continue;
2250
			if (pp->fmt == CMIT_FMT_SHORT)
2251
				break;
2252
		}
2253
		first = 0;
2254

2255
		strbuf_grow(sb, linelen + indent + 20);
2256
		if (indent)
2257
			pp_handle_indent(pp, sb, indent, line, linelen);
2258
		else if (pp->expand_tabs_in_log)
2259
			strbuf_add_tabexpand(sb, opt, pp->color,
2260
					     pp->expand_tabs_in_log, line,
2261
					     linelen);
2262
		else {
2263
			if (pp->fmt == CMIT_FMT_MBOXRD &&
2264
					is_mboxrd_from(line, linelen))
2265
				strbuf_addch(sb, '>');
2266

2267
			append_line_with_color(sb, opt, line, linelen,
2268
					       pp->color, GREP_CONTEXT_BODY,
2269
					       GREP_HEADER_FIELD_MAX);
2270
		}
2271
		strbuf_addch(sb, '\n');
2272
	}
2273
}
2274

2275
void pretty_print_commit(struct pretty_print_context *pp,
2276
			 const struct commit *commit,
2277
			 struct strbuf *sb)
2278
{
2279
	unsigned long beginning_of_body;
2280
	int indent = 4;
2281
	const char *msg;
2282
	const char *reencoded;
2283
	const char *encoding;
2284
	int need_8bit_cte = pp->need_8bit_cte;
2285

2286
	if (pp->fmt == CMIT_FMT_USERFORMAT) {
2287
		repo_format_commit_message(the_repository, commit,
2288
					   user_format, sb, pp);
2289
		return;
2290
	}
2291

2292
	encoding = get_log_output_encoding();
2293
	msg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,
2294
					       encoding);
2295

2296
	if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
2297
		indent = 0;
2298

2299
	/*
2300
	 * We need to check and emit Content-type: to mark it
2301
	 * as 8-bit if we haven't done so.
2302
	 */
2303
	if (cmit_fmt_is_mail(pp->fmt) && need_8bit_cte == 0) {
2304
		int i, ch, in_body;
2305

2306
		for (in_body = i = 0; (ch = msg[i]); i++) {
2307
			if (!in_body) {
2308
				/* author could be non 7-bit ASCII but
2309
				 * the log may be so; skip over the
2310
				 * header part first.
2311
				 */
2312
				if (ch == '\n' && msg[i+1] == '\n')
2313
					in_body = 1;
2314
			}
2315
			else if (non_ascii(ch)) {
2316
				need_8bit_cte = 1;
2317
				break;
2318
			}
2319
		}
2320
	}
2321

2322
	pp_header(pp, encoding, commit, &msg, sb);
2323
	if (pp->fmt != CMIT_FMT_ONELINE && !cmit_fmt_is_mail(pp->fmt)) {
2324
		strbuf_addch(sb, '\n');
2325
	}
2326

2327
	/* Skip excess blank lines at the beginning of body, if any... */
2328
	msg = skip_blank_lines(msg);
2329

2330
	/* These formats treat the title line specially. */
2331
	if (pp->fmt == CMIT_FMT_ONELINE) {
2332
		msg = format_subject(sb, msg, " ");
2333
		strbuf_addch(sb, '\n');
2334
	} else if (cmit_fmt_is_mail(pp->fmt))
2335
		pp_email_subject(pp, &msg, sb, encoding, need_8bit_cte);
2336

2337
	beginning_of_body = sb->len;
2338
	if (pp->fmt != CMIT_FMT_ONELINE)
2339
		pp_remainder(pp, &msg, sb, indent);
2340
	strbuf_rtrim(sb);
2341

2342
	/* Make sure there is an EOLN for the non-oneline case */
2343
	if (pp->fmt != CMIT_FMT_ONELINE)
2344
		strbuf_addch(sb, '\n');
2345

2346
	/*
2347
	 * The caller may append additional body text in e-mail
2348
	 * format.  Make sure we did not strip the blank line
2349
	 * between the header and the body.
2350
	 */
2351
	if (cmit_fmt_is_mail(pp->fmt) && sb->len <= beginning_of_body)
2352
		strbuf_addch(sb, '\n');
2353

2354
	repo_unuse_commit_buffer(the_repository, commit, reencoded);
2355
}
2356

2357
void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
2358
		    struct strbuf *sb)
2359
{
2360
	struct pretty_print_context pp = {0};
2361
	pp.fmt = fmt;
2362
	pretty_print_commit(&pp, commit, sb);
2363
}
2364

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.