From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id AAD4020377 for ; Tue, 12 Mar 2019 04:00:46 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 05/13] support publicinbox.cgitrc directive Date: Tue, 12 Mar 2019 04:00:38 +0000 Message-Id: <20190312040046.4619-6-e@80x24.org> In-Reply-To: <20190312040046.4619-1-e@80x24.org> References: <20190312040046.4619-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 | 15 +++++++- lib/PublicInbox/Config.pm | 54 +++++++++++++++++++++++++-- lib/PublicInbox/Git.pm | 13 ++++++- lib/PublicInbox/SolverGit.pm | 5 ++- 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod index 27d27e4..5ee93e2 100644 --- a/Documentation/public-inbox-config.pod +++ b/Documentation/public-inbox-config.pod @@ -188,16 +188,27 @@ be treated as the default value. Default: 25 -=item coderepo..dir +=item coderepo..dir The path to a git repository for "publicinbox..coderepo" -=item coderepo..cgitUrl +=item coderepo..cgitUrl The URL of the cgit instance associated with the coderepo. Default: none +=item publicinbox.cgitrc + +A path to a L 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..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) diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm index da443e5..490b4c4 100644 --- a/lib/PublicInbox/Config.pm +++ b/lib/PublicInbox/Config.pm @@ -196,15 +196,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; } @@ -225,8 +269,6 @@ sub _fill_code_repo { } @$cgits; } } - # TODO: support gitweb and other repository viewers? - # TODO: parse cgitrc $git; } @@ -291,7 +333,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 265c3fb..8a96e10 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 cd0f94a..3841c56 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) }; -- EW