Skip to content

Commit 6e18251

Browse files
jaysoffiangitster
authored andcommitted
send-email: refactor and ensure prompting doesn't loop forever
Several places in send-email prompt for input, and will do so forever when the input is EOF. This is poor behavior when send-email is run unattended (say from cron). This patch refactors the prompting to an ask() function which takes a prompt, an optional default, and an optional regex to validate the input. The function returns on EOF, or if a default is provided and the user simply types return, or if the input passes the validating regex (which accepts all input by default). The ask() function gives up after 10 tries in case of invalid input. There are four callers of the function: 1) "Who should the emails appear to be from?" which provides a default sender. Previously the user would have to type ctrl-d to accept the default. Now the user can just hit return, or type ctrl-d. 2) "Who should the emails be sent to?". Previously this prompt passed a second argument ("") to $term->readline() which was ignored. I believe the intent was to allow the user to just hit return. Now the user can do so, or type ctrl-d. 3) "Message-ID to be used as In-Reply-To for the first email?". Previously this prompt passed a second argument (effectively undef) to $term->readline() which was ignored. I believe the intent was the same as for (2), to allow the user to just hit return. Now the user can do so, or type ctrl-d. 4) "Send this email?". Previously this prompt would loop forever until it got a valid reply. Now it stops prompting on EOF or a valid reply. In the case where confirm = "inform", it now defaults to "y" on EOF or the user hitting return, otherwise an invalid reply causes send-email to terminate. A followup patch adds tests for the new functionality. Signed-off-by: Jay Soffian <jaysoffian@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 18d5cf9 commit 6e18251

File tree

1 file changed

+34
-32
lines changed

1 file changed

+34
-32
lines changed

git-send-email.perl

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -606,32 +606,40 @@ ($)
606606
do_edit(@files);
607607
}
608608

609+
sub ask {
610+
my ($prompt, %arg) = @_;
611+
my $valid_re = $arg{valid_re} || ""; # "" matches anything
612+
my $default = $arg{default};
613+
my $resp;
614+
my $i = 0;
615+
while ($i++ < 10) {
616+
$resp = $term->readline($prompt);
617+
if (!defined $resp) { # EOF
618+
print "\n";
619+
return defined $default ? $default : undef;
620+
}
621+
if ($resp eq '' and defined $default) {
622+
return $default;
623+
}
624+
if ($resp =~ /$valid_re/) {
625+
return $resp;
626+
}
627+
}
628+
return undef;
629+
}
630+
609631
my $prompting = 0;
610632
if (!defined $sender) {
611633
$sender = $repoauthor || $repocommitter || '';
612-
613-
while (1) {
614-
$_ = $term->readline("Who should the emails appear to be from? [$sender] ");
615-
last if defined $_;
616-
print "\n";
617-
}
618-
619-
$sender = $_ if ($_);
634+
$sender = ask("Who should the emails appear to be from? [$sender] ",
635+
default => $sender);
620636
print "Emails will be sent from: ", $sender, "\n";
621637
$prompting++;
622638
}
623639

624640
if (!@to) {
625-
626-
627-
while (1) {
628-
$_ = $term->readline("Who should the emails be sent to? ", "");
629-
last if defined $_;
630-
print "\n";
631-
}
632-
633-
my $to = $_;
634-
push @to, parse_address_line($to);
641+
my $to = ask("Who should the emails be sent to? ");
642+
push @to, parse_address_line($to) if defined $to; # sanitized/validated later
635643
$prompting++;
636644
}
637645

@@ -651,13 +659,8 @@ sub expand_aliases {
651659
@bcclist = expand_aliases(@bcclist);
652660

653661
if ($thread && !defined $initial_reply_to && $prompting) {
654-
while (1) {
655-
$_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
656-
last if defined $_;
657-
print "\n";
658-
}
659-
660-
$initial_reply_to = $_;
662+
$initial_reply_to = ask(
663+
"Message-ID to be used as In-Reply-To for the first email? ");
661664
}
662665
if (defined $initial_reply_to) {
663666
$initial_reply_to =~ s/^\s*<?//;
@@ -839,8 +842,10 @@ sub send_message
839842

840843
if ($needs_confirm && !$dry_run) {
841844
print "\n$header\n";
845+
my $ask_default;
842846
if ($needs_confirm eq "inform") {
843847
$confirm_unconfigured = 0; # squelch this message for the rest of this run
848+
$ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
844849
print " The Cc list above has been expanded by additional\n";
845850
print " addresses found in the patch commit message. By default\n";
846851
print " send-email prompts before sending whenever this occurs.\n";
@@ -851,13 +856,10 @@ sub send_message
851856
print " To retain the current behavior, but squelch this message,\n";
852857
print " run 'git config --global sendemail.confirm auto'.\n\n";
853858
}
854-
while (1) {
855-
chomp ($_ = $term->readline(
856-
"Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
857-
));
858-
last if /^(?:yes|y|no|n|quit|q|all|a)/i;
859-
print "\n";
860-
}
859+
$_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
860+
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
861+
default => $ask_default);
862+
die "Send this email reply required" unless defined $_;
861863
if (/^n/i) {
862864
return;
863865
} elsif (/^q/i) {

0 commit comments

Comments
 (0)