]> Sergey Matveev's repositories - public-inbox.git/commitdiff
rename 'GitCatFile' package to 'Git'
authorEric Wong <e@80x24.org>
Tue, 22 Dec 2015 00:17:33 +0000 (00:17 +0000)
committerEric Wong <e@80x24.org>
Tue, 22 Dec 2015 00:58:13 +0000 (00:58 +0000)
We'll be using it for more than just cat-file.
Adding a `popen' API for internal use allows us to save a bunch
of code in other places.

12 files changed:
MANIFEST
lib/PublicInbox/ExtMsg.pm
lib/PublicInbox/Feed.pm
lib/PublicInbox/Git.pm [moved from lib/PublicInbox/GitCatFile.pm with 92% similarity]
lib/PublicInbox/Mbox.pm
lib/PublicInbox/NNTP.pm
lib/PublicInbox/NewsGroup.pm
lib/PublicInbox/SearchIdx.pm
lib/PublicInbox/SearchView.pm
lib/PublicInbox/View.pm
lib/PublicInbox/WWW.pm
t/git.t

index 4c3b07df4340b499647c67338b19e587cda3e4c7..5d45046d25b6c17d03e5da6013ceccecaea850cf 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -21,7 +21,7 @@ examples/public-inbox.psgi
 lib/PublicInbox/Config.pm
 lib/PublicInbox/Feed.pm
 lib/PublicInbox/Filter.pm
-lib/PublicInbox/GitCatFile.pm
+lib/PublicInbox/Git.pm
 lib/PublicInbox/Hval.pm
 lib/PublicInbox/MDA.pm
 lib/PublicInbox/View.pm
index 82f4c63dc5ddd8b19820b58bda131f87a535d68d..0b667545a6e06e29744e6efec151d783510405be 100644 (file)
@@ -72,21 +72,10 @@ sub ext_msg {
        my $path = "HEAD:" . mid2path($mid);
 
        foreach my $n (@nox) {
-               my @cmd = ('git', "--git-dir=$n->{git_dir}", 'cat-file',
-                          '-t', $path);
-               my $pid = open my $fh, '-|';
-               defined $pid or die "fork failed: $!\n";
-
-               if ($pid == 0) {
-                       open STDERR, '>', '/dev/null'; # ignore errors
-                       exec @cmd or die "exec failed: $!\n";
-               } else {
-                       my $type = eval { local $/; <$fh> };
-                       close $fh;
-                       if ($? == 0 && $type eq "blob\n") {
-                               return r302($n->{url}, $mid);
-                       }
-               }
+               # TODO: reuse existing PublicInbox::Git objects to save forks
+               my $git = PublicInbox::Git->new($n->{git_dir});
+               my (undef, $type, undef) = $git->check($path);
+               return r302($n->{url}, $mid) if ($type eq 'blob');
        }
 
        # fall back to partial MID matching
index 68f1e67bf1bba4939df8b66c413a861bee49d018..150bea038241b57addb71cd34866d71cac3f7c7f 100644 (file)
@@ -9,7 +9,7 @@ use Email::Address;
 use Email::MIME;
 use Date::Parse qw(strptime);
 use PublicInbox::Hval;
-use PublicInbox::GitCatFile;
+use PublicInbox::Git;
 use PublicInbox::View;
 use PublicInbox::MID qw/mid_clean mid2path/;
 use POSIX qw/strftime/;
@@ -66,7 +66,7 @@ sub emit_atom {
        my $max = $ctx->{max} || MAX_PER_PAGE;
        my $feed_opts = get_feedopts($ctx);
        my $x = atom_header($feed_opts);
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        each_recent_blob($ctx, sub {
                my ($path, undef, $ts) = @_;
                if (defined $x) {
@@ -75,7 +75,6 @@ sub emit_atom {
                }
                add_to_feed($feed_opts, $fh, $path, $git);
        });
-       $git = undef; # destroy pipes
        end_feed($fh);
 }
 
@@ -105,11 +104,10 @@ sub emit_atom_thread {
        $feed_opts->{url} = $html_url;
        $feed_opts->{emit_header} = 1;
 
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        foreach my $msg (@{$res->{msgs}}) {
                add_to_feed($feed_opts, $fh, mid2path($msg->mid), $git);
        }
-       $git = undef; # destroy pipes
        end_feed($fh);
 }
 
@@ -167,7 +165,7 @@ sub emit_html_index {
 
 sub emit_index_nosrch {
        my ($ctx, $state, $fh) = @_;
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        my (undef, $last) = each_recent_blob($ctx, sub {
                my ($path, $commit, $ts, $u, $subj) = @_;
                $state->{first} ||= $commit;
@@ -219,14 +217,11 @@ sub each_recent_blob {
        # get recent messages
        # we could use git log -z, but, we already know ssoma will not
        # leave us with filenames with spaces in them..
-       my @cmd = ('git', "--git-dir=$ctx->{git_dir}",
-                       qw/log --no-notes --no-color --raw -r
-                          --abbrev=16 --abbrev-commit/,
-                       "--format=%h%x00%ct%x00%an%x00%s%x00");
-       push @cmd, $range;
-
-       my $pid = open(my $log, '-|', @cmd) or
-               die('open `'.join(' ', @cmd) . " pipe failed: $!\n");
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
+       my $log = $git->popen(qw/log --no-notes --no-color --raw -r
+                               --abbrev=16 --abbrev-commit/,
+                               "--format=%h%x00%ct%x00%an%x00%s%x00",
+                               $range);
        my %deleted; # only an optimization at this point
        my $last;
        my $nr = 0;
