]> Sergey Matveev's repositories - public-inbox.git/commitdiff
support publicinbox.cgitrc directive
authorEric Wong <e@80x24.org>
Fri, 8 Mar 2019 01:21:22 +0000 (01:21 +0000)
committerEric Wong <e@80x24.org>
Thu, 4 Apr 2019 09:13:58 +0000 (09:13 +0000)
We can save admins the trouble of declaring [coderepo "..."]
sections in the public-inbox config by parsing the cgitrc
directly.

Macro expansion (e.g. $HTTP_HOST) expansion is not supported,
yet; but may be in the future.

Documentation/public-inbox-config.pod
lib/PublicInbox/Config.pm
lib/PublicInbox/Git.pm
lib/PublicInbox/SolverGit.pm

index 27d27e4e2f4fea980994e67be9502277b85a6e25..5ee93e2e736cc5883951893ac1106966564389df 100644 (file)
@@ -188,16 +188,27 @@ be treated as the default value.
 
 Default: 25
 
-=item coderepo.<name>.dir
+=item coderepo.<nick>.dir
 
 The path to a git repository for "publicinbox.<name>.coderepo"
 
-=item coderepo.<name>.cgitUrl
+=item coderepo.<nick>.cgitUrl
 
 The URL of the cgit instance associated with the coderepo.
 
 Default: none
 
+=item publicinbox.cgitrc
+
+A path to a L<cgitrc(5)> file.  "repo.url" directives in the cgitrc
+will be mapped to the nickname of a coderepo (without trailing slash),
+and "repo.path" directives map to "coderepo.<nick>.dir".
+Use of this directive allows admins of existing cgit installations
+to skip declaring coderepo sections and map inboxes directly to
+code repositories known to cgit.
+
+Macro expansion (e.g. C<$HTTP_HOST>) is not yet supported.
+
 =back
 
 =head2 NAMED LIMITER (PSGI)
index 2ff266f184499d2660f755ffc75e8be01d80f9d2..4b24672003a1d98132c1c80c322bc49824204ad1 100644 (file)
@@ -197,15 +197,59 @@ sub valid_inbox_name ($) {
        1;
 }
 
+sub cgit_repo_merge ($$) {
+       my ($self, $repo) = @_;
+       # $repo = { url => 'foo.git', path => '/path/to/foo.git' }
+       my $nick = $repo->{url};
+       $self->{"coderepo.$nick.dir"} ||= $repo->{path};
+       $self->{"coderepo.$nick.cgiturl"} ||= $nick;
+}
+
+sub parse_cgitrc {
+       my ($self, $cgitrc, $nesting) = @_;
+
+       # same limit as cgit/configfile.c::parse_configfile
+       return if $nesting > 8;
+
+       open my $fh, '<', $cgitrc or do {
+               warn "failed to open cgitrc=$cgitrc: $!\n";
+               return;
+       };
+
+       # FIXME: this doesn't support macro expansion via $VARS, yet
+       my $repo;
+       foreach (<$fh>) {
+               chomp;
+               if (m!\Arepo\.url=(.+?)/*\z!) {
+                       my $nick = $1;
+                       cgit_repo_merge($self, $repo) if $repo;
+                       $repo = { url => $nick };
+               } elsif (m!\Arepo\.path=(.+)\z!) {
+                       if (defined $repo) {
+                               $repo->{path} = $1;
+                       } else {
+                               warn "$_ without repo.url\n";
+                       }
+               } elsif (m!\Ainclude=(.+)\z!) {
+                       parse_cgitrc($self, $1, $nesting + 1);
+               }
+       }
+       cgit_repo_merge($self, $repo) if $repo;
+}
+
 # parse a code repo
 # Only git is supported at the moment, but SVN and Hg are possibilities
 sub _fill_code_repo {
        my ($self, $nick) = @_;
        my $pfx = "coderepo.$nick";
 
+       # TODO: support gitweb and other repository viewers?
+       if (defined(my $cgitrc = delete $self->{'publicinbox.cgitrc'})) {
+               parse_cgitrc($self, $cgitrc, 0);
+       }
        my $dir = $self->{"$pfx.dir"}; # aka "GIT_DIR"
        unless (defined $dir) {
-               warn "$pfx.repodir unset";
+               warn "$pfx.dir unset";
                return;
        }
 
@@ -226,8 +270,6 @@ sub _fill_code_repo {
                        } @$cgits;
                }
        }
-       # TODO: support gitweb and other repository viewers?
-       # TODO: parse cgitrc
 
        $git;
 }
@@ -292,7 +334,11 @@ sub _fill {
                my $code_repos = $self->{-code_repos};
                my $repo_objs = $rv->{-repo_objs} = [];
                foreach my $nick (@$ibx_code_repos) {
-                       valid_inbox_name($nick) or next;
+                       my @parts = split(m!/!, $nick);
+                       my $valid = 0;
+                       $valid += valid_inbox_name($_) foreach (@parts);
+                       $valid == scalar(@parts) or next;
+
                        my $repo = $code_repos->{$nick} ||=
                                                _fill_code_repo($self, $nick);
                        push @$repo_objs, $repo if $repo;
index 265c3fb4507a1173de3d485d6de5cf332976a335..8a96e10c1139be7d4d1b44e959e1ea9e3d676f38 100644 (file)
@@ -288,10 +288,19 @@ sub src_blob_url {
        local_nick($self);
 }
 
+sub host_prefix_url ($$) {
+       my ($env, $url) = @_;
+       return $url if index($url, '//') >= 0;
+       my $scheme = $env->{'psgi.url_scheme'};
+       my $host_port = $env->{HTTP_HOST} ||
+               "$env->{SERVER_NAME}:$env->{SERVER_PORT}";
+       "$scheme://$host_port". ($env->{SCRIPT_NAME} || '/') . $url;
+}
+
 sub pub_urls {
-       my ($self) = @_;
+       my ($self, $env) = @_;
        if (my $urls = $self->{cgit_url}) {
-               return @$urls;
+               return map { host_prefix_url($env, $_) } @$urls;
        }
        local_nick($self);
 }
index cd0f94a10c831b2caa8325f8b14bc1f05a2cc3a5..3841c56719932a7c5ea4988b38bed549c3c9200d 100644 (file)
@@ -85,7 +85,8 @@ sub solve_existing ($$) {
                # push @ambiguous, [ $git, @oids ];
 
                dbg($self, "`$oid_b' ambiguous in " .
-                               join("\n\t", $git->pub_urls) . "\n" .
+                               join("\n\t", $git->pub_urls($self->{psgi_env}))
+                                . "\n" .
                                join('', map { "$_ blob\n" } @oids));
        }
        scalar(@ambiguous) ? \@ambiguous : undef;
@@ -483,7 +484,7 @@ sub resolve_patch ($$) {
        if (my $existing = solve_existing($self, $want)) {
                my ($found_git, undef, $type, undef) = @$existing;
                dbg($self, "found $cur_want in " .
-                       join("\n", $found_git->pub_urls));
+                       join("\n", $found_git->pub_urls($self->{psgi_env})));
 
                if ($cur_want eq $self->{oid_want} || $type ne 'blob') {
                        eval { delete($self->{user_cb})->($existing) };