pretty.con commit pretty.c: make git_pretty_formats_config return -1 on git_config_string failure (a26bc61)
   1#include "cache.h"
   2#include "commit.h"
   3#include "utf8.h"
   4#include "diff.h"
   5#include "revision.h"
   6#include "string-list.h"
   7#include "mailmap.h"
   8#include "log-tree.h"
   9#include "notes.h"
  10#include "color.h"
  11#include "reflog-walk.h"
  12#include "gpg-interface.h"
  13
  14static char *user_format;
  15static struct cmt_fmt_map {
  16        const char *name;
  17        enum cmit_fmt format;
  18        int is_tformat;
  19        int is_alias;
  20        const char *user_format;
  21} *commit_formats;
  22static size_t builtin_formats_len;
  23static size_t commit_formats_len;
  24static size_t commit_formats_alloc;
  25static struct cmt_fmt_map *find_commit_format(const char *sought);
  26
  27static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
  28{
  29        free(user_format);
  30        user_format = xstrdup(cp);
  31        if (is_tformat)
  32                rev->use_terminator = 1;
  33        rev->commit_format = CMIT_FMT_USERFORMAT;
  34}
  35
  36static int git_pretty_formats_config(const char *var, const char *value, void *cb)
  37{
  38        struct cmt_fmt_map *commit_format = NULL;
  39        const char *name;
  40        const char *fmt;
  41        int i;
  42
  43        if (!starts_with(var, "pretty."))
  44                return 0;
  45
  46        name = var + strlen("pretty.");
  47        for (i = 0; i < builtin_formats_len; i++) {
  48                if (!strcmp(commit_formats[i].name, name))
  49                        return 0;
  50        }
  51
  52        for (i = builtin_formats_len; i < commit_formats_len; i++) {
  53                if (!strcmp(commit_formats[i].name, name)) {
  54                        commit_format = &commit_formats[i];
  55                        break;
  56                }
  57        }
  58
  59        if (!commit_format) {
  60                ALLOC_GROW(commit_formats, commit_formats_len+1,
  61                           commit_formats_alloc);
  62                commit_format = &commit_formats[commit_formats_len];
  63                memset(commit_format, 0, sizeof(*commit_format));
  64                commit_formats_len++;
  65        }
  66
  67        commit_format->name = xstrdup(name);
  68        commit_format->format = CMIT_FMT_USERFORMAT;
  69        if (git_config_string(&fmt, var, value))
  70                return -1;
  71
  72        if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
  73                commit_format->is_tformat = fmt[0] == 't';
  74                fmt = strchr(fmt, ':') + 1;
  75        } else if (strchr(fmt, '%'))
  76                commit_format->is_tformat = 1;
  77        else
  78                commit_format->is_alias = 1;
  79        commit_format->user_format = fmt;
  80
  81        return 0;
  82}
  83
  84static void setup_commit_formats(void)
  85{
  86        struct cmt_fmt_map builtin_formats[] = {
  87                { "raw",        CMIT_FMT_RAW,           0 },
  88                { "medium",     CMIT_FMT_MEDIUM,        0 },
  89                { "short",      CMIT_FMT_SHORT,         0 },
  90                { "email",      CMIT_FMT_EMAIL,         0 },
  91                { "fuller",     CMIT_FMT_FULLER,        0 },
  92                { "full",       CMIT_FMT_FULL,          0 },
  93                { "oneline",    CMIT_FMT_ONELINE,       1 }
  94        };
  95        commit_formats_len = ARRAY_SIZE(builtin_formats);
  96        builtin_formats_len = commit_formats_len;
  97        ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
  98        memcpy(commit_formats, builtin_formats,
  99               sizeof(*builtin_formats)*ARRAY_SIZE(builtin_formats));
 100
 101        git_config(git_pretty_formats_config, NULL);
 102}
 103
 104static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
 105                                                        const char *original,
 106                                                        int num_redirections)
 107{
 108        struct cmt_fmt_map *found = NULL;
 109        size_t found_match_len = 0;
 110        int i;
 111
 112        if (num_redirections >= commit_formats_len)
 113                die("invalid --pretty format: "
 114                    "'%s' references an alias which points to itself",
 115                    original);
 116
 117        for (i = 0; i < commit_formats_len; i++) {
 118                size_t match_len;
 119
 120                if (!starts_with(commit_formats[i].name, sought))
 121                        continue;
 122
 123                match_len = strlen(commit_formats[i].name);
 124                if (found == NULL || found_match_len > match_len) {
 125                        found = &commit_formats[i];
 126                        found_match_len = match_len;
 127                }
 128        }
 129
 130        if (found && found->is_alias) {
 131                found = find_commit_format_recursive(found->user_format,
 132                                                     original,
 133                                                     num_redirections+1);
 134        }
 135
 136        return found;
 137}
 138
 139static struct cmt_fmt_map *find_commit_format(const char *sought)
 140{
 141        if (!commit_formats)
 142                setup_commit_formats();
 143
 144        return find_commit_format_recursive(sought, sought, 0);
 145}
 146
 147void get_commit_format(const char *arg, struct rev_info *rev)
 148{
 149        struct cmt_fmt_map *commit_format;
 150
 151        rev->use_terminator = 0;
 152        if (!arg || !*arg) {
 153                rev->commit_format = CMIT_FMT_DEFAULT;
 154                return;
 155        }
 156        if (starts_with(arg, "format:") || starts_with(arg, "tformat:")) {
 157                save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't');
 158                return;
 159        }
 160
 161        if (strchr(arg, '%')) {
 162                save_user_format(rev, arg, 1);
 163                return;
 164        }
 165
 166        commit_format = find_commit_format(arg);
 167        if (!commit_format)
 168                die("invalid --pretty format: %s", arg);
 169
 170        rev->commit_format = commit_format->format;
 171        rev->use_terminator = commit_format->is_tformat;
 172        if (commit_format->format == CMIT_FMT_USERFORMAT) {
 173                save_user_format(rev, commit_format->user_format,
 174                                 commit_format->is_tformat);
 175        }
 176}
 177
 178/*
 179 * Generic support for pretty-printing the header
 180 */
 181static int get_one_line(const char *msg)
 182{
 183        int ret = 0;
 184
 185        for (;;) {
 186                char c = *msg++;
 187                if (!c)
 188                        break;
 189                ret++;
 190                if (c == '\n')
 191                        break;
 192        }
 193        return ret;
 194}
 195
 196/* High bit set, or ISO-2022-INT */
 197static int non_ascii(int ch)
 198{
 199        return !isascii(ch) || ch == '\033';
 200}
 201
 202int has_non_ascii(const char *s)
 203{
 204        int ch;
 205        if (!s)
 206                return 0;
 207        while ((ch = *s++) != '\0') {
 208                if (non_ascii(ch))
 209                        return 1;
 210        }
 211        return 0;
 212}
 213
 214static int is_rfc822_special(char ch)
 215{
 216        switch (ch) {
 217        case '(':
 218        case ')':
 219        case '<':
 220        case '>':
 221        case '[':
 222        case ']':
 223        case ':':
 224        case ';':
 225        case '@':
 226        case ',':
 227        case '.':
 228        case '"':
 229        case '\\':
 230                return 1;
 231        default:
 232                return 0;
 233        }
 234}
 235
 236static int needs_rfc822_quoting(const char *s, int len)
 237{
 238        int i;
 239        for (i = 0; i < len; i++)
 240                if (is_rfc822_special(s[i]))
 241                        return 1;
 242        return 0;
 243}
 244
 245static int last_line_length(struct strbuf *sb)
 246{
 247        int i;
 248
 249        /* How many bytes are already used on the last line? */
 250        for (i = sb->len - 1; i >= 0; i--)
 251                if (sb->buf[i] == '\n')
 252                        break;
 253        return sb->len - (i + 1);
 254}
 255
 256static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
 257{
 258        int i;
 259
 260        /* just a guess, we may have to also backslash-quote */
 261        strbuf_grow(out, len + 2);
 262
 263        strbuf_addch(out, '"');
 264        for (i = 0; i < len; i++) {
 265                switch (s[i]) {
 266                case '"':
 267                case '\\':
 268                        strbuf_addch(out, '\\');
 269                        /* fall through */
 270                default:
 271                        strbuf_addch(out, s[i]);
 272                }
 273        }
 274        strbuf_addch(out, '"');
 275}
 276
 277enum rfc2047_type {
 278        RFC2047_SUBJECT,
 279        RFC2047_ADDRESS
 280};
 281
 282static int is_rfc2047_special(char ch, enum rfc2047_type type)
 283{
 284        /*
 285         * rfc2047, section 4.2:
 286         *
 287         *    8-bit values which correspond to printable ASCII characters other
 288         *    than "=", "?", and "_" (underscore), MAY be represented as those
 289         *    characters.  (But see section 5 for restrictions.)  In
 290         *    particular, SPACE and TAB MUST NOT be represented as themselves
 291         *    within encoded words.
 292         */
 293
 294        /*
 295         * rule out non-ASCII characters and non-printable characters (the
 296         * non-ASCII check should be redundant as isprint() is not localized
 297         * and only knows about ASCII, but be defensive about that)
 298         */
 299        if (non_ascii(ch) || !isprint(ch))
 300                return 1;
 301
 302        /*
 303         * rule out special printable characters (' ' should be the only
 304         * whitespace character considered printable, but be defensive and use
 305         * isspace())
 306         */
 307        if (isspace(ch) || ch == '=' || ch == '?' || ch == '_')
 308                return 1;
 309
 310        /*
 311         * rfc2047, section 5.3:
 312         *
 313         *    As a replacement for a 'word' entity within a 'phrase', for example,
 314         *    one that precedes an address in a From, To, or Cc header.  The ABNF
 315         *    definition for 'phrase' from RFC 822 thus becomes:
 316         *
 317         *    phrase = 1*( encoded-word / word )
 318         *
 319         *    In this case the set of characters that may be used in a "Q"-encoded
 320         *    'encoded-word' is restricted to: <upper and lower case ASCII
 321         *    letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
 322         *    (underscore, ASCII 95.)>.  An 'encoded-word' that appears within a
 323         *    'phrase' MUST be separated from any adjacent 'word', 'text' or
 324         *    'special' by 'linear-white-space'.
 325         */
 326
 327        if (type != RFC2047_ADDRESS)
 328                return 0;
 329
 330        /* '=' and '_' are special cases and have been checked above */
 331        return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
 332}
 333
 334static int needs_rfc2047_encoding(const char *line, int len,
 335                                  enum rfc2047_type type)
 336{
 337        int i;
 338
 339        for (i = 0; i < len; i++) {
 340                int ch = line[i];
 341                if (non_ascii(ch) || ch == '\n')
 342                        return 1;
 343                if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
 344                        return 1;
 345        }
 346
 347        return 0;
 348}
 349
 350static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
 351                       const char *encoding, enum rfc2047_type type)
 352{
 353        static const int max_encoded_length = 76; /* per rfc2047 */
 354        int i;
 355        int line_len = last_line_length(sb);
 356
 357        strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
 358        strbuf_addf(sb, "=?%s?q?", encoding);
 359        line_len += strlen(encoding) + 5; /* 5 for =??q? */
 360
 361        while (len) {
 362                /*
 363                 * RFC 2047, section 5 (3):
 364                 *
 365                 * Each 'encoded-word' MUST represent an integral number of
 366                 * characters.  A multi-octet character may not be split across
 367                 * adjacent 'encoded- word's.
 368                 */
 369                const unsigned char *p = (const unsigned char *)line;
 370                int chrlen = mbs_chrlen(&line, &len, encoding);
 371                int is_special = (chrlen > 1) || is_rfc2047_special(*p, type);
 372
 373                /* "=%02X" * chrlen, or the byte itself */
 374                const char *encoded_fmt = is_special ? "=%02X"    : "%c";
 375                int         encoded_len = is_special ? 3 * chrlen : 1;
 376
 377                /*
 378                 * According to RFC 2047, we could encode the special character
 379                 * ' ' (space) with '_' (underscore) for readability. But many
 380                 * programs do not understand this and just leave the
 381                 * underscore in place. Thus, we do nothing special here, which
 382                 * causes ' ' to be encoded as '=20', avoiding this problem.
 383                 */
 384
 385                if (line_len + encoded_len + 2 > max_encoded_length) {
 386                        /* It won't fit with trailing "?=" --- break the line */
 387                        strbuf_addf(sb, "?=\n =?%s?q?", encoding);
 388                        line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
 389                }
 390
 391                for (i = 0; i < chrlen; i++)
 392                        strbuf_addf(sb, encoded_fmt, p[i]);
 393                line_len += encoded_len;
 394        }
 395        strbuf_addstr(sb, "?=");
 396}
 397
 398static const char *show_ident_date(const struct ident_split *ident,
 399                                   enum date_mode mode)
 400{
 401        unsigned long date = 0;
 402        long tz = 0;
 403
 404        if (ident->date_begin && ident->date_end)
 405                date = strtoul(ident->date_begin, NULL, 10);
 406        if (date_overflows(date))
 407                date = 0;
 408        else {
 409                if (ident->tz_begin && ident->tz_end)
 410                        tz = strtol(ident->tz_begin, NULL, 10);
 411                if (tz >= INT_MAX || tz <= INT_MIN)
 412                        tz = 0;
 413        }
 414        return show_date(date, tz, mode);
 415}
 416
 417void pp_user_info(struct pretty_print_context *pp,
 418                  const char *what, struct strbuf *sb,
 419                  const char *line, const char *encoding)
 420{
 421        struct ident_split ident;
 422        char *line_end;
 423        const char *mailbuf, *namebuf;
 424        size_t namelen, maillen;
 425        int max_length = 78; /* per rfc2822 */
 426
 427        if (pp->fmt == CMIT_FMT_ONELINE)
 428                return;
 429
 430        line_end = strchrnul(line, '\n');
 431        if (split_ident_line(&ident, line, line_end - line))
 432                return;
 433
 434        mailbuf = ident.mail_begin;
 435        maillen = ident.mail_end - ident.mail_begin;
 436        namebuf = ident.name_begin;
 437        namelen = ident.name_end - ident.name_begin;
 438
 439        if (pp->mailmap)
 440                map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
 441
 442        if (pp->fmt == CMIT_FMT_EMAIL) {
 443                if (pp->from_ident && ident_cmp(pp->from_ident, &ident)) {
 444                        struct strbuf buf = STRBUF_INIT;
 445
 446                        strbuf_addstr(&buf, "From: ");
 447                        strbuf_add(&buf, namebuf, namelen);
 448                        strbuf_addstr(&buf, " <");
 449                        strbuf_add(&buf, mailbuf, maillen);
 450                        strbuf_addstr(&buf, ">\n");
 451                        string_list_append(&pp->in_body_headers,
 452                                           strbuf_detach(&buf, NULL));
 453
 454                        mailbuf = pp->from_ident->mail_begin;
 455                        maillen = pp->from_ident->mail_end - mailbuf;
 456                        namebuf = pp->from_ident->name_begin;
 457                        namelen = pp->from_ident->name_end - namebuf;
 458                }
 459
 460                strbuf_addstr(sb, "From: ");
 461                if (needs_rfc2047_encoding(namebuf, namelen, RFC2047_ADDRESS)) {
 462                        add_rfc2047(sb, namebuf, namelen,
 463                                    encoding, RFC2047_ADDRESS);
 464                        max_length = 76; /* per rfc2047 */
 465                } else if (needs_rfc822_quoting(namebuf, namelen)) {
 466                        struct strbuf quoted = STRBUF_INIT;
 467                        add_rfc822_quoted(&quoted, namebuf, namelen);
 468                        strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
 469                                                        -6, 1, max_length);
 470                        strbuf_release(&quoted);
 471                } else {
 472                        strbuf_add_wrapped_bytes(sb, namebuf, namelen,
 473                                                 -6, 1, max_length);
 474                }
 475
 476                if (max_length <
 477                    last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
 478                        strbuf_addch(sb, '\n');
 479                strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
 480        } else {
 481                strbuf_addf(sb, "%s: %.*s%.*s <%.*s>\n", what,
 482                            (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0, "    ",
 483                            (int)namelen, namebuf, (int)maillen, mailbuf);
 484        }
 485
 486        switch (pp->fmt) {
 487        case CMIT_FMT_MEDIUM:
 488                strbuf_addf(sb, "Date:   %s\n",
 489                            show_ident_date(&ident, pp->date_mode));
 490                break;
 491        case CMIT_FMT_EMAIL:
 492                strbuf_addf(sb, "Date: %s\n",
 493                            show_ident_date(&ident, DATE_RFC2822));
 494                break;
 495        case CMIT_FMT_FULLER:
 496                strbuf_addf(sb, "%sDate: %s\n", what,
 497                            show_ident_date(&ident, pp->date_mode));
 498                break;
 499        default:
 500                /* notin' */
 501                break;
 502        }
 503}
 504
 505static int is_empty_line(const char *line, int *len_p)
 506{
 507        int len = *len_p;
 508        while (len && isspace(line[len - 1]))
 509                len--;
 510        *len_p = len;
 511        return !len;
 512}
 513
 514static const char *skip_empty_lines(const char *msg)
 515{
 516        for (;;) {
 517                int linelen = get_one_line(msg);
 518                int ll = linelen;
 519                if (!linelen)
 520                        break;
 521                if (!is_empty_line(msg, &ll))
 522                        break;
 523                msg += linelen;
 524        }
 525        return msg;
 526}
 527
 528static void add_merge_info(const struct pretty_print_context *pp,
 529                           struct strbuf *sb, const struct commit *commit)
 530{
 531        struct commit_list *parent = commit->parents;
 532
 533        if ((pp->fmt == CMIT_FMT_ONELINE) || (pp->fmt == CMIT_FMT_EMAIL) ||
 534            !parent || !parent->next)
 535                return;
 536
 537        strbuf_addstr(sb, "Merge:");
 538
 539        while (parent) {
 540                struct commit *p = parent->item;
 541                const char *hex = NULL;
 542                if (pp->abbrev)
 543                        hex = find_unique_abbrev(p->object.sha1, pp->abbrev);
 544                if (!hex)
 545                        hex = sha1_to_hex(p->object.sha1);
 546                parent = parent->next;
 547
 548                strbuf_addf(sb, " %s", hex);
 549        }
 550        strbuf_addch(sb, '\n');
 551}
 552
 553static char *get_header(const struct commit *commit, const char *msg,
 554                        const char *key)
 555{
 556        int key_len = strlen(key);
 557        const char *line = msg;
 558
 559        while (line) {
 560                const char *eol = strchr(line, '\n'), *next;
 561
 562                if (line == eol)
 563                        return NULL;
 564                if (!eol) {
 565                        warning("malformed commit (header is missing newline): %s",
 566                                sha1_to_hex(commit->object.sha1));
 567                        eol = line + strlen(line);
 568                        next = NULL;
 569                } else
 570                        next = eol + 1;
 571                if (eol - line > key_len &&
 572                    !strncmp(line, key, key_len) &&
 573                    line[key_len] == ' ') {
 574                        return xmemdupz(line + key_len + 1, eol - line - key_len - 1);
 575                }
 576                line = next;
 577        }
 578        return NULL;
 579}
 580
 581static char *replace_encoding_header(char *buf, const char *encoding)
 582{
 583        struct strbuf tmp = STRBUF_INIT;
 584        size_t start, len;
 585        char *cp = buf;
 586
 587        /* guess if there is an encoding header before a \n\n */
 588        while (strncmp(cp, "encoding ", strlen("encoding "))) {
 589                cp = strchr(cp, '\n');
 590                if (!cp || *++cp == '\n')
 591                        return buf;
 592        }
 593        start = cp - buf;
 594        cp = strchr(cp, '\n');
 595        if (!cp)
 596                return buf; /* should not happen but be defensive */
 597        len = cp + 1 - (buf + start);
 598
 599        strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
 600        if (is_encoding_utf8(encoding)) {
 601                /* we have re-coded to UTF-8; drop the header */
 602                strbuf_remove(&tmp, start, len);
 603        } else {
 604                /* just replaces XXXX in 'encoding XXXX\n' */
 605                strbuf_splice(&tmp, start + strlen("encoding "),
 606                                          len - strlen("encoding \n"),
 607                                          encoding, strlen(encoding));
 608        }
 609        return strbuf_detach(&tmp, NULL);
 610}
 611
 612char *logmsg_reencode(const struct commit *commit,
 613                      char **commit_encoding,
 614                      const char *output_encoding)
 615{
 616        static const char *utf8 = "UTF-8";
 617        const char *use_encoding;
 618        char *encoding;
 619        char *msg = commit->buffer;
 620        char *out;
 621
 622        if (!msg) {
 623                enum object_type type;
 624                unsigned long size;
 625
 626                msg = read_sha1_file(commit->object.sha1, &type, &size);
 627                if (!msg)
 628                        die("Cannot read commit object %s",
 629                            sha1_to_hex(commit->object.sha1));
 630                if (type != OBJ_COMMIT)
 631                        die("Expected commit for '%s', got %s",
 632                            sha1_to_hex(commit->object.sha1), typename(type));
 633        }
 634
 635        if (!output_encoding || !*output_encoding) {
 636                if (commit_encoding)
 637                        *commit_encoding =
 638                                get_header(commit, msg, "encoding");
 639                return msg;
 640        }
 641        encoding = get_header(commit, msg, "encoding");
 642        if (commit_encoding)
 643                *commit_encoding = encoding;
 644        use_encoding = encoding ? encoding : utf8;
 645        if (same_encoding(use_encoding, output_encoding)) {
 646                /*
 647                 * No encoding work to be done. If we have no encoding header
 648                 * at all, then there's nothing to do, and we can return the
 649                 * message verbatim (whether newly allocated or not).
 650                 */
 651                if (!encoding)
 652                        return msg;
 653
 654                /*
 655                 * Otherwise, we still want to munge the encoding header in the
 656                 * result, which will be done by modifying the buffer. If we
 657                 * are using a fresh copy, we can reuse it. But if we are using
 658                 * the cached copy from commit->buffer, we need to duplicate it
 659                 * to avoid munging commit->buffer.
 660                 */
 661                out = msg;
 662                if (out == commit->buffer)
 663                        out = xstrdup(out);
 664        }
 665        else {
 666                /*
 667                 * There's actual encoding work to do. Do the reencoding, which
 668                 * still leaves the header to be replaced in the next step. At
 669                 * this point, we are done with msg. If we allocated a fresh
 670                 * copy, we can free it.
 671                 */
 672                out = reencode_string(msg, output_encoding, use_encoding);
 673                if (out && msg != commit->buffer)
 674                        free(msg);
 675        }
 676
 677        /*
 678         * This replacement actually consumes the buffer we hand it, so we do
 679         * not have to worry about freeing the old "out" here.
 680         */
 681        if (out)
 682                out = replace_encoding_header(out, output_encoding);
 683
 684        if (!commit_encoding)
 685                free(encoding);
 686        /*
 687         * If the re-encoding failed, out might be NULL here; in that
 688         * case we just return the commit message verbatim.
 689         */
 690        return out ? out : msg;
 691}
 692
 693void logmsg_free(char *msg, const struct commit *commit)
 694{
 695        if (msg != commit->buffer)
 696                free(msg);
 697}
 698
 699static int mailmap_name(const char **email, size_t *email_len,
 700                        const char **name, size_t *name_len)
 701{
 702        static struct string_list *mail_map;
 703        if (!mail_map) {
 704                mail_map = xcalloc(1, sizeof(*mail_map));
 705                read_mailmap(mail_map, NULL);
 706        }
 707        return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
 708}
 709
 710static size_t format_person_part(struct strbuf *sb, char part,
 711                                 const char *msg, int len, enum date_mode dmode)
 712{
 713        /* currently all placeholders have same length */
 714        const int placeholder_len = 2;
 715        struct ident_split s;
 716        const char *name, *mail;
 717        size_t maillen, namelen;
 718
 719        if (split_ident_line(&s, msg, len) < 0)
 720                goto skip;
 721
 722        name = s.name_begin;
 723        namelen = s.name_end - s.name_begin;
 724        mail = s.mail_begin;
 725        maillen = s.mail_end - s.mail_begin;
 726
 727        if (part == 'N' || part == 'E') /* mailmap lookup */
 728                mailmap_name(&mail, &maillen, &name, &namelen);
 729        if (part == 'n' || part == 'N') {       /* name */
 730                strbuf_add(sb, name, namelen);
 731                return placeholder_len;
 732        }
 733        if (part == 'e' || part == 'E') {       /* email */
 734                strbuf_add(sb, mail, maillen);
 735                return placeholder_len;
 736        }
 737
 738        if (!s.date_begin)
 739                goto skip;
 740
 741        if (part == 't') {      /* date, UNIX timestamp */
 742                strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
 743                return placeholder_len;
 744        }
 745
 746        switch (part) {
 747        case 'd':       /* date */
 748                strbuf_addstr(sb, show_ident_date(&s, dmode));
 749                return placeholder_len;
 750        case 'D':       /* date, RFC2822 style */
 751                strbuf_addstr(sb, show_ident_date(&s, DATE_RFC2822));
 752                return placeholder_len;
 753        case 'r':       /* date, relative */
 754                strbuf_addstr(sb, show_ident_date(&s, DATE_RELATIVE));
 755                return placeholder_len;
 756        case 'i':       /* date, ISO 8601 */
 757                strbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601));
 758                return placeholder_len;
 759        }
 760
 761skip:
 762        /*
 763         * reading from either a bogus commit, or a reflog entry with
 764         * %gn, %ge, etc.; 'sb' cannot be updated, but we still need
 765         * to compute a valid return value.
 766         */
 767        if (part == 'n' || part == 'e' || part == 't' || part == 'd'
 768            || part == 'D' || part == 'r' || part == 'i')
 769                return placeholder_len;
 770
 771        return 0; /* unknown placeholder */
 772}
 773
 774struct chunk {
 775        size_t off;
 776        size_t len;
 777};
 778
 779enum flush_type {
 780        no_flush,
 781        flush_right,
 782        flush_left,
 783        flush_left_and_steal,
 784        flush_both
 785};
 786
 787enum trunc_type {
 788        trunc_none,
 789        trunc_left,
 790        trunc_middle,
 791        trunc_right
 792};
 793
 794struct format_commit_context {
 795        const struct commit *commit;
 796        const struct pretty_print_context *pretty_ctx;
 797        unsigned commit_header_parsed:1;
 798        unsigned commit_message_parsed:1;
 799        struct signature_check signature_check;
 800        enum flush_type flush_type;
 801        enum trunc_type truncate;
 802        char *message;
 803        char *commit_encoding;
 804        size_t width, indent1, indent2;
 805        int auto_color;
 806        int padding;
 807
 808        /* These offsets are relative to the start of the commit message. */
 809        struct chunk author;
 810        struct chunk committer;
 811        size_t message_off;
 812        size_t subject_off;
 813        size_t body_off;
 814
 815        /* The following ones are relative to the result struct strbuf. */
 816        struct chunk abbrev_commit_hash;
 817        struct chunk abbrev_tree_hash;
 818        struct chunk abbrev_parent_hashes;
 819        size_t wrap_start;
 820};
 821
 822static int add_again(struct strbuf *sb, struct chunk *chunk)
 823{
 824        if (chunk->len) {
 825                strbuf_adddup(sb, chunk->off, chunk->len);
 826                return 1;
 827        }
 828
 829        /*
 830         * We haven't seen this chunk before.  Our caller is surely
 831         * going to add it the hard way now.  Remember the most likely
 832         * start of the to-be-added chunk: the current end of the
 833         * struct strbuf.
 834         */
 835        chunk->off = sb->len;
 836        return 0;
 837}
 838
 839static void parse_commit_header(struct format_commit_context *context)
 840{
 841        const char *msg = context->message;
 842        int i;
 843
 844        for (i = 0; msg[i]; i++) {
 845                int eol;
 846                for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
 847                        ; /* do nothing */
 848
 849                if (i == eol) {
 850                        break;
 851                } else if (starts_with(msg + i, "author ")) {
 852                        context->author.off = i + 7;
 853                        context->author.len = eol - i - 7;
 854                } else if (starts_with(msg + i, "committer ")) {
 855                        context->committer.off = i + 10;
 856                        context->committer.len = eol - i - 10;
 857                }
 858                i = eol;
 859        }
 860        context->message_off = i;
 861        context->commit_header_parsed = 1;
 862}
 863
 864static int istitlechar(char c)
 865{
 866        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
 867                (c >= '0' && c <= '9') || c == '.' || c == '_';
 868}
 869
 870static void format_sanitized_subject(struct strbuf *sb, const char *msg)
 871{
 872        size_t trimlen;
 873        size_t start_len = sb->len;
 874        int space = 2;
 875
 876        for (; *msg && *msg != '\n'; msg++) {
 877                if (istitlechar(*msg)) {
 878                        if (space == 1)
 879                                strbuf_addch(sb, '-');
 880                        space = 0;
 881                        strbuf_addch(sb, *msg);
 882                        if (*msg == '.')
 883                                while (*(msg+1) == '.')
 884                                        msg++;
 885                } else
 886                        space |= 1;
 887        }
 888
 889        /* trim any trailing '.' or '-' characters */
 890        trimlen = 0;
 891        while (sb->len - trimlen > start_len &&
 892                (sb->buf[sb->len - 1 - trimlen] == '.'
 893                || sb->buf[sb->len - 1 - trimlen] == '-'))
 894                trimlen++;
 895        strbuf_remove(sb, sb->len - trimlen, trimlen);
 896}
 897
 898const char *format_subject(struct strbuf *sb, const char *msg,
 899                           const char *line_separator)
 900{
 901        int first = 1;
 902
 903        for (;;) {
 904                const char *line = msg;
 905                int linelen = get_one_line(line);
 906
 907                msg += linelen;
 908                if (!linelen || is_empty_line(line, &linelen))
 909                        break;
 910
 911                if (!sb)
 912                        continue;
 913                strbuf_grow(sb, linelen + 2);
 914                if (!first)
 915                        strbuf_addstr(sb, line_separator);
 916                strbuf_add(sb, line, linelen);
 917                first = 0;
 918        }
 919        return msg;
 920}
 921
 922static void parse_commit_message(struct format_commit_context *c)
 923{
 924        const char *msg = c->message + c->message_off;
 925        const char *start = c->message;
 926
 927        msg = skip_empty_lines(msg);
 928        c->subject_off = msg - start;
 929
 930        msg = format_subject(NULL, msg, NULL);
 931        msg = skip_empty_lines(msg);
 932        c->body_off = msg - start;
 933
 934        c->commit_message_parsed = 1;
 935}
 936
 937static void strbuf_wrap(struct strbuf *sb, size_t pos,
 938                        size_t width, size_t indent1, size_t indent2)
 939{
 940        struct strbuf tmp = STRBUF_INIT;
 941
 942        if (pos)
 943                strbuf_add(&tmp, sb->buf, pos);
 944        strbuf_add_wrapped_text(&tmp, sb->buf + pos,
 945                                (int) indent1, (int) indent2, (int) width);
 946        strbuf_swap(&tmp, sb);
 947        strbuf_release(&tmp);
 948}
 949
 950static void rewrap_message_tail(struct strbuf *sb,
 951                                struct format_commit_context *c,
 952                                size_t new_width, size_t new_indent1,
 953                                size_t new_indent2)
 954{
 955        if (c->width == new_width && c->indent1 == new_indent1 &&
 956            c->indent2 == new_indent2)
 957                return;
 958        if (c->wrap_start < sb->len)
 959                strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
 960        c->wrap_start = sb->len;
 961        c->width = new_width;
 962        c->indent1 = new_indent1;
 963        c->indent2 = new_indent2;
 964}
 965
 966static int format_reflog_person(struct strbuf *sb,
 967                                char part,
 968                                struct reflog_walk_info *log,
 969                                enum date_mode dmode)
 970{
 971        const char *ident;
 972
 973        if (!log)
 974                return 2;
 975
 976        ident = get_reflog_ident(log);
 977        if (!ident)
 978                return 2;
 979
 980        return format_person_part(sb, part, ident, strlen(ident), dmode);
 981}
 982
 983static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
 984                          const char *placeholder,
 985                          struct format_commit_context *c)
 986{
 987        if (placeholder[1] == '(') {
 988                const char *begin = placeholder + 2;
 989                const char *end = strchr(begin, ')');
 990                char color[COLOR_MAXLEN];
 991
 992                if (!end)
 993                        return 0;
 994                if (starts_with(begin, "auto,")) {
 995                        if (!want_color(c->pretty_ctx->color))
 996                                return end - placeholder + 1;
 997                        begin += 5;
 998                }
 999                color_parse_mem(begin,
1000                                end - begin,
1001                                "--pretty format", color);
1002                strbuf_addstr(sb, color);
1003                return end - placeholder + 1;
1004        }
1005        if (starts_with(placeholder + 1, "red")) {
1006                strbuf_addstr(sb, GIT_COLOR_RED);
1007                return 4;
1008        } else if (starts_with(placeholder + 1, "green")) {
1009                strbuf_addstr(sb, GIT_COLOR_GREEN);
1010                return 6;
1011        } else if (starts_with(placeholder + 1, "blue")) {
1012                strbuf_addstr(sb, GIT_COLOR_BLUE);
1013                return 5;
1014        } else if (starts_with(placeholder + 1, "reset")) {
1015                strbuf_addstr(sb, GIT_COLOR_RESET);
1016                return 6;
1017        } else
1018                return 0;
1019}
1020
1021static size_t parse_padding_placeholder(struct strbuf *sb,
1022                                        const char *placeholder,
1023                                        struct format_commit_context *c)
1024{
1025        const char *ch = placeholder;
1026        enum flush_type flush_type;
1027        int to_column = 0;
1028
1029        switch (*ch++) {
1030        case '<':
1031                flush_type = flush_right;
1032                break;
1033        case '>':
1034                if (*ch == '<') {
1035                        flush_type = flush_both;
1036                        ch++;
1037                } else if (*ch == '>') {
1038                        flush_type = flush_left_and_steal;
1039                        ch++;
1040                } else
1041                        flush_type = flush_left;
1042                break;
1043        default:
1044                return 0;
1045        }
1046
1047        /* the next value means "wide enough to that column" */
1048        if (*ch == '|') {
1049                to_column = 1;
1050                ch++;
1051        }
1052
1053        if (*ch == '(') {
1054                const char *start = ch + 1;
1055                const char *end = start + strcspn(start, ",)");
1056                char *next;
1057                int width;
1058                if (!end || end == start)
1059                        return 0;
1060                width = strtoul(start, &next, 10);
1061                if (next == start || width == 0)
1062                        return 0;
1063                c->padding = to_column ? -width : width;
1064                c->flush_type = flush_type;
1065
1066                if (*end == ',') {
1067                        start = end + 1;
1068                        end = strchr(start, ')');
1069                        if (!end || end == start)
1070                                return 0;
1071                        if (starts_with(start, "trunc)"))
1072                                c->truncate = trunc_right;
1073                        else if (starts_with(start, "ltrunc)"))
1074                                c->truncate = trunc_left;
1075                        else if (starts_with(start, "mtrunc)"))
1076                                c->truncate = trunc_middle;
1077                        else
1078                                return 0;
1079                } else
1080                        c->truncate = trunc_none;
1081
1082                return end - placeholder + 1;
1083        }
1084        return 0;
1085}
1086
1087static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
1088                                const char *placeholder,
1089                                void *context)
1090{
1091        struct format_commit_context *c = context;
1092        const struct commit *commit = c->commit;
1093        const char *msg = c->message;
1094        struct commit_list *p;
1095        int h1, h2;
1096
1097        /* these are independent of the commit */
1098        switch (placeholder[0]) {
1099        case 'C':
1100                if (starts_with(placeholder + 1, "(auto)")) {
1101                        c->auto_color = 1;
1102                        return 7; /* consumed 7 bytes, "C(auto)" */
1103                } else {
1104                        int ret = parse_color(sb, placeholder, c);
1105                        if (ret)
1106                                c->auto_color = 0;
1107                        /*
1108                         * Otherwise, we decided to treat %C<unknown>
1109                         * as a literal string, and the previous
1110                         * %C(auto) is still valid.
1111                         */
1112                        return ret;
1113                }
1114        case 'n':               /* newline */
1115                strbuf_addch(sb, '\n');
1116                return 1;
1117        case 'x':
1118                /* %x00 == NUL, %x0a == LF, etc. */
1119                if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) &&
1120                    h1 <= 16 &&
1121                    0 <= (h2 = hexval_table[0xff & placeholder[2]]) &&
1122                    h2 <= 16) {
1123                        strbuf_addch(sb, (h1<<4)|h2);
1124                        return 3;
1125                } else
1126                        return 0;
1127        case 'w':
1128                if (placeholder[1] == '(') {
1129                        unsigned long width = 0, indent1 = 0, indent2 = 0;
1130                        char *next;
1131                        const char *start = placeholder + 2;
1132                        const char *end = strchr(start, ')');
1133                        if (!end)
1134                                return 0;
1135                        if (end > start) {
1136                                width = strtoul(start, &next, 10);
1137                                if (*next == ',') {
1138                                        indent1 = strtoul(next + 1, &next, 10);
1139                                        if (*next == ',') {
1140                                                indent2 = strtoul(next + 1,
1141                                                                 &next, 10);
1142                                        }
1143                                }
1144                                if (*next != ')')
1145                                        return 0;
1146                        }
1147                        rewrap_message_tail(sb, c, width, indent1, indent2);
1148                        return end - placeholder + 1;
1149                } else
1150                        return 0;
1151
1152        case '<':
1153        case '>':
1154                return parse_padding_placeholder(sb, placeholder, c);
1155        }
1156
1157        /* these depend on the commit */
1158        if (!commit->object.parsed)
1159                parse_object(commit->object.sha1);
1160
1161        switch (placeholder[0]) {
1162        case 'H':               /* commit hash */
1163                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1164                strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
1165                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1166                return 1;
1167        case 'h':               /* abbreviated commit hash */
1168                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
1169                if (add_again(sb, &c->abbrev_commit_hash)) {
1170                        strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1171                        return 1;
1172                }
1173                strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
1174                                                     c->pretty_ctx->abbrev));
1175                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
1176                c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
1177                return 1;
1178        case 'T':               /* tree hash */
1179                strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1));
1180                return 1;
1181        case 't':               /* abbreviated tree hash */
1182                if (add_again(sb, &c->abbrev_tree_hash))
1183                        return 1;
1184                strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1,
1185                                                     c->pretty_ctx->abbrev));
1186                c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
1187                return 1;
1188        case 'P':               /* parent hashes */
1189                for (p = commit->parents; p; p = p->next) {
1190                        if (p != commit->parents)
1191                                strbuf_addch(sb, ' ');
1192                        strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1));
1193                }
1194                return 1;
1195        case 'p':               /* abbreviated parent hashes */
1196                if (add_again(sb, &c->abbrev_parent_hashes))
1197                        return 1;
1198                for (p = commit->parents; p; p = p->next) {
1199                        if (p != commit->parents)
1200                                strbuf_addch(sb, ' ');
1201                        strbuf_addstr(sb, find_unique_abbrev(
1202                                        p->item->object.sha1,
1203                                        c->pretty_ctx->abbrev));
1204                }
1205                c->abbrev_parent_hashes.len = sb->len -
1206                                              c->abbrev_parent_hashes.off;
1207                return 1;
1208        case 'm':               /* left/right/bottom */
1209                strbuf_addstr(sb, get_revision_mark(NULL, commit));
1210                return 1;
1211        case 'd':
1212                load_ref_decorations(DECORATE_SHORT_REFS);
1213                format_decorations(sb, commit, c->auto_color);
1214                return 1;
1215        case 'g':               /* reflog info */
1216                switch(placeholder[1]) {
1217                case 'd':       /* reflog selector */
1218                case 'D':
1219                        if (c->pretty_ctx->reflog_info)
1220                                get_reflog_selector(sb,
1221                                                    c->pretty_ctx->reflog_info,
1222                                                    c->pretty_ctx->date_mode,
1223                                                    c->pretty_ctx->date_mode_explicit,
1224                                                    (placeholder[1] == 'd'));
1225                        return 2;
1226                case 's':       /* reflog message */
1227                        if (c->pretty_ctx->reflog_info)
1228                                get_reflog_message(sb, c->pretty_ctx->reflog_info);
1229                        return 2;
1230                case 'n':
1231                case 'N':
1232                case 'e':
1233                case 'E':
1234                        return format_reflog_person(sb,
1235                                                    placeholder[1],
1236                                                    c->pretty_ctx->reflog_info,
1237                                                    c->pretty_ctx->date_mode);
1238                }
1239                return 0;       /* unknown %g placeholder */
1240        case 'N':
1241                if (c->pretty_ctx->notes_message) {
1242                        strbuf_addstr(sb, c->pretty_ctx->notes_message);
1243                        return 1;
1244                }
1245                return 0;
1246        }
1247
1248        if (placeholder[0] == 'G') {
1249                if (!c->signature_check.result)
1250                        check_commit_signature(c->commit, &(c->signature_check));
1251                switch (placeholder[1]) {
1252                case 'G':
1253                        if (c->signature_check.gpg_output)
1254                                strbuf_addstr(sb, c->signature_check.gpg_output);
1255                        break;
1256                case '?':
1257                        switch (c->signature_check.result) {
1258                        case 'G':
1259                        case 'B':
1260                        case 'U':
1261                        case 'N':
1262                                strbuf_addch(sb, c->signature_check.result);
1263                        }
1264                        break;
1265                case 'S':
1266                        if (c->signature_check.signer)
1267                                strbuf_addstr(sb, c->signature_check.signer);
1268                        break;
1269                case 'K':
1270                        if (c->signature_check.key)
1271                                strbuf_addstr(sb, c->signature_check.key);
1272                        break;
1273                }
1274                return 2;
1275        }
1276
1277
1278        /* For the rest we have to parse the commit header. */
1279        if (!c->commit_header_parsed)
1280                parse_commit_header(c);
1281
1282        switch (placeholder[0]) {
1283        case 'a':       /* author ... */
1284                return format_person_part(sb, placeholder[1],
1285                                   msg + c->author.off, c->author.len,
1286                                   c->pretty_ctx->date_mode);
1287        case 'c':       /* committer ... */
1288                return format_person_part(sb, placeholder[1],
1289                                   msg + c->committer.off, c->committer.len,
1290                                   c->pretty_ctx->date_mode);
1291        case 'e':       /* encoding */
1292                if (c->commit_encoding)
1293                        strbuf_addstr(sb, c->commit_encoding);
1294                return 1;
1295        case 'B':       /* raw body */
1296                /* message_off is always left at the initial newline */
1297                strbuf_addstr(sb, msg + c->message_off + 1);
1298                return 1;
1299        }
1300
1301        /* Now we need to parse the commit message. */
1302        if (!c->commit_message_parsed)
1303                parse_commit_message(c);
1304
1305        switch (placeholder[0]) {
1306        case 's':       /* subject */
1307                format_subject(sb, msg + c->subject_off, " ");
1308                return 1;
1309        case 'f':       /* sanitized subject */
1310                format_sanitized_subject(sb, msg + c->subject_off);
1311                return 1;
1312        case 'b':       /* body */
1313                strbuf_addstr(sb, msg + c->body_off);
1314                return 1;
1315        }
1316        return 0;       /* unknown placeholder */
1317}
1318
1319static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
1320                                    const char *placeholder,
1321                                    struct format_commit_context *c)
1322{
1323        struct strbuf local_sb = STRBUF_INIT;
1324        int total_consumed = 0, len, padding = c->padding;
1325        if (padding < 0) {
1326                const char *start = strrchr(sb->buf, '\n');
1327                int occupied;
1328                if (!start)
1329                        start = sb->buf;
1330                occupied = utf8_strnwidth(start, -1, 1);
1331                padding = (-padding) - occupied;
1332        }
1333        while (1) {
1334                int modifier = *placeholder == 'C';
1335                int consumed = format_commit_one(&local_sb, placeholder, c);
1336                total_consumed += consumed;
1337
1338                if (!modifier)
1339                        break;
1340
1341                placeholder += consumed;
1342                if (*placeholder != '%')
1343                        break;
1344                placeholder++;
1345                total_consumed++;
1346        }
1347        len = utf8_strnwidth(local_sb.buf, -1, 1);
1348
1349        if (c->flush_type == flush_left_and_steal) {
1350                const char *ch = sb->buf + sb->len - 1;
1351                while (len > padding && ch > sb->buf) {
1352                        const char *p;
1353                        if (*ch == ' ') {
1354                                ch--;
1355                                padding++;
1356                                continue;
1357                        }
1358                        /* check for trailing ansi sequences */
1359                        if (*ch != 'm')
1360                                break;
1361                        p = ch - 1;
1362                        while (ch - p < 10 && *p != '\033')
1363                                p--;
1364                        if (*p != '\033' ||
1365                            ch + 1 - p != display_mode_esc_sequence_len(p))
1366                                break;
1367                        /*
1368                         * got a good ansi sequence, put it back to
1369                         * local_sb as we're cutting sb
1370                         */
1371                        strbuf_insert(&local_sb, 0, p, ch + 1 - p);
1372                        ch = p - 1;
1373                }
1374                strbuf_setlen(sb, ch + 1 - sb->buf);
1375                c->flush_type = flush_left;
1376        }
1377
1378        if (len > padding) {
1379                switch (c->truncate) {
1380                case trunc_left:
1381                        strbuf_utf8_replace(&local_sb,
1382                                            0, len - (padding - 2),
1383                                            "..");
1384                        break;
1385                case trunc_middle:
1386                        strbuf_utf8_replace(&local_sb,
1387                                            padding / 2 - 1,
1388                                            len - (padding - 2),
1389                                            "..");
1390                        break;
1391                case trunc_right:
1392                        strbuf_utf8_replace(&local_sb,
1393                                            padding - 2, len - (padding - 2),
1394                                            "..");
1395                        break;
1396                case trunc_none:
1397                        break;
1398                }
1399                strbuf_addstr(sb, local_sb.buf);
1400        } else {
1401                int sb_len = sb->len, offset = 0;
1402                if (c->flush_type == flush_left)
1403                        offset = padding - len;
1404                else if (c->flush_type == flush_both)
1405                        offset = (padding - len) / 2;
1406                /*
1407                 * we calculate padding in columns, now
1408                 * convert it back to chars
1409                 */
1410                padding = padding - len + local_sb.len;
1411                strbuf_grow(sb, padding);
1412                strbuf_setlen(sb, sb_len + padding);
1413                memset(sb->buf + sb_len, ' ', sb->len - sb_len);
1414                memcpy(sb->buf + sb_len + offset, local_sb.buf,
1415                       local_sb.len);
1416        }
1417        strbuf_release(&local_sb);
1418        c->flush_type = no_flush;
1419        return total_consumed;
1420}
1421
1422static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
1423                                 const char *placeholder,
1424                                 void *context)
1425{
1426        int consumed;
1427        size_t orig_len;
1428        enum {
1429                NO_MAGIC,
1430                ADD_LF_BEFORE_NON_EMPTY,
1431                DEL_LF_BEFORE_EMPTY,
1432                ADD_SP_BEFORE_NON_EMPTY
1433        } magic = NO_MAGIC;
1434
1435        switch (placeholder[0]) {
1436        case '-':
1437                magic = DEL_LF_BEFORE_EMPTY;
1438                break;
1439        case '+':
1440                magic = ADD_LF_BEFORE_NON_EMPTY;
1441                break;
1442        case ' ':
1443                magic = ADD_SP_BEFORE_NON_EMPTY;
1444                break;
1445        default:
1446                break;
1447        }
1448        if (magic != NO_MAGIC)
1449                placeholder++;
1450
1451        orig_len = sb->len;
1452        if (((struct format_commit_context *)context)->flush_type != no_flush)
1453                consumed = format_and_pad_commit(sb, placeholder, context);
1454        else
1455                consumed = format_commit_one(sb, placeholder, context);
1456        if (magic == NO_MAGIC)
1457                return consumed;
1458
1459        if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
1460                while (sb->len && sb->buf[sb->len - 1] == '\n')
1461                        strbuf_setlen(sb, sb->len - 1);
1462        } else if (orig_len != sb->len) {
1463                if (magic == ADD_LF_BEFORE_NON_EMPTY)
1464                        strbuf_insert(sb, orig_len, "\n", 1);
1465                else if (magic == ADD_SP_BEFORE_NON_EMPTY)
1466                        strbuf_insert(sb, orig_len, " ", 1);
1467        }
1468        return consumed + 1;
1469}
1470
1471static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
1472                                   void *context)
1473{
1474        struct userformat_want *w = context;
1475
1476        if (*placeholder == '+' || *placeholder == '-' || *placeholder == ' ')
1477                placeholder++;
1478
1479        switch (*placeholder) {
1480        case 'N':
1481                w->notes = 1;
1482                break;
1483        }
1484        return 0;
1485}
1486
1487void userformat_find_requirements(const char *fmt, struct userformat_want *w)
1488{
1489        struct strbuf dummy = STRBUF_INIT;
1490
1491        if (!fmt) {
1492                if (!user_format)
1493                        return;
1494                fmt = user_format;
1495        }
1496        strbuf_expand(&dummy, fmt, userformat_want_item, w);
1497        strbuf_release(&dummy);
1498}
1499
1500void format_commit_message(const struct commit *commit,
1501                           const char *format, struct strbuf *sb,
1502                           const struct pretty_print_context *pretty_ctx)
1503{
1504        struct format_commit_context context;
1505        const char *output_enc = pretty_ctx->output_encoding;
1506        const char *utf8 = "UTF-8";
1507
1508        memset(&context, 0, sizeof(context));
1509        context.commit = commit;
1510        context.pretty_ctx = pretty_ctx;
1511        context.wrap_start = sb->len;
1512        context.message = logmsg_reencode(commit,
1513                                          &context.commit_encoding,
1514                                          output_enc);
1515
1516        strbuf_expand(sb, format, format_commit_item, &context);
1517        rewrap_message_tail(sb, &context, 0, 0, 0);
1518
1519        if (output_enc) {
1520                if (same_encoding(utf8, output_enc))
1521                        output_enc = NULL;
1522        } else {
1523                if (context.commit_encoding &&
1524                    !same_encoding(context.commit_encoding, utf8))
1525                        output_enc = context.commit_encoding;
1526        }
1527
1528        if (output_enc) {
1529                int outsz;
1530                char *out = reencode_string_len(sb->buf, sb->len,
1531                                                output_enc, utf8, &outsz);
1532                if (out)
1533                        strbuf_attach(sb, out, outsz, outsz + 1);
1534        }
1535
1536        free(context.commit_encoding);
1537        logmsg_free(context.message, commit);
1538        free(context.signature_check.gpg_output);
1539        free(context.signature_check.signer);
1540}
1541
1542static void pp_header(struct pretty_print_context *pp,
1543                      const char *encoding,
1544                      const struct commit *commit,
1545                      const char **msg_p,
1546                      struct strbuf *sb)
1547{
1548        int parents_shown = 0;
1549
1550        for (;;) {
1551                const char *line = *msg_p;
1552                int linelen = get_one_line(*msg_p);
1553
1554                if (!linelen)
1555                        return;
1556                *msg_p += linelen;
1557
1558                if (linelen == 1)
1559                        /* End of header */
1560                        return;
1561
1562                if (pp->fmt == CMIT_FMT_RAW) {
1563                        strbuf_add(sb, line, linelen);
1564                        continue;
1565                }
1566
1567                if (starts_with(line, "parent ")) {
1568                        if (linelen != 48)
1569                                die("bad parent line in commit");
1570                        continue;
1571                }
1572
1573                if (!parents_shown) {
1574                        struct commit_list *parent;
1575                        int num;
1576                        for (parent = commit->parents, num = 0;
1577                             parent;
1578                             parent = parent->next, num++)
1579                                ;
1580                        /* with enough slop */
1581                        strbuf_grow(sb, num * 50 + 20);
1582                        add_merge_info(pp, sb, commit);
1583                        parents_shown = 1;
1584                }
1585
1586                /*
1587                 * MEDIUM == DEFAULT shows only author with dates.
1588                 * FULL shows both authors but not dates.
1589                 * FULLER shows both authors and dates.
1590                 */
1591                if (starts_with(line, "author ")) {
1592                        strbuf_grow(sb, linelen + 80);
1593                        pp_user_info(pp, "Author", sb, line + 7, encoding);
1594                }
1595                if (starts_with(line, "committer ") &&
1596                    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
1597                        strbuf_grow(sb, linelen + 80);
1598                        pp_user_info(pp, "Commit", sb, line + 10, encoding);
1599                }
1600        }
1601}
1602
1603void pp_title_line(struct pretty_print_context *pp,
1604                   const char **msg_p,
1605                   struct strbuf *sb,
1606                   const char *encoding,
1607                   int need_8bit_cte)
1608{
1609        static const int max_length = 78; /* per rfc2047 */
1610        struct strbuf title;
1611
1612        strbuf_init(&title, 80);
1613        *msg_p = format_subject(&title, *msg_p,
1614                                pp->preserve_subject ? "\n" : " ");
1615
1616        strbuf_grow(sb, title.len + 1024);
1617        if (pp->subject) {
1618                strbuf_addstr(sb, pp->subject);
1619                if (needs_rfc2047_encoding(title.buf, title.len, RFC2047_SUBJECT))
1620                        add_rfc2047(sb, title.buf, title.len,
1621                                                encoding, RFC2047_SUBJECT);
1622                else
1623                        strbuf_add_wrapped_bytes(sb, title.buf, title.len,
1624                                         -last_line_length(sb), 1, max_length);
1625        } else {
1626                strbuf_addbuf(sb, &title);
1627        }
1628        strbuf_addch(sb, '\n');
1629
1630        if (need_8bit_cte == 0) {
1631                int i;
1632                for (i = 0; i < pp->in_body_headers.nr; i++) {
1633                        if (has_non_ascii(pp->in_body_headers.items[i].string)) {
1634                                need_8bit_cte = 1;
1635                                break;
1636                        }
1637                }
1638        }
1639
1640        if (need_8bit_cte > 0) {
1641                const char *header_fmt =
1642                        "MIME-Version: 1.0\n"
1643                        "Content-Type: text/plain; charset=%s\n"
1644                        "Content-Transfer-Encoding: 8bit\n";
1645                strbuf_addf(sb, header_fmt, encoding);
1646        }
1647        if (pp->after_subject) {
1648                strbuf_addstr(sb, pp->after_subject);
1649        }
1650        if (pp->fmt == CMIT_FMT_EMAIL) {
1651                strbuf_addch(sb, '\n');
1652        }
1653
1654        if (pp->in_body_headers.nr) {
1655                int i;
1656                for (i = 0; i < pp->in_body_headers.nr; i++) {
1657                        strbuf_addstr(sb, pp->in_body_headers.items[i].string);
1658                        free(pp->in_body_headers.items[i].string);
1659                }
1660                string_list_clear(&pp->in_body_headers, 0);
1661                strbuf_addch(sb, '\n');
1662        }
1663
1664        strbuf_release(&title);
1665}
1666
1667void pp_remainder(struct pretty_print_context *pp,
1668                  const char **msg_p,
1669                  struct strbuf *sb,
1670                  int indent)
1671{
1672        int first = 1;
1673        for (;;) {
1674                const char *line = *msg_p;
1675                int linelen = get_one_line(line);
1676                *msg_p += linelen;
1677
1678                if (!linelen)
1679                        break;
1680
1681                if (is_empty_line(line, &linelen)) {
1682                        if (first)
1683                                continue;
1684                        if (pp->fmt == CMIT_FMT_SHORT)
1685                                break;
1686                }
1687                first = 0;
1688
1689                strbuf_grow(sb, linelen + indent + 20);
1690                if (indent) {
1691                        memset(sb->buf + sb->len, ' ', indent);
1692                        strbuf_setlen(sb, sb->len + indent);
1693                }
1694                strbuf_add(sb, line, linelen);
1695                strbuf_addch(sb, '\n');
1696        }
1697}
1698
1699void pretty_print_commit(struct pretty_print_context *pp,
1700                         const struct commit *commit,
1701                         struct strbuf *sb)
1702{
1703        unsigned long beginning_of_body;
1704        int indent = 4;
1705        const char *msg;
1706        char *reencoded;
1707        const char *encoding;
1708        int need_8bit_cte = pp->need_8bit_cte;
1709
1710        if (pp->fmt == CMIT_FMT_USERFORMAT) {
1711                format_commit_message(commit, user_format, sb, pp);
1712                return;
1713        }
1714
1715        encoding = get_log_output_encoding();
1716        msg = reencoded = logmsg_reencode(commit, NULL, encoding);
1717
1718        if (pp->fmt == CMIT_FMT_ONELINE || pp->fmt == CMIT_FMT_EMAIL)
1719                indent = 0;
1720
1721        /*
1722         * We need to check and emit Content-type: to mark it
1723         * as 8-bit if we haven't done so.
1724         */
1725        if (pp->fmt == CMIT_FMT_EMAIL && need_8bit_cte == 0) {
1726                int i, ch, in_body;
1727
1728                for (in_body = i = 0; (ch = msg[i]); i++) {
1729                        if (!in_body) {
1730                                /* author could be non 7-bit ASCII but
1731                                 * the log may be so; skip over the
1732                                 * header part first.
1733                                 */
1734                                if (ch == '\n' && msg[i+1] == '\n')
1735                                        in_body = 1;
1736                        }
1737                        else if (non_ascii(ch)) {
1738                                need_8bit_cte = 1;
1739                                break;
1740                        }
1741                }
1742        }
1743
1744        pp_header(pp, encoding, commit, &msg, sb);
1745        if (pp->fmt != CMIT_FMT_ONELINE && !pp->subject) {
1746                strbuf_addch(sb, '\n');
1747        }
1748
1749        /* Skip excess blank lines at the beginning of body, if any... */
1750        msg = skip_empty_lines(msg);
1751
1752        /* These formats treat the title line specially. */
1753        if (pp->fmt == CMIT_FMT_ONELINE || pp->fmt == CMIT_FMT_EMAIL)
1754                pp_title_line(pp, &msg, sb, encoding, need_8bit_cte);
1755
1756        beginning_of_body = sb->len;
1757        if (pp->fmt != CMIT_FMT_ONELINE)
1758                pp_remainder(pp, &msg, sb, indent);
1759        strbuf_rtrim(sb);
1760
1761        /* Make sure there is an EOLN for the non-oneline case */
1762        if (pp->fmt != CMIT_FMT_ONELINE)
1763                strbuf_addch(sb, '\n');
1764
1765        /*
1766         * The caller may append additional body text in e-mail
1767         * format.  Make sure we did not strip the blank line
1768         * between the header and the body.
1769         */
1770        if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
1771                strbuf_addch(sb, '\n');
1772
1773        logmsg_free(reencoded, commit);
1774}
1775
1776void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
1777                    struct strbuf *sb)
1778{
1779        struct pretty_print_context pp = {0};
1780        pp.fmt = fmt;
1781        pretty_print_commit(&pp, commit, sb);
1782}