filter-branch: use $SHELL_PATH instead of 'sh'
[gitweb.git] / log-tree.c
index a6423718e76be34e62bc76dcf3c93b32e38aa152..608f697cf3860245510bff907a643d9b6143e724 100644 (file)
@@ -15,7 +15,7 @@ static void show_parents(struct commit *commit, int abbrev)
        }
 }
 
-static void show_decorations(struct commit *commit)
+void show_decorations(struct commit *commit)
 {
        const char *prefix;
        struct name_decoration *decoration;
@@ -79,25 +79,14 @@ static int detect_any_signoff(char *letter, int size)
        return seen_head && seen_name;
 }
 
-static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,
-                                   unsigned long at, const char *signoff)
+static void append_signoff(struct strbuf *sb, const char *signoff)
 {
        static const char signed_off_by[] = "Signed-off-by: ";
        size_t signoff_len = strlen(signoff);
        int has_signoff = 0;
        char *cp;
-       char *buf;
-       unsigned long buf_sz;
-
-       buf = *buf_p;
-       buf_sz = *buf_sz_p;
-       if (buf_sz <= at + strlen(signed_off_by) + signoff_len + 3) {
-               buf_sz += strlen(signed_off_by) + signoff_len + 3;
-               buf = xrealloc(buf, buf_sz);
-               *buf_p = buf;
-               *buf_sz_p = buf_sz;
-       }
-       cp = buf;
+
+       cp = sb->buf;
 
        /* First see if we already have the sign-off by the signer */
        while ((cp = strstr(cp, signed_off_by))) {
@@ -105,29 +94,25 @@ static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,
                has_signoff = 1;
 
                cp += strlen(signed_off_by);
-               if (cp + signoff_len >= buf + at)
+               if (cp + signoff_len >= sb->buf + sb->len)
                        break;
                if (strncmp(cp, signoff, signoff_len))
                        continue;
                if (!isspace(cp[signoff_len]))
                        continue;
                /* we already have him */
-               return at;
+               return;
        }
 
        if (!has_signoff)
-               has_signoff = detect_any_signoff(buf, at);
+               has_signoff = detect_any_signoff(sb->buf, sb->len);
 
        if (!has_signoff)
-               buf[at++] = '\n';
-
-       strcpy(buf + at, signed_off_by);
-       at += strlen(signed_off_by);
-       strcpy(buf + at, signoff);
-       at += signoff_len;
-       buf[at++] = '\n';
-       buf[at] = 0;
-       return at;
+               strbuf_addch(sb, '\n');
+
+       strbuf_addstr(sb, signed_off_by);
+       strbuf_add(sb, signoff, signoff_len);
+       strbuf_addch(sb, '\n');
 }
 
 static unsigned int digits_in_number(unsigned int number)
@@ -140,24 +125,102 @@ static unsigned int digits_in_number(unsigned int number)
        return result;
 }
 