similarity index 92%
rename from lib/PublicInbox/GitCatFile.pm
rename to lib/PublicInbox/Git.pm
index b3666a088d1e4b0784cd89f1f4e7ce405897bd3b..5135862e6ad51bc904e880f94175239d59519707 100644 (file)
@@ -6,7 +6,7 @@
 # This is based on code in Git.pm which is GPLv2, but modified to avoid
 # dependence on environment variables for compatibility with mod_perl.
 # There are also API changes to simplify our usage and data set.
-package PublicInbox::GitCatFile;
+package PublicInbox::Git;
 use strict;
 use warnings;
 use POSIX qw(dup2);
@@ -121,6 +121,16 @@ sub fail {
        die $msg;
 }
 
+sub popen {
+       my ($self, @cmd) = @_;
+       my $mode = '-|';
+       $mode = shift @cmd if ($cmd[0] eq '|-');
+       @cmd = ('git', "--git-dir=$self->{git_dir}", @cmd);
+       my $pid = open my $fh, $mode, @cmd or
+               die('open `'.join(' ', @cmd) . " pipe failed: $!\n");
+       $fh;
+}
+
 sub cleanup {
        my ($self) = @_;
        _destroy($self, qw(in out pid));
index c180a0dc84a2b915dadc8661276e78e023d221ab..0d67981f42a2e30e938f4ba3fa5ccf0f101f8087 100644 (file)
@@ -86,9 +86,9 @@ sub emit_mbox {
        my $fh = $response->([200, ['Content-Type' => "application/$type"]]);
        $fh = PublicInbox::MboxGz->new($fh) if $sfx;
 
-       require PublicInbox::GitCatFile;
+       require PublicInbox::Git;
        my $mid = $ctx->{mid};
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        my %opts = (offset => 0);
        my $nr;
        do {
index 295aee0e1725d093f57df8b649782b47f1816a02..097c57e9b23b8573328b477ac0752ca58b76c9b3 100644 (file)
@@ -9,7 +9,7 @@ use base qw(Danga::Socket);
 use fields qw(nntpd article rbuf ng long_res);
 use PublicInbox::Search;
 use PublicInbox::Msgmap;
-use PublicInbox::GitCatFile;
+use PublicInbox::Git;
 use PublicInbox::MID qw(mid2path);
 use Email::MIME;
 use Data::Dumper qw(Dumper);
index 3a3189584af438f8036f6e1f9353a90898f4c685..b20180e6667aceebd0a1feb516118f38603fa69f 100644 (file)
@@ -10,7 +10,7 @@ use Scalar::Util qw(weaken);
 require Danga::Socket;
 require PublicInbox::Msgmap;
 require PublicInbox::Search;
-require PublicInbox::GitCatFile;
+require PublicInbox::Git;
 
 sub new {
        my ($class, $name, $git_dir, $address) = @_;
@@ -32,7 +32,7 @@ sub defer_weaken {
 sub gcf {
        my ($self) = @_;
        $self->{gcf} ||= eval {
-               my $gcf = PublicInbox::GitCatFile->new($self->{git_dir});
+               my $gcf = PublicInbox::Git->new($self->{git_dir});
 
                # git repos may be repacked and old packs unlinked
                defer_weaken($self, 'gcf');
index e9af547f3fbd7cbfa8ac29a638e9f71ad83773d7..67272997b22149faf3db8b9018a86ac8569f83ae 100644 (file)
@@ -11,6 +11,7 @@ use strict;
 use warnings;
 use base qw(PublicInbox::Search);
 use PublicInbox::MID qw/mid_clean id_compress/;
+require PublicInbox::Git;
 *xpfx = *PublicInbox::Search::xpfx;
 
 use constant MAX_MID_SIZE => 244; # max term size - 1 in Xapian
@@ -331,16 +332,11 @@ sub rlog {
        my $h40 = $hex .'{40}';
        my $addmsg = qr!^:000000 100644 \S+ ($h40) A\t${hex}{2}/${hex}{38}$!;
        my $delmsg = qr!^:100644 000000 ($h40) \S+ D\t${hex}{2}/${hex}{38}$!;
-       my $git_dir = $self->{git_dir};
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($git_dir);
-       my @cmd = ('git', "--git-dir=$git_dir", "log",
-                   qw/--reverse --no-notes --no-color --raw -r --no-abbrev/,
-                   $range);
+       my $git = PublicInbox::Git->new($self->{git_dir});
+       my $log = $git->popen(qw/log --reverse --no-notes --no-color
+                               --raw -r --no-abbrev/, $range);
        my $latest;
        my $bytes;
-       my $pid = open(my $log, '-|', @cmd) or
-               die('open` '.join(' ', @cmd) . " pipe failed: $!\n");
        while (my $line = <$log>) {
                if ($line =~ /$addmsg/o) {
                        my $mime = do_cat_mail($git, $1, \$bytes) or next;
@@ -447,10 +443,8 @@ sub merge_threads {
 
 sub _read_git_config_perm {
        my ($self) = @_;
-       my @cmd = ('git', "--git-dir=$self->{git_dir}",
-                  qw(config core.sharedRepository));
-       my $pid = open(my $fh, '-|', @cmd) or
-               die('open `'.join(' ', @cmd) . " pipe failed: $!\n");
+       my @cmd = qw(config core.sharedRepository);
+       my $fh = PublicInbox::Git->new($self->{git_dir})->popen(@cmd);
        my $perm = <$fh>;
        close $fh;
        chomp $perm if defined $perm;
index ea8a45a4e91f6d4416db9b6792d442d44e150e4a..fec4f39f84d8841c19ce0dc0f10862eed2de2579 100644 (file)
@@ -10,6 +10,7 @@ use PublicInbox::Hval;
 use PublicInbox::View;
 use PublicInbox::MID qw(mid2path mid_clean);
 use Email::MIME;
+require PublicInbox::Git;
 our $LIM = 50;
 
 sub sres_top_html {
@@ -169,12 +170,10 @@ sub tdump {
                $th->order(*PublicInbox::View::rsort_ts);
        }
 
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        my $state = { ctx => $ctx, anchor_idx => 0, pct => \%pct };
        $ctx->{searchview} = 1;
        tdump_ent($fh, $git, $state, $_, 0) for $th->rootset;
-       $git = undef;
        Email::Address->purge_cache;
 
        $fh->write(search_nav_bot($mset, $q). "\n\n" .
@@ -236,8 +235,7 @@ sub html_start {
 sub adump {
        my ($cb, $mset, $q, $ctx) = @_;
        my $fh = $cb->([ 200, ['Content-Type' => 'application/atom+xml']]);
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my $git = $ctx->{git_dir} ||= PublicInbox::Git->new($ctx->{git_dir});
        my $feed_opts = PublicInbox::Feed::get_feedopts($ctx);
        my $x = PublicInbox::Hval->new_oneline($q->{q})->as_html;
        $x = qq{$x - search results};
@@ -251,7 +249,6 @@ sub adump {
                $x = mid2path($x);
                PublicInbox::Feed::add_to_feed($feed_opts, $fh, $x, $git);
        }
-       $git = undef;
        PublicInbox::Feed::end_feed($fh);
 }
 
index 68741c5e0366c13c9e1a2bf05d775d87437c621b..2ca7f95ceb8c77caea34323c749632b724a8e082 100644 (file)
@@ -183,8 +183,8 @@ sub emit_thread_html {
                anchor_idx => 0,
        };
 
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       require PublicInbox::Git;
+       my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
        if ($flat) {
                pre_anchor_entry($seen, $_) for (@$msgs);
                __thread_entry(\$cb, $git, $state, $_, 0) for (@$msgs);
index 5cd3bc6fdfb63caa7b067c53d5908db209347af8..ee414e85d1d5a9442d6a34281df43834e0753cea 100644 (file)
@@ -17,6 +17,7 @@ use PublicInbox::Config qw(try_cat);
 use URI::Escape qw(uri_escape_utf8 uri_unescape);
 use constant SSOMA_URL => 'http://ssoma.public-inbox.org/';
 use constant PI_URL => 'http://public-inbox.org/';
+require PublicInbox::Git;
 our $LISTNAME_RE = qr!\A/([\w\.\-]+)!;
 our $MID_RE = qr!([^/]+)!;
 our $END_RE = qr!(f/|T/|t/|t\.mbox(?:\.gz)?|t\.atom|raw|)!;
@@ -62,7 +63,6 @@ sub preload {
        require PublicInbox::Feed;
        require PublicInbox::View;
        require PublicInbox::Thread;
-       require PublicInbox::GitCatFile;
        require Email::MIME;
        require Digest::SHA;
        require POSIX;
@@ -96,6 +96,7 @@ sub invalid_list {
        my $git_dir = $pi_config->get($listname, "mainrepo");
        if (defined $git_dir) {
                $ctx->{git_dir} = $git_dir;
+               $ctx->{git} = PublicInbox::Git->new($git_dir);
                $ctx->{listname} = $listname;
                return;
        }
@@ -146,18 +147,7 @@ sub mid2blob {
        my ($ctx) = @_;
        require PublicInbox::MID;
        my $path = PublicInbox::MID::mid2path($ctx->{mid});
-       my @cmd = ('git', "--git-dir=$ctx->{git_dir}",
-                       qw(cat-file blob), "HEAD:$path");
-       my $pid = open my $fh, '-|';
-       defined $pid or die "fork failed: $!\n";
-       if ($pid == 0) {
-               open STDERR, '>', '/dev/null'; # ignore errors
-               exec @cmd or die "exec failed: $!\n";
-       } else {
-               my $blob = eval { local $/; <$fh> };
-               close $fh;
-               $? == 0 ? \$blob : undef;
-       }
+       $ctx->{git}->cat_file("HEAD:$path");
 }
 
 # /$LISTNAME/$MESSAGE_ID/raw                    -> raw mbox
diff --git a/t/git.t b/t/git.t
index 4532921ddea305d16078654614ac313b5a7b000b..19fbef157addd704f5c59081c23ad3fea201b2f2 100644 (file)
--- a/t/git.t
+++ b/t/git.t
@@ -7,7 +7,7 @@ use File::Temp qw/tempdir/;
 my $dir = tempdir(CLEANUP => 1);
 use Cwd qw/getcwd/;
 
-use_ok 'PublicInbox::GitCatFile';
+use_ok 'PublicInbox::Git';
 {
        is(system(qw(git init -q --bare), $dir), 0, 'created git directory');
        my @cmd = ('git', "--git-dir=$dir", 'fast-import', '--quiet');
@@ -26,7 +26,7 @@ use_ok 'PublicInbox::GitCatFile';
 }
 
 {
-       my $gcf = PublicInbox::GitCatFile->new($dir);
+       my $gcf = PublicInbox::Git->new($dir);
        my $f = 'HEAD:foo.txt';
        my @x = $gcf->check($f);
        is(scalar @x, 3, 'returned 3 element array for existing file');
@@ -95,7 +95,7 @@ if (1) {
        is(0, $?, 'hashed object successfully');
        chomp $buf;
 
-       my $gcf = PublicInbox::GitCatFile->new($dir);
+       my $gcf = PublicInbox::Git->new($dir);
        my $rsize;
        is($gcf->cat_file($buf, sub {
                $rsize = ${$_[1]};