-# Copyright (C) 2014-2020 all contributors <meta@public-inbox.org>
+# Copyright (C) 2014-2021 all contributors <meta@public-inbox.org>
# License: GPLv2 or later <https://www.gnu.org/licenses/gpl-2.0.txt>
#
# Used to read files from a git repository without excessive forking.
use IO::Poll qw(POLLIN);
use Carp qw(croak);
use Digest::SHA ();
+use PublicInbox::DS qw(dwaitpid);
our @EXPORT_OK = qw(git_unquote git_quote);
our $PIPE_BUFSIZ = 65536; # Linux default
our $in_cleanup;
}
my ($in_r, $p) = popen_rd(\@cmd, undef, $redir);
$self->{$pid} = $p;
+ $self->{"$pid.owner"} = $$;
$out_w->autoflush(1);
if ($^O eq 'linux') { # 1031: F_SETPIPE_SZ
fcntl($out_w, 1031, 4096);
# GitAsyncCat::event_step may delete {pid}
my $p = delete $self->{$pid} or return;
-
- # PublicInbox::DS may not be loaded
- eval { PublicInbox::DS::dwaitpid($p, undef, undef) };
- waitpid($p, 0) if $@; # wait synchronously if not in event loop
+ dwaitpid($p) if $$ == $self->{"$pid.owner"};
}
sub cat_async_abort ($) {
croak(ref($self) . ' ' . ($self->{git_dir} // '') . ": $msg");
}
+# $git->popen(qw(show f00)); # or
+# $git->popen(qw(show f00), { GIT_CONFIG => ... }, { 2 => ... });
sub popen {
- my ($self, @cmd) = @_;
- @cmd = ('git', "--git-dir=$self->{git_dir}", @cmd);
- popen_rd(\@cmd);
+ my ($self, $cmd) = splice(@_, 0, 2);
+ $cmd = [ 'git', "--git-dir=$self->{git_dir}",
+ ref($cmd) ? @$cmd : ($cmd, grep { defined && !ref } @_) ];
+ popen_rd($cmd, grep { !defined || ref } @_); # env and opt
}
+# same args as popen above
sub qx {
- my ($self, @cmd) = @_;
- my $fh = $self->popen(@cmd);
- local $/ = wantarray ? "\n" : undef;
- <$fh>;
+ my $self = shift;
+ my $fh = $self->popen(@_);
+ if (wantarray) {
+ local $/ = "\n";
+ my @ret = <$fh>;
+ close $fh; # caller should check $?
+ @ret;
+ } else {
+ local $/;
+ my $ret = <$fh>;
+ close $fh; # caller should check $?
+ $ret;
+ }
}
# check_async and cat_async may trigger the other, so ensure they're
# templates/this--description in git.git
sub manifest_entry {
my ($self, $epoch, $default_desc) = @_;
- my ($fh, $pid) = $self->popen('show-ref');
+ my $fh = $self->popen('show-ref');
my $dig = Digest::SHA->new(1);
while (read($fh, my $buf, 65536)) {
$dig->add($buf);
}
- close $fh;
- waitpid($pid, 0);
- return if $?; # empty, uninitialized git repo
+ close $fh or return; # empty, uninitialized git repo
+ undef $fh; # for open, below
my $git_dir = $self->{git_dir};
my $ent = {
fingerprint => $dig->hexdigest,