Skip to content

Commit 53ce2e3

Browse files
peffgitster
authored andcommitted
am: add explicit "--retry" option
After a patch fails, you can ask "git am" to try applying it again with new options by running without any of the resume options. E.g.: git am <patch # oops, it failed; let's try again git am --3way But since this second command has no explicit resume option (like "--continue"), it looks just like an invocation to read a fresh patch from stdin. To avoid confusing the two cases, there are some heuristics, courtesy of 8d18550 (builtin-am: reject patches when there's a session in progress, 2015-08-04): if (in_progress) { /* * Catch user error to feed us patches when there is a session * in progress: * * 1. mbox path(s) are provided on the command-line. * 2. stdin is not a tty: the user is trying to feed us a patch * from standard input. This is somewhat unreliable -- stdin * could be /dev/null for example and the caller did not * intend to feed us a patch but wanted to continue * unattended. */ if (argc || (resume_mode == RESUME_FALSE && !isatty(0))) die(_("previous rebase directory %s still exists but mbox given."), state.dir); if (resume_mode == RESUME_FALSE) resume_mode = RESUME_APPLY; [...] So if no resume command is given, then we require that stdin be a tty, and otherwise complain about (potentially) receiving an mbox on stdin. But of course you might not actually have a terminal available! And sadly there is no explicit way to hit this same code path; this is the only place that sets RESUME_APPLY. So you're stuck, and scripts like our test suite have to bend over backwards to create a pseudo-tty. Let's provide an explicit option to trigger this mode. The code turns out to be quite simple; just setting "resume_mode" to RESUME_FALSE is enough to dodge the tty check, and then our state is the same as it would be with the heuristic case (which we'll continue to allow). When we don't have a session in progress, there's already code to complain when resume_mode is set (but we'll add a new test to cover that). To test the new option, we'll convert the existing tests that rely on the fake stdin tty. That lets us test them on more platforms, and will let us simplify test_terminal a bit in a future patch. It does, however, mean we're not testing the tty heuristic at all. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 337b4d4 commit 53ce2e3

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

Documentation/git-am.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ SYNOPSIS
1818
[--quoted-cr=<action>]
1919
[--empty=(stop|drop|keep)]
2020
[(<mbox> | <Maildir>)...]
21-
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)] | --allow-empty)
21+
'git am' (--continue | --skip | --abort | --quit | --retry | --show-current-patch[=(diff|raw)] | --allow-empty)
2222

2323
DESCRIPTION
2424
-----------
@@ -199,6 +199,12 @@ include::rerere-options.txt[]
199199
Abort the patching operation but keep HEAD and the index
200200
untouched.
201201

202+
--retry::
203+
Try to apply the last conflicting patch again. This is generally
204+
only useful for passing extra options to the retry attempt
205+
(e.g., `--3way`), since otherwise you'll just see the same
206+
failure again.
207+
202208
--show-current-patch[=(diff|raw)]::
203209
Show the message at which `git am` has stopped due to
204210
conflicts. If `raw` is specified, show the raw contents of

builtin/am.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
23792379
N_("show the patch being applied"),
23802380
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
23812381
parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
2382+
OPT_CMDMODE(0, "retry", &resume_mode,
2383+
N_("try to apply current patch again"),
2384+
RESUME_APPLY),
23822385
OPT_CMDMODE(0, "allow-empty", &resume_mode,
23832386
N_("record the empty patch as an empty commit"),
23842387
RESUME_ALLOW_EMPTY),

t/t4153-am-resume-override-opts.sh

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
test_description='git-am command-line options override saved options'
44

55
. ./test-lib.sh
6-
. "$TEST_DIRECTORY"/lib-terminal.sh
76

87
format_patch () {
98
git format-patch --stdout -1 "$1" >"$1".eml
@@ -27,7 +26,12 @@ test_expect_success 'setup' '
2726
format_patch side2
2827
'
2928

30-
test_expect_success TTY '--3way overrides --no-3way' '
29+
test_expect_success '--retry fails without in-progress operation' '
30+
test_must_fail git am --retry 2>err &&
31+
test_grep "operation not in progress" err
32+
'
33+
34+
test_expect_success '--3way overrides --no-3way' '
3135
rm -fr .git/rebase-apply &&
3236
git reset --hard &&
3337
git checkout renamed-file &&
@@ -40,7 +44,7 @@ test_expect_success TTY '--3way overrides --no-3way' '
4044
4145
# Applying side1 with am --3way will succeed due to the threeway-merge.
4246
# Applying side2 will fail as --3way does not apply to it.
43-
test_must_fail test_terminal git am --3way </dev/zero &&
47+
test_must_fail git am --retry --3way &&
4448
test_path_is_dir .git/rebase-apply &&
4549
test side1 = "$(cat file2)"
4650
'
@@ -84,7 +88,7 @@ test_expect_success '--signoff overrides --no-signoff' '
8488
test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
8589
'
8690

87-
test_expect_success TTY '--reject overrides --no-reject' '
91+
test_expect_success '--reject overrides --no-reject' '
8892
rm -fr .git/rebase-apply &&
8993
git reset --hard &&
9094
git checkout first &&
@@ -94,7 +98,7 @@ test_expect_success TTY '--reject overrides --no-reject' '
9498
test_path_is_dir .git/rebase-apply &&
9599
test_path_is_missing file.rej &&
96100
97-
test_must_fail test_terminal git am --reject </dev/zero &&
101+
test_must_fail git am --retry --reject </dev/zero &&
98102
test_path_is_dir .git/rebase-apply &&
99103
test_path_is_file file.rej
100104
'

0 commit comments

Comments
 (0)