@matheusbsbs / matheus-bagliano / commits / 6bf4f1b4c9
Fork 0

format-patch: generate MIME header as needed even when there is format.header

Earlier, the callchain from pretty_print_commit() down to pp_title_line() had an unwarranted assumption that the presense of "after_subject" parameter, means the caller has already output MIME headers for attachments. The parameter's primary purpose is to give extra header lines the caller wants to place after pp_title_line() generates the "Subject: " line. This assumption does not hold when the user used the format.header configuration variable to pass extra headers, and caused a message with non-ASCII character to lack proper MIME headers (e.g. 8-bit CTE header). The earlier logic also failed to suppress duplicated MIME headers when "format-patch -s --attach" is asked for and the signer's name demanded 8-bit clean transport. This patch fixes the logic by introducing a separate need_8bit_cte parameter passed down the callchain. This can have one of these values: -1 : we've already done MIME crap and we do not want to add extra header to say this is 8bit in pp_title_line(); 0 : we haven't done MIME and we have not seen anything that is 8bit yet; 1 : we haven't done MIME and we have seen something that is 8bit; pp_title_line() must add MIME header. It adds two tests by Jeff King who independently diagnosed this issue. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Mar 14, 2008 at 17:10 UTC 6bf4f1b4c9d78b2061bd5f3bf77bb21112b755be
5 files changed +57 -16
commit.h
+1 -1
@@ -70,7 +70,7 @@ extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
70 struct strbuf *,
71 int abbrev, const char *subject,
72 const char *after_subject, enum date_mode,
73 - int non_ascii_present);
73 + int need_8bit_cte);
74
75 /** Removes the first commit from a list sorted by date, and adds all
76 * of its parents.
log-tree.c
+6 -1
@@ -146,6 +146,7 @@ void show_log(struct rev_info *opt, const char *sep)
146 int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
147 const char *extra;
148 const char *subject = NULL, *extra_headers = opt->extra_headers;
149 + int need_8bit_cte = 0;
150
151 opt->loginfo = NULL;
152 if (!opt->verbose_header) {
@@ -214,6 +215,8 @@ void show_log(struct rev_info *opt, const char *sep)
215 if (opt->mime_boundary) {
216 static char subject_buffer[1024];
217 static char buffer[1024];
218 +
219 + need_8bit_cte = -1; /* never */
220 snprintf(subject_buffer, sizeof(subject_buffer) - 1,
221 "%s"
222 "MIME-Version: 1.0\n"
@@ -282,9 +285,11 @@ void show_log(struct rev_info *opt, const char *sep)
285 * And then the pretty-printed message itself
286 */
287 strbuf_init(&msgbuf, 0);
288 + if (need_8bit_cte >= 0)
289 + need_8bit_cte = has_non_ascii(opt->add_signoff);
290 pretty_print_commit(opt->commit_format, commit, &msgbuf,
291 abbrev, subject, extra_headers, opt->date_mode,
287 - has_non_ascii(opt->add_signoff));
292 + need_8bit_cte);
293
294 if (opt->add_signoff)
295 append_signoff(&msgbuf, opt->add_signoff);
pretty.c
+11 -13
@@ -659,7 +659,7 @@ static void pp_title_line(enum cmit_fmt fmt,
659 const char *subject,
660 const char *after_subject,
661 const char *encoding,
662 - int plain_non_ascii)
662 + int need_8bit_cte)
663 {
664 struct strbuf title;
665
@@ -692,7 +692,7 @@ static void pp_title_line(enum cmit_fmt fmt,
692 }
693 strbuf_addch(sb, '\n');
694
695 - if (plain_non_ascii) {
695 + if (need_8bit_cte > 0) {
696 const char *header_fmt =
697 "MIME-Version: 1.0\n"
698 "Content-Type: text/plain; charset=%s\n"
@@ -741,9 +741,9 @@ static void pp_remainder(enum cmit_fmt fmt,
741 }
742
743 void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
744 - struct strbuf *sb, int abbrev,
745 - const char *subject, const char *after_subject,
746 - enum date_mode dmode, int plain_non_ascii)
744 + struct strbuf *sb, int abbrev,
745 + const char *subject, const char *after_subject,
746 + enum date_mode dmode, int need_8bit_cte)
747 {
748 unsigned long beginning_of_body;
749 int indent = 4;
@@ -769,13 +769,11 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
769 if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
770 indent = 0;
771
772 - /* After-subject is used to pass in Content-Type: multipart
773 - * MIME header; in that case we do not have to do the
774 - * plaintext content type even if the commit message has
775 - * non 7-bit ASCII character. Otherwise, check if we need
776 - * to say this is not a 7-bit ASCII.
772 + /*
773 + * We need to check and emit Content-type: to mark it
774 + * as 8-bit if we haven't done so.
775 */
778 - if (fmt == CMIT_FMT_EMAIL && !after_subject) {
776 + if (fmt == CMIT_FMT_EMAIL && need_8bit_cte == 0) {
777 int i, ch, in_body;
778
779 for (in_body = i = 0; (ch = msg[i]); i++) {
@@ -788,7 +786,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
786 in_body = 1;
787 }
788 else if (non_ascii(ch)) {
791 - plain_non_ascii = 1;
789 + need_8bit_cte = 1;
790 break;
791 }
792 }
@@ -813,7 +811,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
811 /* These formats treat the title line specially. */
812 if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
813 pp_title_line(fmt, &msg, sb, subject,
816 - after_subject, encoding, plain_non_ascii);
814 + after_subject, encoding, need_8bit_cte);
815
816 beginning_of_body = sb->len;
817 if (fmt != CMIT_FMT_ONELINE)
t/t4021-format-patch-signer-mime.sh
+9 -1
@@ -32,11 +32,19 @@ test_expect_success 'format with signoff without funny signer name' '
32
33 test_expect_success 'format with non ASCII signer name' '
34
35 - GIT_COMMITTER_NAME="$B$O$^$N(B $B$U$K$*$&(B" \
35 + GIT_COMMITTER_NAME="はまの ふにおう" \
36 git format-patch -s --stdout -1 >output &&
37 grep Content-Type output
38
39 '
40
41 +test_expect_success 'attach and signoff do not duplicate mime headers' '
42 +
43 + GIT_COMMITTER_NAME="はまの ふにおう" \
44 + git format-patch -s --stdout -1 --attach >output &&
45 + test `grep -ci ^MIME-Version: output` = 1
46 +
47 +'
48 +
49 test_done
50
t/t4028-format-patch-mime-headers.sh new
+30
@@ -0,0 +1,30 @@
1 +#!/bin/sh
2 +
3 +test_description='format-patch mime headers and extra headers do not conflict'
4 +. ./test-lib.sh
5 +
6 +test_expect_success 'create commit with utf-8 body' '
7 + echo content >file &&
8 + git add file &&
9 + git commit -m one &&
10 + echo more >>file &&
11 + git commit -a -m "two
12 +
13 + utf-8 body: ñ"
14 +'
15 +
16 +test_expect_success 'patch has mime headers' '
17 + rm -f 0001-two.patch &&
18 + git format-patch HEAD^ &&
19 + grep -i "content-type: text/plain; charset=utf-8" 0001-two.patch
20 +'
21 +
22 +test_expect_success 'patch has mime and extra headers' '
23 + rm -f 0001-two.patch &&
24 + git config format.headers "x-foo: bar" &&
25 + git format-patch HEAD^ &&
26 + grep -i "x-foo: bar" 0001-two.patch &&
27 + grep -i "content-type: text/plain; charset=utf-8" 0001-two.patch
28 +'
29 +
30 +test_done