about summary refs log tree commit homepage
path: root/lib/PublicInbox
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-03-08 01:21:22 +0000
committerEric Wong <e@80x24.org>2019-04-04 09:13:58 +0000
commit5af881d954a4ab14e08dd806dd4de1e9f26bfd12 (patch)
tree12e5a0286b841065671a7b3cd0fcfd4db80625fe /lib/PublicInbox
parent721368cd04bfbd03c0d9173fff633ae34f16409a (diff)
downloadpublic-inbox-5af881d954a4ab14e08dd806dd4de1e9f26bfd12.tar.gz
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.
Diffstat (limited to 'lib/PublicInbox')
-rw-r--r--lib/PublicInbox/Config.pm54
-rw-r--r--lib/PublicInbox/Git.pm13
-rw-r--r--lib/PublicInbox/SolverGit.pm5
3 files changed, 64 insertions, 8 deletions
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index 2ff266f1..4b246720 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -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;
diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm
index 265c3fb4..8a96e10c 100644
--- a/lib/PublicInbox/Git.pm
+++ b/lib/PublicInbox/Git.pm
@@ -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);
 }
diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm
index cd0f94a1..3841c567 100644
--- a/lib/PublicInbox/SolverGit.pm
+++ b/lib/PublicInbox/SolverGit.pm
@@ -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) };