@matheusbsbs / matheus-bagliano / commits / f3b4822899
Fork 0

am: support --show-current-patch=raw as a synonym for--show-current-patch

When "git am --show-current-patch" was added in commit 984913a210 ("am: add --show-current-patch", 2018-02-12), "git am" started recommending it as a replacement for .git/rebase-merge/patch. Unfortunately the suggestion is somewhat misguided; for example, the output "git am --show-current-patch" cannot be passed to "git apply" if it is encoded as quoted-printable or base64. To simplify worktree operations and to avoid that users poke into .git, it would be better if "git am" also provided a mode that copies .git/rebase-merge/patch to stdout. One possibility could be to have completely separate options, introducing for example --show-current-message (for .git/rebase-apply/NNNN) and --show-current-diff (for .git/rebase-apply/patch), while possibly deprecating --show-current-patch. That would even remove the need for the first two patches in the series. However, the long common prefix would have prevented using an abbreviated option such as "--show". Therefore, I chose instead to add a string argument to --show-current-patch. The new argument is optional, so that "git am --show-current-patch"'s behavior remains backwards-compatible. The next choice to make is how to handle multiple --show-current-patch options. Right now, something like "git am --abort --show-current-patch" is rejected, and the previous suggestion would likewise have naturally rejected a command line like git am --show-current-message --show-current-diff Therefore, I decided to also reject for example git am --show-current-patch=diff --show-current-patch=raw In other words the whole of --show-current-patch=xxx (including the optional argument) is treated as the command mode. I found this to be more consistent and intuitive, even though it differs from the usual "last one wins" semantics of the git command line. Add the code to parse submodes based on the above design, where for now "raw" is the only valid submode. "raw" prints the full e-mail message just like "git am --show-current-patch". Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Paolo Bonzini committed Feb 20, 2020 at 15:15 UTC f3b4822899dc4ddca688de285f01e1d12aeb33b6
4 files changed +73 -10
Documentation/git-am.txt
+5 -4
@@ -16,7 +16,7 @@ SYNOPSIS
16 [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
17 [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
18 [(<mbox> | <Maildir>)...]
19 -'git am' (--continue | --skip | --abort | --quit | --show-current-patch)
19 +'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=raw])
20
21 DESCRIPTION
22 -----------
@@ -176,9 +176,10 @@ default. You can use `--no-utf8` to override this.
176 Abort the patching operation but keep HEAD and the index
177 untouched.
178
179 ---show-current-patch::
180 - Show the entire e-mail message "git am" has stopped at, because
181 - of conflicts.
179 +--show-current-patch[=raw]::
180 + Show the raw contents of the e-mail message at which `git am`
181 + has stopped due to conflicts. The argument must be omitted or
182 + `raw`.
183
184 DISCUSSION
185 ----------
builtin/am.c
+53 -6
@@ -81,6 +81,10 @@ enum signoff_type {
81 SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
82 };
83
84 +enum show_patch_type {
85 + SHOW_PATCH_RAW = 0,
86 +};
87 +
88 struct am_state {
89 /* state directory path */
90 char *dir;
@@ -2061,7 +2065,7 @@ static void am_abort(struct am_state *state)
2065 am_destroy(state);
2066 }
2067
2064 -static int show_patch(struct am_state *state)
2068 +static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
2069 {
2070 struct strbuf sb = STRBUF_INIT;
2071 const char *patch_path;
@@ -2078,7 +2082,14 @@ static int show_patch(struct am_state *state)
2082 return ret;
2083 }
2084
2081 - patch_path = am_path(state, msgnum(state));
2085 + switch (sub_mode) {
2086 + case SHOW_PATCH_RAW:
2087 + patch_path = am_path(state, msgnum(state));
2088 + break;
2089 + default:
2090 + BUG("invalid mode for --show-current-patch");
2091 + }
2092 +
2093 len = strbuf_read_file(&sb, patch_path, 0);
2094 if (len < 0)
2095 die_errno(_("failed to read '%s'"), patch_path);
@@ -2130,8 +2141,42 @@ enum resume_type {
2141
2142 struct resume_mode {
2143 enum resume_type mode;
2144 + enum show_patch_type sub_mode;
2145 };
2146
2147 +static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset)
2148 +{
2149 + int *opt_value = opt->value;
2150 + struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode);
2151 +
2152 + /*
2153 + * Please update $__git_showcurrentpatch in git-completion.bash
2154 + * when you add new options
2155 + */
2156 + const char *valid_modes[] = {
2157 + [SHOW_PATCH_RAW] = "raw"
2158 + };
2159 + int new_value = SHOW_PATCH_RAW;
2160 +
2161 + if (arg) {
2162 + for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) {
2163 + if (!strcmp(arg, valid_modes[new_value]))
2164 + break;
2165 + }
2166 + if (new_value >= ARRAY_SIZE(valid_modes))
2167 + return error(_("Invalid value for --show-current-patch: %s"), arg);
2168 + }
2169 +
2170 + if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
2171 + return error(_("--show-current-patch=%s is incompatible with "
2172 + "--show-current-patch=%s"),
2173 + arg, valid_modes[resume->sub_mode]);
2174 +
2175 + resume->mode = RESUME_SHOW_PATCH;
2176 + resume->sub_mode = new_value;
2177 + return 0;
2178 +}
2179 +
2180 static int git_am_config(const char *k, const char *v, void *cb)
2181 {
2182 int status;
@@ -2233,9 +2278,11 @@ int cmd_am(int argc, const char **argv, const char *prefix)
2278 OPT_CMDMODE(0, "quit", &resume.mode,
2279 N_("abort the patching operation but keep HEAD where it is."),
2280 RESUME_QUIT),
2236 - OPT_CMDMODE(0, "show-current-patch", &resume.mode,
2237 - N_("show the patch being applied."),
2238 - RESUME_SHOW_PATCH),
2281 + { OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
2282 + "raw",
2283 + N_("show the patch being applied"),
2284 + PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
2285 + parse_opt_show_current_patch, RESUME_SHOW_PATCH },
2286 OPT_BOOL(0, "committer-date-is-author-date",
2287 &state.committer_date_is_author_date,
2288 N_("lie about committer date")),
@@ -2354,7 +2401,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
2401 am_destroy(&state);
2402 break;
2403 case RESUME_SHOW_PATCH:
2357 - ret = show_patch(&state);
2404 + ret = show_patch(&state, resume.sub_mode);
2405 break;
2406 default:
2407 BUG("invalid resume value");
contrib/completion/git-completion.bash
+5
@@ -1180,6 +1180,7 @@ __git_count_arguments ()
1180
1181 __git_whitespacelist="nowarn warn error error-all fix"
1182 __git_patchformat="mbox stgit stgit-series hg mboxrd"
1183 +__git_showcurrentpatch="raw"
1184 __git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
1185
1186 _git_am ()
@@ -1198,6 +1199,10 @@ _git_am ()
1199 __gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
1200 return
1201 ;;
1202 + --show-current-patch=*)
1203 + __gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
1204 + return
1205 + ;;
1206 --*)
1207 __gitcomp_builtin am "" \
1208 "$__git_am_inprogress_options"
t/t4150-am.sh
+10
@@ -666,6 +666,16 @@ test_expect_success 'am --show-current-patch' '
666 test_cmp .git/rebase-apply/0001 actual.patch
667 '
668
669 +test_expect_success 'am --show-current-patch=raw' '
670 + git am --show-current-patch=raw >actual.patch &&
671 + test_cmp .git/rebase-apply/0001 actual.patch
672 +'
673 +
674 +test_expect_success 'am accepts repeated --show-current-patch' '
675 + git am --show-current-patch --show-current-patch=raw >actual.patch &&
676 + test_cmp .git/rebase-apply/0001 actual.patch
677 +'
678 +
679 test_expect_success 'am --skip works' '
680 echo goodbye >expected &&
681 git am --skip &&