X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FGitCatFile.pm;h=4f16762e56c8959eaaed4c7d91d3a7e647f7e729;hb=f76f265a851944b5dedcc3be5f3b5224b6ebda89;hp=b75389e2fdb3ebf5958c5366dffd5356dfbf22d6;hpb=f286304f47685f6530462439b95951e2af86051f;p=public-inbox.git diff --git a/lib/PublicInbox/GitCatFile.pm b/lib/PublicInbox/GitCatFile.pm index b75389e2..4f16762e 100644 --- a/lib/PublicInbox/GitCatFile.pm +++ b/lib/PublicInbox/GitCatFile.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2014, Eric Wong and all contributors +# Copyright (C) 2014-2015 all contributors # License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt) # This is based on code in Git.pm which is GPLv2, but modified to avoid # dependence on environment variables for compatibility with mod_perl. @@ -6,30 +6,20 @@ package PublicInbox::GitCatFile; use strict; use warnings; -use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC); use POSIX qw(dup2); -require IO::Handle; sub new { my ($class, $git_dir) = @_; bless { git_dir => $git_dir }, $class; } -sub set_cloexec { - my ($fh) = @_; - my $flags = fcntl($fh, F_GETFD, 0) or die "fcntl(F_GETFD): $!\n"; - fcntl($fh, F_SETFD, $flags | FD_CLOEXEC) or die "fcntl(F_SETFD): $!\n"; -} - sub _cat_file_begin { my ($self) = @_; return if $self->{pid}; my ($in_r, $in_w, $out_r, $out_w); pipe($in_r, $in_w) or die "pipe failed: $!\n"; - set_cloexec($_) foreach ($in_r, $in_w); pipe($out_r, $out_w) or die "pipe failed: $!\n"; - set_cloexec($_) foreach ($out_r, $out_w); my @cmd = ('git', "--git-dir=$self->{git_dir}", qw(cat-file --batch)); my $pid = fork; @@ -42,7 +32,6 @@ sub _cat_file_begin { close $out_r or die "close failed: $!\n"; close $in_w or die "close failed: $!\n"; - $out_w->autoflush(1); $self->{in} = $in_r; $self->{out} = $out_w; $self->{pid} = $pid; @@ -51,8 +40,16 @@ sub _cat_file_begin { sub cat_file { my ($self, $object) = @_; + $object .= "\n"; + my $len = bytes::length($object); + $self->_cat_file_begin; - print { $self->{out} } $object, "\n" or die "write error: $!\n"; + my $written = syswrite($self->{out}, $object); + if (!defined $written) { + die "pipe write error: $!\n"; + } elsif ($written != $len) { + die "wrote too little to pipe ($written < $len)\n"; + } my $in = $self->{in}; my $head = <$in>; @@ -62,17 +59,17 @@ sub cat_file { my $size = $1; my $bytes_left = $size; - my $buf; + my $offset = 0; my $rv = ''; while ($bytes_left) { - my $read = read($in, $buf, $bytes_left); - defined($read) or die "read pipe failed: $!\n"; - $rv .= $buf; + my $read = read($in, $rv, $bytes_left, $offset); + defined($read) or die "sysread pipe failed: $!\n"; $bytes_left -= $read; + $offset += $read; } - my $read = read($in, $buf, 1); + my $read = read($in, my $buf, 1); defined($read) or die "read pipe failed: $!\n"; if ($read != 1 || $buf ne "\n") { die "newline missing after blob\n";