]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/Fetch.pm
fetch: support running as root
[public-inbox.git] / lib / PublicInbox / Fetch.pm
index 7f60b619e0a4c7b2270cc59882f9410dd86cbb86..5ada1f49e4dc28ba39e2c0278208869575e4456a 100644 (file)
@@ -6,7 +6,7 @@ use strict;
 use v5.10.1;
 use parent qw(PublicInbox::IPC);
 use URI ();
-use PublicInbox::Spawn qw(popen_rd run_die);
+use PublicInbox::Spawn qw(popen_rd run_die spawn);
 use PublicInbox::Admin;
 use PublicInbox::LEI;
 use PublicInbox::LeiCurl;
@@ -60,11 +60,13 @@ sub do_manifest ($$$) {
        $opt->{$_} = $lei->{$_} for (0..2);
        my $cerr = PublicInbox::LeiMirror::run_reap($lei, $curl_cmd, $opt);
        if ($cerr) {
-               return [ 404 ] if ($cerr >> 8) == 22; # 404 Missing
+               return [ 404, $muri ] if ($cerr >> 8) == 22; # 404 Missing
                $lei->child_error($cerr, "@$curl_cmd failed");
                return;
        }
-       my $m1 = PublicInbox::LeiMirror::decode_manifest($ft, $fn, $muri);
+       my $m1 = eval {
+               PublicInbox::LeiMirror::decode_manifest($ft, $fn, $muri);
+       } or return [ 404, $muri ];
        my $mdiff = { %$m1 };
 
        # filter out unchanged entries.  We check modified, too, since
@@ -83,7 +85,7 @@ sub do_manifest ($$$) {
        }
        my (undef, $v1_path, @v2_epochs) =
                PublicInbox::LeiMirror::deduce_epochs($mdiff, $ibx_uri->path);
-       [ 200, $v1_path, \@v2_epochs, $muri, $ft, $mf, $m1 ];
+       [ 200, $muri, $v1_path, \@v2_epochs, $ft, $mf, $m1 ];
 }
 
 sub get_fingerprint2 {
@@ -93,6 +95,13 @@ sub get_fingerprint2 {
        Digest::SHA::sha256(do { local $/; <$rd> });
 }
 
+sub writable_dir ($) {
+       my ($dir) = @_;
+       return unless -d $dir && -w _;
+       my @st = stat($dir);
+       $st[2] & 0222; # any writable bits set? (in case of root)
+}
+
 sub do_fetch { # main entry point
        my ($cls, $lei, $cd) = @_;
        my $ibx_ver;
@@ -106,11 +115,11 @@ sub do_fetch { # main entry point
        } else { # v2:
                require PublicInbox::MultiGit;
                $mg = PublicInbox::MultiGit->new($dir, 'all.git', 'git');
-               my @epochs = $mg->git_epochs;
+               @epochs = $mg->git_epochs;
                my ($git_url, $epoch);
                for my $nr (@epochs) { # try newest epoch, first
                        my $edir = "$dir/git/$nr.git";
-                       unless (-d $edir && -w _) { # must be writable dir
+                       if (!writable_dir($edir)) {
                                $skip->{$nr} = 1;
                                next;
                        }
@@ -120,6 +129,10 @@ sub do_fetch { # main entry point
                                $epoch = $nr;
                        } else {
                                warn "W: $edir missing remote.origin.url\n";
+                               my $pid = spawn([qw(git config -l)], undef,
+                                       { 1 => $lei->{2}, 2 => $lei->{2} });
+                               waitpid($pid, 0);
+                               $lei->child_error($?) if $?;
                        }
                }
                @epochs = grep { !$skip->{$_} } @epochs if $skip;
@@ -135,7 +148,7 @@ EOM
        PublicInbox::LeiMirror::write_makefile($dir, $ibx_ver);
        $lei->qerr("# inbox URL: $ibx_uri/");
        my $res = do_manifest($lei, $dir, $ibx_uri) or return;
-       my ($code, $v1_path, $v2_epochs, $muri, $ft, $mf, $m1) = @$res;
+       my ($code, $muri, $v1_path, $v2_epochs, $ft, $mf, $m1) = @$res;
        if ($code == 404) {
                # any pre-manifest.js.gz instances running? Just fetch all
                # existing ones and unconditionally try cloning the next