From 3377b0c87167d6a8a4df5c8fa05be030e9b5caa4 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 24 Dec 2015 11:36:33 +0000 Subject: git: expand callback to support object ID and type This metadata can be useful on an optional basis; allowing calls to $git->check to be skipped. --- lib/PublicInbox/Git.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index 0f92dd9a..4bc879ff 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -43,10 +43,10 @@ sub cat_file { my $in = $self->{in}; my $head = $in->getline; $head =~ / missing$/ and return undef; - $head =~ /^[0-9a-f]{40} \S+ (\d+)$/ or + $head =~ /^([0-9a-f]{40}) (\S+) (\d+)$/ or fail($self, "Unexpected result from git cat-file: $head"); - my $size = $1; + my ($hex, $type, $size) = ($1, $2, $3); my $ref_type = $ref ? ref($ref) : ''; my $rv; @@ -55,7 +55,7 @@ sub cat_file { my $cb_err; if ($ref_type eq 'CODE') { - $rv = eval { $ref->($in, \$left) }; + $rv = eval { $ref->($in, \$left, $type, $hex) }; $cb_err = $@; # drain the rest my $max = 8192; -- cgit v1.2.3-24-ge0c7 From a517b9d1e4450724dc5cf523bde0ba4642c96e7b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 24 Dec 2015 21:58:00 +0000 Subject: git: factor out cat_file_begin and cat_file_finish Unfortunately, it seems being able to handle callbacks is insufficient; and these methods will allow us to avoid making an extra $git->check call. --- lib/PublicInbox/Git.pm | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index 4bc879ff..aec2db0b 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -34,9 +34,8 @@ sub _bidi_pipe { $self->{$in} = $in_r; } -sub cat_file { - my ($self, $obj, $ref) = @_; - +sub cat_file_begin { + my ($self, $obj) = @_; $self->_bidi_pipe(qw(--batch in out pid)); $self->{out}->print($obj, "\n") or fail($self, "write error: $!"); @@ -46,7 +45,31 @@ sub cat_file { $head =~ /^([0-9a-f]{40}) (\S+) (\d+)$/ or fail($self, "Unexpected result from git cat-file: $head"); - my ($hex, $type, $size) = ($1, $2, $3); + ($in, $1, $2, $3); +} + +sub cat_file_finish { + my ($self, $left) = @_; + my $max = 8192; + my $in = $self->{in}; + my $buf; + while ($left > 0) { + my $r = read($in, $buf, $left > $max ? $max : $left); + defined($r) or fail($self, "read failed: $!"); + $r == 0 and fail($self, 'exited unexpectedly'); + $left -= $r; + } + + my $r = read($in, $buf, 1); + defined($r) or fail($self, "read failed: $!"); + fail($self, 'newline missing after blob') if ($r != 1 || $buf ne "\n"); +} + +sub cat_file { + my ($self, $obj, $ref) = @_; + + my ($in, $hex, $type, $size) = $self->cat_file_begin($obj); + return unless $in; my $ref_type = $ref ? ref($ref) : ''; my $rv; @@ -57,14 +80,6 @@ sub cat_file { if ($ref_type eq 'CODE') { $rv = eval { $ref->($in, \$left, $type, $hex) }; $cb_err = $@; - # drain the rest - my $max = 8192; - while ($left > 0) { - my $r = read($in, my $x, $left > $max ? $max : $left); - defined($r) or fail($self, "read failed: $!"); - $r == 0 and fail($self, 'exited unexpectedly'); - $left -= $r; - } } else { my $offset = 0; my $buf = ''; @@ -77,10 +92,7 @@ sub cat_file { } $rv = \$buf; } - - my $r = read($in, my $buf, 1); - defined($r) or fail($self, "read failed: $!"); - fail($self, 'newline missing after blob') if ($r != 1 || $buf ne "\n"); + $self->cat_file_finish($left); die $cb_err if $cb_err; $rv; -- cgit v1.2.3-24-ge0c7 From dae834c0e548c4f048cfd158c1994879eb643bbd Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 28 Dec 2015 00:04:03 +0000 Subject: git: local $/ for getline We may be setting $/ elsewhere, so do not let our callers inadvertantly break us. --- lib/PublicInbox/Git.pm | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index aec2db0b..a7e50925 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -40,6 +40,7 @@ sub cat_file_begin { $self->{out}->print($obj, "\n") or fail($self, "write error: $!"); my $in = $self->{in}; + local $/ = "\n"; my $head = $in->getline; $head =~ / missing$/ and return undef; $head =~ /^([0-9a-f]{40}) (\S+) (\d+)$/ or @@ -102,6 +103,7 @@ sub check { my ($self, $obj) = @_; $self->_bidi_pipe(qw(--batch-check in_c out_c pid_c)); $self->{out_c}->print($obj, "\n") or fail($self, "write error: $!"); + local $/ = "\n"; chomp(my $line = $self->{in_c}->getline); my ($hex, $type, $size) = split(' ', $line); return if $type eq 'missing'; -- cgit v1.2.3-24-ge0c7 From e82a365d610f4939767c219fd3d642915cd1826c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 31 Dec 2015 21:16:39 +0000 Subject: git: add support for qx wrapper This lets us one-line git commands easily like ``, but without having to remember --git-dir or escape arguments. --- lib/PublicInbox/Git.pm | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index a7e50925..ac556426 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -131,6 +131,14 @@ sub popen { popen_rd(\@cmd); } +sub qx { + my ($self, @cmd) = @_; + my $fh = $self->popen(@cmd); + return <$fh> if wantarray; + local $/; + <$fh> +} + sub cleanup { my ($self) = @_; _destroy($self, qw(in out pid)); -- cgit v1.2.3-24-ge0c7 From 8ceeea662e01a65951d5d07fc9993087242d6206 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Jan 2016 03:21:06 +0000 Subject: honor core.abbrev from git-config(1) We will use core.abbrev=12 by default if unset, as the git default of 7 is too low for long-term usability of links. Some of our callers used 16, which was probably excessive. --- lib/PublicInbox/Git.pm | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index ac556426..23a3e6c7 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -13,6 +13,11 @@ use POSIX qw(dup2); require IO::Handle; use PublicInbox::Spawn qw(spawn popen_rd); +# Documentation/SubmittingPatches recommends 12 (Linux v4.4) +my $abbrev = `git config core.abbrev` || 12; + +sub abbrev { "--abbrev=$abbrev" } + sub new { my ($class, $git_dir) = @_; bless { git_dir => $git_dir }, $class -- cgit v1.2.3-24-ge0c7 From 38f685ef4c78788324089f9d1365c7676aa5a5aa Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 28 Feb 2016 04:23:53 +0000 Subject: git: support arbitrary redirects and env settings on popen We want to be able to redirect stderr to a temporary file while using the normal popen interface in our Git.pm. --- lib/PublicInbox/Git.pm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'lib/PublicInbox/Git.pm') diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index 23a3e6c7..bd945007 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -132,8 +132,16 @@ sub fail { sub popen { my ($self, @cmd) = @_; - @cmd = ('git', "--git-dir=$self->{git_dir}", @cmd); - popen_rd(\@cmd); + my $cmd = [ 'git', "--git-dir=$self->{git_dir}" ]; + my ($env, $opt); + if (ref $cmd[0]) { + push @$cmd, @{$cmd[0]}; + $env = $cmd[1]; + $opt = $cmd[2]; + } else { + push @$cmd, @cmd; + } + popen_rd($cmd, $env, $opt); } sub qx { -- cgit v1.2.3-24-ge0c7 From 64d131a6b4435289f8876b20510a6d80d4dde418 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 3 Mar 2016 03:12:12 +0000 Subject: git: support an error tmpfile for stashing stderr output This should allow us to avoid polluting stderr output when HTTP clients inevitably request broken revisions. --- lib/PublicInbox/Git.pm | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'lib/PublicInbox/Git.pm') 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 { -- cgit v1.2.3-24-ge0c7