]> git.ipfire.org Git - thirdparty/git.git/blame - pretty.c
decorate: color each token separately
[thirdparty/git.git] / pretty.c
CommitLineData
77f091ed 1#include "git-compat-util.h"
b2141fc1 2#include "config.h"
93fc05eb 3#include "commit.h"
32a8f510 4#include "environment.h"
f394e093 5#include "gettext.h"
df6e8744 6#include "hash.h"
41771fa4 7#include "hex.h"
93fc05eb
JS
8#include "utf8.h"
9#include "diff.h"
ca4eed70 10#include "pager.h"
93fc05eb 11#include "revision.h"
c455c87c 12#include "string-list.h"
e0cbc397 13#include "mailmap.h"
3b3d443f 14#include "log-tree.h"
a97a7468 15#include "notes.h"
c002922a 16#include "color.h"
8f8f5476 17#include "reflog-walk.h"
f6667c5e 18#include "gpg-interface.h"
d9f31fbf 19#include "trailer.h"
15ae82d5 20#include "run-command.h"
f9401850 21#include "object-name.h"
93fc05eb 22
304a50ad
PS
23/*
24 * The limit for formatting directives, which enable the caller to append
25 * arbitrarily many bytes to the formatted buffer. This includes padding
26 * and wrapping formatters.
27 */
28#define FORMATTING_LIMIT (16 * 1024)
29
93fc05eb 30static char *user_format;
40957891
WP
31static struct cmt_fmt_map {
32 const char *name;
33 enum cmit_fmt format;
34 int is_tformat;
0893eec8 35 int expand_tabs_in_log;
2d7671ef 36 int is_alias;
618a8550 37 enum date_mode_type default_date_mode_type;
2d7671ef 38 const char *user_format;
40957891 39} *commit_formats;
8028184e 40static size_t builtin_formats_len;
40957891 41static size_t commit_formats_len;
8028184e 42static size_t commit_formats_alloc;
40957891 43static struct cmt_fmt_map *find_commit_format(const char *sought);
93fc05eb 44
b9c7d6e4
JK
45int commit_format_is_empty(enum cmit_fmt fmt)
46{
47 return fmt == CMIT_FMT_USERFORMAT && !*user_format;
48}
49
36407548
NS
50static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
51{
52 free(user_format);
53 user_format = xstrdup(cp);
54 if (is_tformat)
55 rev->use_terminator = 1;
56 rev->commit_format = CMIT_FMT_USERFORMAT;
57}
58
783a86c1 59static int git_pretty_formats_config(const char *var, const char *value,
a4e7e317 60 const struct config_context *ctx UNUSED,
5cf88fd8 61 void *cb UNUSED)
93fc05eb 62{
8028184e
WP
63 struct cmt_fmt_map *commit_format = NULL;
64 const char *name;
65 const char *fmt;
93fc05eb 66 int i;
8028184e 67
95b567c7 68 if (!skip_prefix(var, "pretty.", &name))
8028184e
WP
69 return 0;
70
8028184e
WP
71 for (i = 0; i < builtin_formats_len; i++) {
72 if (!strcmp(commit_formats[i].name, name))
73 return 0;
74 }
75
76 for (i = builtin_formats_len; i < commit_formats_len; i++) {
77 if (!strcmp(commit_formats[i].name, name)) {
78 commit_format = &commit_formats[i];
79 break;
80 }
81 }
82
83 if (!commit_format) {
84 ALLOC_GROW(commit_formats, commit_formats_len+1,
85 commit_formats_alloc);
86 commit_format = &commit_formats[commit_formats_len];
95a2618f 87 memset(commit_format, 0, sizeof(*commit_format));
8028184e
WP
88 commit_formats_len++;
89 }
90
91 commit_format->name = xstrdup(name);
92 commit_format->format = CMIT_FMT_USERFORMAT;
a26bc613
TA
93 if (git_config_string(&fmt, var, value))
94 return -1;
95
e3f1da98
RS
96 if (skip_prefix(fmt, "format:", &fmt))
97 commit_format->is_tformat = 0;
98 else if (skip_prefix(fmt, "tformat:", &fmt) || strchr(fmt, '%'))
8028184e
WP
99 commit_format->is_tformat = 1;
100 else
101 commit_format->is_alias = 1;
102 commit_format->user_format = fmt;
103
104 return 0;
105}
106
40957891 107static void setup_commit_formats(void)
93fc05eb 108{
40957891 109 struct cmt_fmt_map builtin_formats[] = {
0893eec8 110 { "raw", CMIT_FMT_RAW, 0, 0 },
fe37a9c5 111 { "medium", CMIT_FMT_MEDIUM, 0, 8 },
0893eec8
JH
112 { "short", CMIT_FMT_SHORT, 0, 0 },
113 { "email", CMIT_FMT_EMAIL, 0, 0 },
9f23e040 114 { "mboxrd", CMIT_FMT_MBOXRD, 0, 0 },
fe37a9c5
JH
115 { "fuller", CMIT_FMT_FULLER, 0, 8 },
116 { "full", CMIT_FMT_FULL, 0, 8 },
1f0fc1db
DL
117 { "oneline", CMIT_FMT_ONELINE, 1, 0 },
118 { "reference", CMIT_FMT_USERFORMAT, 1, 0,
119 0, DATE_SHORT, "%C(auto)%h (%s, %ad)" },
5a59a230
NTND
120 /*
121 * Please update $__git_log_pretty_formats in
122 * git-completion.bash when you add new formats.
123 */
4da45bef 124 };
40957891 125 commit_formats_len = ARRAY_SIZE(builtin_formats);
8028184e
WP
126 builtin_formats_len = commit_formats_len;
127 ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
921d49be
RS
128 COPY_ARRAY(commit_formats, builtin_formats,
129 ARRAY_SIZE(builtin_formats));
8028184e
WP
130
131 git_config(git_pretty_formats_config, NULL);
40957891
WP
132}
133
2d7671ef
WP
134static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
135 const char *original,
136 int num_redirections)
40957891
WP
137{
138 struct cmt_fmt_map *found = NULL;
139 size_t found_match_len = 0;
140 int i;
141
2d7671ef
WP
142 if (num_redirections >= commit_formats_len)
143 die("invalid --pretty format: "
144 "'%s' references an alias which points to itself",
145 original);
40957891
WP
146
147 for (i = 0; i < commit_formats_len; i++) {
148 size_t match_len;
149
59556548 150 if (!starts_with(commit_formats[i].name, sought))
40957891
WP
151 continue;
152
153 match_len = strlen(commit_formats[i].name);
154 if (found == NULL || found_match_len > match_len) {
155 found = &commit_formats[i];
156 found_match_len = match_len;
157 }
158 }
2d7671ef
WP
159
160 if (found && found->is_alias) {
161 found = find_commit_format_recursive(found->user_format,
162 original,
163 num_redirections+1);
164 }
165
40957891
WP
166 return found;
167}
168
2d7671ef
WP
169static struct cmt_fmt_map *find_commit_format(const char *sought)
170{
171 if (!commit_formats)
172 setup_commit_formats();
173
174 return find_commit_format_recursive(sought, sought, 0);
175}
176
40957891
WP
177void get_commit_format(const char *arg, struct rev_info *rev)
178{
179 struct cmt_fmt_map *commit_format;
93fc05eb 180
4da45bef 181 rev->use_terminator = 0;
c75e7ad2 182 if (!arg) {
4da45bef
JH
183 rev->commit_format = CMIT_FMT_DEFAULT;
184 return;
185 }
e3f1da98
RS
186 if (skip_prefix(arg, "format:", &arg)) {
187 save_user_format(rev, arg, 0);
4da45bef 188 return;
93fc05eb 189 }
40957891 190
e3f1da98 191 if (!*arg || skip_prefix(arg, "tformat:", &arg) || strchr(arg, '%')) {
36407548
NS
192 save_user_format(rev, arg, 1);
193 return;
194 }
93fc05eb 195
40957891
WP
196 commit_format = find_commit_format(arg);
197 if (!commit_format)
198 die("invalid --pretty format: %s", arg);
199
200 rev->commit_format = commit_format->format;
201 rev->use_terminator = commit_format->is_tformat;
0893eec8 202 rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
618a8550
DL
203 if (!rev->date_mode_explicit && commit_format->default_date_mode_type)
204 rev->date_mode.type = commit_format->default_date_mode_type;
8028184e
WP
205 if (commit_format->format == CMIT_FMT_USERFORMAT) {
206 save_user_format(rev, commit_format->user_format,
207 commit_format->is_tformat);
208 }
93fc05eb
JS
209}
210
211/*
212 * Generic support for pretty-printing the header
213 */
214static int get_one_line(const char *msg)
215{
216 int ret = 0;
217
218 for (;;) {
219 char c = *msg++;
220 if (!c)
221 break;
222 ret++;
223 if (c == '\n')
224 break;
225 }
226 return ret;
227}
228
229/* High bit set, or ISO-2022-INT */
cc571142 230static int non_ascii(int ch)
93fc05eb 231{
c2e9364a 232 return !isascii(ch) || ch == '\033';
93fc05eb
JS
233}
234
28e9cf65
JS
235int has_non_ascii(const char *s)
236{
237 int ch;
238 if (!s)
239 return 0;
240 while ((ch = *s++) != '\0') {
241 if (non_ascii(ch))
242 return 1;
243 }
244 return 0;
245}
246
4d03c18a
JK
247static int is_rfc822_special(char ch)
248{
249 switch (ch) {
250 case '(':
251 case ')':
252 case '<':
253 case '>':
254 case '[':
255 case ']':
256 case ':':
257 case ';':
258 case '@':
259 case ',':
260 case '.':
261 case '"':
262 case '\\':
263 return 1;
264 default:
265 return 0;
266 }
267}
268
41dd00ba 269static int needs_rfc822_quoting(const char *s, int len)
4d03c18a
JK
270{
271 int i;
272 for (i = 0; i < len; i++)
273 if (is_rfc822_special(s[i]))
274 return 1;
275 return 0;
276}
277
f9b7204b
JS
278static int last_line_length(struct strbuf *sb)
279{
280 int i;
281
282 /* How many bytes are already used on the last line? */
283 for (i = sb->len - 1; i >= 0; i--)
284 if (sb->buf[i] == '\n')
285 break;
286 return sb->len - (i + 1);
287}
288
4d03c18a
JK
289static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
290{
291 int i;
292
293 /* just a guess, we may have to also backslash-quote */
294 strbuf_grow(out, len + 2);
295
296 strbuf_addch(out, '"');
297 for (i = 0; i < len; i++) {
298 switch (s[i]) {
299 case '"':
300 case '\\':
301 strbuf_addch(out, '\\');
302 /* fall through */
303 default:
304 strbuf_addch(out, s[i]);
305 }
306 }
307 strbuf_addch(out, '"');
308}
309
0fcec2ce
JS
310enum rfc2047_type {
311 RFC2047_SUBJECT,
78273520 312 RFC2047_ADDRESS
0fcec2ce
JS
313};
314
315static int is_rfc2047_special(char ch, enum rfc2047_type type)
93fc05eb 316{
0fcec2ce
JS
317 /*
318 * rfc2047, section 4.2:
319 *
320 * 8-bit values which correspond to printable ASCII characters other
321 * than "=", "?", and "_" (underscore), MAY be represented as those
322 * characters. (But see section 5 for restrictions.) In
323 * particular, SPACE and TAB MUST NOT be represented as themselves
324 * within encoded words.
325 */
326
327 /*
328 * rule out non-ASCII characters and non-printable characters (the
329 * non-ASCII check should be redundant as isprint() is not localized
330 * and only knows about ASCII, but be defensive about that)
331 */
332 if (non_ascii(ch) || !isprint(ch))
333 return 1;
334
335 /*
336 * rule out special printable characters (' ' should be the only
337 * whitespace character considered printable, but be defensive and use
338 * isspace())
339 */
340 if (isspace(ch) || ch == '=' || ch == '?' || ch == '_')
94f6cdf6
JS
341 return 1;
342
0fcec2ce
JS
343 /*
344 * rfc2047, section 5.3:
345 *
346 * As a replacement for a 'word' entity within a 'phrase', for example,
347 * one that precedes an address in a From, To, or Cc header. The ABNF
348 * definition for 'phrase' from RFC 822 thus becomes:
349 *
350 * phrase = 1*( encoded-word / word )
351 *
352 * In this case the set of characters that may be used in a "Q"-encoded
353 * 'encoded-word' is restricted to: <upper and lower case ASCII
354 * letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
355 * (underscore, ASCII 95.)>. An 'encoded-word' that appears within a
356 * 'phrase' MUST be separated from any adjacent 'word', 'text' or
357 * 'special' by 'linear-white-space'.
358 */
359
360 if (type != RFC2047_ADDRESS)
361 return 0;
362
363 /* '=' and '_' are special cases and have been checked above */
364 return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
93fc05eb
JS
365}
366
da55ff3d 367static int needs_rfc2047_encoding(const char *line, int len)
93fc05eb 368{
a1f6baa5 369 int i;
93fc05eb
JS
370
371 for (i = 0; i < len; i++) {
372 int ch = line[i];
c22e7de3 373 if (non_ascii(ch) || ch == '\n')
41dd00ba 374 return 1;
93fc05eb 375 if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
41dd00ba 376 return 1;
93fc05eb 377 }
93fc05eb 378
41dd00ba
JS
379 return 0;
380}
381
6cd3c053 382static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
41dd00ba
JS
383 const char *encoding, enum rfc2047_type type)
384{
385 static const int max_encoded_length = 76; /* per rfc2047 */
386 int i;
387 int line_len = last_line_length(sb);
388
93fc05eb
JS
389 strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
390 strbuf_addf(sb, "=?%s?q?", encoding);
a1f6baa5 391 line_len += strlen(encoding) + 5; /* 5 for =??q? */
6cd3c053
KS
392
393 while (len) {
394 /*
395 * RFC 2047, section 5 (3):
396 *
397 * Each 'encoded-word' MUST represent an integral number of
398 * characters. A multi-octet character may not be split across
399 * adjacent 'encoded- word's.
400 */
401 const unsigned char *p = (const unsigned char *)line;
402 int chrlen = mbs_chrlen(&line, &len, encoding);
403 int is_special = (chrlen > 1) || is_rfc2047_special(*p, type);
404
405 /* "=%02X" * chrlen, or the byte itself */
406 const char *encoded_fmt = is_special ? "=%02X" : "%c";
407 int encoded_len = is_special ? 3 * chrlen : 1;
94f6cdf6
JS
408
409 /*
410 * According to RFC 2047, we could encode the special character
411 * ' ' (space) with '_' (underscore) for readability. But many
412 * programs do not understand this and just leave the
413 * underscore in place. Thus, we do nothing special here, which
414 * causes ' ' to be encoded as '=20', avoiding this problem.
415 */
a1f6baa5 416
6cd3c053
KS
417 if (line_len + encoded_len + 2 > max_encoded_length) {
418 /* It won't fit with trailing "?=" --- break the line */
a1f6baa5
JK
419 strbuf_addf(sb, "?=\n =?%s?q?", encoding);
420 line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
421 }
422
6cd3c053
KS
423 for (i = 0; i < chrlen; i++)
424 strbuf_addf(sb, encoded_fmt, p[i]);
425 line_len += encoded_len;
93fc05eb 426 }
93fc05eb
JS
427 strbuf_addstr(sb, "?=");
428}
429
d1053246 430const char *show_ident_date(const struct ident_split *ident,
a5481a6c 431 const struct date_mode *mode)
9dbe7c3d 432{
dddbad72 433 timestamp_t date = 0;
3f419d45 434 long tz = 0;
9dbe7c3d
RS
435
436 if (ident->date_begin && ident->date_end)
1aeb7e75 437 date = parse_timestamp(ident->date_begin, NULL, 10);
1dca155f
JK
438 if (date_overflows(date))
439 date = 0;
440 else {
441 if (ident->tz_begin && ident->tz_end)
442 tz = strtol(ident->tz_begin, NULL, 10);
3f419d45 443 if (tz >= INT_MAX || tz <= INT_MIN)
1dca155f
JK
444 tz = 0;
445 }
9dbe7c3d
RS
446 return show_date(date, tz, mode);
447}
448
6a5c3379
HM
449static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,
450 const char *buf, size_t buflen)
451{
452 strbuf_addstr(sb, color);
453 strbuf_add(sb, buf, buflen);
454 if (*color)
455 strbuf_addstr(sb, GIT_COLOR_RESET);
456}
457
458static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt,
459 const char *line, size_t linelen,
460 int color, enum grep_context ctx,
461 enum grep_header_field field)
462{
463 const char *buf, *eol, *line_color, *match_color;
464 regmatch_t match;
465 int eflags = 0;
466
467 buf = line;
468 eol = buf + linelen;
469
470 if (!opt || !want_color(color) || opt->invert)
471 goto end;
472
473 line_color = opt->colors[GREP_COLOR_SELECTED];
474 match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
475
476 while (grep_next_match(opt, buf, eol, ctx, &match, field, eflags)) {
477 if (match.rm_so == match.rm_eo)
478 break;
479
480 strbuf_add_with_color(sb, line_color, buf, match.rm_so);
481 strbuf_add_with_color(sb, match_color, buf + match.rm_so,
482 match.rm_eo - match.rm_so);
483 buf += match.rm_eo;
484 eflags = REG_NOTBOL;
485 }
486
487 if (eflags)
488 strbuf_add_with_color(sb, line_color, buf, eol - buf);
489 else {
490end:
491 strbuf_add(sb, buf, eol - buf);
492 }
493}
494
b84d0139
JH
495static int use_in_body_from(const struct pretty_print_context *pp,
496 const struct ident_split *ident)
497{
34bc1b10
JH
498 if (pp->rev && pp->rev->force_in_body_from)
499 return 1;
b84d0139
JH
500 if (ident_cmp(pp->from_ident, ident))
501 return 1;
502 return 0;
503}
504
10f2fbff 505void pp_user_info(struct pretty_print_context *pp,
6bf13944
JK
506 const char *what, struct strbuf *sb,
507 const char *line, const char *encoding)
93fc05eb 508{
3c020bd5 509 struct ident_split ident;
9dbe7c3d 510 char *line_end;
dffd325f
AP
511 const char *mailbuf, *namebuf;
512 size_t namelen, maillen;
41dd00ba 513 int max_length = 78; /* per rfc2822 */
93fc05eb 514
6bf13944 515 if (pp->fmt == CMIT_FMT_ONELINE)
93fc05eb 516 return;
3c020bd5 517
30e77bcb
RS
518 line_end = strchrnul(line, '\n');
519 if (split_ident_line(&ident, line, line_end - line))
93fc05eb 520 return;
3c020bd5 521
dffd325f
AP
522 mailbuf = ident.mail_begin;
523 maillen = ident.mail_end - ident.mail_begin;
524 namebuf = ident.name_begin;
525 namelen = ident.name_end - ident.name_begin;
526
527 if (pp->mailmap)
528 map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
529
9f23e040 530 if (cmit_fmt_is_mail(pp->fmt)) {
b84d0139 531 if (pp->from_ident && use_in_body_from(pp, &ident)) {
a9080475
JK
532 struct strbuf buf = STRBUF_INIT;
533
534 strbuf_addstr(&buf, "From: ");
535 strbuf_add(&buf, namebuf, namelen);
536 strbuf_addstr(&buf, " <");
537 strbuf_add(&buf, mailbuf, maillen);
538 strbuf_addstr(&buf, ">\n");
539 string_list_append(&pp->in_body_headers,
540 strbuf_detach(&buf, NULL));
541
542 mailbuf = pp->from_ident->mail_begin;
543 maillen = pp->from_ident->mail_end - mailbuf;
544 namebuf = pp->from_ident->name_begin;
545 namelen = pp->from_ident->name_end - namebuf;
546 }
547
93fc05eb 548 strbuf_addstr(sb, "From: ");
19d097e3
EB
549 if (pp->encode_email_headers &&
550 needs_rfc2047_encoding(namebuf, namelen)) {
a0511b39 551 add_rfc2047(sb, namebuf, namelen,
dffd325f 552 encoding, RFC2047_ADDRESS);
41dd00ba 553 max_length = 76; /* per rfc2047 */
a0511b39 554 } else if (needs_rfc822_quoting(namebuf, namelen)) {
4d03c18a 555 struct strbuf quoted = STRBUF_INIT;
a0511b39 556 add_rfc822_quoted(&quoted, namebuf, namelen);
41dd00ba
JS
557 strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
558 -6, 1, max_length);
4d03c18a 559 strbuf_release(&quoted);
41dd00ba 560 } else {
a0511b39 561 strbuf_add_wrapped_bytes(sb, namebuf, namelen,
dffd325f 562 -6, 1, max_length);
4d03c18a 563 }
dffd325f 564
97a17e77
RS
565 if (max_length <
566 last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
567 strbuf_addch(sb, '\n');
a0511b39 568 strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
93fc05eb 569 } else {
6a5c3379
HM
570 struct strbuf id = STRBUF_INIT;
571 enum grep_header_field field = GREP_HEADER_FIELD_MAX;
572 struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
573
574 if (!strcmp(what, "Author"))
575 field = GREP_HEADER_AUTHOR;
576 else if (!strcmp(what, "Commit"))
577 field = GREP_HEADER_COMMITTER;
578
579 strbuf_addf(sb, "%s: ", what);
580 if (pp->fmt == CMIT_FMT_FULLER)
581 strbuf_addchars(sb, ' ', 4);
582
583 strbuf_addf(&id, "%.*s <%.*s>", (int)namelen, namebuf,
584 (int)maillen, mailbuf);
585
586 append_line_with_color(sb, opt, id.buf, id.len, pp->color,
587 GREP_CONTEXT_HEAD, field);
588 strbuf_addch(sb, '\n');
589 strbuf_release(&id);
93fc05eb 590 }
dffd325f 591
6bf13944 592 switch (pp->fmt) {
93fc05eb 593 case CMIT_FMT_MEDIUM:
9dbe7c3d 594 strbuf_addf(sb, "Date: %s\n",
a5481a6c 595 show_ident_date(&ident, &pp->date_mode));
93fc05eb
JS
596 break;
597 case CMIT_FMT_EMAIL:
9f23e040 598 case CMIT_FMT_MBOXRD:
9dbe7c3d 599 strbuf_addf(sb, "Date: %s\n",
a5481a6c 600 show_ident_date(&ident, DATE_MODE(RFC2822)));
93fc05eb
JS
601 break;
602 case CMIT_FMT_FULLER:
9dbe7c3d 603 strbuf_addf(sb, "%sDate: %s\n", what,
a5481a6c 604 show_ident_date(&ident, &pp->date_mode));
93fc05eb
JS
605 break;
606 default:
607 /* notin' */
608 break;
609 }
610}
611
77356122 612static int is_blank_line(const char *line, int *len_p)
93fc05eb
JS
613{
614 int len = *len_p;
35b2fa5b 615 while (len && isspace(line[len - 1]))
93fc05eb
JS
616 len--;
617 *len_p = len;
618 return !len;
619}
620
77356122 621const char *skip_blank_lines(const char *msg)
a0109668
RS
622{
623 for (;;) {
624 int linelen = get_one_line(msg);
625 int ll = linelen;
626 if (!linelen)
627 break;
77356122 628 if (!is_blank_line(msg, &ll))
a0109668
RS
629 break;
630 msg += linelen;
631 }
632 return msg;
633}
634
6bf13944
JK
635static void add_merge_info(const struct pretty_print_context *pp,
636 struct strbuf *sb, const struct commit *commit)
93fc05eb
JS
637{
638 struct commit_list *parent = commit->parents;
639
9f23e040 640 if ((pp->fmt == CMIT_FMT_ONELINE) || (cmit_fmt_is_mail(pp->fmt)) ||
93fc05eb
JS
641 !parent || !parent->next)
642 return;
643
644 strbuf_addstr(sb, "Merge:");
645
646 while (parent) {
a94bb683
RS
647 struct object_id *oidp = &parent->item->object.oid;
648 strbuf_addch(sb, ' ');
6bf13944 649 if (pp->abbrev)
30e677e0 650 strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
a94bb683
RS
651 else
652 strbuf_addstr(sb, oid_to_hex(oidp));
93fc05eb 653 parent = parent->next;
93fc05eb
JS
654 }
655 strbuf_addch(sb, '\n');
656}
657
fe6eb7f2 658static char *get_header(const char *msg, const char *key)
93fc05eb 659{
fe6eb7f2
JK
660 size_t len;
661 const char *v = find_commit_header(msg, key, &len);
662 return v ? xmemdupz(v, len) : NULL;
93fc05eb
JS
663}
664
665static char *replace_encoding_header(char *buf, const char *encoding)
666{
f285a2d7 667 struct strbuf tmp = STRBUF_INIT;
93fc05eb
JS
668 size_t start, len;
669 char *cp = buf;
670
671 /* guess if there is an encoding header before a \n\n */
68d6d6eb 672 while (!starts_with(cp, "encoding ")) {
93fc05eb
JS
673 cp = strchr(cp, '\n');
674 if (!cp || *++cp == '\n')
675 return buf;
676 }
677 start = cp - buf;
678 cp = strchr(cp, '\n');
679 if (!cp)
680 return buf; /* should not happen but be defensive */
681 len = cp + 1 - (buf + start);
682
93fc05eb
JS
683 strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
684 if (is_encoding_utf8(encoding)) {
685 /* we have re-coded to UTF-8; drop the header */
686 strbuf_remove(&tmp, start, len);
687 } else {
688 /* just replaces XXXX in 'encoding XXXX\n' */
689 strbuf_splice(&tmp, start + strlen("encoding "),
690 len - strlen("encoding \n"),
691 encoding, strlen(encoding));
692 }
693 return strbuf_detach(&tmp, NULL);
694}
695
424510ed
SB
696const char *repo_logmsg_reencode(struct repository *r,
697 const struct commit *commit,
698 char **commit_encoding,
699 const char *output_encoding)
93fc05eb 700{
330db18c 701 static const char *utf8 = "UTF-8";
93fc05eb
JS
702 const char *use_encoding;
703 char *encoding;
424510ed 704 const char *msg = repo_get_commit_buffer(r, commit, NULL);
93fc05eb
JS
705 char *out;
706
5a10d236
NTND
707 if (!output_encoding || !*output_encoding) {
708 if (commit_encoding)
fe6eb7f2 709 *commit_encoding = get_header(msg, "encoding");
dd0d388c 710 return msg;
5a10d236 711 }
fe6eb7f2 712 encoding = get_header(msg, "encoding");
5a10d236
NTND
713 if (commit_encoding)
714 *commit_encoding = encoding;
93fc05eb 715 use_encoding = encoding ? encoding : utf8;
be5c9fb9
JK
716 if (same_encoding(use_encoding, output_encoding)) {
717 /*
718 * No encoding work to be done. If we have no encoding header
719 * at all, then there's nothing to do, and we can return the
720 * message verbatim (whether newly allocated or not).
721 */
722 if (!encoding)
723 return msg;
724
725 /*
726 * Otherwise, we still want to munge the encoding header in the
727 * result, which will be done by modifying the buffer. If we
728 * are using a fresh copy, we can reuse it. But if we are using
c7c33f50 729 * the cached copy from repo_get_commit_buffer, we need to duplicate it
b66103c3 730 * to avoid munging the cached copy.
be5c9fb9 731 */
424510ed 732 if (msg == get_cached_commit_buffer(r, commit, NULL))
b66103c3
JK
733 out = xstrdup(msg);
734 else
735 out = (char *)msg;
be5c9fb9
JK
736 }
737 else {
738 /*
739 * There's actual encoding work to do. Do the reencoding, which
740 * still leaves the header to be replaced in the next step. At
741 * this point, we are done with msg. If we allocated a fresh
742 * copy, we can free it.
743 */
744 out = reencode_string(msg, output_encoding, use_encoding);
b66103c3 745 if (out)
424510ed 746 repo_unuse_commit_buffer(r, commit, msg);
be5c9fb9
JK
747 }
748
749 /*
750 * This replacement actually consumes the buffer we hand it, so we do
751 * not have to worry about freeing the old "out" here.
752 */
93fc05eb
JS
753 if (out)
754 out = replace_encoding_header(out, output_encoding);
755
5a10d236
NTND
756 if (!commit_encoding)
757 free(encoding);
dd0d388c
JK
758 /*
759 * If the re-encoding failed, out might be NULL here; in that
760 * case we just return the commit message verbatim.
761 */
0988e665 762 return out ? out : msg;
dd0d388c
JK
763}
764
ea02ffa3
AP
765static int mailmap_name(const char **email, size_t *email_len,
766 const char **name, size_t *name_len)
e0cbc397 767{
c455c87c 768 static struct string_list *mail_map;
e0cbc397 769 if (!mail_map) {
ca56dadb 770 CALLOC_ARRAY(mail_map, 1);
4e168333 771 read_mailmap(mail_map);
e0cbc397 772 }
d20d654f 773 return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
e0cbc397
JS
774}
775
c3a670de 776static size_t format_person_part(struct strbuf *sb, char part,
a5481a6c
JK
777 const char *msg, int len,
778 const struct date_mode *dmode)
93fc05eb 779{
c3a670de
MC
780 /* currently all placeholders have same length */
781 const int placeholder_len = 2;
4b340cfa 782 struct ident_split s;
ea02ffa3
AP
783 const char *name, *mail;
784 size_t maillen, namelen;
93fc05eb 785
4b340cfa 786 if (split_ident_line(&s, msg, len) < 0)
c3a670de
MC
787 goto skip;
788
ea02ffa3
AP
789 name = s.name_begin;
790 namelen = s.name_end - s.name_begin;
791 mail = s.mail_begin;
792 maillen = s.mail_end - s.mail_begin;
793
d8b8217c 794 if (part == 'N' || part == 'E' || part == 'L') /* mailmap lookup */
ea02ffa3 795 mailmap_name(&mail, &maillen, &name, &namelen);
e0cbc397 796 if (part == 'n' || part == 'N') { /* name */
ea02ffa3 797 strbuf_add(sb, name, namelen);
c3a670de 798 return placeholder_len;
cde75e59 799 }
d20d654f 800 if (part == 'e' || part == 'E') { /* email */
ea02ffa3 801 strbuf_add(sb, mail, maillen);
c3a670de 802 return placeholder_len;
cde75e59 803 }
d8b8217c
PB
804 if (part == 'l' || part == 'L') { /* local-part */
805 const char *at = memchr(mail, '@', maillen);
806 if (at)
807 maillen = at - mail;
808 strbuf_add(sb, mail, maillen);
809 return placeholder_len;
810 }
93fc05eb 811
4b340cfa 812 if (!s.date_begin)
c3a670de 813 goto skip;
93fc05eb 814
cde75e59 815 if (part == 't') { /* date, UNIX timestamp */
4b340cfa 816 strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
c3a670de 817 return placeholder_len;
cde75e59 818 }
93fc05eb 819
cde75e59
RS
820 switch (part) {
821 case 'd': /* date */
9dbe7c3d 822 strbuf_addstr(sb, show_ident_date(&s, dmode));
c3a670de 823 return placeholder_len;
cde75e59 824 case 'D': /* date, RFC2822 style */
a5481a6c 825 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RFC2822)));
c3a670de 826 return placeholder_len;
cde75e59 827 case 'r': /* date, relative */
a5481a6c 828 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RELATIVE)));
c3a670de 829 return placeholder_len;
466fb674 830 case 'i': /* date, ISO 8601-like */
a5481a6c 831 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601)));
c3a670de 832 return placeholder_len;
466fb674 833 case 'I': /* date, ISO 8601 strict */
a5481a6c 834 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
466fb674 835 return placeholder_len;
b722d456
ZH
836 case 'h': /* date, human */
837 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(HUMAN)));
838 return placeholder_len;
0df62117
RS
839 case 's':
840 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(SHORT)));
841 return placeholder_len;
cde75e59 842 }
c3a670de
MC
843
844skip:
845 /*
4b340cfa
JH
846 * reading from either a bogus commit, or a reflog entry with
847 * %gn, %ge, etc.; 'sb' cannot be updated, but we still need
848 * to compute a valid return value.
c3a670de
MC
849 */
850 if (part == 'n' || part == 'e' || part == 't' || part == 'd'
851 || part == 'D' || part == 'r' || part == 'i')
852 return placeholder_len;
853
854 return 0; /* unknown placeholder */
93fc05eb
JS
855}
856
f29d5958
RS
857struct chunk {
858 size_t off;
859 size_t len;
860};
861
a5752342
NTND
862enum flush_type {
863 no_flush,
864 flush_right,
865 flush_left,
1640632b 866 flush_left_and_steal,
a5752342
NTND
867 flush_both
868};
869
a7f01c6b
NTND
870enum trunc_type {
871 trunc_none,
872 trunc_left,
873 trunc_middle,
874 trunc_right
875};
876
f29d5958 877struct format_commit_context {
018b9deb 878 struct repository *repository;
f29d5958 879 const struct commit *commit;
dd2e794a 880 const struct pretty_print_context *pretty_ctx;
f53bd743
RS
881 unsigned commit_header_parsed:1;
882 unsigned commit_message_parsed:1;
ffb6d7d5 883 struct signature_check signature_check;
a5752342 884 enum flush_type flush_type;
a7f01c6b 885 enum trunc_type truncate;
b000c59b 886 const char *message;
0940a76d 887 char *commit_encoding;
02edd56b 888 size_t width, indent1, indent2;
a95f067e 889 int auto_color;
a5752342 890 int padding;
f29d5958
RS
891
892 /* These offsets are relative to the start of the commit message. */
f29d5958
RS
893 struct chunk author;
894 struct chunk committer;
f53bd743
RS
895 size_t message_off;
896 size_t subject_off;
f29d5958 897 size_t body_off;
b9c62321
RS
898
899 /* The following ones are relative to the result struct strbuf. */
02edd56b 900 size_t wrap_start;
f29d5958
RS
901};
902
903static void parse_commit_header(struct format_commit_context *context)
93fc05eb 904{
177b29dc 905 const char *msg = context->message;
93fc05eb 906 int i;
f29d5958 907
f53bd743 908 for (i = 0; msg[i]; i++) {
e3f1da98 909 const char *name;
f29d5958
RS
910 int eol;
911 for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
912 ; /* do nothing */
913
f29d5958 914 if (i == eol) {
f53bd743 915 break;
e3f1da98
RS
916 } else if (skip_prefix(msg + i, "author ", &name)) {
917 context->author.off = name - msg;
918 context->author.len = msg + eol - name;
919 } else if (skip_prefix(msg + i, "committer ", &name)) {
920 context->committer.off = name - msg;
921 context->committer.len = msg + eol - name;
f29d5958
RS
922 }
923 i = eol;
924 }
f53bd743 925 context->message_off = i;
f29d5958
RS
926 context->commit_header_parsed = 1;
927}
928
46d164b0
SB
929static int istitlechar(char c)
930{
931 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
932 (c >= '0' && c <= '9') || c == '.' || c == '_';
933}
934
47d4676a 935void format_sanitized_subject(struct strbuf *sb, const char *msg, size_t len)
46d164b0
SB
936{
937 size_t trimlen;
871d21d4 938 size_t start_len = sb->len;
46d164b0 939 int space = 2;
47d4676a 940 int i;
46d164b0 941
47d4676a
HV
942 for (i = 0; i < len; i++) {
943 if (istitlechar(msg[i])) {
46d164b0
SB
944 if (space == 1)
945 strbuf_addch(sb, '-');
946 space = 0;
47d4676a
HV
947 strbuf_addch(sb, msg[i]);
948 if (msg[i] == '.')
949 while (msg[i+1] == '.')
950 i++;
46d164b0
SB
951 } else
952 space |= 1;
953 }
954
955 /* trim any trailing '.' or '-' characters */
956 trimlen = 0;
871d21d4
SB
957 while (sb->len - trimlen > start_len &&
958 (sb->buf[sb->len - 1 - trimlen] == '.'
959 || sb->buf[sb->len - 1 - trimlen] == '-'))
46d164b0
SB
960 trimlen++;
961 strbuf_remove(sb, sb->len - trimlen, trimlen);
962}
963
cec08717
RS
964const char *format_subject(struct strbuf *sb, const char *msg,
965 const char *line_separator)
88c44735
RS
966{
967 int first = 1;
968
969 for (;;) {
970 const char *line = msg;
971 int linelen = get_one_line(line);
972
973 msg += linelen;
77356122 974 if (!linelen || is_blank_line(line, &linelen))
88c44735
RS
975 break;
976
f53bd743
RS
977 if (!sb)
978 continue;
88c44735
RS
979 strbuf_grow(sb, linelen + 2);
980 if (!first)
981 strbuf_addstr(sb, line_separator);
982 strbuf_add(sb, line, linelen);
983 first = 0;
984 }
985 return msg;
986}
987
f53bd743
RS
988static void parse_commit_message(struct format_commit_context *c)
989{
177b29dc
PN
990 const char *msg = c->message + c->message_off;
991 const char *start = c->message;
f53bd743 992
77356122 993 msg = skip_blank_lines(msg);
f53bd743
RS
994 c->subject_off = msg - start;
995
996 msg = format_subject(NULL, msg, NULL);
77356122 997 msg = skip_blank_lines(msg);
f53bd743
RS
998 c->body_off = msg - start;
999
1000 c->commit_message_parsed = 1;
1001}
1002
02edd56b
RS
1003static void strbuf_wrap(struct strbuf *sb, size_t pos,
1004 size_t width, size_t indent1, size_t indent2)
1005{
1006 struct strbuf tmp = STRBUF_INIT;
1007
1008 if (pos)
1009 strbuf_add(&tmp, sb->buf, pos);
1010 strbuf_add_wrapped_text(&tmp, sb->buf + pos,
48050c42
PS
1011 cast_size_t_to_int(indent1),
1012 cast_size_t_to_int(indent2),
1013 cast_size_t_to_int(width));
02edd56b
RS
1014 strbuf_swap(&tmp, sb);
1015 strbuf_release(&tmp);
1016}
1017
1018static void rewrap_message_tail(struct strbuf *sb,
1019 struct format_commit_context *c,
1020 size_t new_width, size_t new_indent1,
1021 size_t new_indent2)
1022{
1023 if (c->width == new_width && c->indent1 == new_indent1 &&
1024 c->indent2 == new_indent2)
1025 return;
32ca4249 1026 if (c->wrap_start < sb->len)
02edd56b
RS
1027 strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
1028 c->wrap_start = sb->len;
1029 c->width = new_width;
1030 c->indent1 = new_indent1;
1031 c->indent2 = new_indent2;
1032}
1033
cd1957f5
JK
1034static int format_reflog_person(struct strbuf *sb,
1035 char part,
1036 struct reflog_walk_info *log,
a5481a6c 1037 const struct date_mode *dmode)
cd1957f5
JK
1038{
1039 const char *ident;
1040
1041 if (!log)
1042 return 2;
1043
1044 ident = get_reflog_ident(log);
1045 if (!ident)
1046 return 2;
1047
1048 return format_person_part(sb, part, ident, strlen(ident), dmode);
1049}
1050
fcabc2d9
NTND
1051static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
1052 const char *placeholder,
1053 struct format_commit_context *c)
1054{
e3f1da98 1055 const char *rest = placeholder;
18fb7ffc 1056 const char *basic_color = NULL;
e3f1da98 1057
fcabc2d9
NTND
1058 if (placeholder[1] == '(') {
1059 const char *begin = placeholder + 2;
1060 const char *end = strchr(begin, ')');
1061 char color[COLOR_MAXLEN];
1062
1063 if (!end)
1064 return 0;
18fb7ffc 1065
e3f1da98 1066 if (skip_prefix(begin, "auto,", &begin)) {
fcabc2d9
NTND
1067 if (!want_color(c->pretty_ctx->color))
1068 return end - placeholder + 1;
18fb7ffc
JK
1069 } else if (skip_prefix(begin, "always,", &begin)) {
1070 /* nothing to do; we do not respect want_color at all */
1071 } else {
1072 /* the default is the same as "auto" */
1073 if (!want_color(c->pretty_ctx->color))
1074 return end - placeholder + 1;
fcabc2d9 1075 }
18fb7ffc 1076
f6c5a296
JK
1077 if (color_parse_mem(begin, end - begin, color) < 0)
1078 die(_("unable to parse --pretty format"));
fcabc2d9
NTND
1079 strbuf_addstr(sb, color);
1080 return end - placeholder + 1;
1081 }
18fb7ffc
JK
1082
1083 /*
1084 * We handle things like "%C(red)" above; for historical reasons, there
1085 * are a few colors that can be specified without parentheses (and
1086 * they cannot support things like "auto" or "always" at all).
1087 */
e3f1da98 1088 if (skip_prefix(placeholder + 1, "red", &rest))
18fb7ffc 1089 basic_color = GIT_COLOR_RED;
e3f1da98 1090 else if (skip_prefix(placeholder + 1, "green", &rest))
18fb7ffc 1091 basic_color = GIT_COLOR_GREEN;
e3f1da98 1092 else if (skip_prefix(placeholder + 1, "blue", &rest))
18fb7ffc 1093 basic_color = GIT_COLOR_BLUE;
e3f1da98 1094 else if (skip_prefix(placeholder + 1, "reset", &rest))
18fb7ffc
JK
1095 basic_color = GIT_COLOR_RESET;
1096
1097 if (basic_color && want_color(c->pretty_ctx->color))
1098 strbuf_addstr(sb, basic_color);
1099
e3f1da98 1100 return rest - placeholder;
fcabc2d9
NTND
1101}
1102
9a1180fc 1103static size_t parse_padding_placeholder(const char *placeholder,
a5752342
NTND
1104 struct format_commit_context *c)
1105{
1106 const char *ch = placeholder;
1107 enum flush_type flush_type;
1108 int to_column = 0;
1109
1110 switch (*ch++) {
1111 case '<':
1112 flush_type = flush_right;
1113 break;
1114 case '>':
1115 if (*ch == '<') {
1116 flush_type = flush_both;
1117 ch++;
1640632b
NTND
1118 } else if (*ch == '>') {
1119 flush_type = flush_left_and_steal;
1120 ch++;
a5752342
NTND
1121 } else
1122 flush_type = flush_left;
1123 break;
1124 default:
1125 return 0;
1126 }
1127
1128 /* the next value means "wide enough to that column" */
1129 if (*ch == '|') {
1130 to_column = 1;
1131 ch++;
1132 }
1133
1134 if (*ch == '(') {
1135 const char *start = ch + 1;
a7f01c6b 1136 const char *end = start + strcspn(start, ",)");
a5752342
NTND
1137 char *next;
1138 int width;
f6e0b9f3 1139 if (!*end || end == start)
a5752342 1140 return 0;
066790d7 1141 width = strtol(start, &next, 10);
304a50ad
PS
1142
1143 /*
1144 * We need to limit the amount of padding, or otherwise this
1145 * would allow the user to pad the buffer by arbitrarily many
1146 * bytes and thus cause resource exhaustion.
1147 */
1148 if (width < -FORMATTING_LIMIT || width > FORMATTING_LIMIT)
1149 return 0;
1150
a5752342
NTND
1151 if (next == start || width == 0)
1152 return 0;
066790d7
NTND
1153 if (width < 0) {
1154 if (to_column)
1155 width += term_columns();
1156 if (width < 0)
1157 return 0;
1158 }
a5752342
NTND
1159 c->padding = to_column ? -width : width;
1160 c->flush_type = flush_type;
a7f01c6b
NTND
1161
1162 if (*end == ',') {
1163 start = end + 1;
1164 end = strchr(start, ')');
1165 if (!end || end == start)
1166 return 0;
59556548 1167 if (starts_with(start, "trunc)"))
a7f01c6b 1168 c->truncate = trunc_right;
59556548 1169 else if (starts_with(start, "ltrunc)"))
a7f01c6b 1170 c->truncate = trunc_left;
59556548 1171 else if (starts_with(start, "mtrunc)"))
a7f01c6b
NTND
1172 c->truncate = trunc_middle;
1173 else
1174 return 0;
1175 } else
1176 c->truncate = trunc_none;
1177
a5752342
NTND
1178 return end - placeholder + 1;
1179 }
1180 return 0;
1181}
1182
4f732e0f
AW
1183static int match_placeholder_arg_value(const char *to_parse, const char *candidate,
1184 const char **end, const char **valuestart,
1185 size_t *valuelen)
84ff053d
TB
1186{
1187 const char *p;
1188
1189 if (!(skip_prefix(to_parse, candidate, &p)))
1190 return 0;
4f732e0f
AW
1191 if (valuestart) {
1192 if (*p == '=') {
1193 *valuestart = p + 1;
1194 *valuelen = strcspn(*valuestart, ",)");
1195 p = *valuestart + *valuelen;
1196 } else {
1197 if (*p != ',' && *p != ')')
1198 return 0;
1199 *valuestart = NULL;
1200 *valuelen = 0;
1201 }
1202 }
84ff053d
TB
1203 if (*p == ',') {
1204 *end = p + 1;
1205 return 1;
1206 }
1207 if (*p == ')') {
1208 *end = p;
1209 return 1;
1210 }
1211 return 0;
1212}
1213
4f732e0f
AW
1214static int match_placeholder_bool_arg(const char *to_parse, const char *candidate,
1215 const char **end, int *val)
1216{
1217 const char *argval;
1218 char *strval;
1219 size_t arglen;
1220 int v;
1221
1222 if (!match_placeholder_arg_value(to_parse, candidate, end, &argval, &arglen))
1223 return 0;
1224
1225 if (!argval) {
1226 *val = 1;
1227 return 1;
1228 }
1229
1230 strval = xstrndup(argval, arglen);
1231 v = git_parse_maybe_bool(strval);
1232 free(strval);
1233
1234 if (v == -1)
1235 return 0;
1236
1237 *val = v;
1238
1239 return 1;
1240}
1241
250bea0c
AW
1242static int format_trailer_match_cb(const struct strbuf *key, void *ud)
1243{
1244 const struct string_list *list = ud;
1245 const struct string_list_item *item;
1246
1247 for_each_string_list_item (item, list) {
1248 if (key->len == (uintptr_t)item->util &&
1249 !strncasecmp(item->string, key->buf, key->len))
1250 return 1;
1251 }
1252 return 0;
1253}
1254
3c3d0c42
RS
1255static struct strbuf *expand_separator(struct strbuf *sb,
1256 const char *argval, size_t arglen)
1257{
1258 char *fmt = xstrndup(argval, arglen);
6f1e2d52 1259 const char *format = fmt;
3c3d0c42
RS
1260
1261 strbuf_reset(sb);
6f1e2d52
RS
1262 while (strbuf_expand_step(sb, &format)) {
1263 size_t len;
1264
1265 if (skip_prefix(format, "%", &format))
1266 strbuf_addch(sb, '%');
4416b86c 1267 else if ((len = strbuf_expand_literal(sb, format)))
6f1e2d52
RS
1268 format += len;
1269 else
1270 strbuf_addch(sb, '%');
1271 }
3c3d0c42
RS
1272 free(fmt);
1273 return sb;
1274}
1275
90563aed
HV
1276int format_set_trailers_options(struct process_trailer_options *opts,
1277 struct string_list *filter_list,
1278 struct strbuf *sepbuf,
1279 struct strbuf *kvsepbuf,
636a0aee
HV
1280 const char **arg,
1281 char **invalid_arg)
90563aed
HV
1282{
1283 for (;;) {
1284 const char *argval;
1285 size_t arglen;
1286
636a0aee
HV
1287 if (**arg == ')')
1288 break;
1289
90563aed
HV
1290 if (match_placeholder_arg_value(*arg, "key", arg, &argval, &arglen)) {
1291 uintptr_t len = arglen;
1292
1293 if (!argval)
1294 return -1;
1295
1296 if (len && argval[len - 1] == ':')
1297 len--;
1298 string_list_append(filter_list, argval)->util = (char *)len;
1299
1300 opts->filter = format_trailer_match_cb;
1301 opts->filter_data = filter_list;
1302 opts->only_trailers = 1;
1303 } else if (match_placeholder_arg_value(*arg, "separator", arg, &argval, &arglen)) {
3c3d0c42 1304 opts->separator = expand_separator(sepbuf, argval, arglen);
90563aed 1305 } else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) {
3c3d0c42 1306 opts->key_value_separator = expand_separator(kvsepbuf, argval, arglen);
90563aed
HV
1307 } else if (!match_placeholder_bool_arg(*arg, "only", arg, &opts->only_trailers) &&
1308 !match_placeholder_bool_arg(*arg, "unfold", arg, &opts->unfold) &&
1309 !match_placeholder_bool_arg(*arg, "keyonly", arg, &opts->key_only) &&
636a0aee
HV
1310 !match_placeholder_bool_arg(*arg, "valueonly", arg, &opts->value_only)) {
1311 if (invalid_arg) {
1312 size_t len = strcspn(*arg, ",)");
1313 *invalid_arg = xstrndup(*arg, len);
1314 }
1315 return -1;
1316 }
90563aed
HV
1317 }
1318 return 0;
1319}
1320
b081547e
RS
1321static size_t parse_describe_args(const char *start, struct strvec *args)
1322{
3c6eb4ec
ES
1323 struct {
1324 char *name;
1325 enum {
1d517cea 1326 DESCRIBE_ARG_BOOL,
eccd97d0 1327 DESCRIBE_ARG_INTEGER,
3c6eb4ec
ES
1328 DESCRIBE_ARG_STRING,
1329 } type;
1330 } option[] = {
1d517cea 1331 { "tags", DESCRIBE_ARG_BOOL},
eccd97d0 1332 { "abbrev", DESCRIBE_ARG_INTEGER },
3c6eb4ec
ES
1333 { "exclude", DESCRIBE_ARG_STRING },
1334 { "match", DESCRIBE_ARG_STRING },
1335 };
b081547e
RS
1336 const char *arg = start;
1337
1338 for (;;) {
3c6eb4ec 1339 int found = 0;
b081547e
RS
1340 const char *argval;
1341 size_t arglen = 0;
1d517cea 1342 int optval = 0;
b081547e
RS
1343 int i;
1344
3c6eb4ec
ES
1345 for (i = 0; !found && i < ARRAY_SIZE(option); i++) {
1346 switch (option[i].type) {
1d517cea
ES
1347 case DESCRIBE_ARG_BOOL:
1348 if (match_placeholder_bool_arg(arg, option[i].name, &arg, &optval)) {
1349 if (optval)
1350 strvec_pushf(args, "--%s", option[i].name);
1351 else
1352 strvec_pushf(args, "--no-%s", option[i].name);
1353 found = 1;
1354 }
1355 break;
eccd97d0
ES
1356 case DESCRIBE_ARG_INTEGER:
1357 if (match_placeholder_arg_value(arg, option[i].name, &arg,
1358 &argval, &arglen)) {
1359 char *endptr;
1360 if (!arglen)
1361 return 0;
1362 strtol(argval, &endptr, 10);
1363 if (endptr - argval != arglen)
1364 return 0;
1365 strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
1366 found = 1;
1367 }
1368 break;
3c6eb4ec
ES
1369 case DESCRIBE_ARG_STRING:
1370 if (match_placeholder_arg_value(arg, option[i].name, &arg,
1371 &argval, &arglen)) {
1372 if (!arglen)
1373 return 0;
1374 strvec_pushf(args, "--%s=%.*s", option[i].name, (int)arglen, argval);
1375 found = 1;
1376 }
b081547e
RS
1377 break;
1378 }
1379 }
3c6eb4ec 1380 if (!found)
b081547e
RS
1381 break;
1382
b081547e
RS
1383 }
1384 return arg - start;
1385}
1386
7e77df39
NTND
1387static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1388 const char *placeholder,
9fa708da 1389 void *context)
f29d5958
RS
1390{
1391 struct format_commit_context *c = context;
1392 const struct commit *commit = c->commit;
177b29dc 1393 const char *msg = c->message;
f29d5958 1394 struct commit_list *p;
47d4676a 1395 const char *arg, *eol;
fd2015b3 1396 size_t res;
ad6f028f 1397 char **slot;
93fc05eb 1398
93fc05eb 1399 /* these are independent of the commit */
4416b86c 1400 res = strbuf_expand_literal(sb, placeholder);
fd2015b3
AW
1401 if (res)
1402 return res;
1403
cde75e59
RS
1404 switch (placeholder[0]) {
1405 case 'C':
59556548 1406 if (starts_with(placeholder + 1, "(auto)")) {
b15a3e00 1407 c->auto_color = want_color(c->pretty_ctx->color);
82b83da8 1408 if (c->auto_color && sb->len)
c99ad274 1409 strbuf_addstr(sb, GIT_COLOR_RESET);
a95f067e
NTND
1410 return 7; /* consumed 7 bytes, "C(auto)" */
1411 } else {
1412 int ret = parse_color(sb, placeholder, c);
1413 if (ret)
1414 c->auto_color = 0;
1415 /*
1416 * Otherwise, we decided to treat %C<unknown>
1417 * as a literal string, and the previous
1418 * %C(auto) is still valid.
1419 */
1420 return ret;
c002922a 1421 }
02edd56b
RS
1422 case 'w':
1423 if (placeholder[1] == '(') {
1424 unsigned long width = 0, indent1 = 0, indent2 = 0;
1425 char *next;
1426 const char *start = placeholder + 2;
1427 const char *end = strchr(start, ')');
1428 if (!end)
1429 return 0;
1430 if (end > start) {
1431 width = strtoul(start, &next, 10);
1432 if (*next == ',') {
1433 indent1 = strtoul(next + 1, &next, 10);
1434 if (*next == ',') {
1435 indent2 = strtoul(next + 1,
1436 &next, 10);
1437 }
1438 }
1439 if (*next != ')')
1440 return 0;
1441 }
304a50ad
PS
1442
1443 /*
1444 * We need to limit the format here as it allows the
1445 * user to prepend arbitrarily many bytes to the buffer
1446 * when rewrapping.
1447 */
1448 if (width > FORMATTING_LIMIT ||
1449 indent1 > FORMATTING_LIMIT ||
1450 indent2 > FORMATTING_LIMIT)
1451 return 0;
02edd56b
RS
1452 rewrap_message_tail(sb, c, width, indent1, indent2);
1453 return end - placeholder + 1;
1454 } else
1455 return 0;
a5752342
NTND
1456
1457 case '<':
1458 case '>':
9a1180fc 1459 return parse_padding_placeholder(placeholder, c);
cde75e59 1460 }
93fc05eb 1461
b081547e 1462 if (skip_prefix(placeholder, "(describe", &arg)) {
15ae82d5
RS
1463 struct child_process cmd = CHILD_PROCESS_INIT;
1464 struct strbuf out = STRBUF_INIT;
1465 struct strbuf err = STRBUF_INIT;
96099726
RS
1466 struct pretty_print_describe_status *describe_status;
1467
1468 describe_status = c->pretty_ctx->describe_status;
1469 if (describe_status) {
1470 if (!describe_status->max_invocations)
1471 return 0;
1472 describe_status->max_invocations--;
1473 }
15ae82d5
RS
1474
1475 cmd.git_cmd = 1;
1476 strvec_push(&cmd.args, "describe");
b081547e
RS
1477
1478 if (*arg == ':') {
1479 arg++;
1480 arg += parse_describe_args(arg, &cmd.args);
1481 }
1482
1483 if (*arg != ')') {
1484 child_process_clear(&cmd);
1485 return 0;
1486 }
1487
15ae82d5
RS
1488 strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
1489 pipe_command(&cmd, NULL, 0, &out, 0, &err, 0);
1490 strbuf_rtrim(&out);
1491 strbuf_addbuf(sb, &out);
1492 strbuf_release(&out);
1493 strbuf_release(&err);
b081547e 1494 return arg - placeholder + 1;
15ae82d5
RS
1495 }
1496
93fc05eb
JS
1497 /* these depend on the commit */
1498 if (!commit->object.parsed)
109cd76d 1499 parse_object(the_repository, &commit->object.oid);
93fc05eb 1500
cde75e59
RS
1501 switch (placeholder[0]) {
1502 case 'H': /* commit hash */
a95f067e 1503 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
f2fd0760 1504 strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
a95f067e 1505 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
c3a670de 1506 return 1;
cde75e59 1507 case 'h': /* abbreviated commit hash */
a95f067e 1508 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
30e677e0 1509 strbuf_add_unique_abbrev(sb, &commit->object.oid,
1eb47f16 1510 c->pretty_ctx->abbrev);
a95f067e 1511 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
c3a670de 1512 return 1;
cde75e59 1513 case 'T': /* tree hash */
2e27bd77 1514 strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit)));
c3a670de 1515 return 1;
cde75e59 1516 case 't': /* abbreviated tree hash */
2e27bd77 1517 strbuf_add_unique_abbrev(sb,
c89b6e13 1518 get_commit_tree_oid(commit),
1eb47f16 1519 c->pretty_ctx->abbrev);
c3a670de 1520 return 1;
cde75e59
RS
1521 case 'P': /* parent hashes */
1522 for (p = commit->parents; p; p = p->next) {
1523 if (p != commit->parents)
1524 strbuf_addch(sb, ' ');
f2fd0760 1525 strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
cde75e59 1526 }
c3a670de 1527 return 1;
cde75e59
RS
1528 case 'p': /* abbreviated parent hashes */
1529 for (p = commit->parents; p; p = p->next) {
1530 if (p != commit->parents)
1531 strbuf_addch(sb, ' ');
30e677e0 1532 strbuf_add_unique_abbrev(sb, &p->item->object.oid,
1eb47f16 1533 c->pretty_ctx->abbrev);
cde75e59 1534 }
c3a670de 1535 return 1;
cde75e59 1536 case 'm': /* left/right/bottom */
1df2d656 1537 strbuf_addstr(sb, get_revision_mark(NULL, commit));
c3a670de 1538 return 1;
3b3d443f 1539 case 'd':
a3883a65 1540 format_decorations(sb, commit, c->auto_color, NULL);
3b3d443f 1541 return 1;
9271095c 1542 case 'D':
a3883a65
AK
1543 {
1544 const struct decoration_options opts = {
1545 .prefix = "",
1546 .suffix = ""
1547 };
1548
1549 format_decorations(sb, commit, c->auto_color, &opts);
1550 return 1;
1551 }
ad6f028f
IT
1552 case 'S': /* tag/branch like --source */
1553 if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
1554 return 0;
1555 slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
1556 if (!(slot && *slot))
1557 return 0;
1558 strbuf_addstr(sb, *slot);
1559 return 1;
8f8f5476
TR
1560 case 'g': /* reflog info */
1561 switch(placeholder[1]) {
1562 case 'd': /* reflog selector */
1563 case 'D':
1564 if (c->pretty_ctx->reflog_info)
1565 get_reflog_selector(sb,
1566 c->pretty_ctx->reflog_info,
a5481a6c 1567 &c->pretty_ctx->date_mode,
55ccf85a 1568 c->pretty_ctx->date_mode_explicit,
8f8f5476
TR
1569 (placeholder[1] == 'd'));
1570 return 2;
1571 case 's': /* reflog message */
1572 if (c->pretty_ctx->reflog_info)
1573 get_reflog_message(sb, c->pretty_ctx->reflog_info);
1574 return 2;
cd1957f5
JK
1575 case 'n':
1576 case 'N':
1577 case 'e':
1578 case 'E':
1579 return format_reflog_person(sb,
1580 placeholder[1],
1581 c->pretty_ctx->reflog_info,
a5481a6c 1582 &c->pretty_ctx->date_mode);
8f8f5476
TR
1583 }
1584 return 0; /* unknown %g placeholder */
8b208f02 1585 case 'N':
ddf333f6
JH
1586 if (c->pretty_ctx->notes_message) {
1587 strbuf_addstr(sb, c->pretty_ctx->notes_message);
5b163603
JG
1588 return 1;
1589 }
1590 return 0;
cde75e59
RS
1591 }
1592
f6667c5e 1593 if (placeholder[0] == 'G') {
ffb6d7d5
SG
1594 if (!c->signature_check.result)
1595 check_commit_signature(c->commit, &(c->signature_check));
f6667c5e
JH
1596 switch (placeholder[1]) {
1597 case 'G':
b5726a5d
FS
1598 if (c->signature_check.output)
1599 strbuf_addstr(sb, c->signature_check.output);
f6667c5e
JH
1600 break;
1601 case '?':
ffb6d7d5 1602 switch (c->signature_check.result) {
f6667c5e 1603 case 'G':
54887b46
HJI
1604 switch (c->signature_check.trust_level) {
1605 case TRUST_UNDEFINED:
1606 case TRUST_NEVER:
1607 strbuf_addch(sb, 'U');
1608 break;
1609 default:
1610 strbuf_addch(sb, 'G');
1611 break;
1612 }
1613 break;
f6667c5e 1614 case 'B':
661a1806 1615 case 'E':
e290c4b9 1616 case 'N':
661a1806
MG
1617 case 'X':
1618 case 'Y':
1619 case 'R':
ffb6d7d5 1620 strbuf_addch(sb, c->signature_check.result);
f6667c5e
JH
1621 }
1622 break;
1623 case 'S':
ffb6d7d5
SG
1624 if (c->signature_check.signer)
1625 strbuf_addstr(sb, c->signature_check.signer);
f6667c5e 1626 break;
0174eeaa 1627 case 'K':
ffb6d7d5
SG
1628 if (c->signature_check.key)
1629 strbuf_addstr(sb, c->signature_check.key);
0174eeaa 1630 break;
3daaaabe
MG
1631 case 'F':
1632 if (c->signature_check.fingerprint)
1633 strbuf_addstr(sb, c->signature_check.fingerprint);
1634 break;
4de9394d
MG
1635 case 'P':
1636 if (c->signature_check.primary_key_fingerprint)
1637 strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
1638 break;
54887b46 1639 case 'T':
803978da 1640 strbuf_addstr(sb, gpg_trust_level_to_str(c->signature_check.trust_level));
54887b46 1641 break;
aa4b78d4
JK
1642 default:
1643 return 0;
f6667c5e
JH
1644 }
1645 return 2;
1646 }
1647
cde75e59 1648 /* For the rest we have to parse the commit header. */
018b9deb
JK
1649 if (!c->commit_header_parsed) {
1650 msg = c->message =
1651 repo_logmsg_reencode(c->repository, commit,
1652 &c->commit_encoding, "UTF-8");
f29d5958 1653 parse_commit_header(c);
018b9deb 1654 }
93fc05eb 1655
f29d5958 1656 switch (placeholder[0]) {
c3a670de
MC
1657 case 'a': /* author ... */
1658 return format_person_part(sb, placeholder[1],
d36f8679 1659 msg + c->author.off, c->author.len,
a5481a6c 1660 &c->pretty_ctx->date_mode);
c3a670de
MC
1661 case 'c': /* committer ... */
1662 return format_person_part(sb, placeholder[1],
d36f8679 1663 msg + c->committer.off, c->committer.len,
a5481a6c 1664 &c->pretty_ctx->date_mode);
c3a670de 1665 case 'e': /* encoding */
0940a76d
NTND
1666 if (c->commit_encoding)
1667 strbuf_addstr(sb, c->commit_encoding);
c3a670de 1668 return 1;
1367b12a
EB
1669 case 'B': /* raw body */
1670 /* message_off is always left at the initial newline */
1671 strbuf_addstr(sb, msg + c->message_off + 1);
1672 return 1;
f53bd743
RS
1673 }
1674
1675 /* Now we need to parse the commit message. */
1676 if (!c->commit_message_parsed)
1677 parse_commit_message(c);
1678
1679 switch (placeholder[0]) {
1680 case 's': /* subject */
1681 format_subject(sb, msg + c->subject_off, " ");
1682 return 1;
46d164b0 1683 case 'f': /* sanitized subject */
47d4676a
HV
1684 eol = strchrnul(msg + c->subject_off, '\n');
1685 format_sanitized_subject(sb, msg + c->subject_off, eol - (msg + c->subject_off));
46d164b0 1686 return 1;
c3a670de 1687 case 'b': /* body */
f29d5958 1688 strbuf_addstr(sb, msg + c->body_off);
c3a670de 1689 return 1;
93fc05eb 1690 }
d9f31fbf 1691
58311c66 1692 if (skip_prefix(placeholder, "(trailers", &arg)) {
a388b10f 1693 struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
250bea0c 1694 struct string_list filter_list = STRING_LIST_INIT_NODUP;
0b691d86 1695 struct strbuf sepbuf = STRBUF_INIT;
058761f1 1696 struct strbuf kvsepbuf = STRBUF_INIT;
3e3f3478 1697 size_t ret = 0;
e5fba5d5
JK
1698
1699 opts.no_divider = 1;
1700
84ff053d
TB
1701 if (*arg == ':') {
1702 arg++;
636a0aee 1703 if (format_set_trailers_options(&opts, &filter_list, &sepbuf, &kvsepbuf, &arg, NULL))
90563aed 1704 goto trailer_out;
58311c66
JK
1705 }
1706 if (*arg == ')') {
1707 format_trailers_from_commit(sb, msg + c->subject_off, &opts);
3e3f3478 1708 ret = arg - placeholder + 1;
58311c66 1709 }
250bea0c
AW
1710 trailer_out:
1711 string_list_clear(&filter_list, 0);
0b691d86 1712 strbuf_release(&sepbuf);
3e3f3478 1713 return ret;
d9f31fbf
JK
1714 }
1715
c3a670de 1716 return 0; /* unknown placeholder */
cde75e59
RS
1717}
1718
a5752342
NTND
1719static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
1720 const char *placeholder,
1721 struct format_commit_context *c)
1722{
1723 struct strbuf local_sb = STRBUF_INIT;
81dc898d
PS
1724 size_t total_consumed = 0;
1725 int len, padding = c->padding;
1726
a5752342
NTND
1727 if (padding < 0) {
1728 const char *start = strrchr(sb->buf, '\n');
1729 int occupied;
1730 if (!start)
1731 start = sb->buf;
522cc87f 1732 occupied = utf8_strnwidth(start, strlen(start), 1);
3ad87c80 1733 occupied += c->pretty_ctx->graph_width;
a5752342
NTND
1734 padding = (-padding) - occupied;
1735 }
1736 while (1) {
1737 int modifier = *placeholder == 'C';
81dc898d 1738 size_t consumed = format_commit_one(&local_sb, placeholder, c);
a5752342
NTND
1739 total_consumed += consumed;
1740
1741 if (!modifier)
1742 break;
1743
1744 placeholder += consumed;
1745 if (*placeholder != '%')
1746 break;
1747 placeholder++;
1748 total_consumed++;
1749 }
522cc87f 1750 len = utf8_strnwidth(local_sb.buf, local_sb.len, 1);
1640632b
NTND
1751
1752 if (c->flush_type == flush_left_and_steal) {
1753 const char *ch = sb->buf + sb->len - 1;
1754 while (len > padding && ch > sb->buf) {
1755 const char *p;
1756 if (*ch == ' ') {
1757 ch--;
1758 padding++;
1759 continue;
1760 }
1761 /* check for trailing ansi sequences */
1762 if (*ch != 'm')
1763 break;
1764 p = ch - 1;
b49f309a 1765 while (p > sb->buf && ch - p < 10 && *p != '\033')
1640632b
NTND
1766 p--;
1767 if (*p != '\033' ||
1768 ch + 1 - p != display_mode_esc_sequence_len(p))
1769 break;
1770 /*
1771 * got a good ansi sequence, put it back to
1772 * local_sb as we're cutting sb
1773 */
1774 strbuf_insert(&local_sb, 0, p, ch + 1 - p);
1775 ch = p - 1;
1776 }
1777 strbuf_setlen(sb, ch + 1 - sb->buf);
1778 c->flush_type = flush_left;
1779 }
1780
a7f01c6b
NTND
1781 if (len > padding) {
1782 switch (c->truncate) {
1783 case trunc_left:
1784 strbuf_utf8_replace(&local_sb,
1785 0, len - (padding - 2),
1786 "..");
1787 break;
1788 case trunc_middle:
1789 strbuf_utf8_replace(&local_sb,
1790 padding / 2 - 1,
1791 len - (padding - 2),
1792 "..");
1793 break;
1794 case trunc_right:
1795 strbuf_utf8_replace(&local_sb,
1796 padding - 2, len - (padding - 2),
1797 "..");
1798 break;
1799 case trunc_none:
1800 break;
1801 }
e992d1eb 1802 strbuf_addbuf(sb, &local_sb);
a7f01c6b 1803 } else {
81dc898d 1804 size_t sb_len = sb->len, offset = 0;
a5752342
NTND
1805 if (c->flush_type == flush_left)
1806 offset = padding - len;
1807 else if (c->flush_type == flush_both)
1808 offset = (padding - len) / 2;
1809 /*
1810 * we calculate padding in columns, now
1811 * convert it back to chars
1812 */
1813 padding = padding - len + local_sb.len;
415792ed 1814 strbuf_addchars(sb, ' ', padding);
a5752342
NTND
1815 memcpy(sb->buf + sb_len + offset, local_sb.buf,
1816 local_sb.len);
1817 }
1818 strbuf_release(&local_sb);
1819 c->flush_type = no_flush;
1820 return total_consumed;
1821}
1822
7e77df39
NTND
1823static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
1824 const char *placeholder,
6f1e2d52 1825 struct format_commit_context *context)
9fa708da 1826{
81dc898d 1827 size_t consumed, orig_len;
9fa708da
JH
1828 enum {
1829 NO_MAGIC,
1830 ADD_LF_BEFORE_NON_EMPTY,
1831 DEL_LF_BEFORE_EMPTY,
223a923c 1832 ADD_SP_BEFORE_NON_EMPTY
9fa708da
JH
1833 } magic = NO_MAGIC;
1834
1835 switch (placeholder[0]) {
1836 case '-':
1837 magic = DEL_LF_BEFORE_EMPTY;
1838 break;
1839 case '+':
1840 magic = ADD_LF_BEFORE_NON_EMPTY;
1841 break;
7b88176e
MG
1842 case ' ':
1843 magic = ADD_SP_BEFORE_NON_EMPTY;
1844 break;
9fa708da
JH
1845 default:
1846 break;
1847 }
1de69c0c 1848 if (magic != NO_MAGIC) {
9fa708da
JH
1849 placeholder++;
1850
1de69c0c
PS
1851 switch (placeholder[0]) {
1852 case 'w':
1853 /*
1854 * `%+w()` cannot ever expand to a non-empty string,
1855 * and it potentially changes the layout of preceding
1856 * contents. We're thus not able to handle the magic in
1857 * this combination and refuse the pattern.
1858 */
1859 return 0;
1860 };
1861 }
1862
9fa708da 1863 orig_len = sb->len;
1dd14e8e 1864 if (context->flush_type == no_flush)
a5752342 1865 consumed = format_commit_one(sb, placeholder, context);
1dd14e8e
RS
1866 else
1867 consumed = format_and_pad_commit(sb, placeholder, context);
9fa708da
JH
1868 if (magic == NO_MAGIC)
1869 return consumed;
1870
1871 if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
1872 while (sb->len && sb->buf[sb->len - 1] == '\n')
1873 strbuf_setlen(sb, sb->len - 1);
7b88176e
MG
1874 } else if (orig_len != sb->len) {
1875 if (magic == ADD_LF_BEFORE_NON_EMPTY)
a91cc7fa 1876 strbuf_insertstr(sb, orig_len, "\n");
7b88176e 1877 else if (magic == ADD_SP_BEFORE_NON_EMPTY)
a91cc7fa 1878 strbuf_insertstr(sb, orig_len, " ");
9fa708da
JH
1879 }
1880 return consumed + 1;
1881}
1882
5b163603
JG
1883void userformat_find_requirements(const char *fmt, struct userformat_want *w)
1884{
5b163603
JG
1885 if (!fmt) {
1886 if (!user_format)
1887 return;
1888 fmt = user_format;
1889 }
bd19ee9c
RS
1890 while ((fmt = strchr(fmt, '%'))) {
1891 fmt++;
6f1e2d52
RS
1892 if (skip_prefix(fmt, "%", &fmt))
1893 continue;
1894
1895 if (*fmt == '+' || *fmt == '-' || *fmt == ' ')
1896 fmt++;
1897
1898 switch (*fmt) {
1899 case 'N':
1900 w->notes = 1;
1901 break;
1902 case 'S':
1903 w->source = 1;
1904 break;
1905 case 'd':
1906 case 'D':
1907 w->decorate = 1;
1908 break;
1909 }
1910 }
5b163603
JG
1911}
1912
f54fbf5e
SB
1913void repo_format_commit_message(struct repository *r,
1914 const struct commit *commit,
1915 const char *format, struct strbuf *sb,
1916 const struct pretty_print_context *pretty_ctx)
cde75e59 1917{
3e8ed3b9 1918 struct format_commit_context context = {
018b9deb 1919 .repository = r,
3e8ed3b9
DL
1920 .commit = commit,
1921 .pretty_ctx = pretty_ctx,
1922 .wrap_start = sb->len
1923 };
177b29dc 1924 const char *output_enc = pretty_ctx->output_encoding;
7e77df39 1925 const char *utf8 = "UTF-8";
f29d5958 1926
6f1e2d52
RS
1927 while (strbuf_expand_step(sb, &format)) {
1928 size_t len;
1929
1930 if (skip_prefix(format, "%", &format))
1931 strbuf_addch(sb, '%');
1932 else if ((len = format_commit_item(sb, format, &context)))
1933 format += len;
1934 else
1935 strbuf_addch(sb, '%');
1936 }
02edd56b 1937 rewrap_message_tail(sb, &context, 0, 0, 0);
177b29dc 1938
018b9deb
JK
1939 /*
1940 * Convert output to an actual output encoding; note that
1941 * format_commit_item() will always use UTF-8, so we don't
1942 * have to bother if that's what the output wants.
1943 */
7e77df39
NTND
1944 if (output_enc) {
1945 if (same_encoding(utf8, output_enc))
1946 output_enc = NULL;
1947 } else {
1948 if (context.commit_encoding &&
1949 !same_encoding(context.commit_encoding, utf8))
1950 output_enc = context.commit_encoding;
1951 }
1952
1953 if (output_enc) {
c7d017d7 1954 size_t outsz;
7e77df39
NTND
1955 char *out = reencode_string_len(sb->buf, sb->len,
1956 output_enc, utf8, &outsz);
1957 if (out)
1958 strbuf_attach(sb, out, outsz, outsz + 1);
1959 }
1960
0940a76d 1961 free(context.commit_encoding);
f54fbf5e 1962 repo_unuse_commit_buffer(r, commit, context.message);
93fc05eb
JS
1963}
1964
10f2fbff 1965static void pp_header(struct pretty_print_context *pp,
93fc05eb
JS
1966 const char *encoding,
1967 const struct commit *commit,
1968 const char **msg_p,
1969 struct strbuf *sb)
1970{
1971 int parents_shown = 0;
1972
1973 for (;;) {
e3f1da98 1974 const char *name, *line = *msg_p;
93fc05eb
JS
1975 int linelen = get_one_line(*msg_p);
1976
1977 if (!linelen)
1978 return;
1979 *msg_p += linelen;
1980
1981 if (linelen == 1)
1982 /* End of header */
1983 return;
1984
6bf13944 1985 if (pp->fmt == CMIT_FMT_RAW) {
93fc05eb
JS
1986 strbuf_add(sb, line, linelen);
1987 continue;
1988 }
1989
59556548 1990 if (starts_with(line, "parent ")) {
580f0980 1991 if (linelen != the_hash_algo->hexsz + 8)
93fc05eb
JS
1992 die("bad parent line in commit");
1993 continue;
1994 }
1995
1996 if (!parents_shown) {
4bbaa1eb 1997 unsigned num = commit_list_count(commit->parents);
93fc05eb 1998 /* with enough slop */
580f0980 1999 strbuf_grow(sb, num * (GIT_MAX_HEXSZ + 10) + 20);
6bf13944 2000 add_merge_info(pp, sb, commit);
93fc05eb
JS
2001 parents_shown = 1;
2002 }
2003
2004 /*
2005 * MEDIUM == DEFAULT shows only author with dates.
2006 * FULL shows both authors but not dates.
2007 * FULLER shows both authors and dates.
2008 */
e3f1da98 2009 if (skip_prefix(line, "author ", &name)) {
93fc05eb 2010 strbuf_grow(sb, linelen + 80);
e3f1da98 2011 pp_user_info(pp, "Author", sb, name, encoding);
93fc05eb 2012 }
e3f1da98 2013 if (skip_prefix(line, "committer ", &name) &&
6bf13944 2014 (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
93fc05eb 2015 strbuf_grow(sb, linelen + 80);
e3f1da98 2016 pp_user_info(pp, "Commit", sb, name, encoding);
93fc05eb
JS
2017 }
2018 }
2019}
2020
10f2fbff 2021void pp_title_line(struct pretty_print_context *pp,
b02bd65f
DB
2022 const char **msg_p,
2023 struct strbuf *sb,
b02bd65f 2024 const char *encoding,
267123b4 2025 int need_8bit_cte)
93fc05eb 2026{
41dd00ba 2027 static const int max_length = 78; /* per rfc2047 */
93fc05eb
JS
2028 struct strbuf title;
2029
2030 strbuf_init(&title, 80);
9553d2b2
JK
2031 *msg_p = format_subject(&title, *msg_p,
2032 pp->preserve_subject ? "\n" : " ");
93fc05eb
JS
2033
2034 strbuf_grow(sb, title.len + 1024);
6d167fd7
RS
2035 if (pp->print_email_subject) {
2036 if (pp->rev)
2037 fmt_output_email_subject(sb, pp->rev);
19d097e3
EB
2038 if (pp->encode_email_headers &&
2039 needs_rfc2047_encoding(title.buf, title.len))
41dd00ba
JS
2040 add_rfc2047(sb, title.buf, title.len,
2041 encoding, RFC2047_SUBJECT);
2042 else
2043 strbuf_add_wrapped_bytes(sb, title.buf, title.len,
2044 -last_line_length(sb), 1, max_length);
93fc05eb
JS
2045 } else {
2046 strbuf_addbuf(sb, &title);
2047 }
2048 strbuf_addch(sb, '\n');
2049
a9080475
JK
2050 if (need_8bit_cte == 0) {
2051 int i;
2052 for (i = 0; i < pp->in_body_headers.nr; i++) {
2053 if (has_non_ascii(pp->in_body_headers.items[i].string)) {
2054 need_8bit_cte = 1;
2055 break;
2056 }
2057 }
2058 }
2059
6bf4f1b4 2060 if (need_8bit_cte > 0) {
93fc05eb
JS
2061 const char *header_fmt =
2062 "MIME-Version: 1.0\n"
2063 "Content-Type: text/plain; charset=%s\n"
2064 "Content-Transfer-Encoding: 8bit\n";
2065 strbuf_addf(sb, header_fmt, encoding);
2066 }
6bf13944
JK
2067 if (pp->after_subject) {
2068 strbuf_addstr(sb, pp->after_subject);
93fc05eb 2069 }
9f23e040 2070 if (cmit_fmt_is_mail(pp->fmt)) {
93fc05eb
JS
2071 strbuf_addch(sb, '\n');
2072 }
a9080475
JK
2073
2074 if (pp->in_body_headers.nr) {
2075 int i;
2076 for (i = 0; i < pp->in_body_headers.nr; i++) {
2077 strbuf_addstr(sb, pp->in_body_headers.items[i].string);
2078 free(pp->in_body_headers.items[i].string);
2079 }
2080 string_list_clear(&pp->in_body_headers, 0);
2081 strbuf_addch(sb, '\n');
2082 }
2083
93fc05eb
JS
2084 strbuf_release(&title);
2085}
2086
7cc13c71
LT
2087static int pp_utf8_width(const char *start, const char *end)
2088{
2089 int width = 0;
2090 size_t remain = end - start;
2091
2092 while (remain) {
2093 int n = utf8_width(&start, &remain);
2094 if (n < 0 || !start)
2095 return -1;
2096 width += n;
2097 }
2098 return width;
2099}
2100
6a5c3379
HM
2101static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
2102 int color, int tabwidth, const char *line,
2103 int linelen)
7cc13c71
LT
2104{
2105 const char *tab;
2106
2107 while ((tab = memchr(line, '\t', linelen)) != NULL) {
2108 int width = pp_utf8_width(line, tab);
2109
2110 /*
2111 * If it wasn't well-formed utf8, or it
2112 * had characters with badly defined
2113 * width (control characters etc), just
2114 * give up on trying to align things.
2115 */
2116 if (width < 0)
2117 break;
2118
2119 /* Output the data .. */
6a5c3379
HM
2120 append_line_with_color(sb, opt, line, tab - line, color,
2121 GREP_CONTEXT_BODY,
2122 GREP_HEADER_FIELD_MAX);
7cc13c71
LT
2123
2124 /* .. and the de-tabified tab */
fe37a9c5 2125 strbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));
7cc13c71
LT
2126
2127 /* Skip over the printed part .. */
2128 linelen -= tab + 1 - line;
2129 line = tab + 1;
2130 }
2131
2132 /*
2133 * Print out everything after the last tab without
2134 * worrying about width - there's nothing more to
2135 * align.
2136 */
6a5c3379
HM
2137 append_line_with_color(sb, opt, line, linelen, color, GREP_CONTEXT_BODY,
2138 GREP_HEADER_FIELD_MAX);
7cc13c71
LT
2139}
2140
2141/*
2142 * pp_handle_indent() prints out the intendation, and
2143 * the whole line (without the final newline), after
2144 * de-tabifying.
2145 */
2146static void pp_handle_indent(struct pretty_print_context *pp,
2147 struct strbuf *sb, int indent,
2148 const char *line, int linelen)
2149{
6a5c3379
HM
2150 struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
2151
7cc13c71
LT
2152 strbuf_addchars(sb, ' ', indent);
2153 if (pp->expand_tabs_in_log)
6a5c3379
HM
2154 strbuf_add_tabexpand(sb, opt, pp->color, pp->expand_tabs_in_log,
2155 line, linelen);
7cc13c71 2156 else
6a5c3379
HM
2157 append_line_with_color(sb, opt, line, linelen, pp->color,
2158 GREP_CONTEXT_BODY,
2159 GREP_HEADER_FIELD_MAX);
7cc13c71
LT
2160}
2161
9f23e040
EW
2162static int is_mboxrd_from(const char *line, int len)
2163{
2164 /*
2165 * a line matching /^From $/ here would only have len == 4
2166 * at this point because is_empty_line would've trimmed all
2167 * trailing space
2168 */
2169 return len > 4 && starts_with(line + strspn(line, ">"), "From ");
2170}
2171
10f2fbff 2172void pp_remainder(struct pretty_print_context *pp,
b02bd65f
DB
2173 const char **msg_p,
2174 struct strbuf *sb,
2175 int indent)
93fc05eb 2176{
6a5c3379 2177 struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
93fc05eb 2178 int first = 1;
6a5c3379 2179
93fc05eb
JS
2180 for (;;) {
2181 const char *line = *msg_p;
2182 int linelen = get_one_line(line);
2183 *msg_p += linelen;
2184
2185 if (!linelen)
2186 break;
2187
77356122 2188 if (is_blank_line(line, &linelen)) {
93fc05eb
JS
2189 if (first)
2190 continue;
6bf13944 2191 if (pp->fmt == CMIT_FMT_SHORT)
93fc05eb
JS
2192 break;
2193 }
2194 first = 0;
2195
2196 strbuf_grow(sb, linelen + indent + 20);
415792ed 2197 if (indent)
7cc13c71 2198 pp_handle_indent(pp, sb, indent, line, linelen);
0893eec8 2199 else if (pp->expand_tabs_in_log)
6a5c3379
HM
2200 strbuf_add_tabexpand(sb, opt, pp->color,
2201 pp->expand_tabs_in_log, line,
2202 linelen);
9f23e040
EW
2203 else {
2204 if (pp->fmt == CMIT_FMT_MBOXRD &&
2205 is_mboxrd_from(line, linelen))
2206 strbuf_addch(sb, '>');
2207
6a5c3379
HM
2208 append_line_with_color(sb, opt, line, linelen,
2209 pp->color, GREP_CONTEXT_BODY,
2210 GREP_HEADER_FIELD_MAX);
9f23e040 2211 }
93fc05eb
JS
2212 strbuf_addch(sb, '\n');
2213 }
2214}
2215
10f2fbff 2216void pretty_print_commit(struct pretty_print_context *pp,
6bf13944
JK
2217 const struct commit *commit,
2218 struct strbuf *sb)
93fc05eb
JS
2219{
2220 unsigned long beginning_of_body;
2221 int indent = 4;
dd0d388c 2222 const char *msg;
b000c59b 2223 const char *reencoded;
93fc05eb 2224 const char *encoding;
6bf13944 2225 int need_8bit_cte = pp->need_8bit_cte;
93fc05eb 2226
6bf13944 2227 if (pp->fmt == CMIT_FMT_USERFORMAT) {
bab82164
ÆAB
2228 repo_format_commit_message(the_repository, commit,
2229 user_format, sb, pp);
93fc05eb
JS
2230 return;
2231 }
2232
e297cf5a 2233 encoding = get_log_output_encoding();
ecb5091f
ÆAB
2234 msg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,
2235 encoding);
93fc05eb 2236
9f23e040 2237 if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
93fc05eb
JS
2238 indent = 0;
2239
6bf4f1b4
JH
2240 /*
2241 * We need to check and emit Content-type: to mark it
2242 * as 8-bit if we haven't done so.
93fc05eb 2243 */
9f23e040 2244 if (cmit_fmt_is_mail(pp->fmt) && need_8bit_cte == 0) {
93fc05eb
JS
2245 int i, ch, in_body;
2246
2247 for (in_body = i = 0; (ch = msg[i]); i++) {
2248 if (!in_body) {
2249 /* author could be non 7-bit ASCII but
2250 * the log may be so; skip over the
2251 * header part first.
2252 */
2253 if (ch == '\n' && msg[i+1] == '\n')
2254 in_body = 1;
2255 }
2256 else if (non_ascii(ch)) {
6bf4f1b4 2257 need_8bit_cte = 1;
93fc05eb
JS
2258 break;
2259 }
2260 }
2261 }
2262
6bf13944 2263 pp_header(pp, encoding, commit, &msg, sb);
6d167fd7 2264 if (pp->fmt != CMIT_FMT_ONELINE && !pp->print_email_subject) {
93fc05eb
JS
2265 strbuf_addch(sb, '\n');
2266 }
2267
2268 /* Skip excess blank lines at the beginning of body, if any... */
77356122 2269 msg = skip_blank_lines(msg);
93fc05eb
JS
2270
2271 /* These formats treat the title line specially. */
9f23e040 2272 if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
6bf13944 2273 pp_title_line(pp, &msg, sb, encoding, need_8bit_cte);
93fc05eb
JS
2274
2275 beginning_of_body = sb->len;
6bf13944
JK
2276 if (pp->fmt != CMIT_FMT_ONELINE)
2277 pp_remainder(pp, &msg, sb, indent);
93fc05eb
JS
2278 strbuf_rtrim(sb);
2279
2280 /* Make sure there is an EOLN for the non-oneline case */
6bf13944 2281 if (pp->fmt != CMIT_FMT_ONELINE)
93fc05eb
JS
2282 strbuf_addch(sb, '\n');
2283
2284 /*
2285 * The caller may append additional body text in e-mail
2286 * format. Make sure we did not strip the blank line
2287 * between the header and the body.
2288 */
9f23e040 2289 if (cmit_fmt_is_mail(pp->fmt) && sb->len <= beginning_of_body)
93fc05eb 2290 strbuf_addch(sb, '\n');
a97a7468 2291
ecb5091f 2292 repo_unuse_commit_buffer(the_repository, commit, reencoded);
93fc05eb 2293}
8b8a5374
JK
2294
2295void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
2296 struct strbuf *sb)
2297{
2298 struct pretty_print_context pp = {0};
6bf13944
JK
2299 pp.fmt = fmt;
2300 pretty_print_commit(&pp, commit, sb);
8b8a5374 2301}