]> git.ipfire.org Git - thirdparty/git.git/commitdiff
am: support --show-current-patch=raw as a synonym for--show-current-patch
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 20 Feb 2020 14:15:18 +0000 (15:15 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 20 Feb 2020 21:20:40 +0000 (13:20 -0800)
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>
Documentation/git-am.txt
builtin/am.c
contrib/completion/git-completion.bash
t/t4150-am.sh

index 11ca61b00b459ef40f5cac0038989f2db7390400..590b711536b97eaab7d4693d644a2bbc3aaf723e 100644 (file)
@@ -16,7 +16,7 @@ SYNOPSIS
         [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
         [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
         [(<mbox> | <Maildir>)...]
-'git am' (--continue | --skip | --abort | --quit | --show-current-patch)
+'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=raw])
 
 DESCRIPTION
 -----------
@@ -176,9 +176,10 @@ default.   You can use `--no-utf8` to override this.
        Abort the patching operation but keep HEAD and the index
        untouched.
 
---show-current-patch::
-       Show the entire e-mail message "git am" has stopped at, because
-       of conflicts.
+--show-current-patch[=raw]::
+       Show the raw contents of the e-mail message at which `git am`
+       has stopped due to conflicts.  The argument must be omitted or
+       `raw`.
 
 DISCUSSION
 ----------
index bd3cda8becc7d618434c8074b3777a00b5e94d06..54b04da86d9a515de3c60f56fb44c612647ff2b2 100644 (file)
@@ -81,6 +81,10 @@ enum signoff_type {
        SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
 };
 
+enum show_patch_type {
+       SHOW_PATCH_RAW = 0,
+};
+
 struct am_state {
        /* state directory path */
        char *dir;
@@ -2061,7 +2065,7 @@ static void am_abort(struct am_state *state)
        am_destroy(state);
 }
 
-static int show_patch(struct am_state *state)
+static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
 {
        struct strbuf sb = STRBUF_INIT;
        const char *patch_path;
@@ -2078,7 +2082,14 @@ static int show_patch(struct am_state *state)
                return ret;
        }
 
-       patch_path = am_path(state, msgnum(state));
+       switch (sub_mode) {
+       case SHOW_PATCH_RAW:
+               patch_path = am_path(state, msgnum(state));
+               break;
+       default:
+               BUG("invalid mode for --show-current-patch");
+       }
+
        len = strbuf_read_file(&sb, patch_path, 0);
        if (len < 0)
                die_errno(_("failed to read '%s'"), patch_path);
@@ -2130,8 +2141,42 @@ enum resume_type {
 
 struct resume_mode {
        enum resume_type mode;
+       enum show_patch_type sub_mode;
 };
 
+static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset)
+{
+       int *opt_value = opt->value;
+       struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode);
+
+       /*
+        * Please update $__git_showcurrentpatch in git-completion.bash
+        * when you add new options
+        */
+       const char *valid_modes[] = {
+               [SHOW_PATCH_RAW] = "raw"
+       };
+       int new_value = SHOW_PATCH_RAW;
+
+       if (arg) {
+               for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) {
+                       if (!strcmp(arg, valid_modes[new_value]))
+                               break;
+               }
+               if (new_value >= ARRAY_SIZE(valid_modes))
+                       return error(_("Invalid value for --show-current-patch: %s"), arg);
+       }
+
+       if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
+               return error(_("--show-current-patch=%s is incompatible with "
+                              "--show-current-patch=%s"),
+                            arg, valid_modes[resume->sub_mode]);
+
+       resume->mode = RESUME_SHOW_PATCH;
+       resume->sub_mode = new_value;
+       return 0;
+}
+
 static int git_am_config(const char *k, const char *v, void *cb)
 {
        int status;
@@ -2233,9 +2278,11 @@ int cmd_am(int argc, const char **argv, const char *prefix)
                OPT_CMDMODE(0, "quit", &resume.mode,
                        N_("abort the patching operation but keep HEAD where it is."),
                        RESUME_QUIT),
-               OPT_CMDMODE(0, "show-current-patch", &resume.mode,
-                       N_("show the patch being applied."),
-                       RESUME_SHOW_PATCH),
+               { OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
+                 "raw",
+                 N_("show the patch being applied"),
+                 PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+                 parse_opt_show_current_patch, RESUME_SHOW_PATCH },
                OPT_BOOL(0, "committer-date-is-author-date",
                        &state.committer_date_is_author_date,
                        N_("lie about committer date")),
@@ -2354,7 +2401,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
                am_destroy(&state);
                break;
        case RESUME_SHOW_PATCH:
-               ret = show_patch(&state);
+               ret = show_patch(&state, resume.sub_mode);
                break;
        default:
                BUG("invalid resume value");
index e4d9ff4a95ceb56e568131c148de5aaed85219c2..2673fc162c73b37d95726605f1b168816012ba08 100644 (file)
@@ -1180,6 +1180,7 @@ __git_count_arguments ()
 
 __git_whitespacelist="nowarn warn error error-all fix"
 __git_patchformat="mbox stgit stgit-series hg mboxrd"
+__git_showcurrentpatch="raw"
 __git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
 
 _git_am ()
@@ -1198,6 +1199,10 @@ _git_am ()
                __gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
                return
                ;;
+       --show-current-patch=*)
+               __gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
+               return
+               ;;
        --*)
                __gitcomp_builtin am "" \
                        "$__git_am_inprogress_options"
index 4f1e24ecbecd87667251eab612c9b966405d53c6..afe456e75ed0b633729986efa676bf604e4932e9 100755 (executable)
@@ -666,6 +666,16 @@ test_expect_success 'am --show-current-patch' '
        test_cmp .git/rebase-apply/0001 actual.patch
 '
 
+test_expect_success 'am --show-current-patch=raw' '
+       git am --show-current-patch=raw >actual.patch &&
+       test_cmp .git/rebase-apply/0001 actual.patch
+'
+
+test_expect_success 'am accepts repeated --show-current-patch' '
+       git am --show-current-patch --show-current-patch=raw >actual.patch &&
+       test_cmp .git/rebase-apply/0001 actual.patch
+'
+
 test_expect_success 'am --skip works' '
        echo goodbye >expected &&
        git am --skip &&