]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/LeiMirror.pm
multi_git: hoist out common epoch/alternates handling
[public-inbox.git] / lib / PublicInbox / LeiMirror.pm
index 23813dcf00464ff7bf9d0dcbdf08c2ade036934f..c113c9debf8bfccdc0834e09cd1c56d05f167f3c 100644 (file)
@@ -1,13 +1,13 @@
 # Copyright (C) 2021 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
-# "lei add-external --mirror" support
+# "lei add-external --mirror" support (also "public-inbox-clone");
 package PublicInbox::LeiMirror;
 use strict;
 use v5.10.1;
 use parent qw(PublicInbox::IPC);
 use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
-use PublicInbox::Spawn qw(popen_rd spawn);
+use PublicInbox::Spawn qw(popen_rd spawn run_die);
 use File::Temp ();
 use Fcntl qw(SEEK_SET);
 
@@ -181,7 +181,7 @@ sub index_cloned_inbox {
 
 sub run_reap {
        my ($lei, $cmd, $opt) = @_;
-       $lei->qerr("# @$cmd");
+       $lei->qerr("# @$cmd" . ($opt->{-C} ? " (in $opt->{-C})" : ''));
        $opt->{pgid} = 0 if $lei->{sock};
        my $pid = spawn($cmd, undef, $opt);
        my $reap = PublicInbox::OnDestroy->new($lei->can('sigint_reap'), $pid);
@@ -209,7 +209,6 @@ sub clone_v2 {
        my $lei = $self->{lei};
        my $curl = $self->{curl} //= PublicInbox::LeiCurl->new($lei) or return;
        my $pfx //= $curl->torsocks($lei, $v2_uris->[0]) or return;
-       my @epochs;
        my $dst = $self->{dst};
        my @src_edst;
        for my $uri (@$v2_uris) {
@@ -220,17 +219,21 @@ failed to extract epoch number from $src
 
                my $nr = $1 + 0;
                $edst .= "/git/$nr.git";
-               push @src_edst, [ $src, $edst ];
+               push @src_edst, $src, $edst;
        }
        my $lk = bless { lock_path => "$dst/inbox.lock" }, 'PublicInbox::Lock';
        _try_config($self);
        my $on_destroy = $lk->lock_for_scope($$);
        my @cmd = clone_cmd($lei, my $opt = {});
-       while (my $pair = shift(@src_edst)) {
-               my $cmd = [ @$pfx, @cmd, @$pair ];
+       while (my ($src, $edst) = splice(@src_edst, 0, 2)) {
+               my $cmd = [ @$pfx, @cmd, $src, $edst ];
                my $cerr = run_reap($lei, $cmd, $opt);
                return $lei->child_error($cerr, "@$cmd failed") if $cerr;
        }
+       require PublicInbox::MultiGit;
+       my $mg = PublicInbox::MultiGit->new($dst, 'all.git', 'git');
+       $mg->fill_alternates;
+       for my $i ($mg->git_epochs) { $mg->epoch_cfg_set($i) }
        undef $on_destroy; # unlock
        index_cloned_inbox($self, 2);
 }
@@ -238,15 +241,15 @@ failed to extract epoch number from $src
 # PSGI mount prefixes and manifest.js.gz prefixes don't always align...
 sub deduce_epochs ($$) {
        my ($m, $path) = @_;
-       my ($v1_bare, @v2_epochs);
+       my ($v1_ent, @v2_epochs);
        my $path_pfx = '';
        $path =~ s!/+\z!!;
        do {
-               $v1_bare = $m->{$path};
+               $v1_ent = $m->{$path};
                @v2_epochs = grep(m!\A\Q$path\E/git/[0-9]+\.git\z!, keys %$m);
-       } while (!defined($v1_bare) && !@v2_epochs &&
+       } while (!defined($v1_ent) && !@v2_epochs &&
                $path =~ s!\A(/[^/]+)/!/! and $path_pfx .= $1);
-       ($path_pfx, $v1_bare, @v2_epochs);
+       ($path_pfx, $v1_ent ? $path : undef, @v2_epochs);
 }
 
 sub decode_manifest ($$$) {
@@ -282,20 +285,20 @@ sub try_manifest {
                return $lei->child_error($cerr, "@$cmd failed");
        }
        my $m = decode_manifest($ft, $fn, $uri);
-       my ($path_pfx, $v1_bare, @v2_epochs) = deduce_epochs($m, $path);
+       my ($path_pfx, $v1_path, @v2_epochs) = deduce_epochs($m, $path);
        if (@v2_epochs) {
                # It may be possible to have v1 + v2 in parallel someday:
-               $lei->err(<<EOM) if defined $v1_bare;
-# `$v1_bare' appears to be a v1 inbox while v2 epochs exist:
+               $lei->err(<<EOM) if defined $v1_path;
+# `$v1_path' appears to be a v1 inbox while v2 epochs exist:
 # @v2_epochs
-# ignoring $v1_bare (use --inbox-version=1 to force v1 instead)
+# ignoring $v1_path (use --inbox-version=1 to force v1 instead)
 EOM
                @v2_epochs = map {
                        $uri->path($path_pfx.$_);
                        $uri->clone
                } @v2_epochs;
                clone_v2($self, \@v2_epochs);
-       } elsif (defined $v1_bare) {
+       } elsif (defined $v1_path) {
                clone_v1($self);
        } else {
                die "E: confused by <$uri>, possible matches:\n\t",