]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/Gcf2.pm
config: lazy-load coderepos, support extindex
[public-inbox.git] / lib / PublicInbox / Gcf2.pm
index 7983c84147bc6ccf1fa27c1e77b9ad49f5d1f43d..99f4ae04e75587b28ca54c8817376a8971edf3ee 100644 (file)
@@ -1,11 +1,12 @@
-# Copyright (C) 2020 all contributors <meta@public-inbox.org>
+# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
 # backend for a git-cat-file-workalike based on libgit2,
 # other libgit2 stuff may go here, too.
 package PublicInbox::Gcf2;
 use strict;
-use PublicInbox::Spawn qw(which popen_rd);
+use v5.10.1;
+use PublicInbox::Spawn qw(which popen_rd); # may set PERL_INLINE_DIRECTORY
 use Fcntl qw(LOCK_EX);
 use IO::Handle; # autoflush
 my (%CFG, $c_src, $lockfh);
@@ -35,7 +36,7 @@ BEGIN {
                if (open(my $fh, '<', $f)) {
                        chomp($l, $c);
                        local $/;
-                       $c_src = <$fh>;
+                       defined($c_src = <$fh>) or die "read $f: $!\n";
                        $CFG{LIBS} = $l;
                        $CFG{CCFLAGSEX} = $c;
                        last;
@@ -56,17 +57,38 @@ undef $c_src;
 undef %CFG;
 undef $lockfh;
 
-# Usage: $^X -MPublicInbox::Gcf2 -e 'PublicInbox::Gcf2::loop()'
+sub add_alt ($$) {
+       my ($gcf2, $objdir) = @_;
+
+       # libgit2 (tested 0.27.7+dfsg.1-0.2 and 0.28.3+dfsg.1-1~bpo10+1
+       # in Debian) doesn't handle relative epochs properly when nested
+       # multiple levels.  Add all the absolute paths to workaround it,
+       # since $EXTINDEX_DIR/ALL.git/objects/info/alternates uses absolute
+       # paths to reference $V2INBOX_DIR/all.git/objects and
+       # $V2INBOX_DIR/all.git/objects/info/alternates uses relative paths
+       # to refer to $V2INBOX_DIR/git/$EPOCH.git/objects
+       #
+       # See https://bugs.debian.org/975607
+       if (open(my $fh, '<', "$objdir/info/alternates")) {
+               chomp(my @abs_alt = grep(m!^/!, <$fh>));
+               $gcf2->add_alternate($_) for @abs_alt;
+       }
+       $gcf2->add_alternate($objdir);
+       1;
+}
+
+# Usage: $^X -MPublicInbox::Gcf2 -e PublicInbox::Gcf2::loop
 # (see lib/PublicInbox/Gcf2Client.pm)
-sub loop {
+sub loop () {
        my $gcf2 = new();
+       my %seen;
        STDERR->autoflush(1);
        STDOUT->autoflush(1);
 
        while (<STDIN>) {
                chomp;
                my ($oid, $git_dir) = split(/ /, $_, 2);
-               $gcf2->add_alternate("$git_dir/objects");
+               $seen{$git_dir} //= add_alt($gcf2, "$git_dir/objects");
                if (!$gcf2->cat_oid(1, $oid)) {
                        # retry once if missing.  We only get unabbreviated OIDs
                        # from SQLite or Xapian DBs, here, so malicious clients
@@ -74,7 +96,7 @@ sub loop {
                        warn "I: $$ $oid missing, retrying in $git_dir\n";
 
                        $gcf2 = new();
-                       $gcf2->add_alternate("$git_dir/objects");
+                       %seen = ($git_dir => add_alt($gcf2,"$git_dir/objects"));
 
                        if ($gcf2->cat_oid(1, $oid)) {
                                warn "I: $$ $oid found after retry\n";