git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] fix git-send-email with recent versions of Term::ReadLine::Gnu
@ 2023-08-08 18:09 Jeff King
  2023-08-08 18:14 ` [PATCH 1/2] send-email: drop FakeTerm hack Jeff King
  2023-08-08 18:15 ` [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object Jeff King
  0 siblings, 2 replies; 5+ messages in thread
From: Jeff King @ 2023-08-08 18:09 UTC (permalink / raw)
  To: git

Using git-send-email with the latest release of Term::ReadLine::Gnu
causes any invocations which prompt more than once to fail. Details are
in the second patch, which fixes it. The first patch cleans up an
obsolete workaround that obscured the root cause of the problem.

The affected version of Term::ReadLine::Gnu is v1.46, which hit Debian
unstable in the past few weeks. So we should consider this for maint
and perhaps even for the -rc candidates, since people will presumably
start running into this more and more.

  [1/2]: send-email: drop FakeTerm hack
  [2/2]: send-email: avoid creating more than one Term::ReadLine object

 git-send-email.perl   | 32 +++++++++++---------------------
 t/t9001-send-email.sh |  5 +++--
 2 files changed, 14 insertions(+), 23 deletions(-)

-Peff

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] send-email: drop FakeTerm hack
  2023-08-08 18:09 [PATCH 0/2] fix git-send-email with recent versions of Term::ReadLine::Gnu Jeff King
@ 2023-08-08 18:14 ` Jeff King
  2023-08-08 20:13   ` Taylor Blau
  2023-08-08 18:15 ` [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object Jeff King
  1 sibling, 1 reply; 5+ messages in thread
From: Jeff King @ 2023-08-08 18:14 UTC (permalink / raw)
  To: git

Back in 280242d1cc (send-email: do not barf when Term::ReadLine does not
like your terminal, 2006-07-02), we added a fallback for when
Term::ReadLine's constructor failed: we'd have a FakeTerm object
instead, which would then die if anybody actually tried to call
readline() on it. Since we instantiated the $term variable at program
startup, we needed this workaround to let the program run in modes when
we did not prompt the user.

But later, in f4dc9432fd (send-email: lazily load modules for a big
speedup, 2021-05-28), we started loading Term::ReadLine lazily only when
ask() is called. So at that point we know we're trying to prompt the
user, and we can just die if ReadLine instantiation fails, rather than
making this fake object to lazily delay showing the error.

This should be OK even if there is no tty (e.g., we're in a cron job),
because Term::ReadLine will return a stub object in that case whose "IN"
and "OUT" functions return undef. And since 5906f54e47 (send-email:
don't attempt to prompt if tty is closed, 2009-03-31), we check for that
case and skip prompting.

And we can be sure that FakeTerm was not kicking in for such a
situation, because it has actually been broken since that commit! It
does not define "IN" or "OUT" methods, so perl would barf with an error.
If FakeTerm was in use, we were neither honoring what 5906f54e47 tried
to do, nor producing the readable message that 280242d1cc intended.

So we're better off just dropping FakeTerm entirely, and letting the
error reported by constructing Term::ReadLine through.

Signed-off-by: Jeff King <peff@peff.net>
---
The smaller change is to implement:

  sub IN { return undef }

for FakeTerm, which would then behave according to 5906f54e47's "no tty"
behavior. But after reading through the relevant history, I'm fairly
convinced that just dropping it is the right path. If it were actually
kicking in ever, people would be complaining about the obscure
"$term->IN is not defined" error message from perl.

 git-send-email.perl | 22 ++--------------------
 1 file changed, 2 insertions(+), 20 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index affbb88509..4cb6ee9327 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -26,18 +26,6 @@
 
 Getopt::Long::Configure qw/ pass_through /;
 
-package FakeTerm;
-sub new {
-	my ($class, $reason) = @_;
-	return bless \$reason, shift;
-}
-sub readline {
-	my $self = shift;
-	die "Cannot use readline on FakeTerm: $$self";
-}
-package main;
-
-
 sub usage {
 	print <<EOT;
 git send-email' [<options>] <file|directory>
@@ -972,16 +960,10 @@ sub get_patch_subject {
 }
 
 sub term {
-	my $term = eval {
-		require Term::ReadLine;
-		$ENV{"GIT_SEND_EMAIL_NOTTY"}
+	require Term::ReadLine;
+	return $ENV{"GIT_SEND_EMAIL_NOTTY"}
 			? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
 			: Term::ReadLine->new('git-send-email');
-	};
-	if ($@) {
-		$term = FakeTerm->new("$@: going non-interactive");
-	}
-	return $term;
 }
 
 sub ask {
-- 
2.42.0.rc0.376.g66bfc4f195


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object
  2023-08-08 18:09 [PATCH 0/2] fix git-send-email with recent versions of Term::ReadLine::Gnu Jeff King
  2023-08-08 18:14 ` [PATCH 1/2] send-email: drop FakeTerm hack Jeff King
@ 2023-08-08 18:15 ` Jeff King
  2023-08-08 20:16   ` Taylor Blau
  1 sibling, 1 reply; 5+ messages in thread
From: Jeff King @ 2023-08-08 18:15 UTC (permalink / raw)
  To: git

