t5537: move http tests out to t5539
[gitweb.git] / pretty.c
index d59579a2c0190a397fd0ceb5e051d241f731f5ed..87db08bd749e74fef0b2372ab71ea98baf57b322 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -40,7 +40,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c
        const char *fmt;
        int i;
 
-       if (prefixcmp(var, "pretty."))
+       if (!starts_with(var, "pretty."))
                return 0;
 
        name = var + strlen("pretty.");
@@ -67,7 +67,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c
        commit_format->name = xstrdup(name);
        commit_format->format = CMIT_FMT_USERFORMAT;
        git_config_string(&fmt, var, value);
-       if (!prefixcmp(fmt, "format:") || !prefixcmp(fmt, "tformat:")) {
+       if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
                commit_format->is_tformat = fmt[0] == 't';
                fmt = strchr(fmt, ':') + 1;
        } else if (strchr(fmt, '%'))
@@ -115,7 +115,7 @@ static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
        for (i = 0; i < commit_formats_len; i++) {
                size_t match_len;
 
-               if (prefixcmp(commit_formats[i].name, sought))
+               if (!starts_with(commit_formats[i].name, sought))
                        continue;
 
                match_len = strlen(commit_formats[i].name);
@@ -151,7 +151,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
                rev->commit_format = CMIT_FMT_DEFAULT;
                return;
        }
-       if (!prefixcmp(arg, "format:") || !prefixcmp(arg, "tformat:")) {
+       if (starts_with(arg, "format:") || starts_with(arg, "tformat:")) {
                save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't');
                return;
        }
@@ -393,36 +393,36 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
        strbuf_addstr(sb, "?=");
 }
 