+static int has_non_ascii(const char *s)
+{
+       int ch;
+       if (!s)
+               return 0;
+       while ((ch = *s++) != '\0') {
+               if (non_ascii(ch))
+                       return 1;
+       }
+       return 0;
+}
+
+void log_write_email_headers(struct rev_info *opt, const char *name,
+                            const char **subject_p, const char **extra_headers_p)
+{
+       const char *subject = NULL;
+       const char *extra_headers = opt->extra_headers;
+       if (opt->total > 0) {
+               static char buffer[64];
+               snprintf(buffer, sizeof(buffer),
+                        "Subject: [%s %0*d/%d] ",
+                        opt->subject_prefix,
+                        digits_in_number(opt->total),
+                        opt->nr, opt->total);
+               subject = buffer;
+       } else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) {
+               static char buffer[256];
+               snprintf(buffer, sizeof(buffer),
+                        "Subject: [%s] ",
+                        opt->subject_prefix);
+               subject = buffer;
+       } else {
+               subject = "Subject: ";
+       }
+
+       printf("From %s Mon Sep 17 00:00:00 2001\n", name);
+       if (opt->message_id)
+               printf("Message-Id: <%s>\n", opt->message_id);
+       if (opt->ref_message_id)
+               printf("In-Reply-To: <%s>\nReferences: <%s>\n",
+                      opt->ref_message_id, opt->ref_message_id);
+       if (opt->mime_boundary) {
+               static char subject_buffer[1024];
+               static char buffer[1024];
+               snprintf(subject_buffer, sizeof(subject_buffer) - 1,
+                        "%s"
+                        "MIME-Version: 1.0\n"
+                        "Content-Type: multipart/mixed;"
+                        " boundary=\"%s%s\"\n"
+                        "\n"
+                        "This is a multi-part message in MIME "
+                        "format.\n"
+                        "--%s%s\n"
+                        "Content-Type: text/plain; "
+                        "charset=UTF-8; format=fixed\n"
+                        "Content-Transfer-Encoding: 8bit\n\n",
+                        extra_headers ? extra_headers : "",
+                        mime_boundary_leader, opt->mime_boundary,
+                        mime_boundary_leader, opt->mime_boundary);
+               extra_headers = subject_buffer;
+
+               snprintf(buffer, sizeof(buffer) - 1,
+                        "--%s%s\n"
+                        "Content-Type: text/x-patch;"
+                        " name=\"%s.diff\"\n"
+                        "Content-Transfer-Encoding: 8bit\n"
+                        "Content-Disposition: %s;"
+                        " filename=\"%s.diff\"\n\n",
+                        mime_boundary_leader, opt->mime_boundary,
+                        name,
+                        opt->no_inline ? "attachment" : "inline",
+                        name);
+               opt->diffopt.stat_sep = buffer;
+       }
+       *subject_p = subject;
+       *extra_headers_p = extra_headers;
+}
+
 void show_log(struct rev_info *opt, const char *sep)
 {
-       char *msgbuf = NULL;
-       unsigned long msgbuf_len = 0;
+       struct strbuf msgbuf;
        struct log_info *log = opt->loginfo;
        struct commit *commit = log->commit, *parent = log->parent;
        int abbrev = opt->diffopt.abbrev;
        int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
        const char *extra;
-       int len;
        const char *subject = NULL, *extra_headers = opt->extra_headers;
 
        opt->loginfo = NULL;
        if (!opt->verbose_header) {
-               if (opt->left_right) {
-                       if (commit->object.flags & BOUNDARY)
-                               putchar('-');
-                       else if (commit->object.flags & SYMMETRIC_LEFT)
+               if (commit->object.flags & BOUNDARY)
+                       putchar('-');
+               else if (commit->object.flags & UNINTERESTING)
+                       putchar('^');
+               else if (opt->left_right) {
+                       if (commit->object.flags & SYMMETRIC_LEFT)
                                putchar('<');
                        else
                                putchar('>');
@@ -191,71 +254,16 @@ void show_log(struct rev_info *opt, const char *sep)
         */
 
        if (opt->commit_format == CMIT_FMT_EMAIL) {
-               char *sha1 = sha1_to_hex(commit->object.sha1);
-               if (opt->total > 0) {
-                       static char buffer[64];
-                       snprintf(buffer, sizeof(buffer),
-                                       "Subject: [%s %0*d/%d] ",
-                                       opt->subject_prefix,
-                                       digits_in_number(opt->total),
-                                       opt->nr, opt->total);
-                       subject = buffer;
-               } else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) {
-                       static char buffer[256];
-                       snprintf(buffer, sizeof(buffer),
-                                       "Subject: [%s] ",
-                                       opt->subject_prefix);
-                       subject = buffer;
-               } else {
-                       subject = "Subject: ";
-               }
-
-               printf("From %s Mon Sep 17 00:00:00 2001\n", sha1);
-               if (opt->message_id)
-                       printf("Message-Id: <%s>\n", opt->message_id);
-               if (opt->ref_message_id)
-                       printf("In-Reply-To: <%s>\nReferences: <%s>\n",
-                              opt->ref_message_id, opt->ref_message_id);
-               if (opt->mime_boundary) {
-                       static char subject_buffer[1024];
-                       static char buffer[1024];
-                       snprintf(subject_buffer, sizeof(subject_buffer) - 1,
-                                "%s"
-                                "MIME-Version: 1.0\n"
-                                "Content-Type: multipart/mixed;"
-                                " boundary=\"%s%s\"\n"
-                                "\n"
-                                "This is a multi-part message in MIME "
-                                "format.\n"
-                                "--%s%s\n"
-                                "Content-Type: text/plain; "
-                                "charset=UTF-8; format=fixed\n"
-                                "Content-Transfer-Encoding: 8bit\n\n",
-                                extra_headers ? extra_headers : "",
-                                mime_boundary_leader, opt->mime_boundary,
-                                mime_boundary_leader, opt->mime_boundary);
-                       extra_headers = subject_buffer;
-
-                       snprintf(buffer, sizeof(buffer) - 1,
-                                "--%s%s\n"
-                                "Content-Type: text/x-patch;"
-                                " name=\"%s.diff\"\n"
-                                "Content-Transfer-Encoding: 8bit\n"
-                                "Content-Disposition: %s;"
-                                " filename=\"%s.diff\"\n\n",
-                                mime_boundary_leader, opt->mime_boundary,
-                                sha1,
-                                opt->no_inline ? "attachment" : "inline",
-                                sha1);
-                       opt->diffopt.stat_sep = buffer;
-               }
+               log_write_email_headers(opt, sha1_to_hex(commit->object.sha1),
+                                       &subject, &extra_headers);
        } else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
-               fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
-                     stdout);
+               fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout);
                if (opt->commit_format != CMIT_FMT_ONELINE)
                        fputs("commit ", stdout);
                if (commit->object.flags & BOUNDARY)
                        putchar('-');
+               else if (commit->object.flags & UNINTERESTING)
+                       putchar('^');
                else if (opt->left_right) {
                        if (commit->object.flags & SYMMETRIC_LEFT)
                                putchar('<');
@@ -271,8 +279,7 @@ void show_log(struct rev_info *opt, const char *sep)
                               diff_unique_abbrev(parent->object.sha1,
                                                  abbrev_commit));
                show_decorations(commit);
-               printf("%s",
-                      diff_get_color(opt->diffopt.color_diff, DIFF_RESET));
+               printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
                putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
                if (opt->reflog_info) {
                        show_reflog_message(opt->reflog_info,
@@ -285,21 +292,25 @@ void show_log(struct rev_info *opt, const char *sep)
                }
        }
 
+       if (!commit->buffer)
+               return;
+
        /*
         * And then the pretty-printed message itself
         */
-       len = pretty_print_commit(opt->commit_format, commit, ~0u,
-                                 &msgbuf, &msgbuf_len, abbrev, subject,
-                                 extra_headers, opt->date_mode);
+       strbuf_init(&msgbuf, 0);
+       pretty_print_commit(opt->commit_format, commit, &msgbuf,
+                           abbrev, subject, extra_headers, opt->date_mode,
+                           has_non_ascii(opt->add_signoff));
 
        if (opt->add_signoff)
-               len = append_signoff(&msgbuf, &msgbuf_len, len,
-                                    opt->add_signoff);
+               append_signoff(&msgbuf, opt->add_signoff);
        if (opt->show_log_size)
-               printf("log size %i\n", len);
+               printf("log size %i\n", (int)msgbuf.len);
 
-       printf("%s%s%s", msgbuf, extra, sep);
-       free(msgbuf);
+       if (msgbuf.len)
+               printf("%s%s%s", msgbuf.buf, extra, sep);
+       strbuf_release(&msgbuf);
 }
 
 int log_tree_diff_flush(struct rev_info *opt)
@@ -321,7 +332,8 @@ int log_tree_diff_flush(struct rev_info *opt)
                 * output for readability.
                 */
                show_log(opt, opt->diffopt.msg_sep);
-               if (opt->verbose_header &&
+               if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
+                   opt->verbose_header &&
                    opt->commit_format != CMIT_FMT_ONELINE) {
                        int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
                        if ((pch & opt->diffopt.output_format) == pch)