mailinfo: allow squelching quoted CRLF warning

In previous change, Git starts to warn for quoted CRLF in decoded base64/QP email. Despite those warnings are usually helpful, quoted CRLF could be part of some users' workflow. Let's give them an option to turn off the warning completely. Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Đoàn Trần Công Danh committed May 10, 2021 at 00:12 UTC f1aa29944320e51441e5b5e32591e69f2fa74de2
5 files changed +62 -3
Documentation/git-mailinfo.txt
+19 -1
@@ -9,7 +9,9 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
9 SYNOPSIS
10 --------
11 [verse]
12 -'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--[no-]scissors] <msg> <patch>
12 +'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n]
13 + [--[no-]scissors] [--quoted-cr=<action>]
14 + <msg> <patch>
15
16
17 DESCRIPTION
@@ -89,6 +91,22 @@ This can be enabled by default with the configuration option mailinfo.scissors.
91 --no-scissors::
92 Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
93
94 +--quoted-cr=<action>::
95 + Action when processes email messages sent with base64 or
96 + quoted-printable encoding, and the decoded lines end with a CRLF
97 + instead of a simple LF.
98 ++
99 +The valid actions are:
100 ++
101 +--
102 +* `nowarn`: Git will do nothing when such a CRLF is found.
103 +* `warn`: Git will issue a warning for each message if such a CRLF is
104 + found.
105 +--
106 ++
107 +The default action could be set by configuration option `mailinfo.quotedCR`.
108 +If no such configuration option has been set, `warn` will be used.
109 +
110 <msg>::
111 The commit log message extracted from e-mail, usually
112 except the title line which comes from e-mail Subject.
builtin/mailinfo.c
+12
@@ -38,6 +38,15 @@ static int parse_opt_explicit_encoding(const struct option *opt,
38 return 0;
39 }
40
41 +static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int unset)
42 +{
43 + BUG_ON_OPT_NEG(unset);
44 +
45 + if (mailinfo_parse_quoted_cr_action(arg, opt->value) != 0)
46 + return error(_("bad action '%s' for '%s'"), arg, "--quoted-cr");
47 + return 0;
48 +}
49 +
50 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
51 {
52 struct metainfo_charset meta_charset;
@@ -61,6 +70,9 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
70 N_("re-code metadata to this encoding"),
71 PARSE_OPT_NONEG, parse_opt_explicit_encoding),
72 OPT_BOOL(0, "scissors", &mi.use_scissors, N_("use scissors")),
73 + OPT_CALLBACK_F(0, "quoted-cr", &mi.quoted_cr, N_("<action>"),
74 + N_("action when quoted CR is found"),
75 + PARSE_OPT_NONEG, parse_opt_quoted_cr),
76 OPT_HIDDEN_BOOL(0, "inbody-headers", &mi.use_inbody_headers,
77 N_("use headers in message's body")),
78 OPT_END()
mailinfo.c
+19 -1
@@ -1040,7 +1040,8 @@ static void handle_filter_flowed(struct mailinfo *mi, struct strbuf *line,
1040
1041 static void summarize_quoted_cr(struct mailinfo *mi)
1042 {
1043 - if (mi->have_quoted_cr)
1043 + if (mi->have_quoted_cr &&
1044 + mi->quoted_cr == quoted_cr_warn)
1045 warning(_("quoted CRLF detected"));
1046 }
1047
@@ -1220,6 +1221,17 @@ int mailinfo(struct mailinfo *mi, const char *msg, const char *patch)
1221 return mi->input_error;
1222 }
1223
1224 +int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action)
1225 +{
1226 + if (!strcmp(actionstr, "nowarn"))
1227 + *action = quoted_cr_nowarn;
1228 + else if (!strcmp(actionstr, "warn"))
1229 + *action = quoted_cr_warn;
1230 + else
1231 + return -1;
1232 + return 0;
1233 +}
1234 +
1235 static int git_mailinfo_config(const char *var, const char *value, void *mi_)
1236 {
1237 struct mailinfo *mi = mi_;
@@ -1230,6 +1242,11 @@ static int git_mailinfo_config(const char *var, const char *value, void *mi_)
1242 mi->use_scissors = git_config_bool(var, value);
1243 return 0;
1244 }
1245 + if (!strcmp(var, "mailinfo.quotedcr")) {
1246 + if (mailinfo_parse_quoted_cr_action(value, &mi->quoted_cr) != 0)
1247 + return error(_("bad action '%s' for '%s'"), value, var);
1248 + return 0;
1249 + }
1250 /* perhaps others here */
1251 return 0;
1252 }
@@ -1242,6 +1259,7 @@ void setup_mailinfo(struct mailinfo *mi)
1259 strbuf_init(&mi->charset, 0);
1260 strbuf_init(&mi->log_message, 0);
1261 strbuf_init(&mi->inbody_header_accum, 0);
1262 + mi->quoted_cr = quoted_cr_warn;
1263 mi->header_stage = 1;
1264 mi->use_inbody_headers = 1;
1265 mi->content_top = mi->content;
mailinfo.h
+7
@@ -5,6 +5,11 @@
5
6 #define MAX_BOUNDARIES 5
7
8 +enum quoted_cr_action {
9 + quoted_cr_nowarn,
10 + quoted_cr_warn,
11 +};
12 +
13 struct mailinfo {
14 FILE *input;
15 FILE *output;
@@ -14,6 +19,7 @@ struct mailinfo {
19 struct strbuf email;
20 int keep_subject;
21 int keep_non_patch_brackets_in_subject;
22 + int quoted_cr; /* enum quoted_cr_action */
23 int add_message_id;
24 int use_scissors;
25 int use_inbody_headers;
@@ -40,6 +46,7 @@ struct mailinfo {
46 int input_error;
47 };
48
49 +int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action);
50 void setup_mailinfo(struct mailinfo *);
51 int mailinfo(struct mailinfo *, const char *msg, const char *patch);
52 void clear_mailinfo(struct mailinfo *);
t/t5100-mailinfo.sh
+5 -1
@@ -255,7 +255,11 @@ test_expect_success 'mailinfo warn CR in base64 encoded email' '
255 check_quoted_cr_mail quoted-cr/0001 &&
256 test_must_be_empty quoted-cr/0001.err &&
257 check_quoted_cr_mail quoted-cr/0002 &&
258 - grep "quoted CRLF detected" quoted-cr/0002.err
258 + grep "quoted CRLF detected" quoted-cr/0002.err &&
259 + check_quoted_cr_mail quoted-cr/0001 --quoted-cr=nowarn &&
260 + test_must_be_empty quoted-cr/0001.err &&
261 + check_quoted_cr_mail quoted-cr/0002 --quoted-cr=nowarn &&
262 + test_must_be_empty quoted-cr/0002.err
263 '
264
265 test_done