Skip to content

Commit 42b8b5b

Browse files
committed
Merge branch 'jk/am-retry'
"git am" has a safety feature to prevent it from starting a new session when there already is a session going. It reliably triggers when a mbox is given on the command line, but it has to rely on the tty-ness of the standard input. Add an explicit way to opt out of this safety with a command line option. * jk/am-retry: test-terminal: drop stdin handling am: add explicit "--retry" option
2 parents cff3b03 + 62c71ac commit 42b8b5b

File tree

4 files changed

+22
-32
lines changed

4 files changed

+22
-32
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
-----------
@@ -208,6 +208,12 @@ Valid <action> for the `--whitespace` option are:
208208
Abort the patching operation but keep HEAD and the index
209209
untouched.
210210

211+
--retry::
212+
Try to apply the last conflicting patch again. This is generally
213+
only useful for passing extra options to the retry attempt
214+
(e.g., `--3way`), since otherwise you'll just see the same
215+
failure again.
216+
211217
--show-current-patch[=(diff|raw)]::
212218
Show the message at which `git am` has stopped due to
213219
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
@@ -2393,6 +2393,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
23932393
N_("show the patch being applied"),
23942394
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
23952395
parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
2396+
OPT_CMDMODE(0, "retry", &resume_mode,
2397+
N_("try to apply current patch again"),
2398+
RESUME_APPLY),
23962399
OPT_CMDMODE(0, "allow-empty", &resume_mode,
23972400
N_("record the empty patch as an empty commit"),
23982401
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
'

t/test-terminal.perl

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@
55
use IO::Pty;
66
use File::Copy;
77

8-
# Run @$argv in the background with stdio redirected to $in, $out and $err.
8+
# Run @$argv in the background with stdio redirected to $out and $err.
99
sub start_child {
10-
my ($argv, $in, $out, $err) = @_;
10+
my ($argv, $out, $err) = @_;
1111
my $pid = fork;
1212
if (not defined $pid) {
1313
die "fork failed: $!"
1414
} elsif ($pid == 0) {
15-
open STDIN, "<&", $in;
1615
open STDOUT, ">&", $out;
1716
open STDERR, ">&", $err;
18-
close $in;
1917
close $out;
2018
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
2119
}
@@ -51,17 +49,6 @@ sub xsendfile {
5149
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
5250
}
5351

54-
sub copy_stdin {
55-
my ($in) = @_;
56-
my $pid = fork;
57-
if (!$pid) {
58-
xsendfile($in, \*STDIN);
59-
exit 0;
60-
}
61-
close($in);
62-
return $pid;
63-
}
64-
6552
sub copy_stdio {
6653
my ($out, $err) = @_;
6754
my $pid = fork;
@@ -81,25 +68,15 @@ sub copy_stdio {
8168
die "usage: test-terminal program args";
8269
}
8370
$ENV{TERM} = 'vt100';
84-
my $parent_in = new IO::Pty;
8571
my $parent_out = new IO::Pty;
8672
my $parent_err = new IO::Pty;
87-
$parent_in->set_raw();
8873
$parent_out->set_raw();
8974
$parent_err->set_raw();
90-
$parent_in->slave->set_raw();
9175
$parent_out->slave->set_raw();
9276
$parent_err->slave->set_raw();
93-
my $pid = start_child(\@ARGV, $parent_in->slave, $parent_out->slave, $parent_err->slave);
94-
close $parent_in->slave;
77+
my $pid = start_child(\@ARGV, $parent_out->slave, $parent_err->slave);
9578
close $parent_out->slave;
9679
close $parent_err->slave;
97-
my $in_pid = copy_stdin($parent_in);
9880
copy_stdio($parent_out, $parent_err);
9981
my $ret = finish_child($pid);
100-
# If the child process terminates before our copy_stdin() process is able to
101-
# write all of its data to $parent_in, the copy_stdin() process could stall.
102-
# Send SIGTERM to it to ensure it terminates.
103-
kill 'TERM', $in_pid;
104-
finish_child($in_pid);
10582
exit($ret);

0 commit comments

Comments
 (0)