]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
repobrowse: commits with path redirect to root with anchor
authorEric Wong <e@80x24.org>
Wed, 20 Jan 2016 22:35:23 +0000 (22:35 +0000)
committerEric Wong <e@80x24.org>
Tue, 5 Apr 2016 18:58:27 +0000 (18:58 +0000)
We shall save clients the overhead of making extra HTTP requests
to follow partial paths.  This ought to improve cache hit
effectiveness on both the server and client side by reducing
the potential different pages we may set.

lib/PublicInbox/RepobrowseBase.pm
lib/PublicInbox/RepobrowseGitCommit.pm
t/repobrowse_git_commit.t [new file with mode: 0644]

index 14926d70c762e5ee2e615d0bf5e10c833600cc39..dd854ffc5ed273caf611c2193b1087c2ec40925f 100644 (file)
@@ -60,7 +60,7 @@ sub mime_type {
 sub html_start {
        my ($self, $req, $title_html, $opts) = @_;
        my $desc = $req->{repo_info}->{desc_html};
-       my $meta;
+       my $meta = '';
 
        if ($opts) {
                my @robots;
@@ -76,4 +76,42 @@ sub html_start {
                "</head><body><pre><b>$desc</b>";
 }
 
+sub r {
+       my ($self, $status, $req, @extra) = @_;
+       my @h;
+
+       my $body = '';
+       if ($status == 301 || $status == 302) {
+               # The goal is to be able to make redirects like we make
+               # <a href=> tags with '../'
+               my $cgi = $req->{cgi};
+               my $base;
+               $base = ref($cgi) eq 'CGI' ? $cgi->url(-base).'/' : $cgi->base;
+               my ($redir) = @extra;
+               if ($redir =~ m!\A\.\./!) { # relative redirect
+                       my @orig = split(m!/+!, $cgi->path_info, -1);
+                       shift @orig; # drop leading '/'
+                       my @dest = split(m!/+!, $redir);
+
+                       while ($dest[0] eq '..') {
+                               pop @orig;
+                               shift @dest;
+                       }
+                       my $end = '';
+                       $end = pop @dest if $dest[-1] =~ /\A[#\?]/;
+                       $redir = $base . join('/', @orig, @dest) . $end;
+               } else {
+                       $redir = $base . '/' . $redir;
+               }
+               push @h, qw(Content-Type text/plain Location), $redir;
+
+               # mainly for curl (no-'-L') users:
+               $body = "Redirecting to $redir\n";
+       } else {
+               die "not implemented, yet: $status";
+       }
+
+       [ $status, \@h, [ $body ] ]
+}
+
 1;
index d6843a6dd0a00356cabc21ec6baf69eda87cf7f8..edc277176f66c043f5584789e51c7f2aafc2485b 100644 (file)
@@ -137,24 +137,23 @@ sub call_git_commit {
        my $q = PublicInbox::RepobrowseGitQuery->new($req->{cgi});
        my $id = $q->{id};
        $id eq '' and $id = 'HEAD';
+
+       my $expath = $req->{expath};
+       if ($expath ne '') {
+               my $relup = join('', map { '../' } @{$req->{extra}});
+               my $qs = $q->qs;
+               return $self->r(301, $req, "$relup$qs#".to_attr($expath));
+       }
+
        my $git = $req->{repo_info}->{git};
        my @cmd = (qw(show -z --numstat -p --encoding=UTF-8
                        --no-notes --no-color -c), $git->abbrev);
-       my @path;
-
-       # kill trailing slash
-       my $extra = $req->{extra};
-       if (@$extra) {
-               pop @$extra if $extra->[-1] eq '';
-               @path = (join('/', @$extra));
-               push @cmd, '--follow';
-       }
 
-       my $log = $git->popen(@cmd, GIT_FMT, $id, '--', @path);
+       my $log = $git->popen(@cmd, GIT_FMT, $id, '--');
        my $H = <$log>;
 
        # maybe the path didn't exist, yet, zip them back up
-       return git_commit_404($req, $q, $path[0]) unless defined $H;
+       return git_commit_404($req, $q) unless defined $H;
        sub {
                my ($res) = @_; # Plack callback
                my $fh = $res->([200, ['Content-Type'=>'text/html']]);
@@ -164,19 +163,12 @@ sub call_git_commit {
 }
 
 sub git_commit_404 {
-       my ($req, $q, $path) = @_;
+       my ($req, $q) = @_;
        my $x = 'Missing commit or path';
        my $pfx = "$req->{relcmd}commit";
 
-       # print STDERR "path: $path\n";
        my $try = 'try';
        $x = "<html><head><title>$x</title></head><body><pre><b>$x</b>\n\n";
-       if (defined $path) {
-               my $qs = $q->qs;
-               $x .= "<a\nhref=\"$pfx$qs\">" .
-                       "try without the path <s>$path</s></a>\n";
-               $try = 'or';
-       }
        my $qs = $q->qs(id => '');
        $x .= "<a\nhref=\"$pfx$qs\">$try the latest commit in HEAD</a>\n";
        $x .= '</pre></body>';
diff --git a/t/repobrowse_git_commit.t b/t/repobrowse_git_commit.t
new file mode 100644 (file)
index 0000000..f13cd90
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright (C) 2016 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+use strict;
+use warnings;
+
+my $test = require './t/repobrowse_common_git.perl';
+test_psgi($test->{app}, sub {
+       my ($cb) = @_;
+       my $path = '/path/to/something';
+       my $req = 'http://example.com/test.git/commit';
+       my $res = $cb->(GET($req . $path));
+       is($res->code, 301, 'got 301 to anchor');
+       is($res->header('Location'), "$req#path:to:something",
+               'redirected to anchor from path');
+
+       my $q = '?id=deadbeef';
+       $res = $cb->(GET($req . $path . $q));
+       is($res->code, 301, 'got 301 with query string');
+       is($res->header('Location'), "$req$q#path:to:something",
+               'redirected to anchor from path with query');
+});
+
+done_testing();