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" optionmaint
commit
42b8b5bfd0
|
@ -18,7 +18,7 @@ SYNOPSIS
|
||||||
[--quoted-cr=<action>]
|
[--quoted-cr=<action>]
|
||||||
[--empty=(stop|drop|keep)]
|
[--empty=(stop|drop|keep)]
|
||||||
[(<mbox> | <Maildir>)...]
|
[(<mbox> | <Maildir>)...]
|
||||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)] | --allow-empty)
|
'git am' (--continue | --skip | --abort | --quit | --retry | --show-current-patch[=(diff|raw)] | --allow-empty)
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -208,6 +208,12 @@ Valid <action> for the `--whitespace` option are:
|
||||||
Abort the patching operation but keep HEAD and the index
|
Abort the patching operation but keep HEAD and the index
|
||||||
untouched.
|
untouched.
|
||||||
|
|
||||||
|
--retry::
|
||||||
|
Try to apply the last conflicting patch again. This is generally
|
||||||
|
only useful for passing extra options to the retry attempt
|
||||||
|
(e.g., `--3way`), since otherwise you'll just see the same
|
||||||
|
failure again.
|
||||||
|
|
||||||
--show-current-patch[=(diff|raw)]::
|
--show-current-patch[=(diff|raw)]::
|
||||||
Show the message at which `git am` has stopped due to
|
Show the message at which `git am` has stopped due to
|
||||||
conflicts. If `raw` is specified, show the raw contents of
|
conflicts. If `raw` is specified, show the raw contents of
|
||||||
|
|
|
@ -2393,6 +2393,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
N_("show the patch being applied"),
|
N_("show the patch being applied"),
|
||||||
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
|
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
|
||||||
parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
|
parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
|
||||||
|
OPT_CMDMODE(0, "retry", &resume_mode,
|
||||||
|
N_("try to apply current patch again"),
|
||||||
|
RESUME_APPLY),
|
||||||
OPT_CMDMODE(0, "allow-empty", &resume_mode,
|
OPT_CMDMODE(0, "allow-empty", &resume_mode,
|
||||||
N_("record the empty patch as an empty commit"),
|
N_("record the empty patch as an empty commit"),
|
||||||
RESUME_ALLOW_EMPTY),
|
RESUME_ALLOW_EMPTY),
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
test_description='git-am command-line options override saved options'
|
test_description='git-am command-line options override saved options'
|
||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
. "$TEST_DIRECTORY"/lib-terminal.sh
|
|
||||||
|
|
||||||
format_patch () {
|
format_patch () {
|
||||||
git format-patch --stdout -1 "$1" >"$1".eml
|
git format-patch --stdout -1 "$1" >"$1".eml
|
||||||
|
@ -27,7 +26,12 @@ test_expect_success 'setup' '
|
||||||
format_patch side2
|
format_patch side2
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success TTY '--3way overrides --no-3way' '
|
test_expect_success '--retry fails without in-progress operation' '
|
||||||
|
test_must_fail git am --retry 2>err &&
|
||||||
|
test_grep "operation not in progress" err
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--3way overrides --no-3way' '
|
||||||
rm -fr .git/rebase-apply &&
|
rm -fr .git/rebase-apply &&
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
git checkout renamed-file &&
|
git checkout renamed-file &&
|
||||||
|
@ -40,7 +44,7 @@ test_expect_success TTY '--3way overrides --no-3way' '
|
||||||
|
|
||||||
# Applying side1 with am --3way will succeed due to the threeway-merge.
|
# Applying side1 with am --3way will succeed due to the threeway-merge.
|
||||||
# Applying side2 will fail as --3way does not apply to it.
|
# Applying side2 will fail as --3way does not apply to it.
|
||||||
test_must_fail test_terminal git am --3way </dev/zero &&
|
test_must_fail git am --retry --3way &&
|
||||||
test_path_is_dir .git/rebase-apply &&
|
test_path_is_dir .git/rebase-apply &&
|
||||||
test side1 = "$(cat file2)"
|
test side1 = "$(cat file2)"
|
||||||
'
|
'
|
||||||
|
@ -84,7 +88,7 @@ test_expect_success '--signoff overrides --no-signoff' '
|
||||||
test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
|
test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success TTY '--reject overrides --no-reject' '
|
test_expect_success '--reject overrides --no-reject' '
|
||||||
rm -fr .git/rebase-apply &&
|
rm -fr .git/rebase-apply &&
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
git checkout first &&
|
git checkout first &&
|
||||||
|
@ -94,7 +98,7 @@ test_expect_success TTY '--reject overrides --no-reject' '
|
||||||
test_path_is_dir .git/rebase-apply &&
|
test_path_is_dir .git/rebase-apply &&
|
||||||
test_path_is_missing file.rej &&
|
test_path_is_missing file.rej &&
|
||||||
|
|
||||||
test_must_fail test_terminal git am --reject </dev/zero &&
|
test_must_fail git am --retry --reject </dev/zero &&
|
||||||
test_path_is_dir .git/rebase-apply &&
|
test_path_is_dir .git/rebase-apply &&
|
||||||
test_path_is_file file.rej
|
test_path_is_file file.rej
|
||||||
'
|
'
|
||||||
|
|
|
@ -5,17 +5,15 @@ use warnings;
|
||||||
use IO::Pty;
|
use IO::Pty;
|
||||||
use File::Copy;
|
use File::Copy;
|
||||||
|
|
||||||
# Run @$argv in the background with stdio redirected to $in, $out and $err.
|
# Run @$argv in the background with stdio redirected to $out and $err.
|
||||||
sub start_child {
|
sub start_child {
|
||||||
my ($argv, $in, $out, $err) = @_;
|
my ($argv, $out, $err) = @_;
|
||||||
my $pid = fork;
|
my $pid = fork;
|
||||||
if (not defined $pid) {
|
if (not defined $pid) {
|
||||||
die "fork failed: $!"
|
die "fork failed: $!"
|
||||||
} elsif ($pid == 0) {
|
} elsif ($pid == 0) {
|
||||||
open STDIN, "<&", $in;
|
|
||||||
open STDOUT, ">&", $out;
|
open STDOUT, ">&", $out;
|
||||||
open STDERR, ">&", $err;
|
open STDERR, ">&", $err;
|
||||||
close $in;
|
|
||||||
close $out;
|
close $out;
|
||||||
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
|
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
|
||||||
}
|
}
|
||||||
|
@ -51,17 +49,6 @@ sub xsendfile {
|
||||||
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
|
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub copy_stdin {
|
|
||||||
my ($in) = @_;
|
|
||||||
my $pid = fork;
|
|
||||||
if (!$pid) {
|
|
||||||
xsendfile($in, \*STDIN);
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
close($in);
|
|
||||||
return $pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub copy_stdio {
|
sub copy_stdio {
|
||||||
my ($out, $err) = @_;
|
my ($out, $err) = @_;
|
||||||
my $pid = fork;
|
my $pid = fork;
|
||||||
|
@ -81,25 +68,15 @@ if ($#ARGV < 1) {
|
||||||
die "usage: test-terminal program args";
|
die "usage: test-terminal program args";
|
||||||
}
|
}
|
||||||
$ENV{TERM} = 'vt100';
|
$ENV{TERM} = 'vt100';
|
||||||
my $parent_in = new IO::Pty;
|
|
||||||
my $parent_out = new IO::Pty;
|
my $parent_out = new IO::Pty;
|
||||||
my $parent_err = new IO::Pty;
|
my $parent_err = new IO::Pty;
|
||||||
$parent_in->set_raw();
|
|
||||||
$parent_out->set_raw();
|
$parent_out->set_raw();
|
||||||
$parent_err->set_raw();
|
$parent_err->set_raw();
|
||||||
$parent_in->slave->set_raw();
|
|
||||||
$parent_out->slave->set_raw();
|
$parent_out->slave->set_raw();
|
||||||
$parent_err->slave->set_raw();
|
$parent_err->slave->set_raw();
|
||||||
my $pid = start_child(\@ARGV, $parent_in->slave, $parent_out->slave, $parent_err->slave);
|
my $pid = start_child(\@ARGV, $parent_out->slave, $parent_err->slave);
|
||||||
close $parent_in->slave;
|
|
||||||
close $parent_out->slave;
|
close $parent_out->slave;
|
||||||
close $parent_err->slave;
|
close $parent_err->slave;
|
||||||
my $in_pid = copy_stdin($parent_in);
|
|
||||||
copy_stdio($parent_out, $parent_err);
|
copy_stdio($parent_out, $parent_err);
|
||||||
my $ret = finish_child($pid);
|
my $ret = finish_child($pid);
|
||||||
# If the child process terminates before our copy_stdin() process is able to
|
|
||||||
# write all of its data to $parent_in, the copy_stdin() process could stall.
|
|
||||||
# Send SIGTERM to it to ensure it terminates.
|
|
||||||
kill 'TERM', $in_pid;
|
|
||||||
finish_child($in_pid);
|
|
||||||
exit($ret);
|
exit($ret);
|
||||||
|
|
Loading…
Reference in New Issue