-void pp_user_info(const struct pretty_print_context *pp,
+static const char *show_ident_date(const struct ident_split *ident,
+                                  enum date_mode mode)
+{
+       unsigned long date = 0;
+       int tz = 0;
+
+       if (ident->date_begin && ident->date_end)
+               date = strtoul(ident->date_begin, NULL, 10);
+       if (ident->tz_begin && ident->tz_end)
+               tz = strtol(ident->tz_begin, NULL, 10);
+       return show_date(date, tz, mode);
+}
+
+void pp_user_info(struct pretty_print_context *pp,
                  const char *what, struct strbuf *sb,
                  const char *line, const char *encoding)
 {
-       struct strbuf name;
-       struct strbuf mail;
        struct ident_split ident;
-       int linelen;
-       char *line_end, *date;
+       char *line_end;
        const char *mailbuf, *namebuf;
        size_t namelen, maillen;
        int max_length = 78; /* per rfc2822 */
-       unsigned long time;
-       int tz;
 
        if (pp->fmt == CMIT_FMT_ONELINE)
                return;
 
-       line_end = strchr(line, '\n');
-       if (!line_end) {
-               line_end = strchr(line, '\0');
-               if (!line_end)
-                       return;
-       }
-
-       linelen = ++line_end - line;
-       if (split_ident_line(&ident, line, linelen))
+       line_end = strchrnul(line, '\n');
+       if (split_ident_line(&ident, line, line_end - line))
                return;
 
-
        mailbuf = ident.mail_begin;
        maillen = ident.mail_end - ident.mail_begin;
        namebuf = ident.name_begin;
@@ -431,54 +431,62 @@ void pp_user_info(const struct pretty_print_context *pp,
        if (pp->mailmap)
                map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
 
-       strbuf_init(&mail, 0);
-       strbuf_init(&name, 0);
-
-       strbuf_add(&mail, mailbuf, maillen);
-       strbuf_add(&name, namebuf, namelen);
-
-       namelen = name.len + mail.len + 3; /* ' ' + '<' + '>' */
-       time = strtoul(ident.date_begin, &date, 10);
-       tz = strtol(date, NULL, 10);
-
        if (pp->fmt == CMIT_FMT_EMAIL) {
+               if (pp->from_ident && ident_cmp(pp->from_ident, &ident)) {
+                       struct strbuf buf = STRBUF_INIT;
+
+                       strbuf_addstr(&buf, "From: ");
+                       strbuf_add(&buf, namebuf, namelen);
+                       strbuf_addstr(&buf, " <");
+                       strbuf_add(&buf, mailbuf, maillen);
+                       strbuf_addstr(&buf, ">\n");
+                       string_list_append(&pp->in_body_headers,
+                                          strbuf_detach(&buf, NULL));
+
+                       mailbuf = pp->from_ident->mail_begin;
+                       maillen = pp->from_ident->mail_end - mailbuf;
+                       namebuf = pp->from_ident->name_begin;
+                       namelen = pp->from_ident->name_end - namebuf;
+               }
+
                strbuf_addstr(sb, "From: ");
-               if (needs_rfc2047_encoding(name.buf, name.len, RFC2047_ADDRESS)) {
-                       add_rfc2047(sb, name.buf, name.len,
+               if (needs_rfc2047_encoding(namebuf, namelen, RFC2047_ADDRESS)) {
+                       add_rfc2047(sb, namebuf, namelen,
                                    encoding, RFC2047_ADDRESS);
                        max_length = 76; /* per rfc2047 */
-               } else if (needs_rfc822_quoting(name.buf, name.len)) {
+               } else if (needs_rfc822_quoting(namebuf, namelen)) {
                        struct strbuf quoted = STRBUF_INIT;
-                       add_rfc822_quoted(&quoted, name.buf, name.len);
+                       add_rfc822_quoted(&quoted, namebuf, namelen);
                        strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
                                                        -6, 1, max_length);
                        strbuf_release(&quoted);
                } else {
-                       strbuf_add_wrapped_bytes(sb, name.buf, name.len,
+                       strbuf_add_wrapped_bytes(sb, namebuf, namelen,
                                                 -6, 1, max_length);
                }
-               if (namelen - name.len + last_line_length(sb) > max_length)
-                       strbuf_addch(sb, '\n');
 
-               strbuf_addf(sb, " <%s>\n", mail.buf);
+               if (max_length <
+                   last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
+                       strbuf_addch(sb, '\n');
+               strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
        } else {
-               strbuf_addf(sb, "%s: %.*s%s <%s>\n", what,
-                             (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0,
-                             "    ", name.buf, mail.buf);
+               strbuf_addf(sb, "%s: %.*s%.*s <%.*s>\n", what,
+                           (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0, "    ",
+                           (int)namelen, namebuf, (int)maillen, mailbuf);
        }
 
-       strbuf_release(&mail);
-       strbuf_release(&name);
-
        switch (pp->fmt) {
        case CMIT_FMT_MEDIUM:
-               strbuf_addf(sb, "Date:   %s\n", show_date(time, tz, pp->date_mode));
+               strbuf_addf(sb, "Date:   %s\n",
+                           show_ident_date(&ident, pp->date_mode));
                break;
        case CMIT_FMT_EMAIL:
-               strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822));
+               strbuf_addf(sb, "Date: %s\n",
+                           show_ident_date(&ident, DATE_RFC2822));
                break;
        case CMIT_FMT_FULLER:
-               strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, pp->date_mode));
+               strbuf_addf(sb, "%sDate: %s\n", what,
+                           show_ident_date(&ident, pp->date_mode));
                break;
        default:
                /* notin' */
@@ -489,7 +497,7 @@ void pp_user_info(const struct pretty_print_context *pp,
 static int is_empty_line(const char *line, int *len_p)
 {
        int len = *len_p;
-       while (len && isspace(line[len-1]))
+       while (len && isspace(line[len - 1]))
                len--;
        *len_p = len;
        return !len;
@@ -696,8 +704,6 @@ static size_t format_person_part(struct strbuf *sb, char part,
 {
        /* currently all placeholders have same length */
        const int placeholder_len = 2;
-       int tz;
-       unsigned long date = 0;
        struct ident_split s;
        const char *name, *mail;
        size_t maillen, namelen;
@@ -724,30 +730,23 @@ static size_t format_person_part(struct strbuf *sb, char part,
        if (!s.date_begin)
                goto skip;
 
-       date = strtoul(s.date_begin, NULL, 10);
-
        if (part == 't') {      /* date, UNIX timestamp */
                strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
                return placeholder_len;
        }
 
-       /* parse tz */
-       tz = strtoul(s.tz_begin + 1, NULL, 10);
-       if (*s.tz_begin == '-')
-               tz = -tz;
-
        switch (part) {
        case 'd':       /* date */
-               strbuf_addstr(sb, show_date(date, tz, dmode));
+               strbuf_addstr(sb, show_ident_date(&s, dmode));
                return placeholder_len;
        case 'D':       /* date, RFC2822 style */
-               strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_RFC2822));
                return placeholder_len;
        case 'r':       /* date, relative */
-               strbuf_addstr(sb, show_date(date, tz, DATE_RELATIVE));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_RELATIVE));
                return placeholder_len;
        case 'i':       /* date, ISO 8601 */
-               strbuf_addstr(sb, show_date(date, tz, DATE_ISO8601));
+               strbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601));
                return placeholder_len;
        }
 
@@ -841,10 +840,10 @@ static void parse_commit_header(struct format_commit_context *context)
 
                if (i == eol) {
                        break;
-               } else if (!prefixcmp(msg + i, "author ")) {
+               } else if (starts_with(msg + i, "author ")) {
                        context->author.off = i + 7;
                        context->author.len = eol - i - 7;
-               } else if (!prefixcmp(msg + i, "committer ")) {
+               } else if (starts_with(msg + i, "committer ")) {
                        context->committer.off = i + 10;
                        context->committer.len = eol - i - 10;
                }
@@ -984,7 +983,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
 
                if (!end)
                        return 0;
-               if (!prefixcmp(begin, "auto,")) {
+               if (starts_with(begin, "auto,")) {
                        if (!want_color(c->pretty_ctx->color))
                                return end - placeholder + 1;
                        begin += 5;
@@ -995,16 +994,16 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
                strbuf_addstr(sb, color);
                return end - placeholder + 1;
        }
-       if (!prefixcmp(placeholder + 1, "red")) {
+       if (starts_with(placeholder + 1, "red")) {
                strbuf_addstr(sb, GIT_COLOR_RED);
                return 4;
-       } else if (!prefixcmp(placeholder + 1, "green")) {
+       } else if (starts_with(placeholder + 1, "green")) {
                strbuf_addstr(sb, GIT_COLOR_GREEN);
                return 6;
-       } else if (!prefixcmp(placeholder + 1, "blue")) {
+       } else if (starts_with(placeholder + 1, "blue")) {
                strbuf_addstr(sb, GIT_COLOR_BLUE);
                return 5;
-       } else if (!prefixcmp(placeholder + 1, "reset")) {
+       } else if (starts_with(placeholder + 1, "reset")) {
                strbuf_addstr(sb, GIT_COLOR_RESET);
                return 6;
        } else
@@ -1061,11 +1060,11 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
                        end = strchr(start, ')');
                        if (!end || end == start)
                                return 0;
-                       if (!prefixcmp(start, "trunc)"))
+                       if (starts_with(start, "trunc)"))
                                c->truncate = trunc_right;
-                       else if (!prefixcmp(start, "ltrunc)"))
+                       else if (starts_with(start, "ltrunc)"))
                                c->truncate = trunc_left;
-                       else if (!prefixcmp(start, "mtrunc)"))
+                       else if (starts_with(start, "mtrunc)"))
                                c->truncate = trunc_middle;
                        else
                                return 0;
@@ -1090,7 +1089,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
        /* these are independent of the commit */
        switch (placeholder[0]) {
        case 'C':
-               if (!prefixcmp(placeholder + 1, "(auto)")) {
+               if (starts_with(placeholder + 1, "(auto)")) {
                        c->auto_color = 1;
                        return 7; /* consumed 7 bytes, "C(auto)" */
                } else {
@@ -1532,7 +1531,7 @@ void format_commit_message(const struct commit *commit,
        free(context.signature_check.signer);
 }
 
-static void pp_header(const struct pretty_print_context *pp,
+static void pp_header(struct pretty_print_context *pp,
                      const char *encoding,
                      const struct commit *commit,
                      const char **msg_p,
@@ -1557,7 +1556,7 @@ static void pp_header(const struct pretty_print_context *pp,
                        continue;
                }
 
-               if (!prefixcmp(line, "parent ")) {
+               if (starts_with(line, "parent ")) {
                        if (linelen != 48)
                                die("bad parent line in commit");
                        continue;
@@ -1581,11 +1580,11 @@ static void pp_header(const struct pretty_print_context *pp,
                 * FULL shows both authors but not dates.
                 * FULLER shows both authors and dates.
                 */
-               if (!prefixcmp(line, "author ")) {
+               if (starts_with(line, "author ")) {
                        strbuf_grow(sb, linelen + 80);
                        pp_user_info(pp, "Author", sb, line + 7, encoding);
                }
-               if (!prefixcmp(line, "committer ") &&
+               if (starts_with(line, "committer ") &&
                    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
                        strbuf_grow(sb, linelen + 80);
                        pp_user_info(pp, "Commit", sb, line + 10, encoding);
@@ -1593,7 +1592,7 @@ static void pp_header(const struct pretty_print_context *pp,
        }
 }
 
-void pp_title_line(const struct pretty_print_context *pp,
+void pp_title_line(struct pretty_print_context *pp,
                   const char **msg_p,
                   struct strbuf *sb,
                   const char *encoding,
@@ -1620,6 +1619,16 @@ void pp_title_line(const struct pretty_print_context *pp,
        }
        strbuf_addch(sb, '\n');
 
+       if (need_8bit_cte == 0) {
+               int i;
+               for (i = 0; i < pp->in_body_headers.nr; i++) {
+                       if (has_non_ascii(pp->in_body_headers.items[i].string)) {
+                               need_8bit_cte = 1;
+                               break;
+                       }
+               }
+       }
+
        if (need_8bit_cte > 0) {
                const char *header_fmt =
                        "MIME-Version: 1.0\n"
@@ -1633,10 +1642,21 @@ void pp_title_line(const struct pretty_print_context *pp,
        if (pp->fmt == CMIT_FMT_EMAIL) {
                strbuf_addch(sb, '\n');
        }
+
+       if (pp->in_body_headers.nr) {
+               int i;
+               for (i = 0; i < pp->in_body_headers.nr; i++) {
+                       strbuf_addstr(sb, pp->in_body_headers.items[i].string);
+                       free(pp->in_body_headers.items[i].string);
+               }
+               string_list_clear(&pp->in_body_headers, 0);
+               strbuf_addch(sb, '\n');
+       }
+
        strbuf_release(&title);
 }
 
-void pp_remainder(const struct pretty_print_context *pp,
+void pp_remainder(struct pretty_print_context *pp,
                  const char **msg_p,
                  struct strbuf *sb,
                  int indent)
@@ -1668,7 +1688,7 @@ void pp_remainder(const struct pretty_print_context *pp,
        }
 }
 
-void pretty_print_commit(const struct pretty_print_context *pp,
+void pretty_print_commit(struct pretty_print_context *pp,
                         const struct commit *commit,
                         struct strbuf *sb)
 {