Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2021-05-16 15:05:23 +0300
committerJunio C Hamano <gitster@pobox.com>2021-05-16 15:05:23 +0300
commit483932a3d8dae23207de8ec8683a5236ef3098d9 (patch)
tree39286e75cc8f9bf8b016965fc384ee078a117a98 /builtin
parentc8e34a7ac20b5d512cb2f1f789eca2a3b12b129f (diff)
parent59b519ab7e703ebdbad06bd9ba3cae6e55d880d0 (diff)
Merge branch 'dd/mailinfo-quoted-cr'
"git mailinfo" (hence "git am") learned the "--quoted-cr" option to control how lines ending with CRLF wrapped in base64 or qp are handled. * dd/mailinfo-quoted-cr: am: learn to process quoted lines that ends with CRLF mailinfo: allow stripping quoted CR without warning mailinfo: allow squelching quoted CRLF warning mailinfo: warn if CRLF found in decoded base64/QP email mailinfo: stop parsing options manually mailinfo: load default metainfo_charset lazily
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c51
-rw-r--r--builtin/mailinfo.c115
2 files changed, 133 insertions, 33 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 8355e3566f..0b2d886c81 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -116,6 +116,7 @@ struct am_state {
int keep; /* enum keep_type */
int message_id;
int scissors; /* enum scissors_type */
+ int quoted_cr; /* enum quoted_cr_action */
struct strvec git_apply_opts;
const char *resolvemsg;
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);
state->scissors = SCISSORS_UNSET;
+ state->quoted_cr = quoted_cr_unset;
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);
}
+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.
*/
@@ -397,6 +409,12 @@ static void am_load(struct am_state *state)
else
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);
strvec_clear(&state->git_apply_opts);
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);
+ 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);
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");
}
+ 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.output = xfopen(am_path(state, "info"), "w");
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),
OPT_BOOL('c', "scissors", &state.scissors,
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"),
N_("pass it through git-apply"),
0),
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cfb667a594..01d16ef9e5 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -7,54 +7,103 @@
#include "utf8.h"
#include "strbuf.h"
#include "mailinfo.h"
+#include "parse-options.h"
-static const char mailinfo_usage[] =
- "git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info";
+static const char * const mailinfo_usage[] = {
+ /* TRANSLATORS: keep <> in "<" mail ">" info. */
+ N_("git mailinfo [<options>] <msg> <patch> < mail >info"),
+ NULL,
+};
+
+struct metainfo_charset
+{
+ enum {
+ CHARSET_DEFAULT,
+ CHARSET_NO_REENCODE,
+ CHARSET_EXPLICIT,
+ } policy;
+ const char *charset;
+};
+
+static int parse_opt_explicit_encoding(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct metainfo_charset *meta_charset = opt->value;
+
+ BUG_ON_OPT_NEG(unset);
+
+ meta_charset->policy = CHARSET_EXPLICIT;
+ meta_charset->charset = arg;
+
+ return 0;
+}
+
+static int parse_opt_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;
+}
int cmd_mailinfo(int argc, const char **argv, const char *prefix)
{
- const char *def_charset;
+ struct metainfo_charset meta_charset;
struct mailinfo mi;
int status;
char *msgfile, *patchfile;
+ struct option options[] = {
+ OPT_BOOL('k', NULL, &mi.keep_subject, N_("keep subject")),
+ OPT_BOOL('b', NULL, &mi.keep_non_patch_brackets_in_subject,
+ N_("keep non patch brackets in subject")),
+ OPT_BOOL('m', "message-id", &mi.add_message_id,
+ N_("copy Message-ID to the end of commit message")),
+ OPT_SET_INT_F('u', NULL, &meta_charset.policy,
+ N_("re-code metadata to i18n.commitEncoding"),
+ CHARSET_DEFAULT, PARSE_OPT_NONEG),
+ OPT_SET_INT_F('n', NULL, &meta_charset.policy,
+ N_("disable charset re-coding of metadata"),
+ CHARSET_NO_REENCODE, PARSE_OPT_NONEG),
+ OPT_CALLBACK_F(0, "encoding", &meta_charset, N_("encoding"),
+ N_("re-code metadata to this encoding"),
+ PARSE_OPT_NONEG, parse_opt_explicit_encoding),
+ OPT_BOOL(0, "scissors", &mi.use_scissors, N_("use scissors")),
+ OPT_CALLBACK_F(0, "quoted-cr", &mi.quoted_cr, N_("<action>"),
+ N_("action when quoted CR is found"),
+ PARSE_OPT_NONEG, parse_opt_quoted_cr),
+ OPT_HIDDEN_BOOL(0, "inbody-headers", &mi.use_inbody_headers,
+ N_("use headers in message's body")),
+ OPT_END()
+ };
+
setup_mailinfo(&mi);
+ meta_charset.policy = CHARSET_DEFAULT;
- def_charset = get_commit_output_encoding();
- mi.metainfo_charset = def_charset;
-
- while (1 < argc && argv[1][0] == '-') {
- if (!strcmp(argv[1], "-k"))
- mi.keep_subject = 1;
- else if (!strcmp(argv[1], "-b"))
- mi.keep_non_patch_brackets_in_subject = 1;
- else if (!strcmp(argv[1], "-m") || !strcmp(argv[1], "--message-id"))
- mi.add_message_id = 1;
- else if (!strcmp(argv[1], "-u"))
- mi.metainfo_charset = def_charset;
- else if (!strcmp(argv[1], "-n"))
- mi.metainfo_charset = NULL;
- else if (starts_with(argv[1], "--encoding="))
- mi.metainfo_charset = argv[1] + 11;
- else if (!strcmp(argv[1], "--scissors"))
- mi.use_scissors = 1;
- else if (!strcmp(argv[1], "--no-scissors"))
- mi.use_scissors = 0;
- else if (!strcmp(argv[1], "--no-inbody-headers"))
- mi.use_inbody_headers = 0;
- else
- usage(mailinfo_usage);
- argc--; argv++;
- }
+ argc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0);
- if (argc != 3)
- usage(mailinfo_usage);
+ if (argc != 2)
+ usage_with_options(mailinfo_usage, options);
+
+ switch (meta_charset.policy) {
+ case CHARSET_DEFAULT:
+ mi.metainfo_charset = get_commit_output_encoding();
+ break;
+ case CHARSET_NO_REENCODE:
+ mi.metainfo_charset = NULL;
+ break;
+ case CHARSET_EXPLICIT:
+ break;
+ default:
+ BUG("invalid meta_charset.policy");
+ }
mi.input = stdin;
mi.output = stdout;
- msgfile = prefix_filename(prefix, argv[1]);
- patchfile = prefix_filename(prefix, argv[2]);
+ msgfile = prefix_filename(prefix, argv[0]);
+ patchfile = prefix_filename(prefix, argv[1]);
status = !!mailinfo(&mi, msgfile, patchfile);
clear_mailinfo(&mi);