]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
www: improve handling of missing coderepos
authorEric Wong <e@80x24.org>
Mon, 30 Sep 2024 21:30:06 +0000 (21:30 +0000)
committerEric Wong <e@80x24.org>
Wed, 2 Oct 2024 17:40:35 +0000 (17:40 +0000)
Git coderepos may appear and disappear during the lifetime of
an -httpd or -netd instance.  This happens quite frequently on
on my git.kernel.org mirror and is and clutters up stderr, so
we'll validate the existance of a git directory before trying
to serve anything.

Whether or not this should be the case for inboxes is yet-to-be
decided, especially since there's inbox-specific information
inside in PI_CONFIG (e.g. address, newsgroup) and we only use a
project listing for coderepos.

lib/PublicInbox/Config.pm
lib/PublicInbox/Git.pm
t/config.t
t/solver_git.t

index d76deca408348f1c123384ae3342444b2ae245f7..442759dec9f2a820561724e3b5fed22106236dac 100644 (file)
@@ -375,7 +375,9 @@ sub valid_dir ($$) {
 sub fill_coderepo {
        my ($self, $nick) = @_;
        my $pfx = "coderepo.$nick";
-       my $git = PublicInbox::Git->new(valid_dir($self, "$pfx.dir") // return);
+       my $git_dir = valid_dir($self, "$pfx.dir") // return;
+       -e $git_dir // return;
+       my $git = PublicInbox::Git->new($git_dir);
        if (defined(my $cgits = $self->{"$pfx.cgiturl"})) {
                $git->{cgit_url} = $cgits = _array($cgits);
                $self->{"$pfx.cgiturl"} = $cgits;
@@ -701,13 +703,14 @@ sub glob2re ($) {
 
 sub get_coderepo {
        my ($self, $nick) = @_;
-       $self->{-coderepos}->{$nick} // do {
+       my $git = $self->{-coderepos}->{$nick} // do {
                defined($self->{-cgit_scan_path}) ? do {
                        apply_cgit_scan_path($self);
                        my $cr = fill_coderepo($self, $nick);
                        $cr ? ($self->{-coderepos}->{$nick} = $cr) : undef;
                } : undef;
        };
+       $git && -e $git->{git_dir} ? $git : undef;
 }
 
 1;
index c43f98632a9b225758344ae8417c69808a9f8b97..b3f39adf832774f1350c991c2131f948f055d35f 100644 (file)
@@ -250,7 +250,9 @@ sub cat_async_step ($$) {
        my $cmd = ref($req) ? $$req : $req;
        # ->fail may be called via Gcf2Client.pm
        my $info = $self->{-bc} && substr($cmd, 0, 5) eq 'info ';
-       if ($head =~ /^([0-9a-f]{40,}) (\S+) ([0-9]+)$/) {
+       if (!defined $head) {
+               $self->fail("E: $self->{git_dir} gone? (\$!=$!)");
+       } elsif ($head =~ /^([0-9a-f]{40,}) (\S+) ([0-9]+)$/) {
                ($oid, $type, $size) = ($1, $2, $3 + 0);
                unless ($info) { # --batch-command
                        $bref = $self->{sock}->my_bufread($size + 1) or
index c41a42d366783a7fa2fc73cb6c6bdeeeb80d21a1..956ad35c495aa954702d7bbcb4e857e600fb6864 100644 (file)
@@ -7,7 +7,7 @@ use_ok 'PublicInbox';
 ok(defined(eval('$PublicInbox::VERSION')), 'VERSION defined');
 use_ok 'PublicInbox::Config';
 my ($tmpdir, $for_destroy) = tmpdir();
-use autodie qw(open close);
+use autodie qw(close mkdir open);
 my $validate_git_behavior = $ENV{TEST_VALIDATE_GIT_BEHAVIOR};
 
 {
@@ -240,8 +240,9 @@ for my $s (@valid) {
        inboxdir = /path/to/foo
        coderepo = project
 [coderepo "project"]
-       dir = /path/to/project.git
+       dir = $tmpdir/project.git
 EOF
+       mkdir "$tmpdir/project.git"; # must exist for ->fill_coderepo
        my $t1 = $cfg->lookup_name('test1');
        my $t2 = $cfg->lookup_name('test2');
        ok $cfg->repo_objs($t1)->[0], 'coderepo parsed';
index 694e2671feca65f7763fd675e976b2220106512f..6cc5eeba2aac4dc2a4821709f0d8d498e62dff1f 100644 (file)
@@ -6,8 +6,11 @@ use PublicInbox::TestCommon;
 use Cwd qw(abs_path);
 require_git v2.6;
 use PublicInbox::ContentHash qw(git_sha);
-use PublicInbox::Spawn qw(run_qx);
-require_mods(qw(DBD::SQLite Xapian));
+use PublicInbox::Spawn qw(run_qx which);
+use File::Path qw(remove_tree);
+use PublicInbox::IO qw(write_file);
+use autodie qw(symlink unlink);
+require_mods qw(DBD::SQLite Xapian);
 require PublicInbox::SolverGit;
 my $rdr = { 2 => \(my $null) };
 my $git_dir = xqx([qw(git rev-parse --git-common-dir)], undef, $rdr);
@@ -22,6 +25,8 @@ my $patch2 = eml_load 't/solve/0002-rename-with-modifications.patch';
 my $patch2_oid = git_sha(1, $patch2)->hexdigest;
 
 my ($tmpdir, $for_destroy) = tmpdir();
+my $gone_repo = "$tmpdir/to-be-deleted.git";
+
 my $ibx = create_inbox 'v2', version => 2,
                        indexlevel => 'medium', sub {
        my ($im) = @_;
@@ -287,6 +292,8 @@ SKIP: {
 [coderepo "binfoo"]
        dir = $binfoo
        cgiturl = http://example.com/binfoo
+[coderepo "goner"]
+       dir = $gone_repo
 EOF
        close $cfgfh or die;
        my $exp_digest;
@@ -450,9 +457,32 @@ EOF
                        my $t = XML::TreePP->new->parse($res->content);
                        ok(scalar @{$t->{feed}->{entry}}, 'got tag entries');
                }
+
+               # test disappearing repos
+               $res = $cb->(GET('/goner/'));
+               is $res->code, 200, 'coderepo summary for goner repo';
+               $res = $cb->(GET("/goner/$oid{'iso-8859-1'}/s/"));
+               is $res->code, 200, 'goner repo OID /s/ still available';
+               $stderr_empty->();
+               remove_tree $gone_repo;
+
+               $res = $cb->(GET('/goner/'));
+               is $res->code, 404, '/goner/ repo summary';
+               $stderr_empty->();
+
+               $res = $cb->(GET("/goner/$oid{'iso-8859-1'}/s/"));
+               is $res->code, 404, 'gone repo OID /s/';
+               $stderr_empty->();
        };
+
+       state $cp = which('cp');
+       $cp or xbail "`cp' not available (WTF!?)";
+       xsys_e $cp, qw(-Rp), $binfoo, $gone_repo;
+
        test_psgi(sub { $www->call(@_) }, $client);
        my $env = { PI_CONFIG => $cfgpath, TMPDIR => $tmpdir };
+
+       xsys_e $cp, qw(-Rp), $binfoo, $gone_repo; # for test_httpd $client
        test_httpd($env, $client, 7, sub {
        SKIP: {
                require_cmd('curl', 1) or skip 'no curl', 1;