diff options
-rw-r--r-- | lib/PublicInbox/Git.pm | 22 | ||||
-rw-r--r-- | t/git.t | 12 |
2 files changed, 26 insertions, 8 deletions
diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index bd945007..2b6782a7 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -12,6 +12,8 @@ use warnings; use POSIX qw(dup2); require IO::Handle; use PublicInbox::Spawn qw(spawn popen_rd); +use IO::File; +use Fcntl qw(:seek); # Documentation/SubmittingPatches recommends 12 (Linux v4.4) my $abbrev = `git config core.abbrev` || 12; @@ -20,7 +22,25 @@ sub abbrev { "--abbrev=$abbrev" } sub new { my ($class, $git_dir) = @_; - bless { git_dir => $git_dir }, $class + bless { git_dir => $git_dir, err => IO::File->new_tmpfile }, $class +} + +sub err_begin ($) { + my $err = $_[0]->{err}; + sysseek($err, 0, SEEK_SET) or die "sysseek failed: $!"; + truncate($err, 0) or die "truncate failed: $!"; + my $ret = fileno($err); + defined $ret or die "fileno failed: $!"; + $ret; +} + +sub err ($) { + my $err = $_[0]->{err}; + sysseek($err, 0, SEEK_SET) or die "sysseek failed: $!"; + defined(sysread($err, my $buf, -s $err)) or die "sysread failed: $!"; + sysseek($err, 0, SEEK_SET) or die "sysseek failed: $!"; + truncate($err, 0) or die "truncate failed: $!"; + $buf; } sub _bidi_pipe { @@ -141,27 +141,25 @@ if (1) { { my $git = PublicInbox::Git->new($dir); - open my $tmperr, '>&', \*STDERR or die "dup stderr failed: $!\n"; - open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; - my $err = $git->popen(qw(cat-file blob non-existent)); + my $err = $git->popen([qw(cat-file blob non-existent)], undef, + { 2 => $git->err_begin }); my @out = <$err>; my $close_ret = close $err; my $close_err = $?; - open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; is(join('', @out), '', 'no output on stdout on error'); isnt($close_err, 0, 'close set $? on bad command'); ok(!$close_ret, 'close returned error on bad command'); + isnt($git->err, '', 'got stderr output'); - open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; - $err = $git->popen(qw(tag -l)); + $err = $git->popen([qw(tag -l)], undef, { 2 => $git->err_begin }); @out = <$err>; $close_ret = close $err; $close_err = $?; - open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; is(join('', @out), '', 'no output on stdout on error'); ok(!$close_err, 'close clobbered $? on empty output'); ok($close_ret, 'close returned error on empty output'); + is($git->err, '', 'no stderr output'); } done_testing(); |