Merge branch 'russian-l10n' of https://github.com/DJm00n/git-po-ru
[alt-git.git] / pretty.c
blob718530bbab5204b88972849abb95eabd0d3bedaf
1 #include "git-compat-util.h"
2 #include "config.h"
3 #include "commit.h"
4 #include "environment.h"
5 #include "gettext.h"
6 #include "hash.h"
7 #include "hex.h"
8 #include "utf8.h"
9 #include "diff.h"
10 #include "pager.h"
11 #include "revision.h"
12 #include "string-list.h"
13 #include "mailmap.h"
14 #include "log-tree.h"
15 #include "notes.h"
16 #include "color.h"
17 #include "reflog-walk.h"
18 #include "gpg-interface.h"
19 #include "trailer.h"
20 #include "run-command.h"
21 #include "object-name.h"
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.
28 #define FORMATTING_LIMIT (16 * 1024)
30 static char *user_format;
31 static struct cmt_fmt_map {
32 const char *name;
33 enum cmit_fmt format;
34 int is_tformat;
35 int expand_tabs_in_log;
36 int is_alias;
37 enum date_mode_type default_date_mode_type;
38 const char *user_format;
39 } *commit_formats;
40 static size_t builtin_formats_len;
41 static size_t commit_formats_len;
42 static size_t commit_formats_alloc;
43 static struct cmt_fmt_map *find_commit_format(const char *sought);
45 int commit_format_is_empty(enum cmit_fmt fmt)
47 return fmt == CMIT_FMT_USERFORMAT && !*user_format;
50 static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
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;
59 static int git_pretty_formats_config(const char *var, const char *value,
60 const struct config_context *ctx UNUSED,
61 void *cb UNUSED)
63 struct cmt_fmt_map *commit_format = NULL;
64 const char *name;
65 const char *fmt;
66 int i;
68 if (!skip_prefix(var, "pretty.", &name))
69 return 0;
71 for (i = 0; i < builtin_formats_len; i++) {
72 if (!strcmp(commit_formats[i].name, name))
73 return 0;
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;
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];
87 memset(commit_format, 0, sizeof(*commit_format));
88 commit_formats_len++;
91 commit_format->name = xstrdup(name);
92 commit_format->format = CMIT_FMT_USERFORMAT;
93 if (git_config_string(&fmt, var, value))
94 return -1;
96 if (skip_prefix(fmt, "format:", &fmt))
97 commit_format->is_tformat = 0;
98 else if (skip_prefix(fmt, "tformat:", &fmt) || strchr(fmt, '%'))
99 commit_format->is_tformat = 1;
100 else
101 commit_format->is_alias = 1;
102 commit_format->user_format = fmt;
104 return 0;
107 static void setup_commit_formats(void)
109 struct cmt_fmt_map builtin_formats[] = {
110 { "raw", CMIT_FMT_RAW, 0, 0 },
111 { "medium", CMIT_FMT_MEDIUM, 0, 8 },
112 { "short", CMIT_FMT_SHORT, 0, 0 },
113 { "email", CMIT_FMT_EMAIL, 0, 0 },
114 { "mboxrd", CMIT_FMT_MBOXRD, 0, 0 },
115 { "fuller", CMIT_FMT_FULLER, 0, 8 },
116 { "full", CMIT_FMT_FULL, 0, 8 },
117 { "oneline", CMIT_FMT_ONELINE, 1, 0 },
118 { "reference", CMIT_FMT_USERFORMAT, 1, 0,
119 0, DATE_SHORT, "%C(auto)%h (%s, %ad)" },
121 * Please update $__git_log_pretty_formats in
122 * git-completion.bash when you add new formats.
125 commit_formats_len = ARRAY_SIZE(builtin_formats);
126 builtin_formats_len = commit_formats_len;
127 ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
128 COPY_ARRAY(commit_formats, builtin_formats,
129 ARRAY_SIZE(builtin_formats));
131 git_config(git_pretty_formats_config, NULL);
134 static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
135 const char *original,
136 int num_redirections)
138 struct cmt_fmt_map *found = NULL;
139 size_t found_match_len = 0;
140 int i;
142 if (num_redirections >= commit_formats_len)
143 die("invalid --pretty format: "
144 "'%s' references an alias which points to itself",
145 original);
147 for (i = 0; i < commit_formats_len; i++) {
148 size_t match_len;
150 if (!starts_with(commit_formats[i].name, sought))
151 continue;
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;
160 if (found && found->is_alias) {
161 found = find_commit_format_recursive(found->user_format,
162 original,
163 num_redirections+1);
166 return found;
169 static struct cmt_fmt_map *find_commit_format(const char *sought)
171 if (!commit_formats)
172 setup_commit_formats();
174 return find_commit_format_recursive(sought, sought, 0);
177 void get_commit_format(const char *arg, struct rev_info *rev)
179 struct cmt_fmt_map *commit_format;
181 rev->use_terminator = 0;
182 if (!arg) {
183 rev->commit_format = CMIT_FMT_DEFAULT;
184 return;
186 if (skip_prefix(arg, "format:", &arg)) {
187 save_user_format(rev, arg, 0);
188 return;
191 if (!*arg || skip_prefix(arg, "tformat:", &arg) || strchr(arg, '%')) {
192 save_user_format(rev, arg, 1);
193 return;
196 commit_format = find_commit_format(arg);
197 if (!commit_format)
198 die("invalid --pretty format: %s", arg);
200 rev->commit_format = commit_format->format;
201 rev->use_terminator = commit_format->is_tformat;
202 rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
203 if (!rev->date_mode_explicit && commit_format->default_date_mode_type)
204 rev->date_mode.type = commit_format->default_date_mode_type;
205 if (commit_format->format == CMIT_FMT_USERFORMAT) {
206 save_user_format(rev, commit_format->user_format,
207 commit_format->is_tformat);
212 * Generic support for pretty-printing the header
214 static int get_one_line(const char *msg)
216 int ret = 0;
218 for (;;) {
219 char c = *msg++;
220 if (!c)
221 break;
222 ret++;
223 if (c == '\n')
224 break;
226 return ret;
229 /* High bit set, or ISO-2022-INT */
230 static int non_ascii(int ch)
232 return !isascii(ch) || ch == '\033';
235 int has_non_ascii(const char *s)
237 int ch;
238 if (!s)
239 return 0;
240 while ((ch = *s++) != '\0') {
241 if (non_ascii(ch))
242 return 1;
244 return 0;
247 static int is_rfc822_special(char ch)
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;
269 static int needs_rfc822_quoting(const char *s, int len)
271 int i;
272 for (i = 0; i < len; i++)
273 if (is_rfc822_special(s[i]))
274 return 1;
275 return 0;
278 static int last_line_length(struct strbuf *sb)
280 int i;
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);
289 static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
291 int i;
293 /* just a guess, we may have to also backslash-quote */
294 strbuf_grow(out, len + 2);
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]);
307 strbuf_addch(out, '"');
310 enum rfc2047_type {
311 RFC2047_SUBJECT,
312 RFC2047_ADDRESS
315 static int is_rfc2047_special(char ch, enum rfc2047_type type)
318 * rfc2047, section 4.2:
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.
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)
332 if (non_ascii(ch) || !isprint(ch))
333 return 1;
336 * rule out special printable characters (' ' should be the only
337 * whitespace character considered printable, but be defensive and use
338 * isspace())
340 if (isspace(ch) || ch == '=' || ch == '?' || ch == '_')
341 return 1;
344 * rfc2047, section 5.3:
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:
350 * phrase = 1*( encoded-word / word )
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'.
360 if (type != RFC2047_ADDRESS)
361 return 0;
363 /* '=' and '_' are special cases and have been checked above */
364 return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
367 static int needs_rfc2047_encoding(const char *line, int len)
369 int i;
371 for (i = 0; i < len; i++) {
372 int ch = line[i];
373 if (non_ascii(ch) || ch == '\n')
374 return 1;
375 if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
376 return 1;
379 return 0;
382 static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
383 const char *encoding, enum rfc2047_type type)
385 static const int max_encoded_length = 76; /* per rfc2047 */
386 int i;
387 int line_len = last_line_length(sb);
389 strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
390 strbuf_addf(sb, "=?%s?q?", encoding);
391 line_len += strlen(encoding) + 5; /* 5 for =??q? */
393 while (len) {
395 * RFC 2047, section 5 (3):
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.
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);
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;
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.
417 if (line_len + encoded_len + 2 > max_encoded_length) {
418 /* It won't fit with trailing "?=" --- break the line */
419 strbuf_addf(sb, "?=\n =?%s?q?", encoding);
420 line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
423 for (i = 0; i < chrlen; i++)
424 strbuf_addf(sb, encoded_fmt, p[i]);
425 line_len += encoded_len;
427 strbuf_addstr(sb, "?=");
430 const char *show_ident_date(const struct ident_split *ident,
431 const struct date_mode *mode)
433 timestamp_t date = 0;
434 long tz = 0;
436 if (ident->date_begin && ident->date_end)
437 date = parse_timestamp(ident->date_begin, NULL, 10);
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);
443 if (tz >= INT_MAX || tz <= INT_MIN)
444 tz = 0;
446 return show_date(date, tz, mode);
449 static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,
450 const char *buf, size_t buflen)
452 strbuf_addstr(sb, color);
453 strbuf_add(sb, buf, buflen);
454 if (*color)
455 strbuf_addstr(sb, GIT_COLOR_RESET);
458 static 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)
463 const char *buf, *eol, *line_color, *match_color;
464 regmatch_t match;
465 int eflags = 0;
467 buf = line;
468 eol = buf + linelen;
470 if (!opt || !want_color(color) || opt->invert)
471 goto end;
473 line_color = opt->colors[GREP_COLOR_SELECTED];
474 match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
476 while (grep_next_match(opt, buf, eol, ctx, &match, field, eflags)) {
477 if (match.rm_so == match.rm_eo)
478 break;
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;
487 if (eflags)
488 strbuf_add_with_color(sb, line_color, buf, eol - buf);
489 else {
490 end:
491 strbuf_add(sb, buf, eol - buf);
495 static int use_in_body_from(const struct pretty_print_context *pp,
496 const struct ident_split *ident)
498 if (pp->rev && pp->rev->force_in_body_from)
499 return 1;
500 if (ident_cmp(pp->from_ident, ident))
501 return 1;
502 return 0;
505 void pp_user_info(struct pretty_print_context *pp,
506 const char *what, struct strbuf *sb,
507 const char *line, const char *encoding)
509 struct ident_split ident;
510 char *line_end;
511 const char *mailbuf, *namebuf;
512 size_t namelen, maillen;
513 int max_length = 78; /* per rfc2822 */
515 if (pp->fmt == CMIT_FMT_ONELINE)
516 return;
518 line_end = strchrnul(line, '\n');
519 if (split_ident_line(&ident, line, line_end - line))
520 return;
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;
527 if (pp->mailmap)
528 map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
530 if (cmit_fmt_is_mail(pp->fmt)) {
531 if (pp->from_ident && use_in_body_from(pp, &ident)) {
532 struct strbuf buf = STRBUF_INIT;
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));
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;
548 strbuf_addstr(sb, "From: ");
549 if (pp->encode_email_headers &&
550 needs_rfc2047_encoding(namebuf, namelen)) {
551 add_rfc2047(sb, namebuf, namelen,
552 encoding, RFC2047_ADDRESS);
553 max_length = 76; /* per rfc2047 */
554 } else if (needs_rfc822_quoting(namebuf, namelen)) {
555 struct strbuf quoted = STRBUF_INIT;
556 add_rfc822_quoted(&quoted, namebuf, namelen);
557 strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
558 -6, 1, max_length);
559 strbuf_release(&quoted);
560 } else {
561 strbuf_add_wrapped_bytes(sb, namebuf, namelen,
562 -6, 1, max_length);
565 if (max_length <
566 last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
567 strbuf_addch(sb, '\n');
568 strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
569 } else {
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;
574 if (!strcmp(what, "Author"))
575 field = GREP_HEADER_AUTHOR;
576 else if (!strcmp(what, "Commit"))
577 field = GREP_HEADER_COMMITTER;
579 strbuf_addf(sb, "%s: ", what);
580 if (pp->fmt == CMIT_FMT_FULLER)
581 strbuf_addchars(sb, ' ', 4);
583 strbuf_addf(&id, "%.*s <%.*s>", (int)namelen, namebuf,
584 (int)maillen, mailbuf);
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);
592 switch (pp->fmt) {
593 case CMIT_FMT_MEDIUM:
594 strbuf_addf(sb, "Date: %s\n",
595 show_ident_date(&ident, &pp->date_mode));
596 break;
597 case CMIT_FMT_EMAIL:
598 case CMIT_FMT_MBOXRD:
599 strbuf_addf(sb, "Date: %s\n",
600 show_ident_date(&ident, DATE_MODE(RFC2822)));
601 break;
602 case CMIT_FMT_FULLER:
603 strbuf_addf(sb, "%sDate: %s\n", what,
604 show_ident_date(&ident, &pp->date_mode));
605 break;
606 default:
607 /* notin' */
608 break;
612 static int is_blank_line(const char *line, int *len_p)
614 int len = *len_p;
615 while (len && isspace(line[len - 1]))
616 len--;
617 *len_p = len;
618 return !len;
621 const char *skip_blank_lines(const char *msg)
623 for (;;) {
624 int linelen = get_one_line(msg);
625 int ll = linelen;
626 if (!linelen)
627 break;
628 if (!is_blank_line(msg, &ll))
629 break;
630 msg += linelen;
632 return msg;
635 static void add_merge_info(const struct pretty_print_context *pp,
636 struct strbuf *sb, const struct commit *commit)
638 struct commit_list *parent = commit->parents;
640 if ((pp->fmt == CMIT_FMT_ONELINE) || (cmit_fmt_is_mail(pp->fmt)) ||
641 !parent || !parent->next)
642 return;
644 strbuf_addstr(sb, "Merge:");
646 while (parent) {
647 struct object_id *oidp = &parent->item->object.oid;
648 strbuf_addch(sb, ' ');
649 if (pp->abbrev)
650 strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
651 else
652 strbuf_addstr(sb, oid_to_hex(oidp));
653 parent = parent->next;
655 strbuf_addch(sb, '\n');
658 static char *get_header(const char *msg, const char *key)
660 size_t len;
661 const char *v = find_commit_header(msg, key, &len);
662 return v ? xmemdupz(v, len) : NULL;
665 static char *replace_encoding_header(char *buf, const char *encoding)
667 struct strbuf tmp = STRBUF_INIT;
668 size_t start, len;
669 char *cp = buf;
671 /* guess if there is an encoding header before a \n\n */
672 while (!starts_with(cp, "encoding ")) {
673 cp = strchr(cp, '\n');
674 if (!cp || *++cp == '\n')
675 return buf;
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);
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));
693 return strbuf_detach(&tmp, NULL);
696 const char *repo_logmsg_reencode(struct repository *r,
697 const struct commit *commit,
698 char **commit_encoding,
699 const char *output_encoding)
701 static const char *utf8 = "UTF-8";
702 const char *use_encoding;
703 char *encoding;
704 const char *msg = repo_get_commit_buffer(r, commit, NULL);
705 char *out;
707 if (!output_encoding || !*output_encoding) {
708 if (commit_encoding)
709 *commit_encoding = get_header(msg, "encoding");
710 return msg;
712 encoding = get_header(msg, "encoding");
713 if (commit_encoding)
714 *commit_encoding = encoding;
715 use_encoding = encoding ? encoding : utf8;
716 if (same_encoding(use_encoding, output_encoding)) {
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).
722 if (!encoding)
723 return msg;
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
729 * the cached copy from repo_get_commit_buffer, we need to duplicate it
730 * to avoid munging the cached copy.
732 if (msg == get_cached_commit_buffer(r, commit, NULL))
733 out = xstrdup(msg);
734 else
735 out = (char *)msg;
737 else {
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.
744 out = reencode_string(msg, output_encoding, use_encoding);
745 if (out)
746 repo_unuse_commit_buffer(r, commit, msg);
750 * This replacement actually consumes the buffer we hand it, so we do
751 * not have to worry about freeing the old "out" here.
753 if (out)
754 out = replace_encoding_header(out, output_encoding);
756 if (!commit_encoding)
757 free(encoding);
759 * If the re-encoding failed, out might be NULL here; in that
760 * case we just return the commit message verbatim.
762 return out ? out : msg;
765 static int mailmap_name(const char **email, size_t *email_len,
766 const char **name, size_t *name_len)
768 static struct string_list *mail_map;
769 if (!mail_map) {
770 CALLOC_ARRAY(mail_map, 1);
771 read_mailmap(mail_map);
773 return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
776 static size_t format_person_part(struct strbuf *sb, char part,
777 const char *msg, int len,
778 const struct date_mode *dmode)
780 /* currently all placeholders have same length */
781 const int placeholder_len = 2;
782 struct ident_split s;
783 const char *name, *mail;
784 size_t maillen, namelen;
786 if (split_ident_line(&s, msg, len) < 0)
787 goto skip;
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;
794 if (part == 'N' || part == 'E' || part == 'L') /* mailmap lookup */
795 mailmap_name(&mail, &maillen, &name, &namelen);
796 if (part == 'n' || part == 'N') { /* name */
797 strbuf_add(sb, name, namelen);
798 return placeholder_len;
800 if (part == 'e' || part == 'E') { /* email */
801 strbuf_add(sb, mail, maillen);
802 return placeholder_len;
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;
812 if (!s.date_begin)
813 goto skip;
815 if (part == 't') { /* date, UNIX timestamp */
816 strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
817 return placeholder_len;
820 switch (part) {
821 case 'd': /* date */
822 strbuf_addstr(sb, show_ident_date(&s, dmode));
823 return placeholder_len;
824 case 'D': /* date, RFC2822 style */
825 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RFC2822)));
826 return placeholder_len;
827 case 'r': /* date, relative */
828 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RELATIVE)));
829 return placeholder_len;
830 case 'i': /* date, ISO 8601-like */
831 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601)));
832 return placeholder_len;
833 case 'I': /* date, ISO 8601 strict */
834 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
835 return placeholder_len;
836 case 'h': /* date, human */
837 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(HUMAN)));
838 return placeholder_len;
839 case 's':
840 strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(SHORT)));
841 return placeholder_len;
844 skip:
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.
850 if (part == 'n' || part == 'e' || part == 't' || part == 'd'
851 || part == 'D' || part == 'r' || part == 'i')
852 return placeholder_len;
854 return 0; /* unknown placeholder */
857 struct chunk {
858 size_t off;
859 size_t len;
862 enum flush_type {
863 no_flush,
864 flush_right,
865 flush_left,
866 flush_left_and_steal,
867 flush_both
870 enum trunc_type {
871 trunc_none,
872 trunc_left,
873 trunc_middle,
874 trunc_right
877 struct format_commit_context {
878 struct repository *repository;
879 const struct commit *commit;
880 const struct pretty_print_context *pretty_ctx;
881 unsigned commit_header_parsed:1;
882 unsigned commit_message_parsed:1;
883 struct signature_check signature_check;
884 enum flush_type flush_type;
885 enum trunc_type truncate;
886 const char *message;
887 char *commit_encoding;
888 size_t width, indent1, indent2;
889 int auto_color;
890 int padding;
892 /* These offsets are relative to the start of the commit message. */
893 struct chunk author;
894 struct chunk committer;
895 size_t message_off;
896 size_t subject_off;
897 size_t body_off;
899 /* The following ones are relative to the result struct strbuf. */
900 size_t wrap_start;
903 static void parse_commit_header(struct format_commit_context *context)
905 const char *msg = context->message;
906 int i;
908 for (i = 0; msg[i]; i++) {
909 const char *name;
910 int eol;
911 for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
912 ; /* do nothing */
914 if (i == eol) {
915 break;
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;
923 i = eol;
925 context->message_off = i;
926 context->commit_header_parsed = 1;
929 static int istitlechar(char c)
931 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
932 (c >= '0' && c <= '9') || c == '.' || c == '_';
935 void format_sanitized_subject(struct strbuf *sb, const char *msg, size_t len)
937 size_t trimlen;
938 size_t start_len = sb->len;
939 int space = 2;
940 int i;
942 for (i = 0; i < len; i++) {
943 if (istitlechar(msg[i])) {
944 if (space == 1)
945 strbuf_addch(sb, '-');
946 space = 0;
947 strbuf_addch(sb, msg[i]);
948 if (msg[i] == '.')
949 while (msg[i+1] == '.')
950 i++;
951 } else
952 space |= 1;
955 /* trim any trailing '.' or '-' characters */
956 trimlen = 0;
957 while (sb->len - trimlen > start_len &&
958 (sb->buf[sb->len - 1 - trimlen] == '.'
959 || sb->buf[sb->len - 1 - trimlen] == '-'))
960 trimlen++;
961 strbuf_remove(sb, sb->len - trimlen, trimlen);
964 const char *format_subject(struct strbuf *sb, const char *msg,
965 const char *line_separator)
967 int first = 1;
969 for (;;) {
970 const char *line = msg;
971 int linelen = get_one_line(line);
973 msg += linelen;
974 if (!linelen || is_blank_line(line, &linelen))
975 break;
977 if (!sb)
978 continue;
979 strbuf_grow(sb, linelen + 2);
980 if (!first)
981 strbuf_addstr(sb, line_separator);
982 strbuf_add(sb, line, linelen);
983 first = 0;
985 return msg;
988 static void parse_commit_message(struct format_commit_context *c)
990 const char *msg = c->message + c->message_off;
991 const char *start = c->message;
993 msg = skip_blank_lines(msg);
994 c->subject_off = msg - start;
996 msg = format_subject(NULL, msg, NULL);
997 msg = skip_blank_lines(msg);
998 c->body_off = msg - start;
1000 c->commit_message_parsed = 1;
1003 static void strbuf_wrap(struct strbuf *sb, size_t pos,
1004 size_t width, size_t indent1, size_t indent2)
1006 struct strbuf tmp = STRBUF_INIT;
1008 if (pos)
1009 strbuf_add(&tmp, sb->buf, pos);
1010 strbuf_add_wrapped_text(&tmp, sb->buf + pos,
1011 cast_size_t_to_int(indent1),
1012 cast_size_t_to_int(indent2),
1013 cast_size_t_to_int(width));
1014 strbuf_swap(&tmp, sb);
1015 strbuf_release(&tmp);
1018 static 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)
1023 if (c->width == new_width && c->indent1 == new_indent1 &&
1024 c->indent2 == new_indent2)
1025 return;
1026 if (c->wrap_start < sb->len)
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;
1034 static int format_reflog_person(struct strbuf *sb,
1035 char part,
1036 struct reflog_walk_info *log,
1037 const struct date_mode *dmode)
1039 const char *ident;
1041 if (!log)
1042 return 2;
1044 ident = get_reflog_ident(log);
1045 if (!ident)
1046 return 2;
1048 return format_person_part(sb, part, ident, strlen(ident), dmode);
1051 static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
1052 const char *placeholder,
1053 struct format_commit_context *c)
1055 const char *rest = placeholder;
1056 const char *basic_color = NULL;
1058 if (placeholder[1] == '(') {
1059 const char *begin = placeholder + 2;
1060 const char *end = strchr(begin, ')');
1061 char color[COLOR_MAXLEN];
1063 if (!end)
1064 return 0;
1066 if (skip_prefix(begin, "auto,", &begin)) {
1067 if (!want_color(c->pretty_ctx->color))
1068 return end - placeholder + 1;
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;
1077 if (color_parse_mem(begin, end - begin, color) < 0)
1078 die(_("unable to parse --pretty format"));
1079 strbuf_addstr(sb, color);
1080 return end - placeholder + 1;
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).
1088 if (skip_prefix(placeholder + 1, "red", &rest))
1089 basic_color = GIT_COLOR_RED;
1090 else if (skip_prefix(placeholder + 1, "green", &rest))
1091 basic_color = GIT_COLOR_GREEN;
1092 else if (skip_prefix(placeholder + 1, "blue", &rest))
1093 basic_color = GIT_COLOR_BLUE;
1094 else if (skip_prefix(placeholder + 1, "reset", &rest))
1095 basic_color = GIT_COLOR_RESET;
1097 if (basic_color && want_color(c->pretty_ctx->color))
1098 strbuf_addstr(sb, basic_color);
1100 return rest - placeholder;
1103 static size_t parse_padding_placeholder(const char *placeholder,
1104 struct format_commit_context *c)
1106 const char *ch = placeholder;
1107 enum flush_type flush_type;
1108 int to_column = 0;
1110 switch (*ch++) {
1111 case '<':
1112 flush_type = flush_right;
1113 break;
1114 case '>':
1115 if (*ch == '<') {
1116 flush_type = flush_both;
1117 ch++;
1118 } else if (*ch == '>') {
1119 flush_type = flush_left_and_steal;
1120 ch++;
1121 } else
1122 flush_type = flush_left;
1123 break;
1124 default:
1125 return 0;
1128 /* the next value means "wide enough to that column" */
1129 if (*ch == '|') {
1130 to_column = 1;
1131 ch++;
1134 if (*ch == '(') {
1135 const char *start = ch + 1;
1136 const char *end = start + strcspn(start, ",)");
1137 char *next;
1138 int width;
1139 if (!*end || end == start)
1140 return 0;
1141 width = strtol(start, &next, 10);
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.
1148 if (width < -FORMATTING_LIMIT || width > FORMATTING_LIMIT)
1149 return 0;
1151 if (next == start || width == 0)
1152 return 0;
1153 if (width < 0) {
1154 if (to_column)
1155 width += term_columns();
1156 if (width < 0)
1157 return 0;
1159 c->padding = to_column ? -width : width;
1160 c->flush_type = flush_type;
1162 if (*end == ',') {
1163 start = end + 1;
1164 end = strchr(start, ')');
1165 if (!end || end == start)
1166 return 0;
1167 if (starts_with(start, "trunc)"))
1168 c->truncate = trunc_right;
1169 else if (starts_with(start, "ltrunc)"))
1170 c->truncate = trunc_left;
1171 else if (starts_with(start, "mtrunc)"))
1172 c->truncate = trunc_middle;
1173 else
1174 return 0;
1175 } else
1176 c->truncate = trunc_none;
1178 return end - placeholder + 1;
1180 return 0;
1183 static int match_placeholder_arg_value(const char *to_parse, const char *candidate,
1184 const char **end, const char **valuestart,
1185 size_t *valuelen)
1187 const char *p;
1189 if (!(skip_prefix(to_parse, candidate, &p)))
1190 return 0;
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;
1203 if (*p == ',') {
1204 *end = p + 1;
1205 return 1;
1207 if (*p == ')') {
1208 *end = p;
1209 return 1;
1211 return 0;
1214 static int match_placeholder_bool_arg(const char *to_parse, const char *candidate,
1215 const char **end, int *val)
1217 const char *argval;
1218 char *strval;
1219 size_t arglen;
1220 int v;
1222 if (!match_placeholder_arg_value(to_parse, candidate, end, &argval, &arglen))
1223 return 0;
1225 if (!argval) {
1226 *val = 1;
1227 return 1;
1230 strval = xstrndup(argval, arglen);
1231 v = git_parse_maybe_bool(strval);
1232 free(strval);
1234 if (v == -1)
1235 return 0;
1237 *val = v;
1239 return 1;
1242 static int format_trailer_match_cb(const struct strbuf *key, void *ud)
1244 const struct string_list *list = ud;
1245 const struct string_list_item *item;
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;
1252 return 0;
1255 static struct strbuf *expand_separator(struct strbuf *sb,
1256 const char *argval, size_t arglen)
1258 char *fmt = xstrndup(argval, arglen);
1259 const char *format = fmt;
1261 strbuf_reset(sb);
1262 while (strbuf_expand_step(sb, &format)) {
1263 size_t len;
1265 if (skip_prefix(format, "%", &format))
1266 strbuf_addch(sb, '%');
1267 else if ((len = strbuf_expand_literal(sb, format)))
1268 format += len;
1269 else
1270 strbuf_addch(sb, '%');
1272 free(fmt);
1273 return sb;
1276 int format_set_trailers_options(struct process_trailer_options *opts,
1277 struct string_list *filter_list,
1278 struct strbuf *sepbuf,
1279 struct strbuf *kvsepbuf,
1280 const char **arg,
1281 char **invalid_arg)
1283 for (;;) {
1284 const char *argval;
1285 size_t arglen;
1287 if (**arg == ')')
1288 break;
1290 if (match_placeholder_arg_value(*arg, "key", arg, &argval, &arglen)) {
1291 uintptr_t len = arglen;
1293 if (!argval)
1294 return -1;
1296 if (len && argval[len - 1] == ':')
1297 len--;
1298 string_list_append(filter_list, argval)->util = (char *)len;
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)) {
1304 opts->separator = expand_separator(sepbuf, argval, arglen);
1305 } else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) {
1306 opts->key_value_separator = expand_separator(kvsepbuf, argval, arglen);
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) &&
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);
1315 return -1;
1318 return 0;
1321 static size_t parse_describe_args(const char *start, struct strvec *args)
1323 struct {
1324 char *name;
1325 enum {
1326 DESCRIBE_ARG_BOOL,
1327 DESCRIBE_ARG_INTEGER,
1328 DESCRIBE_ARG_STRING,
1329 } type;
1330 } option[] = {
1331 { "tags", DESCRIBE_ARG_BOOL},
1332 { "abbrev", DESCRIBE_ARG_INTEGER },
1333 { "exclude", DESCRIBE_ARG_STRING },
1334 { "match", DESCRIBE_ARG_STRING },
1336 const char *arg = start;
1338 for (;;) {
1339 int found = 0;
1340 const char *argval;
1341 size_t arglen = 0;
1342 int optval = 0;
1343 int i;
1345 for (i = 0; !found && i < ARRAY_SIZE(option); i++) {
1346 switch (option[i].type) {
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;
1355 break;
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;
1368 break;
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;
1377 break;
1380 if (!found)
1381 break;
1384 return arg - start;
1387 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1388 const char *placeholder,
1389 void *context)
1391 struct format_commit_context *c = context;
1392 const struct commit *commit = c->commit;
1393 const char *msg = c->message;
1394 struct commit_list *p;
1395 const char *arg, *eol;
1396 size_t res;
1397 char **slot;
1399 /* these are independent of the commit */
1400 res = strbuf_expand_literal(sb, placeholder);
1401 if (res)
1402 return res;
1404 switch (placeholder[0]) {
1405 case 'C':
1406 if (starts_with(placeholder + 1, "(auto)")) {
1407 c->auto_color = want_color(c->pretty_ctx->color);
1408 if (c->auto_color && sb->len)
1409 strbuf_addstr(sb, GIT_COLOR_RESET);
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;
1416 * Otherwise, we decided to treat %C<unknown>
1417 * as a literal string, and the previous
1418 * %C(auto) is still valid.
1420 return ret;
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);
1439 if (*next != ')')
1440 return 0;
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.
1448 if (width > FORMATTING_LIMIT ||
1449 indent1 > FORMATTING_LIMIT ||
1450 indent2 > FORMATTING_LIMIT)
1451 return 0;
1452 rewrap_message_tail(sb, c, width, indent1, indent2);
1453 return end - placeholder + 1;
1454 } else
1455 return 0;
1457 case '<':
1458 case '>':
1459 return parse_padding_placeholder(placeholder, c);
1462 if (skip_prefix(placeholder, "(describe", &arg)) {
1463 struct child_process cmd = CHILD_PROCESS_INIT;
1464 struct strbuf out = STRBUF_INIT;
1465 struct strbuf err = STRBUF_INIT;
1466 struct pretty_print_describe_status *describe_status;
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--;
1475 cmd.git_cmd = 1;
1476 strvec_push(&cmd.args, "describe");
1478 if (*arg == ':') {
1479 arg++;
1480 arg += parse_describe_args(arg, &cmd.args);
1483 if (*arg != ')') {
1484 child_process_clear(&cmd);
1485 return 0;
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);
1494 return arg - placeholder + 1;
1497 /* these depend on the commit */
1498 if (!commit->object.parsed)
1499 parse_object(the_repository, &commit->object.oid);
1501 switch (placeholder[0]) {
1502 case 'H': /* commit hash */
1503 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1504 strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
1505 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1506 return 1;
1507 case 'h': /* abbreviated commit hash */
1508 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1509 strbuf_add_unique_abbrev(sb, &commit->object.oid,
1510 c->pretty_ctx->abbrev);
1511 strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1512 return 1;
1513 case 'T': /* tree hash */
1514 strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit)));
1515 return 1;
1516 case 't': /* abbreviated tree hash */
1517 strbuf_add_unique_abbrev(sb,
1518 get_commit_tree_oid(commit),
1519 c->pretty_ctx->abbrev);
1520 return 1;
1521 case 'P': /* parent hashes */
1522 for (p = commit->parents; p; p = p->next) {
1523 if (p != commit->parents)
1524 strbuf_addch(sb, ' ');
1525 strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
1527 return 1;
1528 case 'p': /* abbreviated parent hashes */
1529 for (p = commit->parents; p; p = p->next) {
1530 if (p != commit->parents)
1531 strbuf_addch(sb, ' ');
1532 strbuf_add_unique_abbrev(sb, &p->item->object.oid,
1533 c->pretty_ctx->abbrev);
1535 return 1;
1536 case 'm': /* left/right/bottom */
1537 strbuf_addstr(sb, get_revision_mark(NULL, commit));
1538 return 1;
1539 case 'd':
1540 format_decorations(sb, commit, c->auto_color);
1541 return 1;
1542 case 'D':
1543 format_decorations_extended(sb, commit, c->auto_color, "", ", ", "");
1544 return 1;
1545 case 'S': /* tag/branch like --source */
1546 if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
1547 return 0;
1548 slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
1549 if (!(slot && *slot))
1550 return 0;
1551 strbuf_addstr(sb, *slot);
1552 return 1;
1553 case 'g': /* reflog info */
1554 switch(placeholder[1]) {
1555 case 'd': /* reflog selector */
1556 case 'D':
1557 if (c->pretty_ctx->reflog_info)
1558 get_reflog_selector(sb,
1559 c->pretty_ctx->reflog_info,
1560 &c->pretty_ctx->date_mode,
1561 c->pretty_ctx->date_mode_explicit,
1562 (placeholder[1] == 'd'));
1563 return 2;
1564 case 's': /* reflog message */
1565 if (c->pretty_ctx->reflog_info)
1566 get_reflog_message(sb, c->pretty_ctx->reflog_info);
1567 return 2;
1568 case 'n':
1569 case 'N':
1570 case 'e':
1571 case 'E':
1572 return format_reflog_person(sb,
1573 placeholder[1],
1574 c->pretty_ctx->reflog_info,
1575 &c->pretty_ctx->date_mode);
1577 return 0; /* unknown %g placeholder */
1578 case 'N':
1579 if (c->pretty_ctx->notes_message) {
1580 strbuf_addstr(sb, c->pretty_ctx->notes_message);
1581 return 1;
1583 return 0;
1586 if (placeholder[0] == 'G') {
1587 if (!c->signature_check.result)
1588 check_commit_signature(c->commit, &(c->signature_check));
1589 switch (placeholder[1]) {
1590 case 'G':
1591 if (c->signature_check.output)
1592 strbuf_addstr(sb, c->signature_check.output);
1593 break;
1594 case '?':
1595 switch (c->signature_check.result) {
1596 case 'G':
1597 switch (c->signature_check.trust_level) {
1598 case TRUST_UNDEFINED:
1599 case TRUST_NEVER:
1600 strbuf_addch(sb, 'U');
1601 break;
1602 default:
1603 strbuf_addch(sb, 'G');
1604 break;
1606 break;
1607 case 'B':
1608 case 'E':
1609 case 'N':
1610 case 'X':
1611 case 'Y':
1612 case 'R':
1613 strbuf_addch(sb, c->signature_check.result);
1615 break;
1616 case 'S':
1617 if (c->signature_check.signer)
1618 strbuf_addstr(sb, c->signature_check.signer);
1619 break;
1620 case 'K':
1621 if (c->signature_check.key)
1622 strbuf_addstr(sb, c->signature_check.key);
1623 break;
1624 case 'F':
1625 if (c->signature_check.fingerprint)
1626 strbuf_addstr(sb, c->signature_check.fingerprint);
1627 break;
1628 case 'P':
1629 if (c->signature_check.primary_key_fingerprint)
1630 strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
1631 break;
1632 case 'T':
1633 strbuf_addstr(sb, gpg_trust_level_to_str(c->signature_check.trust_level));
1634 break;
1635 default:
1636 return 0;
1638 return 2;
1641 /* For the rest we have to parse the commit header. */
1642 if (!c->commit_header_parsed) {
1643 msg = c->message =
1644 repo_logmsg_reencode(c->repository, commit,
1645 &c->commit_encoding, "UTF-8");
1646 parse_commit_header(c);
1649 switch (placeholder[0]) {
1650 case 'a': /* author ... */
1651 return format_person_part(sb, placeholder[1],
1652 msg + c->author.off, c->author.len,
1653 &c->pretty_ctx->date_mode);
1654 case 'c': /* committer ... */
1655 return format_person_part(sb, placeholder[1],
1656 msg + c->committer.off, c->committer.len,
1657 &c->pretty_ctx->date_mode);
1658 case 'e': /* encoding */
1659 if (c->commit_encoding)
1660 strbuf_addstr(sb, c->commit_encoding);
1661 return 1;
1662 case 'B': /* raw body */
1663 /* message_off is always left at the initial newline */
1664 strbuf_addstr(sb, msg + c->message_off + 1);
1665 return 1;
1668 /* Now we need to parse the commit message. */
1669 if (!c->commit_message_parsed)
1670 parse_commit_message(c);
1672 switch (placeholder[0]) {
1673 case 's': /* subject */
1674 format_subject(sb, msg + c->subject_off, " ");
1675 return 1;
1676 case 'f': /* sanitized subject */
1677 eol = strchrnul(msg + c->subject_off, '\n');
1678 format_sanitized_subject(sb, msg + c->subject_off, eol - (msg + c->subject_off));
1679 return 1;
1680 case 'b': /* body */
1681 strbuf_addstr(sb, msg + c->body_off);
1682 return 1;
1685 if (skip_prefix(placeholder, "(trailers", &arg)) {
1686 struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1687 struct string_list filter_list = STRING_LIST_INIT_NODUP;
1688 struct strbuf sepbuf = STRBUF_INIT;
1689 struct strbuf kvsepbuf = STRBUF_INIT;
1690 size_t ret = 0;
1692 opts.no_divider = 1;
1694 if (*arg == ':') {
1695 arg++;
1696 if (format_set_trailers_options(&opts, &filter_list, &sepbuf, &kvsepbuf, &arg, NULL))
1697 goto trailer_out;
1699 if (*arg == ')') {
1700 format_trailers_from_commit(sb, msg + c->subject_off, &opts);
1701 ret = arg - placeholder + 1;
1703 trailer_out:
1704 string_list_clear(&filter_list, 0);
1705 strbuf_release(&sepbuf);
1706 return ret;
1709 return 0; /* unknown placeholder */
1712 static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
1713 const char *placeholder,
1714 struct format_commit_context *c)
1716 struct strbuf local_sb = STRBUF_INIT;
1717 size_t total_consumed = 0;
1718 int len, padding = c->padding;
1720 if (padding < 0) {
1721 const char *start = strrchr(sb->buf, '\n');
1722 int occupied;
1723 if (!start)
1724 start = sb->buf;
1725 occupied = utf8_strnwidth(start, strlen(start), 1);
1726 occupied += c->pretty_ctx->graph_width;
1727 padding = (-padding) - occupied;
1729 while (1) {
1730 int modifier = *placeholder == 'C';
1731 size_t consumed = format_commit_one(&local_sb, placeholder, c);
1732 total_consumed += consumed;
1734 if (!modifier)
1735 break;
1737 placeholder += consumed;
1738 if (*placeholder != '%')
1739 break;
1740 placeholder++;
1741 total_consumed++;
1743 len = utf8_strnwidth(local_sb.buf, local_sb.len, 1);
1745 if (c->flush_type == flush_left_and_steal) {
1746 const char *ch = sb->buf + sb->len - 1;
1747 while (len > padding && ch > sb->buf) {
1748 const char *p;
1749 if (*ch == ' ') {
1750 ch--;
1751 padding++;
1752 continue;
1754 /* check for trailing ansi sequences */
1755 if (*ch != 'm')
1756 break;
1757 p = ch - 1;
1758 while (p > sb->buf && ch - p < 10 && *p != '\033')
1759 p--;
1760 if (*p != '\033' ||
1761 ch + 1 - p != display_mode_esc_sequence_len(p))
1762 break;
1764 * got a good ansi sequence, put it back to
1765 * local_sb as we're cutting sb
1767 strbuf_insert(&local_sb, 0, p, ch + 1 - p);
1768 ch = p - 1;
1770 strbuf_setlen(sb, ch + 1 - sb->buf);
1771 c->flush_type = flush_left;
1774 if (len > padding) {
1775 switch (c->truncate) {
1776 case trunc_left:
1777 strbuf_utf8_replace(&local_sb,
1778 0, len - (padding - 2),
1779 "..");
1780 break;
1781 case trunc_middle:
1782 strbuf_utf8_replace(&local_sb,
1783 padding / 2 - 1,
1784 len - (padding - 2),
1785 "..");
1786 break;
1787 case trunc_right:
1788 strbuf_utf8_replace(&local_sb,
1789 padding - 2, len - (padding - 2),
1790 "..");
1791 break;
1792 case trunc_none:
1793 break;
1795 strbuf_addbuf(sb, &local_sb);
1796 } else {
1797 size_t sb_len = sb->len, offset = 0;
1798 if (c->flush_type == flush_left)
1799 offset = padding - len;
1800 else if (c->flush_type == flush_both)
1801 offset = (padding - len) / 2;
1803 * we calculate padding in columns, now
1804 * convert it back to chars
1806 padding = padding - len + local_sb.len;
1807 strbuf_addchars(sb, ' ', padding);
1808 memcpy(sb->buf + sb_len + offset, local_sb.buf,
1809 local_sb.len);
1811 strbuf_release(&local_sb);
1812 c->flush_type = no_flush;
1813 return total_consumed;
1816 static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
1817 const char *placeholder,
1818 struct format_commit_context *context)
1820 size_t consumed, orig_len;
1821 enum {
1822 NO_MAGIC,
1823 ADD_LF_BEFORE_NON_EMPTY,
1824 DEL_LF_BEFORE_EMPTY,
1825 ADD_SP_BEFORE_NON_EMPTY
1826 } magic = NO_MAGIC;
1828 switch (placeholder[0]) {
1829 case '-':
1830 magic = DEL_LF_BEFORE_EMPTY;
1831 break;
1832 case '+':
1833 magic = ADD_LF_BEFORE_NON_EMPTY;
1834 break;
1835 case ' ':
1836 magic = ADD_SP_BEFORE_NON_EMPTY;
1837 break;
1838 default:
1839 break;
1841 if (magic != NO_MAGIC) {
1842 placeholder++;
1844 switch (placeholder[0]) {
1845 case 'w':
1847 * `%+w()` cannot ever expand to a non-empty string,
1848 * and it potentially changes the layout of preceding
1849 * contents. We're thus not able to handle the magic in
1850 * this combination and refuse the pattern.
1852 return 0;
1856 orig_len = sb->len;
1857 if (context->flush_type == no_flush)
1858 consumed = format_commit_one(sb, placeholder, context);
1859 else
1860 consumed = format_and_pad_commit(sb, placeholder, context);
1861 if (magic == NO_MAGIC)
1862 return consumed;
1864 if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
1865 while (sb->len && sb->buf[sb->len - 1] == '\n')
1866 strbuf_setlen(sb, sb->len - 1);
1867 } else if (orig_len != sb->len) {
1868 if (magic == ADD_LF_BEFORE_NON_EMPTY)
1869 strbuf_insertstr(sb, orig_len, "\n");
1870 else if (magic == ADD_SP_BEFORE_NON_EMPTY)
1871 strbuf_insertstr(sb, orig_len, " ");
1873 return consumed + 1;
1876 void userformat_find_requirements(const char *fmt, struct userformat_want *w)
1878 if (!fmt) {
1879 if (!user_format)
1880 return;
1881 fmt = user_format;
1883 while ((fmt = strchr(fmt, '%'))) {
1884 fmt++;
1885 if (skip_prefix(fmt, "%", &fmt))
1886 continue;
1888 if (*fmt == '+' || *fmt == '-' || *fmt == ' ')
1889 fmt++;
1891 switch (*fmt) {
1892 case 'N':
1893 w->notes = 1;
1894 break;
1895 case 'S':
1896 w->source = 1;
1897 break;
1898 case 'd':
1899 case 'D':
1900 w->decorate = 1;
1901 break;
1906 void repo_format_commit_message(struct repository *r,
1907 const struct commit *commit,
1908 const char *format, struct strbuf *sb,
1909 const struct pretty_print_context *pretty_ctx)
1911 struct format_commit_context context = {
1912 .repository = r,
1913 .commit = commit,
1914 .pretty_ctx = pretty_ctx,
1915 .wrap_start = sb->len
1917 const char *output_enc = pretty_ctx->output_encoding;
1918 const char *utf8 = "UTF-8";
1920 while (strbuf_expand_step(sb, &format)) {
1921 size_t len;
1923 if (skip_prefix(format, "%", &format))
1924 strbuf_addch(sb, '%');
1925 else if ((len = format_commit_item(sb, format, &context)))
1926 format += len;
1927 else
1928 strbuf_addch(sb, '%');
1930 rewrap_message_tail(sb, &context, 0, 0, 0);
1933 * Convert output to an actual output encoding; note that
1934 * format_commit_item() will always use UTF-8, so we don't
1935 * have to bother if that's what the output wants.
1937 if (output_enc) {
1938 if (same_encoding(utf8, output_enc))
1939 output_enc = NULL;
1940 } else {
1941 if (context.commit_encoding &&
1942 !same_encoding(context.commit_encoding, utf8))
1943 output_enc = context.commit_encoding;
1946 if (output_enc) {
1947 size_t outsz;
1948 char *out = reencode_string_len(sb->buf, sb->len,
1949 output_enc, utf8, &outsz);
1950 if (out)
1951 strbuf_attach(sb, out, outsz, outsz + 1);
1954 free(context.commit_encoding);
1955 repo_unuse_commit_buffer(r, commit, context.message);
1958 static void pp_header(struct pretty_print_context *pp,
1959 const char *encoding,
1960 const struct commit *commit,
1961 const char **msg_p,
1962 struct strbuf *sb)
1964 int parents_shown = 0;
1966 for (;;) {
1967 const char *name, *line = *msg_p;
1968 int linelen = get_one_line(*msg_p);
1970 if (!linelen)
1971 return;
1972 *msg_p += linelen;
1974 if (linelen == 1)
1975 /* End of header */
1976 return;
1978 if (pp->fmt == CMIT_FMT_RAW) {
1979 strbuf_add(sb, line, linelen);
1980 continue;
1983 if (starts_with(line, "parent ")) {
1984 if (linelen != the_hash_algo->hexsz + 8)
1985 die("bad parent line in commit");
1986 continue;
1989 if (!parents_shown) {
1990 unsigned num = commit_list_count(commit->parents);
1991 /* with enough slop */
1992 strbuf_grow(sb, num * (GIT_MAX_HEXSZ + 10) + 20);
1993 add_merge_info(pp, sb, commit);
1994 parents_shown = 1;
1998 * MEDIUM == DEFAULT shows only author with dates.
1999 * FULL shows both authors but not dates.
2000 * FULLER shows both authors and dates.
2002 if (skip_prefix(line, "author ", &name)) {
2003 strbuf_grow(sb, linelen + 80);
2004 pp_user_info(pp, "Author", sb, name, encoding);
2006 if (skip_prefix(line, "committer ", &name) &&
2007 (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
2008 strbuf_grow(sb, linelen + 80);
2009 pp_user_info(pp, "Commit", sb, name, encoding);
2014 void pp_title_line(struct pretty_print_context *pp,
2015 const char **msg_p,
2016 struct strbuf *sb,
2017 const char *encoding,
2018 int need_8bit_cte)
2020 static const int max_length = 78; /* per rfc2047 */
2021 struct strbuf title;
2023 strbuf_init(&title, 80);
2024 *msg_p = format_subject(&title, *msg_p,
2025 pp->preserve_subject ? "\n" : " ");
2027 strbuf_grow(sb, title.len + 1024);
2028 if (pp->print_email_subject) {
2029 if (pp->rev)
2030 fmt_output_email_subject(sb, pp->rev);
2031 if (pp->encode_email_headers &&
2032 needs_rfc2047_encoding(title.buf, title.len))
2033 add_rfc2047(sb, title.buf, title.len,
2034 encoding, RFC2047_SUBJECT);
2035 else
2036 strbuf_add_wrapped_bytes(sb, title.buf, title.len,
2037 -last_line_length(sb), 1, max_length);
2038 } else {
2039 strbuf_addbuf(sb, &title);
2041 strbuf_addch(sb, '\n');
2043 if (need_8bit_cte == 0) {
2044 int i;
2045 for (i = 0; i < pp->in_body_headers.nr; i++) {
2046 if (has_non_ascii(pp->in_body_headers.items[i].string)) {
2047 need_8bit_cte = 1;
2048 break;
2053 if (need_8bit_cte > 0) {
2054 const char *header_fmt =
2055 "MIME-Version: 1.0\n"
2056 "Content-Type: text/plain; charset=%s\n"
2057 "Content-Transfer-Encoding: 8bit\n";
2058 strbuf_addf(sb, header_fmt, encoding);
2060 if (pp->after_subject) {
2061 strbuf_addstr(sb, pp->after_subject);
2063 if (cmit_fmt_is_mail(pp->fmt)) {
2064 strbuf_addch(sb, '\n');
2067 if (pp->in_body_headers.nr) {
2068 int i;
2069 for (i = 0; i < pp->in_body_headers.nr; i++) {
2070 strbuf_addstr(sb, pp->in_body_headers.items[i].string);
2071 free(pp->in_body_headers.items[i].string);
2073 string_list_clear(&pp->in_body_headers, 0);
2074 strbuf_addch(sb, '\n');
2077 strbuf_release(&title);
2080 static int pp_utf8_width(const char *start, const char *end)
2082 int width = 0;
2083 size_t remain = end - start;
2085 while (remain) {
2086 int n = utf8_width(&start, &remain);
2087 if (n < 0 || !start)
2088 return -1;
2089 width += n;
2091 return width;
2094 static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
2095 int color, int tabwidth, const char *line,
2096 int linelen)
2098 const char *tab;
2100 while ((tab = memchr(line, '\t', linelen)) != NULL) {
2101 int width = pp_utf8_width(line, tab);
2104 * If it wasn't well-formed utf8, or it
2105 * had characters with badly defined
2106 * width (control characters etc), just
2107 * give up on trying to align things.
2109 if (width < 0)
2110 break;
2112 /* Output the data .. */
2113 append_line_with_color(sb, opt, line, tab - line, color,
2114 GREP_CONTEXT_BODY,
2115 GREP_HEADER_FIELD_MAX);
2117 /* .. and the de-tabified tab */
2118 strbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));
2120 /* Skip over the printed part .. */
2121 linelen -= tab + 1 - line;
2122 line = tab + 1;
2126 * Print out everything after the last tab without
2127 * worrying about width - there's nothing more to
2128 * align.
2130 append_line_with_color(sb, opt, line, linelen, color, GREP_CONTEXT_BODY,
2131 GREP_HEADER_FIELD_MAX);
2135 * pp_handle_indent() prints out the intendation, and
2136 * the whole line (without the final newline), after
2137 * de-tabifying.
2139 static void pp_handle_indent(struct pretty_print_context *pp,
2140 struct strbuf *sb, int indent,
2141 const char *line, int linelen)
2143 struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
2145 strbuf_addchars(sb, ' ', indent);
2146 if (pp->expand_tabs_in_log)
2147 strbuf_add_tabexpand(sb, opt, pp->color, pp->expand_tabs_in_log,
2148 line, linelen);
2149 else
2150 append_line_with_color(sb, opt, line, linelen, pp->color,
2151 GREP_CONTEXT_BODY,
2152 GREP_HEADER_FIELD_MAX);
2155 static int is_mboxrd_from(const char *line, int len)
2158 * a line matching /^From $/ here would only have len == 4
2159 * at this point because is_empty_line would've trimmed all
2160 * trailing space
2162 return len > 4 && starts_with(line + strspn(line, ">"), "From ");
2165 void pp_remainder(struct pretty_print_context *pp,
2166 const char **msg_p,
2167 struct strbuf *sb,
2168 int indent)
2170 struct grep_opt *opt = pp->rev ? &pp->rev->grep_filter : NULL;
2171 int first = 1;
2173 for (;;) {
2174 const char *line = *msg_p;
2175 int linelen = get_one_line(line);
2176 *msg_p += linelen;
2178 if (!linelen)
2179 break;
2181 if (is_blank_line(line, &linelen)) {
2182 if (first)
2183 continue;
2184 if (pp->fmt == CMIT_FMT_SHORT)
2185 break;
2187 first = 0;
2189 strbuf_grow(sb, linelen + indent + 20);
2190 if (indent)
2191 pp_handle_indent(pp, sb, indent, line, linelen);
2192 else if (pp->expand_tabs_in_log)
2193 strbuf_add_tabexpand(sb, opt, pp->color,
2194 pp->expand_tabs_in_log, line,
2195 linelen);
2196 else {
2197 if (pp->fmt == CMIT_FMT_MBOXRD &&
2198 is_mboxrd_from(line, linelen))
2199 strbuf_addch(sb, '>');
2201 append_line_with_color(sb, opt, line, linelen,
2202 pp->color, GREP_CONTEXT_BODY,
2203 GREP_HEADER_FIELD_MAX);
2205 strbuf_addch(sb, '\n');
2209 void pretty_print_commit(struct pretty_print_context *pp,
2210 const struct commit *commit,
2211 struct strbuf *sb)
2213 unsigned long beginning_of_body;
2214 int indent = 4;
2215 const char *msg;
2216 const char *reencoded;
2217 const char *encoding;
2218 int need_8bit_cte = pp->need_8bit_cte;
2220 if (pp->fmt == CMIT_FMT_USERFORMAT) {
2221 repo_format_commit_message(the_repository, commit,
2222 user_format, sb, pp);
2223 return;
2226 encoding = get_log_output_encoding();
2227 msg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,
2228 encoding);
2230 if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
2231 indent = 0;
2234 * We need to check and emit Content-type: to mark it
2235 * as 8-bit if we haven't done so.
2237 if (cmit_fmt_is_mail(pp->fmt) && need_8bit_cte == 0) {
2238 int i, ch, in_body;
2240 for (in_body = i = 0; (ch = msg[i]); i++) {
2241 if (!in_body) {
2242 /* author could be non 7-bit ASCII but
2243 * the log may be so; skip over the
2244 * header part first.
2246 if (ch == '\n' && msg[i+1] == '\n')
2247 in_body = 1;
2249 else if (non_ascii(ch)) {
2250 need_8bit_cte = 1;
2251 break;
2256 pp_header(pp, encoding, commit, &msg, sb);
2257 if (pp->fmt != CMIT_FMT_ONELINE && !pp->print_email_subject) {
2258 strbuf_addch(sb, '\n');
2261 /* Skip excess blank lines at the beginning of body, if any... */
2262 msg = skip_blank_lines(msg);
2264 /* These formats treat the title line specially. */
2265 if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
2266 pp_title_line(pp, &msg, sb, encoding, need_8bit_cte);
2268 beginning_of_body = sb->len;
2269 if (pp->fmt != CMIT_FMT_ONELINE)
2270 pp_remainder(pp, &msg, sb, indent);
2271 strbuf_rtrim(sb);
2273 /* Make sure there is an EOLN for the non-oneline case */
2274 if (pp->fmt != CMIT_FMT_ONELINE)
2275 strbuf_addch(sb, '\n');
2278 * The caller may append additional body text in e-mail
2279 * format. Make sure we did not strip the blank line
2280 * between the header and the body.
2282 if (cmit_fmt_is_mail(pp->fmt) && sb->len <= beginning_of_body)
2283 strbuf_addch(sb, '\n');
2285 repo_unuse_commit_buffer(the_repository, commit, reencoded);
2288 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
2289 struct strbuf *sb)
2291 struct pretty_print_context pp = {0};
2292 pp.fmt = fmt;
2293 pretty_print_commit(&pp, commit, sb);