my $repo = delete $git->{-repo} or return index_next($self);
my $roots_fh = delete $repo->{roots_fh} // die 'BUG: no {roots_fh}';
seek($roots_fh, 0, SEEK_SET);
- chomp(my @roots = <$roots_fh>);
- $roots_fh = eof($roots_fh) | close $roots_fh; # detect readline errors
+ chomp(my @roots = PublicInbox::IO::read_all $roots_fh);
if (!@roots) {
warn("E: $git->{git_dir} has no root commits\n");
return index_next($self);
#
# See https://bugs.debian.org/975607
if (open(my $fh, '<', "$objdir/info/alternates")) {
- chomp(my @abs_alt = grep(m!^/!, <$fh>));
- $fh = eof($fh) | close $fh; # detect readline errors
+ chomp(my @abs_alt = grep m!^/!, PublicInbox::IO::read_all $fh);
$gcf2->add_alternate($_) for @abs_alt;
}
$gcf2->add_alternate($objdir);
IO::Poll::_poll($_[1] // -1, fileno($_[0]), my $ev = POLLIN);
}
-sub read_all ($;$$) {
+sub read_all ($;$$$) { # pass $len=0 to read until EOF for :utf8 handles
use autodie qw(read);
- my ($io, $len, $bref) = @_;
+ my ($io, $len, $bref, $off) = @_;
$bref //= \(my $buf);
- my $r = read($io, $$bref, $len //= -s $io);
- croak("read($io) ($r != $len)") if $len != $r;
- $$bref;
+ $off //= 0;
+ my $r = 0;
+ if (my $left = $len //= -s $io) { # known size (binmode :raw/:unix)
+ do { # retry for binmode :unix
+ $r = read($io, $$bref, $left, $off += $r) or croak(
+ "read($io) premature EOF ($left/$len remain)");
+ } while ($left -= $r);
+ } else { # read until EOF
+ while (($r = read($io, $$bref, 65536, $off += $r))) {}
+ }
+ wantarray ? split(/^/sm, $$bref) : $$bref
}
sub try_cat ($) {
sub input_fh {
my ($self, $ifmt, $fh, $name, @args) = @_;
if ($ifmt eq 'eml') {
- my $buf = do { local $/; <$fh> };
- my $ok = defined($buf) ? 1 : 0;
- ++$ok if eof($fh);
- ++$ok if $fh->close;
- $ok == 3 or return $self->{lei}->child_error($?, <<"");
-error reading $name: $! (\$?=$?)
+ my $buf = eval { PublicInbox::IO::read_all $fh, 0 };
+ my $e = $@;
+ return $self->{lei}->child_error($?, <<"") if !$fh->close || $e;
+error reading $name: $! (\$?=$?) (\$@=$e)
PublicInbox::Eml::strip_from($buf);
my $dstfh = delete $fgrp->{dstfh} or return;
seek($srcfh, 0, SEEK_SET);
seek($dstfh, 0, SEEK_SET);
- my %src = map { chomp; split(/\0/) } (<$srcfh>);
- my %dst = map { chomp; split(/\0/) } (<$dstfh>);
- $srcfh = eof($srcfh) | close $srcfh; # detects readline errors
- $dstfh = eof($dstfh) | close $dstfh; # ditto
+ my %src = map { chomp; split /\0/ } PublicInbox::IO::read_all $srcfh;
+ my %dst = map { chomp; split /\0/ } PublicInbox::IO::read_all $dstfh;
+ $srcfh = $dstfh = undef;
my $w = start_update_ref($fgrp) or return;
my $lei = $fgrp->{lei};
my $ndel;
my $l = File::Spec->abs2rel($alt, File::Spec->rel2abs($o));
open my $fh, '+>>', my $f = "$o/info/alternates";
seek($fh, 0, SEEK_SET); # Perl did SEEK_END when it saw '>>'
- my $seen = grep(/\A\Q$l\E\n/, <$fh>); # error check with eof
- eof($fh) or die "not at `$f' EOF ($!)"; # $! was set by readline
+ my $seen = grep /\A\Q$l\E\n/, PublicInbox::IO::read_all $fh;
print $fh "$l\n" if !$seen;
close $fh;
}
my $d = "$lei->{ale}->{git}->{git_dir}/objects";
open my $fh, '+>>', my $f = "$dir/git/0.git/objects/info/alternates";
seek($fh, 0, SEEK_SET); # Perl did SEEK_END when it saw '>>'
- my $seen = grep(/\A\Q$d\E\n/, <$fh>);
- eof($fh) or die "not at `$f' EOF ($!)"; # $! was set by readline
+ my $seen = grep /\A\Q$d\E\n/, PublicInbox::IO::read_all $fh;
print $fh "$d\n" if !$seen;
close $fh;
}
sub read_out_err ($) {
my ($opt) = @_;
- local $/;
for my $fd (1, 2) { # read stdout/stderr
my $fh = delete($opt->{"fh.$fd"}) // next;
seek($fh, 0, SEEK_SET);
my $dst = $opt->{$fd};
$dst = $opt->{$fd} = $dst->[1] if ref($dst) eq 'ARRAY';
- $$dst .= <$fh>;
- $fh = eof($fh) | close $fh; # detects readline errors
+ PublicInbox::IO::read_all $fh, 0, $dst, length($$dst);
}
}
sub xbail (@) { BAIL_OUT join(' ', map { ref() ? (explain($_)) : ($_) } @_) }
-sub read_all ($;$$) {
+sub read_all ($;$$$) {
require PublicInbox::IO;
- PublicInbox::IO::read_all($_[0], $_[1], $_[2])
+ PublicInbox::IO::read_all($_[0], $_[1], $_[2], $_[3])
}
sub eml_load ($) {
my ($path, $cb) = @_;
open(my $fh, '<', $path);
require PublicInbox::Eml;
- PublicInbox::Eml->new(\(read_all($fh)));
+ PublicInbox::Eml->new(\(scalar read_all $fh));
}
sub tmpdir (;$) {
PublicInbox::Import::load_config($pi_cfg);
my $err;
my $mime = PublicInbox::Eml->new(do{
- defined(my $data = do { local $/; <STDIN> }) or die "read STDIN: $!\n";
+ my $data = PublicInbox::IO::read_all \*STDIN;
PublicInbox::Eml::strip_from($data);
if ($train ne 'rm') {
# in case there's bugs in our code or user error.
my $emergency = $ENV{PI_EMERGENCY} || "$ENV{HOME}/.public-inbox/emergency/";
$ems = PublicInbox::Emergency->new($emergency);
-my $str = do { local $/; <STDIN> };
+my $str = PublicInbox::IO::read_all \*STDIN;
PublicInbox::Eml::strip_from($str);
$ems->prepare(\$str);
my $eml = PublicInbox::Eml->new(\$str);
my @ibxs = PublicInbox::Admin::resolve_inboxes(\@ARGV, $opt);
PublicInbox::AdminEdit::check_editable(\@ibxs);
-defined(my $data = do { local $/; <STDIN> }) or die "read STDIN: $!\n";
+my $data = PublicInbox::IO::read_all \*STDIN;
PublicInbox::Eml::strip_from($data);
my $n_purged = 0;