am: learn to process quoted lines that ends with CRLF
In previous changes, mailinfo has learnt to process lines that decoded from base64 or quoted-printable, and ends with CRLF. Let's teach "am" that new trick, too. Signed-off-by: Đoàn Trần Công Danh <congdanhqx@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
133a4fda59
commit
59b519ab7e
@ -15,6 +15,7 @@ SYNOPSIS
|
|||||||
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
|
||||||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||||
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
||||||
|
[--quoted-cr=<action>]
|
||||||
[(<mbox> | <Maildir>)...]
|
[(<mbox> | <Maildir>)...]
|
||||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
||||||
|
|
||||||
@ -59,6 +60,9 @@ OPTIONS
|
|||||||
--no-scissors::
|
--no-scissors::
|
||||||
Ignore scissors lines (see linkgit:git-mailinfo[1]).
|
Ignore scissors lines (see linkgit:git-mailinfo[1]).
|
||||||
|
|
||||||
|
--quoted-cr=<action>::
|
||||||
|
This flag will be passed down to 'git mailinfo' (see linkgit:git-mailinfo[1]).
|
||||||
|
|
||||||
-m::
|
-m::
|
||||||
--message-id::
|
--message-id::
|
||||||
Pass the `-m` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]),
|
Pass the `-m` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]),
|
||||||
|
51
builtin/am.c
51
builtin/am.c
@ -116,6 +116,7 @@ struct am_state {
|
|||||||
int keep; /* enum keep_type */
|
int keep; /* enum keep_type */
|
||||||
int message_id;
|
int message_id;
|
||||||
int scissors; /* enum scissors_type */
|
int scissors; /* enum scissors_type */
|
||||||
|
int quoted_cr; /* enum quoted_cr_action */
|
||||||
struct strvec git_apply_opts;
|
struct strvec git_apply_opts;
|
||||||
const char *resolvemsg;
|
const char *resolvemsg;
|
||||||
int committer_date_is_author_date;
|
int committer_date_is_author_date;
|
||||||
@ -145,6 +146,7 @@ static void am_state_init(struct am_state *state)
|
|||||||
git_config_get_bool("am.messageid", &state->message_id);
|
git_config_get_bool("am.messageid", &state->message_id);
|
||||||
|
|
||||||
state->scissors = SCISSORS_UNSET;
|
state->scissors = SCISSORS_UNSET;
|
||||||
|
state->quoted_cr = quoted_cr_unset;
|
||||||
|
|
||||||
strvec_init(&state->git_apply_opts);
|
strvec_init(&state->git_apply_opts);
|
||||||
|
|
||||||
@ -165,6 +167,16 @@ static void am_state_release(struct am_state *state)
|
|||||||
strvec_clear(&state->git_apply_opts);
|
strvec_clear(&state->git_apply_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int am_option_parse_quoted_cr(const struct option *opt,
|
||||||
|
const char *arg, int unset)
|
||||||
|
{
|
||||||
|
BUG_ON_OPT_NEG(unset);
|
||||||
|
|
||||||
|
if (mailinfo_parse_quoted_cr_action(arg, opt->value) != 0)
|
||||||
|
return error(_("bad action '%s' for '%s'"), arg, "--quoted-cr");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns path relative to the am_state directory.
|
* Returns path relative to the am_state directory.
|
||||||
*/
|
*/
|
||||||
@ -397,6 +409,12 @@ static void am_load(struct am_state *state)
|
|||||||
else
|
else
|
||||||
state->scissors = SCISSORS_UNSET;
|
state->scissors = SCISSORS_UNSET;
|
||||||
|
|
||||||
|
read_state_file(&sb, state, "quoted-cr", 1);
|
||||||
|
if (!*sb.buf)
|
||||||
|
state->quoted_cr = quoted_cr_unset;
|
||||||
|
else if (mailinfo_parse_quoted_cr_action(sb.buf, &state->quoted_cr) != 0)
|
||||||
|
die(_("could not parse %s"), am_path(state, "quoted-cr"));
|
||||||
|
|
||||||
read_state_file(&sb, state, "apply-opt", 1);
|
read_state_file(&sb, state, "apply-opt", 1);
|
||||||
strvec_clear(&state->git_apply_opts);
|
strvec_clear(&state->git_apply_opts);
|
||||||
if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
|
if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
|
||||||
@ -1002,6 +1020,24 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
|
|||||||
}
|
}
|
||||||
write_state_text(state, "scissors", str);
|
write_state_text(state, "scissors", str);
|
||||||
|
|
||||||
|
switch (state->quoted_cr) {
|
||||||
|
case quoted_cr_unset:
|
||||||
|
str = "";
|
||||||
|
break;
|
||||||
|
case quoted_cr_nowarn:
|
||||||
|
str = "nowarn";
|
||||||
|
break;
|
||||||
|
case quoted_cr_warn:
|
||||||
|
str = "warn";
|
||||||
|
break;
|
||||||
|
case quoted_cr_strip:
|
||||||
|
str = "strip";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG("invalid value for state->quoted_cr");
|
||||||
|
}
|
||||||
|
write_state_text(state, "quoted-cr", str);
|
||||||
|
|
||||||
sq_quote_argv(&sb, state->git_apply_opts.v);
|
sq_quote_argv(&sb, state->git_apply_opts.v);
|
||||||
write_state_text(state, "apply-opt", sb.buf);
|
write_state_text(state, "apply-opt", sb.buf);
|
||||||
|
|
||||||
@ -1162,6 +1198,18 @@ static int parse_mail(struct am_state *state, const char *mail)
|
|||||||
BUG("invalid value for state->scissors");
|
BUG("invalid value for state->scissors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (state->quoted_cr) {
|
||||||
|
case quoted_cr_unset:
|
||||||
|
break;
|
||||||
|
case quoted_cr_nowarn:
|
||||||
|
case quoted_cr_warn:
|
||||||
|
case quoted_cr_strip:
|
||||||
|
mi.quoted_cr = state->quoted_cr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG("invalid value for state->quoted_cr");
|
||||||
|
}
|
||||||
|
|
||||||
mi.input = xfopen(mail, "r");
|
mi.input = xfopen(mail, "r");
|
||||||
mi.output = xfopen(am_path(state, "info"), "w");
|
mi.output = xfopen(am_path(state, "info"), "w");
|
||||||
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
|
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
|
||||||
@ -2242,6 +2290,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
|||||||
0, PARSE_OPT_NONEG),
|
0, PARSE_OPT_NONEG),
|
||||||
OPT_BOOL('c', "scissors", &state.scissors,
|
OPT_BOOL('c', "scissors", &state.scissors,
|
||||||
N_("strip everything before a scissors line")),
|
N_("strip everything before a scissors line")),
|
||||||
|
OPT_CALLBACK_F(0, "quoted-cr", &state.quoted_cr, N_("action"),
|
||||||
|
N_("pass it through git-mailinfo"),
|
||||||
|
PARSE_OPT_NONEG, am_option_parse_quoted_cr),
|
||||||
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
|
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
|
||||||
N_("pass it through git-apply"),
|
N_("pass it through git-apply"),
|
||||||
0),
|
0),
|
||||||
|
@ -1333,6 +1333,7 @@ __git_whitespacelist="nowarn warn error error-all fix"
|
|||||||
__git_patchformat="mbox stgit stgit-series hg mboxrd"
|
__git_patchformat="mbox stgit stgit-series hg mboxrd"
|
||||||
__git_showcurrentpatch="diff raw"
|
__git_showcurrentpatch="diff raw"
|
||||||
__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
|
__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
|
||||||
|
__git_quoted_cr="nowarn warn strip"
|
||||||
|
|
||||||
_git_am ()
|
_git_am ()
|
||||||
{
|
{
|
||||||
@ -1354,6 +1355,10 @@ _git_am ()
|
|||||||
__gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
|
__gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--quoted-cr=*)
|
||||||
|
__gitcomp "$__git_quoted_cr" "" "${cur##--quoted-cr=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
--*)
|
--*)
|
||||||
__gitcomp_builtin am "" \
|
__gitcomp_builtin am "" \
|
||||||
"$__git_am_inprogress_options"
|
"$__git_am_inprogress_options"
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define MAX_BOUNDARIES 5
|
#define MAX_BOUNDARIES 5
|
||||||
|
|
||||||
enum quoted_cr_action {
|
enum quoted_cr_action {
|
||||||
|
quoted_cr_unset = -1,
|
||||||
quoted_cr_nowarn,
|
quoted_cr_nowarn,
|
||||||
quoted_cr_warn,
|
quoted_cr_warn,
|
||||||
quoted_cr_strip,
|
quoted_cr_strip,
|
||||||
|
37
t/t4258-am-quoted-cr.sh
Executable file
37
t/t4258-am-quoted-cr.sh
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='test am --quoted-cr=<action>'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
DATA="$TEST_DIRECTORY/t4258"
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
test_write_lines one two three >text &&
|
||||||
|
test_commit one text &&
|
||||||
|
test_write_lines one owt three >text &&
|
||||||
|
test_commit two text
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am warn if quoted-cr is found' '
|
||||||
|
git reset --hard one &&
|
||||||
|
test_must_fail git am "$DATA/mbox" 2>err &&
|
||||||
|
grep "quoted CRLF detected" err
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am --quoted-cr=strip' '
|
||||||
|
test_might_fail git am --abort &&
|
||||||
|
git reset --hard one &&
|
||||||
|
git am --quoted-cr=strip "$DATA/mbox" &&
|
||||||
|
git diff --exit-code HEAD two
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am with config mailinfo.quotecr=strip' '
|
||||||
|
test_might_fail git am --abort &&
|
||||||
|
git reset --hard one &&
|
||||||
|
test_config mailinfo.quotedCr strip &&
|
||||||
|
git am "$DATA/mbox" &&
|
||||||
|
git diff --exit-code HEAD two
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
12
t/t4258/mbox
Normal file
12
t/t4258/mbox
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
From: A U Thor <mail@example.com>
|
||||||
|
To: list@example.org
|
||||||
|
Subject: [PATCH v2] sample
|
||||||
|
Date: Mon, 3 Aug 2020 22:40:55 +0700
|
||||||
|
Message-Id: <msg-id@example.com>
|
||||||
|
Content-Type: text/plain; charset="utf-8"
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
VGhpcyBpcyBjb21taXQgbWVzc2FnZS4NCi0tLQ0KIHRleHQgfCAyICstDQogMSBmaWxlIGNoYW5n
|
||||||
|
ZWQsIDEgaW5zZXJ0aW9uKCspLCAxIGRlbGV0aW9uKC0pDQoNCmRpZmYgLS1naXQgYS90ZXh0IGIv
|
||||||
|
dGV4dA0KaW5kZXggNTYyNmFiZi4uZjcxOWVmZCAxMDA2NDQNCi0tLSBhL3RleHQNCisrKyBiL3Rl
|
||||||
|
eHQNCkBAIC0xICsxIEBADQotb25lDQordHdvDQotLSANCjIuMzEuMQoK
|
Loading…
Reference in New Issue
Block a user