Every time git-send-email calls its ask() function to prompt the user,
we call term(), which instantiates a new Term::ReadLine object. But in
v1.46 of Term::ReadLine::Gnu (which provides the Term::ReadLine
interface on some platforms), its constructor refuses to create a second
instance[1]. So on systems with that version of the module, most
git-send-email instances will fail (as we usually prompt for both "to"
and "in-reply-to" unless the user provided them on the command line).

We can fix this by keeping a single instance variable and returning it
for each call to term(). In perl 5.10 and up, we could do that with a
"state" variable. But since we only require 5.008, we'll do it the
old-fashioned way, with a lexical "my" in its own scope.

Note that the tests in t9001 detect this problem as-is, since the
failure mode is for the program to die. But let's also beef up the
"Prompting works" test to check that it correctly handles multiple
inputs (if we had chosen to keep our FakeTerm hack in the previous
commit, then the failure mode would be incorrectly ignoring prompts
after the first).

[1] For discussion of why multiple instances are forbidden, see:
    https://github.com/hirooih/perl-trg/issues/16

Signed-off-by: Jeff King <peff@peff.net>
---
 git-send-email.perl   | 18 +++++++++++++-----
 t/t9001-send-email.sh |  5 +++--
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 4cb6ee9327..897cea6564 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -959,11 +959,19 @@ sub get_patch_subject {
 	do_edit(@files);
 }
 
-sub term {
-	require Term::ReadLine;
-	return $ENV{"GIT_SEND_EMAIL_NOTTY"}
-			? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
-			: Term::ReadLine->new('git-send-email');
+{
+	# Only instantiate one $term per program run, since some
+	# Term::ReadLine providers refuse to create a second instance.
+	my $term;
+	sub term {
+		require Term::ReadLine;
+		if (!defined $term) {
+			$term = $ENV{"GIT_SEND_EMAIL_NOTTY"}
+				? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
+				: Term::ReadLine->new('git-send-email');
+		}
+		return $term;
+	}
 }
 
 sub ask {
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 48bf0af2ee..0662ff8120 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -337,13 +337,14 @@ test_expect_success $PREREQ 'Show all headers' '
 test_expect_success $PREREQ 'Prompting works' '
 	clean_fake_sendmail &&
 	(echo "to@example.com" &&
-	 echo ""
+	 echo "my-message-id@example.com"
 	) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
 		--smtp-server="$(pwd)/fake.sendmail" \
 		$patches \
 		2>errors &&
 		grep "^From: A U Thor <author@example.com>\$" msgtxt1 &&
-		grep "^To: to@example.com\$" msgtxt1
+		grep "^To: to@example.com\$" msgtxt1 &&
+		grep "^In-Reply-To: <my-message-id@example.com>" msgtxt1
 '
 
 test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' '
-- 
2.42.0.rc0.376.g66bfc4f195

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] send-email: drop FakeTerm hack
  2023-08-08 18:14 ` [PATCH 1/2] send-email: drop FakeTerm hack Jeff King
@ 2023-08-08 20:13   ` Taylor Blau
  0 siblings, 0 replies; 5+ messages in thread
From: Taylor Blau @ 2023-08-08 20:13 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Tue, Aug 08, 2023 at 02:14:36PM -0400, Jeff King wrote:
> The smaller change is to implement:
>
>   sub IN { return undef }
>
> for FakeTerm, which would then behave according to 5906f54e47's "no tty"
> behavior. But after reading through the relevant history, I'm fairly
> convinced that just dropping it is the right path. If it were actually
> kicking in ever, people would be complaining about the obscure
> "$term->IN is not defined" error message from perl.

All makes sense. Thanks for the detailed commit message, as always :-).

Thanks,
Taylor

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object
  2023-08-08 18:15 ` [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object Jeff King
@ 2023-08-08 20:16   ` Taylor Blau
  0 siblings, 0 replies; 5+ messages in thread
From: Taylor Blau @ 2023-08-08 20:16 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Tue, Aug 08, 2023 at 02:15:31PM -0400, Jeff King wrote:
> Every time git-send-email calls its ask() function to prompt the user,
> we call term(), which instantiates a new Term::ReadLine object. But in
> v1.46 of Term::ReadLine::Gnu (which provides the Term::ReadLine
> interface on some platforms), its constructor refuses to create a second
> instance[1]. So on systems with that version of the module, most
> git-send-email instances will fail (as we usually prompt for both "to"
> and "in-reply-to" unless the user provided them on the command line).

Nice one ;-). Everything you wrote here makes sense, as does
initializing the Term::ReadLine object only once.

> Note that the tests in t9001 detect this problem as-is, since the
> failure mode is for the program to die. But let's also beef up the
> "Prompting works" test to check that it correctly handles multiple
> inputs (if we had chosen to keep our FakeTerm hack in the previous
> commit, then the failure mode would be incorrectly ignoring prompts
> after the first).

Thanks for improving the test coverage while you're here.

Everything here LGTM.

Thanks,
Taylor

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-08-08 21:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-08 18:09 [PATCH 0/2] fix git-send-email with recent versions of Term::ReadLine::Gnu Jeff King
2023-08-08 18:14 ` [PATCH 1/2] send-email: drop FakeTerm hack Jeff King
2023-08-08 20:13   ` Taylor Blau
2023-08-08 18:15 ` [PATCH 2/2] send-email: avoid creating more than one Term::ReadLine object Jeff King
2023-08-08 20:16   ` Taylor Blau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).