diff options
-rw-r--r-- | lib/PublicInbox/Repobrowse.pm | 23 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseConfig.pm | 15 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseGitLog.pm | 2 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseGitSummary.pm | 2 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseGitTag.pm | 4 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseRoot.pm | 71 |
6 files changed, 100 insertions, 17 deletions
diff --git a/lib/PublicInbox/Repobrowse.pm b/lib/PublicInbox/Repobrowse.pm index f344e0f8..cc18255d 100644 --- a/lib/PublicInbox/Repobrowse.pm +++ b/lib/PublicInbox/Repobrowse.pm @@ -61,6 +61,12 @@ sub no_tslash { [ "Redirecting to $url\n" ] ] } +sub root_index { + my ($self) = @_; + my $mod = load_once('PublicInbox::RepobrowseRoot'); + $mod->new->call($self->{rconfig}); # RepobrowseRoot::call +} + sub run { my ($self, $cgi, $method) = @_; return r(405, 'Method Not Allowed') if ($method !~ /\AGET|HEAD\z/); @@ -68,11 +74,12 @@ sub run { # URL syntax: / repo [ / cmd [ / path ] ] # cmd: log | commit | diff | tree | view | blob | snapshot # repo and path (@extra) may both contain '/' - my $rconfig = $self->{rconfig}; my $path_info = uri_unescape($cgi->path_info); my (undef, $repo_path, @extra) = split(m{/+}, $path_info, -1); - return r404() unless $repo_path; + return $self->root_index($self) unless length($repo_path); + + my $rconfig = $self->{rconfig}; # RepobrowseConfig my $repo_info; until ($repo_info = $rconfig->lookup($repo_path)) { my $p = shift @extra or last; @@ -104,12 +111,8 @@ sub run { if ($path_info =~ m!/\z!) { $tslash = $path_info =~ tr!/!!; } else { - my @repo = split('/', $repo_path); - if (@repo > 1) { - $req->{relcmd} = "./$repo[-1]/"; - } else { - $req->{relcmd} = "/$repo[-1]/"; - } + my @x = split('/', $repo_path); + $req->{relcmd} = @x > 1 ? "./$x[-1]/" : "/$x[-1]/"; } } while (@extra && $extra[-1] eq '') { @@ -117,9 +120,7 @@ sub run { ++$tslash; } - if ($tslash && $path_info ne '/' && $NO_TSLASH{$mod}) { - return no_tslash($cgi); - } + return no_tslash($cgi) if ($tslash && $NO_TSLASH{$mod}); $req->{tslash} = $tslash; $mod = load_once("PublicInbox::Repobrowse$vcs$mod"); diff --git a/lib/PublicInbox/RepobrowseConfig.pm b/lib/PublicInbox/RepobrowseConfig.pm index 800db05d..5752beed 100644 --- a/lib/PublicInbox/RepobrowseConfig.pm +++ b/lib/PublicInbox/RepobrowseConfig.pm @@ -11,6 +11,8 @@ sub new { $file = default_file() unless defined($file); my $self = bless PublicInbox::Config::git_config_dump($file), $class; $self->{-cache} = {}; + # for root + $self->{-groups} = { -hidden => [], -none => [] }; $self; } @@ -36,8 +38,9 @@ sub lookup { my $path = $self->{"repo.$repo_path.path"}; (defined $path && -d $path) or return; $rv->{path} = $path; - $rv->{path_info} = $repo_path; + $rv->{repo} = $repo_path; + # gitweb compatibility foreach my $key (qw(description cloneurl)) { $rv->{$key} = try_cat("$path/$key"); } @@ -45,10 +48,18 @@ sub lookup { $rv->{desc_html} = PublicInbox::Hval->new_oneline($rv->{description})->as_html; - foreach my $key (qw(publicinbox vcs readme)) { + foreach my $key (qw(publicinbox vcs readme group)) { $rv->{$key} = $self->{"repo.$repo_path.$key"}; } + my $g = $rv->{group}; + defined $g or $g = '-none'; + if (ref($g) eq 'ARRAY') { + push @{$self->{-groups}->{$_} ||= []}, $repo_path foreach @$g; + } else { + push @{$self->{-groups}->{$g} ||= []}, $repo_path; + } + # of course git is the default VCS $rv->{vcs} ||= 'git'; $self->{-cache}->{$repo_path} = $rv; diff --git a/lib/PublicInbox/RepobrowseGitLog.pm b/lib/PublicInbox/RepobrowseGitLog.pm index 197d2cb1..0c360e73 100644 --- a/lib/PublicInbox/RepobrowseGitLog.pm +++ b/lib/PublicInbox/RepobrowseGitLog.pm @@ -29,7 +29,7 @@ sub call_git_log { sub { my ($res) = @_; # Plack callback my $fh = $res->([200, ['Content-Type'=>'text/html']]); - my $title = utf8_html("log: $repo_info->{path_info} ($h)"); + my $title = "log: $repo_info->{repo} ".utf8_html("($h)"); $fh->write($self->html_start($req, $title)); git_log_stream($req, $q, $log, $fh, $git); $fh->close; diff --git a/lib/PublicInbox/RepobrowseGitSummary.pm b/lib/PublicInbox/RepobrowseGitSummary.pm index 65e32b6a..db601ad9 100644 --- a/lib/PublicInbox/RepobrowseGitSummary.pm +++ b/lib/PublicInbox/RepobrowseGitSummary.pm @@ -37,7 +37,7 @@ sub emit_summary { $fh = $res->([200, ['Content-Type'=>'text/html; charset=UTF-8']]); # ref names are unpredictable in length and requires tables :< $fh->write($self->html_start($req, - "$repo_info->{path_info}: overview") . + "$repo_info->{repo}: overview") . '</pre><table>'); my $rel = $req->{relcmd}; diff --git a/lib/PublicInbox/RepobrowseGitTag.pm b/lib/PublicInbox/RepobrowseGitTag.pm index ebda729e..229d5ff0 100644 --- a/lib/PublicInbox/RepobrowseGitTag.pm +++ b/lib/PublicInbox/RepobrowseGitTag.pm @@ -133,7 +133,7 @@ sub git_tag_list { # tag names are unpredictable in length and requires tables :< $fh->write($self->html_start($req, - "$repo_info->{path_info}: tag list") . + "$repo_info->{repo}: tag list") . '</pre><table><tr>' . join('', map { "<th><tt>$_</tt></th>" } qw(tag subject date)). '</tr>'); @@ -166,7 +166,7 @@ sub unknown_tag_type { my $obj_link = qq(<a\nhref="$rel$cmd?id=$hex">$label</a>\n); $fh->write($self->html_start($req, - "$repo_info->{path_info}: ref: $h") . + "$repo_info->{repo}: ref: $h") . "\n\n <b>$h</b> (lightweight tag)\nobject $obj_link\n"); } diff --git a/lib/PublicInbox/RepobrowseRoot.pm b/lib/PublicInbox/RepobrowseRoot.pm new file mode 100644 index 00000000..fda96437 --- /dev/null +++ b/lib/PublicInbox/RepobrowseRoot.pm @@ -0,0 +1,71 @@ +# Copyright (C) 2016 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# displays the root '/' where all the projects lie +package PublicInbox::RepobrowseRoot; +use strict; +use warnings; +use base qw(PublicInbox::RepobrowseBase); +use PublicInbox::Hval qw(utf8_html); + +sub call { + my ($self, $rconfig) = @_; + sub { + my ($res) = @_; # PSGI callback + my @h = ('Content-Type', 'text/html; charset=UTF-8'); + my $fh = $res->([200, \@h]); + repobrowse_index($fh, $rconfig); + $fh->close; + } +} + +sub repobrowse_index { + my ($fh, $rconfig) = @_; + my $title = 'repobrowse index'; + $fh->write("<html><head><title>$title</title>" . + PublicInbox::Hval::STYLE . + "</head><body><pre><b>$title</b>"); + + # preload all groups + foreach my $k (sort keys %$rconfig) { + $k =~ /\Arepo\.(.+)\.path\z/ or next; + my $repo_path = $1; + $rconfig->lookup($repo_path); # insert into groups + } + + my $groups = $rconfig->{-groups}; + if (scalar(keys %$groups) > 2) { # default has '-none' + '-hidden' + $fh->write("\n\n<b>uncategorized</b></pre>". + "<table\nsummary=repoindex>"); + } else { + $fh->write("</pre><table\nsummary=repoindex>"); + } + foreach my $repo_path (sort @{$groups->{-none}}) { + my $r = $rconfig->lookup($repo_path); + my $p = PublicInbox::Hval->utf8($r->{repo}); + my $l = $p->as_html; + $p = $p->as_path; + $fh->write(qq(<tr><td><tt><a\nhref="$p">$l</a></tt></td>) . + "<td><tt> $r->{desc_html}</tt></td></tr>"); + } + + foreach my $group (keys %$groups) { + next if $group =~ /\A-(?:none|hidden)\z/; + my $g = utf8_html($group); + $fh->write("<tr><td><pre> </pre></td></tr>". + "<tr><td><pre><b>$g</b></pre></tr>"); + foreach my $repo_path (sort @{$groups->{$group}}) { + my $r = $rconfig->lookup($repo_path); + my $p = PublicInbox::Hval->utf8($r->{repo}); + my $l = $p->as_html; + $p = $p->as_path; + $fh->write('<tr><td><tt> ' . + qq(<a\nhref="$p">$l</a></tt></td>) . + "<td><tt> $r->{desc_html}</tt></td></tr>"); + } + } + + $fh->write('</table></body></html>'); +} + +1; |