]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
repobrowse: switch to new URL format to avoid query strings
authorEric Wong <e@80x24.org>
Wed, 15 Feb 2017 22:35:18 +0000 (22:35 +0000)
committerEric Wong <e@80x24.org>
Thu, 16 Feb 2017 04:27:50 +0000 (04:27 +0000)
Query strings make endpoint caching more difficult since
they're order-independent.  They are also more likely lost
or truncated inadvertantly when copy+pasting, so try to
avoid them for default endpoints.

There's still some things which are broken and followup
commits will be needed to fix them.

20 files changed:
lib/PublicInbox/RepoBase.pm
lib/PublicInbox/RepoGit.pm
lib/PublicInbox/RepoGitAtom.pm
lib/PublicInbox/RepoGitBlob.pm
lib/PublicInbox/RepoGitCommit.pm
lib/PublicInbox/RepoGitDiff.pm
lib/PublicInbox/RepoGitDiffCommon.pm
lib/PublicInbox/RepoGitLog.pm
lib/PublicInbox/RepoGitPatch.pm
lib/PublicInbox/RepoGitPlain.pm
lib/PublicInbox/RepoGitQuery.pm
lib/PublicInbox/RepoGitSnapshot.pm
lib/PublicInbox/RepoGitSummary.pm
lib/PublicInbox/RepoGitTag.pm
lib/PublicInbox/RepoGitTree.pm
lib/PublicInbox/Repobrowse.pm
t/repobrowse_git_atom.t
t/repobrowse_git_commit.t
t/repobrowse_git_plain.t
t/repobrowse_git_tree.t

index 97f13b2568c84a776f2ff4222ca6a2a4ebdcee16..668e97116b7de9bf2832ca52c443ccbc08303c30 100644 (file)
@@ -3,7 +3,6 @@
 package PublicInbox::RepoBase;
 use strict;
 use warnings;
-require PublicInbox::RepoGitQuery;
 use PublicInbox::Hval;
 our %MIME_TYPE_WHITELIST = ('application/pdf' => 1);
 
index b44457ca4dacbec93a33b4fb339312818c233e68..114eb656a4343ad9976aef6356b47390578ce181 100644 (file)
@@ -50,17 +50,17 @@ sub git_dec_links ($$) {
                        $h = PublicInbox::Hval->utf8($h);
                        my $r = $h->as_href;
                        $h = $h->as_html;
-                       push @l, qq($s -&gt; <a\nhref="${rel}log?h=$r">$h</a>);
+                       push @l, qq($s -&gt; <a\nhref="${rel}log/$r">$h</a>);
                } elsif (s/\Atag: //) {
                        my $h = PublicInbox::Hval->utf8($_);
                        my $r = $h->as_href;
                        $h = $h->as_html;
-                       push @l, qq(<a\nhref="${rel}tag?h=$r"><b>$h</b></a>);
+                       push @l, qq(<a\nhref="${rel}tag/$r"><b>$h</b></a>);
                } else {
                        my $h = PublicInbox::Hval->utf8($_);
                        my $r = $h->as_href;
                        $h = $h->as_html;
-                       push @l, qq(<a\nhref="${rel}log?h=$r">$h</a>);
+                       push @l, qq(<a\nhref="${rel}log/$r">$h</a>);
                }
        }
        @l;
index 6d0caa02b7da23dc505a01ea93ab4abd6d8f03ab..cf4df11cd6b6226997ab854f96110b0207490073 100644 (file)
@@ -46,7 +46,7 @@ sub flush_hdr ($$$) {
        $$dst .= '</published>';
        $$dst .= qq(<link\nrel="alternate"\ntype="text/html"\nhref=");
        $$dst .= $url;
-       $$dst .= '/commit?id=';
+       $$dst .= '/commit/';
 
        my $H = $hdr->{H};
        $$dst .= $H;
@@ -67,7 +67,7 @@ sub git_atom_sed ($$) {
        my $rel = $req->{relcmd};
        my $repo_info = $req->{repo_info};
        my $title = join('/', $repo_info->{repo}, @{$req->{extra}});
-       $title = utf8_html("$title, branch $req->{q}->{h}");
+       $title = utf8_html("$title, $req->{-tip}");
        my $url = repo_root_url($self, $req);
        my $hdr = {};
        my $subtitle = $repo_info->desc_html;
@@ -76,7 +76,7 @@ sub git_atom_sed ($$) {
                qq(<title>$title</title>) .
                qq(<subtitle>$subtitle</subtitle>) .
                qq(<link\nrel="alternate"\ntype="text/html"\nhref="$url"\n/>);
-       my ($plinks, $id, $ai);
+       my ($plinks, $ai);
        my $end = '';
        my $blines;
        sub {
@@ -140,12 +140,11 @@ sub call_git_atom {
 
        my $git = $repo_info->{git};
        my $env = $req->{env};
-       my $q =$req->{'q'} = PublicInbox::RepoGitQuery->new($env);
-       my $h = $q->{h};
+       my $tip = $req->{-tip};
        my $read_log = sub {
                my $cmd = $git->cmd(qw(log --no-notes --no-color
                                        --abbrev-commit), $git->abbrev,
-                                       $ATOM_FMT, "-$max", $h, '--');
+                                       $ATOM_FMT, "-$max", $tip, '--');
                my $expath = $req->{expath};
                push @$cmd, $expath if $expath ne '';
                my $rdr = { 2 => $git->err_begin };
@@ -155,13 +154,13 @@ sub call_git_atom {
 
        sub {
                $env->{'qspawn.response'} = $_[0];
-               return $read_log->() if $h ne '';
+               return $read_log->() if $tip ne '';
 
                my $cmd = $git->cmd(qw(symbolic-ref --short HEAD));
                my $rdr = { 2 => $git->err_begin };
                my $qsp = PublicInbox::Qspawn->new($cmd, undef, undef, $rdr);
                $qsp->psgi_qx($env, undef, sub {
-                       chomp($h = ${$_[0]});
+                       chomp($tip = ${$_[0]});
                        $read_log->();
                })
        }
index 586b4acc4f3b2579e2fec3bce115f661f14c6320..f9c28c221ac273204344fa05f0b98cbfd0488533 100644 (file)
@@ -12,10 +12,7 @@ our @EXPORT = qw(git_blob_mime_type git_blob_stream_response);
 sub call_git_blob {
        my ($self, $req) = @_;
        my $git = $req->{repo_info}->{git};
-       my $q = PublicInbox::RepoGitQuery->new($req->{env});
-       my $id = $q->{id};
-       $id eq '' and $id = 'HEAD';
-       $id .= ":$req->{expath}";
+       my $id = $req->{-tip} . ':' . $req->{expath};
 
        my ($cat, $hex, $type, $size) = $git->cat_file_begin($id);
        return unless defined $cat;
index e98c3c1819cddc20b69cce3453867a44cf2dda1d..c1cf06db1c2eb13dda5812cf49e42ea0477151d6 100644 (file)
@@ -37,11 +37,9 @@ sub commit_header {
        my @p = split(' ', $p);
 
        my $rel = $req->{relcmd};
-       my $q = $req->{'q'};
-       my $qs = $req->{qs} = $q->qs(id => $h);
        my $x = $self->html_start($req, $s) . "\n" .
-               qq(   commit $H (<a\nhref="${rel}patch$qs">patch</a>)\n) .
-               qq(     tree <a\nrel=nofollow\nhref="${rel}tree?id=$h">$t</a>);
+               qq(   commit $H (<a\nhref="${rel}patch/$h">patch</a>)\n) .
+               qq(     tree <a\nrel=nofollow\nhref="${rel}tree/$h">$t</a>);
 
        my $git = $req->{repo_info}->{git};
        # extra show path information, if any
@@ -56,7 +54,7 @@ sub commit_header {
                        my $e = PublicInbox::Hval->utf8($_, join('/', @t));
                        $ep = $e->as_path;
                        my $eh = $e->as_html;
-                       $ep = "${rel}tree/$ep?id=$h";
+                       $ep = "${rel}tree/$ep/$h";
                        qq(<a\nrel=nofollow\nhref="$ep">$eh</a>);
                } @$extra);
                $path = "/$ep";
@@ -66,10 +64,10 @@ sub commit_header {
        my $np = scalar @p;
        if ($np == 1) {
                my $p = $p[0];
-               $x .= git_parent_line('   parent', $p, $q, $git, $rel, $path);
+               $x .= git_parent_line('   parent', $p, $git, $rel);
        } elsif ($np > 1) {
                $req->{mhelp} = CC_MERGE;
-               my @common = ($q, $git, $rel, $path);
+               my @common = ($git, $rel);
                my @t = @p;
                my $p = shift @t;
                $x .= git_parent_line('  parents', $p, @common);
@@ -119,24 +117,20 @@ sub git_commit_sed ($$) {
 sub call_git_commit { # RepoBase calls this
        my ($self, $req) = @_;
        my $env = $req->{env};
-       my $q = PublicInbox::RepoGitQuery->new($env);
-       my $id = $q->{id};
-       $id eq '' and $id = 'HEAD';
+       my $tip = $req->{-tip};
 
        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));
+               return $self->r(301, $req, "$relup#".to_attr($expath));
        }
 
        my $git = $req->{repo_info}->{git};
        my $cmd = $git->cmd(qw(show -z --numstat -p --encoding=UTF-8
                        --no-notes --no-color -c),
-                       $git->abbrev, GIT_FMT, $id, '--');
+                       $git->abbrev, GIT_FMT, $tip, '--');
        my $rdr = { 2 => $git->err_begin };
        my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr);
-       $req->{'q'} = $q;
        $env->{'qspawn.quiet'} = 1;
        $qsp->psgi_return($env, undef, sub { # parse header
                my ($r, $bref) = @_;
@@ -159,8 +153,7 @@ sub git_commit_404 {
 
        my $try = 'try';
        $x = "<html><head><title>$x</title></head><body><pre><b>$x</b>\n\n";
-       my $qs = $req->{'q'}->qs(id => '');
-       $x .= "<a\nhref=\"$pfx$qs\">$try the latest commit in HEAD</a>\n";
+       $x .= "<a\nhref=\"$pfx\">$try the latest commit in HEAD</a>\n";
        $x .= '</pre></body>';
 
        [404, ['Content-Type'=>'text/html'], [ $x ]];
@@ -168,11 +161,10 @@ sub git_commit_404 {
 
 # FIXME: horrifically expensive...
 sub git_parent_line {
-       my ($pfx, $p, $q, $git, $rel, $path) = @_;
-       my $qs = $q->qs(id => $p);
+       my ($pfx, $p, $git, $rel) = @_;
        my $t = git_commit_title($git, $p);
        $t = defined $t ? utf8_html($t) : '';
-       $pfx . qq( <a\nid=P\nhref="${rel}commit$path$qs">$p</a> $t\n);
+       $pfx . qq( <a\nid=P\nhref="${rel}commit/$p">$p</a> $t\n);
 }
 
 # do not break anchor links if the combined diff doesn't show changes:
@@ -186,14 +178,13 @@ sub show_unchanged {
                qq( See the <a\nhref="#P">parents</a>, ) .
                "or view final state(s) below:\n\n";
        my $rel = $req->{relcmd};
-       my $qs = $req->{qs};
        foreach my $anchor (@unchanged) {
                my $fn = $anchors->{$anchor};
                my $p = PublicInbox::Hval->utf8(git_unquote($fn));
                $p = $p->as_path;
                $fn = utf8_html($fn);
                $$dst .= qq(\t<a\nrel=nofollow);
-               $$dst .= qq(\nid="$anchor"\nhref="${rel}tree/$p$qs">);
+               $$dst .= qq(\nid="$anchor"\nhref="${rel}tree/$p">);
                $$dst .= "$fn</a>\n";
        }
 }
index bb71e7385fbf91179d471741a1bb7f269c2dd6c2..ef4717ac5d40f9956bfdb1396a326429a0766dea 100644 (file)
@@ -34,11 +34,8 @@ sub git_diff_sed ($$) {
 
 sub call_git_diff {
        my ($self, $req) = @_;
+       my ($id, $id2) = split(/\.\./, $req->{h});
        my $env = $req->{env};
-       my $q = PublicInbox::RepoGitQuery->new($env);
-       my $id = $q->{id};
-       my $id2 = $q->{id2};
-
        my $git = $req->{repo_info}->{git};
        my $cmd = $git->cmd(qw(diff-tree -z --numstat -p --encoding=UTF-8
                                --no-color -M -B -D -r), $id2, $id, '--');
index 0604f9dd4549447ae6612aa139ba9d75ebf8c95d..3e3ea4ee04f40b3569392397cf0bce8569b4a33b 100644 (file)
@@ -68,17 +68,16 @@ sub git_diff_ab_hunk ($$$$) {
                $na = defined $na ? "#n$na" : '';
                my $p = $req->{p}->[0];
                $rv .= qq(<a\nrel=nofollow);
-               $rv .= qq(\nhref="${rel}tree/$req->{path_a}?id=$p$na">);
+               $rv .= qq(\nhref="${rel}tree/$p/$req->{path_a}$na">);
                $rv .= "$ca</a>";
        }
        $rv .= ' ';
        if (defined($nb) && $nb == 0) { # deleted file
                $rv .= $cb;
        } else {
-               my $h = $req->{h};
                $nb = defined $nb ? "#n$nb" : '';
                $rv .= qq(<a\nrel=nofollow);
-               $rv .= qq(\nhref="${rel}tree/$req->{path_b}?id=$h$nb">);
+               $rv .= qq(\nhref="${rel}tree/$req->{-tip}/$req->{path_b}$nb">);
                $rv .= "$cb</a>";
        }
        $rv . ' @@' . utf8_html($ctx);
@@ -129,7 +128,7 @@ sub git_diff_cc_hunk {
        } else {
                my $h = $req->{h};
                $rv .= qq( <a\nrel=nofollow);
-               $rv .= qq(\nhref="${rel}tree/$path?id=$h#n$n">$last</a>);
+               $rv .= qq(\nhref="${rel}tree/$h/$path#n$n">$last</a>);
        }
        $rv .= " $at" . utf8_html($ctx);
 }
index 9cfa526e7e310dec9b5ade5c9e5a843a4b5c7c1a..09409eddab17485fd3ed93637630eb3f47f4c73c 100644 (file)
@@ -27,18 +27,18 @@ sub parent_links {
 
 sub flush_log_hdr ($$$) {
        my ($req, $dst, $hdr) = @_;
-       my $rel = $req->{relcmd};
+       my $lpfx = $req->{lpfx};
        my $seen = $req->{seen};
        $$dst .= '<hr /><pre>' if scalar keys %$seen;
        my $id = $hdr->{h};
        $seen->{$id} = 1;
        $$dst .= qq(<a\nid=p$id\n);
-       $$dst .= qq(href="${rel}commit?id=$id"><b>);
+       $$dst .= qq(href="${lpfx}commit/$id"><b>);
        $$dst .= utf8_html($hdr->{'s'}); # FIXME may still OOM
        $$dst .= '</b></a>';
        my $D = $hdr->{D}; # FIXME: thousands of decorations may OOM us
        if ($D ne '') {
-               $$dst .= ' (' . join(', ', git_dec_links($rel, $D)) . ')';
+               $$dst .= ' (' . join(', ', git_dec_links($lpfx, $D)) . ')';
        }
        my @p = split(/ /, $hdr->{p});
        push @{$req->{parents}}, @p;
@@ -56,14 +56,14 @@ sub git_log_sed_end ($$) {
        my $np = 0;
        my $seen = $req->{seen};
        my $git = $req->{repo_info}->{git};
-       my $rel = $req->{relcmd};
+       my $lpfx = $req->{lpfx};
        foreach my $p (@{$req->{parents}}) {
                next if $seen->{$p};
                $seen->{$p} = ++$np;
                my $s = git_commit_title($git, $p);
-               $m .= qq(\n<a\nid=p$p\nhref="?h=$p">$p</a>\t);
+               $m .= qq(\n<a\nid=p$p\nhref="$p">$p</a>\t);
                $s = defined($s) ? utf8_html($s) : '';
-               $m .= qq(<a\nhref="${rel}commit?id=$p">$s</a>);
+               $m .= qq(<a\nhref="${lpfx}commit/$p">$s</a>);
        }
        if ($np == 0) {
                $$dst .= "No commits follow";
@@ -123,17 +123,22 @@ sub call_git_log {
        my ($self, $req) = @_;
        my $repo_info = $req->{repo_info};
        my $max = $repo_info->{max_commit_count} || 50;
+       my $h = $req->{h};
        $max = int($max);
        $max = 50 if $max == 0;
        my $env = $req->{env};
-       my $q = $req->{'q'} = PublicInbox::RepoGitQuery->new($env);
-       my $h = $q->{h};
-       $h eq '' and $h = 'HEAD';
        my $git = $repo_info->{git};
        my $cmd = $git->cmd(qw(log --no-notes --no-color --abbrev-commit),
-                               $git->abbrev, $LOG_FMT, "-$max", $h, '--');
+                               $git->abbrev, $LOG_FMT, "-$max",
+                               $req->{-tip}, '--');
        my $rdr = { 2 => $git->err_begin };
-       my $title = "log: $repo_info->{repo} (" . utf8_html($h). ')';
+       my $title = "log: $repo_info->{repo}";
+       if (defined $h) {
+               $title .= ' ('. utf8_html($h). ')';
+               $req->{lpfx} = $req->{relcmd};
+       } else {
+               $req->{lpfx} = $req->{relcmd}.$req->{-tip};
+       }
        $req->{lhtml} = $self->html_start($req, $title) . "\n\n";
        my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr);
        $qsp->psgi_return($env, undef, sub {
index e9227b6fe5136102eff7d03b82ed6f2eda22a119..d851457c3e676bc18deb137f02c59cd2aa347301 100644 (file)
@@ -17,13 +17,12 @@ sub call_git_patch {
        my ($self, $req) = @_;
        my $git = $req->{repo_info}->{git};
        my $env = $req->{env};
-       my $q = PublicInbox::RepoGitQuery->new($env);
-       my $id = $q->{id};
-       $id =~ /\A[\w-]+([~\^][~\^\d])*\z/ or $id = 'HEAD';
+       my $tip = $req->{-tip};
+       $tip =~ /\A[\w-]+([~\^][~\^\d])*\z/;
 
        # limit scope, don't take extra args to avoid wasting server
        # resources buffering:
-       my $range = "$id~1..$id^0";
+       my $range = "$tip~1..$tip^0";
        my $cmd = $git->cmd(@CMD, $sig." $range", $range, '--');
        my $expath = $req->{expath};
        push @$cmd, $expath if $expath ne '';
index 2ba24e08f5888390182f443778eb1b3e80e0e446..6114a8584ffd0dfff6e48c6afbd8b8dec51e5fc4 100644 (file)
@@ -11,10 +11,7 @@ use PublicInbox::Qspawn;
 sub call_git_plain {
        my ($self, $req) = @_;
        my $git = $req->{repo_info}->{git};
-       my $q = PublicInbox::RepoGitQuery->new($req->{env});
-       my $id = $q->{id};
-       $id eq '' and $id = 'HEAD';
-       $id .= ":$req->{expath}";
+       my $id = $req->{-tip} . ':' . $req->{expath};
        my ($cat, $hex, $type, $size) = $git->cat_file_begin($id);
        return unless defined $cat;
 
index 638a13160b34e2a84266141e5203728c6347cc3b..c8d4a256bfab27114ddf591dfab3f3940d5ae2fc 100644 (file)
@@ -7,7 +7,7 @@ use strict;
 use warnings;
 use PublicInbox::Hval;
 use URI::Escape qw(uri_unescape);
-my @KNOWN_PARAMS = qw(id id2 ofs);
+my @KNOWN_PARAMS = qw(id id2 ofs);
 
 sub new {
        my ($class, $env) = @_;
index e05ad80cd08962b77ab9dddced04688c9f1d904d..9ba4c04a0fded372ab4bfc98510a0f7f7abbd417 100644 (file)
@@ -36,9 +36,7 @@ our %FMT_TYPES = (
 sub call_git_snapshot ($$) { # invoked by PublicInbox::RepoBase::call
        my ($self, $req) = @_;
 
-       my @extra = @{$req->{extra}};
-       my $ref = shift @extra;
-       return $self->r(404) if (!defined $ref) || scalar(@extra);
+       my $ref = $req->{-tip};
        my $orig_fn = $ref;
 
        # just in case git changes refname rules, don't allow wonky filenames
index e9e1458b33da97520ed1d04d3fe81d5dee1595f3..0ecef981872a3bc5c070b4e06649dfff71d20c91 100644 (file)
@@ -58,10 +58,10 @@ sub for_each_ref {
                my $sref;
                if ($type eq 'tag') {
                        $h = "<b>$h</b>";
-                       $sref = $ref = $rel . 'tag?h=' . $ref;
+                       $sref = $ref = $rel . 'tag/' . $ref;
                } elsif ($type eq 'commit') {
-                       $sref = $rel . 'commit?h=' . $ref;
-                       $ref = $rel . 'log?h=' . $ref;
+                       $sref = $rel . 'commit/' . $ref;
+                       $ref = $rel . 'log/' . $ref;
                } else {
                        # no point in wasting code to support tagged
                        # trees/blobs...
@@ -82,7 +82,7 @@ sub for_each_ref {
        foreach my $r (@$readme) {
                my $doc = $git->cat_file('HEAD:'.$r);
                defined $doc or next;
-               $fh->write('<pre>' . readme_path_links($rel, $r) .
+               $fh->write('<pre>' . readme_path_links($req, $rel, $r) .
                        " (HEAD)\n\n" . utf8_html($$doc) . '</pre>');
        }
        $fh->write('</body></html>');
@@ -90,17 +90,17 @@ sub for_each_ref {
 }
 
 sub readme_path_links {
-       my ($rel, $readme) = @_;
+       my ($req, $rel, $readme) = @_;
        my @path = split(m!/+!, $readme);
 
-       my $s = "tree <a\nhref=\"${rel}tree\">root</a>/";
+       my $s = "tree <a\nhref=\"${rel}tree/$req->{-tip}\">root</a>/";
        my @t;
        $s .= join('/', (map {
                push @t, $_;
                my $e = PublicInbox::Hval->utf8($_, join('/', @t));
                my $ep = $e->as_path;
                my $eh = $e->as_html;
-               $e = "<a\nhref=\"${rel}tree/$ep\">$eh</a>";
+               $e = "<a\nhref=\"${rel}tree/$req->{-tip}/$ep\">$eh</a>";
                # bold the last one
                scalar(@t) == scalar(@path) ? "<b>$e</b>" : $e;
        } @path));
index 96835b2cd7fb48d4bc565293683d2ef531fc37e3..d046f8535f5d51186343c7075d1146bcce7757ed 100644 (file)
@@ -19,9 +19,8 @@ my %cmd_map = ( # type => action
 sub call_git_tag {
        my ($self, $req) = @_;
 
-       my $q = PublicInbox::RepoGitQuery->new($req->{env});
-       my $h = $q->{h};
-       $h eq '' and return git_tag_list($self, $req);
+       my $h = $req->{h};
+       defined $h or return git_tag_list($self, $req);
        sub {
                my ($res) = @_;
                git_tag_show($self, $req, $h, $res);
@@ -58,7 +57,7 @@ sub git_show_tag_as_tag {
        my $label = "$type $obj";
        my $cmd = $cmd_map{$type} || 'show';
        my $rel = $req->{relcmd};
-       my $obj_link = qq(<a\nhref="$rel$cmd?id=$obj">$label</a>);
+       my $obj_link = qq(<a\nhref="$rel$cmd/$obj">$label</a>);
        $head = $h . "\n\n   tag <b>$tag</b>\nobject $obj_link\n";
        if (my $tagger = $h{tagger}) {
                $head .= 'tagger ' . join("\t", creator_split($tagger)) . "\n";
@@ -147,7 +146,7 @@ sub git_each_tag_sed ($$) {
                        my $h = $ref->as_html;
                        $ref = $ref->as_href;
                        $dst .= qq(<tr><td><tt>) .
-                               qq(<a\nhref="?h=$ref"><b>$h</b></a>) .
+                               qq(<a\nhref="tag/$ref"><b>$h</b></a>) .
                                qq(</tt></td><td><tt>$date</tt></td><td><tt>) .
                                utf8_html($s) . '</tt></td></tr>';
                }
@@ -189,7 +188,7 @@ sub unknown_tag_type {
        my $rel = $req->{relcmd};
        my $label = "$type $hex";
        my $cmd = $cmd_map{$type} || 'show';
-       my $obj_link = qq(<a\nhref="$rel$cmd?id=$hex">$label</a>\n);
+       my $obj_link = qq(<a\nhref="$rel$cmd/$hex">$label</a>\n);
 
        $fh->write($self->html_start($req,
                                "$repo_info->{repo}: ref: $h") .
index 4a68cf69c963807987275d5108fc7abaca7672f5..840af9adf03c664813e719bab033b1f1eb076b9e 100644 (file)
@@ -21,14 +21,7 @@ sub call_git_tree {
        my ($self, $req) = @_;
        my @extra = @{$req->{extra}};
        my $git = $req->{repo_info}->{git};
-       my $q = PublicInbox::RepoGitQuery->new($req->{env});
-       my $id = $q->{id};
-       if ($id eq '') {
-               chomp($id = $git->qx(qw(rev-parse --short=10 HEAD)));
-               $q->{id} = $id;
-       }
-
-       my $obj = "$id:$req->{expath}";
+       my $obj = "$req->{-tip}:$req->{expath}";
        my ($hex, $type, $size) = $git->check($obj);
 
        unless (defined($type)) {
@@ -41,7 +34,7 @@ sub call_git_tree {
        if ($type eq 'tree') {
                $opts->{noindex} = 1;
                $req->{thtml} = $self->html_start($req, $title, $opts) . "\n";
-               git_tree_show($req, $hex, $q);
+               git_tree_show($req, $hex);
        } elsif ($type eq 'blob') {
                sub {
                        my $res = $_[0];
@@ -49,7 +42,7 @@ sub call_git_tree {
                                ['Content-Type','text/html; charset=UTF-8']]);
                        $fh->write($self->html_start($req, $title, $opts) .
                                        "\n");
-                       git_blob_show($req, $fh, $git, $hex, $q);
+                       git_blob_show($req, $fh, $git, $hex);
                        $fh->write('</body></html>');
                        $fh->close;
                }
@@ -60,15 +53,15 @@ sub call_git_tree {
 }
 
 sub cur_path {
-       my ($req, $q) = @_;
-       my $qs = $q->qs;
+       my ($req) = @_;
        my @ex = @{$req->{extra}} or return '<b>root</b>';
        my $s;
 
+       my $tip = $req->{-tip};
        my $rel = $req->{relcmd};
        # avoid relative paths, here, we don't want to propagate
        # trailing-slash URLs although we tolerate them
-       $s = "<a\nhref=\"${rel}tree$qs\">root</a>/";
+       $s = "<a\nhref=\"${rel}tree/$tip\">root</a>/";
        my $cur = pop @ex;
        my @t;
        $s .= join('/', (map {
@@ -76,37 +69,38 @@ sub cur_path {
                my $e = PublicInbox::Hval->utf8($_, join('/', @t));
                my $ep = $e->as_path;
                my $eh = $e->as_html;
-               "<a\nhref=\"${rel}tree/$ep$qs\">$eh</a>";
+               "<a\nhref=\"${rel}tree/$tip/$ep\">$eh</a>";
        } @ex), '<b>'.utf8_html($cur).'</b>');
 }
 
 sub git_blob_show {
-       my ($req, $fh, $git, $hex, $q) = @_;
+       my ($req, $fh, $git, $hex) = @_;
        # ref: buffer_is_binary in git.git
        my $to_read = 8000; # git uses this size to detect binary files
        my $text_p;
        my $n = 0;
 
+       my $tip = $req->{-tip};
        my $rel = $req->{relcmd};
-       my $plain = join('/', "${rel}plain", @{$req->{extra}});
-       $plain = PublicInbox::Hval->utf8($plain)->as_path . $q->qs;
-       my $t = cur_path($req, $q);
-       my $h = qq{\npath: $t\n\nblob $hex};
+       my $plain = join('/', "${rel}plain/$tip", @{$req->{extra}});
+       $plain = PublicInbox::Hval->utf8($plain)->as_path;
+       my $t = cur_path($req);
+       my $s = qq{\npath: $t\n\nblob $hex};
        my $end = '';
 
        $git->cat_file($hex, sub {
                my ($cat, $left) = @_; # $$left == $size
-               $h .= qq{\t$$left bytes (<a\nhref="$plain">raw</a>)};
+               $s .= qq{\t$$left bytes (<a\nhref="$plain">raw</a>)};
                $to_read = $$left if $to_read > $$left;
                my $r = read($cat, my $buf, $to_read);
                return unless defined($r) && $r > 0;
                $$left -= $r;
 
                if (index($buf, "\0") >= 0) {
-                       $fh->write("$h\n$BINARY_MSG</pre>");
+                       $fh->write("$s\n$BINARY_MSG</pre>");
                        return;
                }
-               $fh->write($h."</pre><hr/><table\nsummary=blob><tr><td><pre>");
+               $fh->write($s."</pre><hr/><table\nsummary=blob><tr><td><pre>");
                $text_p = 1;
 
                while (1) {
@@ -147,7 +141,6 @@ sub git_tree_sed ($) {
        my ($req) = @_;
        my @lines;
        my $buf = '';
-       my $qs = $req->{qs};
        my $pfx = $req->{tpfx};
        my $end;
        sub {
@@ -180,29 +173,30 @@ sub git_tree_sed ($) {
                        # 'plain' and 'log' links intentionally omitted
                        # for brevity and speed
                        $dst .= qq($m\t).
-                               qq($s\t<a\nhref="$pfx$ref$qs">$path</a>\n);
+                               qq($s\t<a\nhref="$pfx/$ref">$path</a>\n);
                }
                $dst;
        }
 }
 
 sub git_tree_show {
-       my ($req, $hex, $q) = @_;
+       my ($req, $hex) = @_;
        my $git = $req->{repo_info}->{git};
        my $cmd = $git->cmd(qw(ls-tree -l -z), $git->abbrev, $hex);
        my $rdr = { 2 => $git->err_begin };
        my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr);
-       my $t = cur_path($req, $q);
+       my $t = cur_path($req);
        my $pfx;
 
        $req->{thtml} .= "\npath: $t\n\n<b>mode\tsize\tname</b>\n";
-       $req->{qs} = $q->qs;
        if ($req->{tslash}) {
-               $pfx = './';
+               $pfx = '../';
        } elsif (defined(my $last = $req->{extra}->[-1])) {
-               $pfx = PublicInbox::Hval->utf8($last)->as_path . '/';
+               $pfx = PublicInbox::Hval->utf8($last)->as_path;
+       } elsif (defined $req->{h}) {
+               $pfx = $req->{-tip};
        } else {
-               $pfx = 'tree/';
+               $pfx = 'tree/' . $req->{-tip};
        }
        $req->{tpfx} = $pfx;
        my $env = $req->{env};
index c16f10fd98379766692415aeeba18a15567068c2..2513a105805d5d62aeb3aea3cc867828e639889f 100644 (file)
@@ -89,7 +89,7 @@ sub call {
        my $method = $env->{REQUEST_METHOD};
        return r(405, 'Method Not Allowed') if ($method !~ /\AGET|HEAD|POST\z/);
 
-       # URL syntax: / repo [ / cmd [ / path ] ]
+       # URL syntax: / repo [ / cmd [ / head [ / path ] ] ]
        # cmd: log | commit | diff | tree | view | blob | snapshot
        # repo and path (@extra) may both contain '/'
        my $path_info = $env->{PATH_INFO};
@@ -116,13 +116,16 @@ sub call {
        my $vcs_lc = $repo_info->{vcs};
        my $vcs = $VCS{$vcs_lc} or return r404();
        my $mod;
+       my $h;
        if (defined $cmd && length $cmd) {
                $mod = $CMD{$cmd};
-               unless ($mod) {
+               if ($mod) {
+                       $h = shift @extra if @extra;
+               } else {
                        unshift @extra, $cmd;
                        $mod = 'Fallback';
                }
-               $req->{relcmd} = '../' x scalar(@extra);
+               $req->{relcmd} = '../' x (scalar(@extra) + 1);
        } else {
                $mod = 'Summary';
                $cmd = 'summary';
@@ -137,7 +140,8 @@ sub call {
                pop @extra;
                ++$tslash;
        }
-
+       $req->{h} = $h;
+       $req->{-tip} = defined $h ? $h : 'HEAD';
        return no_tslash($env) if ($tslash && $NO_TSLASH{$mod});
 
        $req->{tslash} = $tslash;
index 1f8e95e3c1c648d857f9e0f2567d54daac43c30d..6769bf9fdabed667e4158519e3e350cc5e5c51ea 100644 (file)
@@ -23,11 +23,7 @@ test_psgi($test->{app}, sub {
        like($body, qr!<pre\s*[^>]+>\* header:\n  add header</pre>!,
                'body wrapped in <pre>');
 
-       $res = $cb->(GET($req . '/'));
-       my $sl = dechunk($res);
-       is($body, $sl, 'slash returned identical to non-trailing slash');
-
-       $res = $cb->(GET($req . '/foo.txt'));
+       $res = $cb->(GET($req . '/master/foo.txt'));
        is($res->code, 200, 'got 200');
        $body = dechunk($res);
        like($body, qr{\bhref="http://[^/]+/test\.git/}, 'hrefs OK');
index ed2d6d56d762c40cd625892f45dfa3b2fd71e878..f591302321548a0a71f3f3de563214c8dd0bc485 100644 (file)
@@ -8,24 +8,12 @@ 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');
+       my $res;
 
        $res = $cb->(GET($req));
        is($res->code, 200, 'got proper 200 response for default');
        my $body = dechunk($res);
        like($body, qr!</html>\z!, 'response body finished');
-
-       $res = $cb->(GET($req.$q));
-       is($res->code, 404, 'got 404 response for bad id');
 });
 
 done_testing();
index 27347f70b2a9045fbc7d1259668e53908ce3570b..a93fa10e8095cc352963e35df02cfeae90f703c8 100644 (file)
@@ -7,11 +7,12 @@ my $test = require './t/repobrowse_common_git.perl';
 test_psgi($test->{app}, sub {
        my ($cb) = @_;
 
-       my $req = 'http://example.com/test.git/plain/dir';
+       my $req = 'http://example.com/test.git/plain/master/dir';
        my $res = $cb->(GET($req));
        is(200, $res->code, 'got 200 response from dir');
        my $noslash_body = dechunk($res);
-       like($noslash_body, qr{href="dir/dur">dur</a></li>}, 'path ok w/o slash');
+       like($noslash_body, qr{href="dir/dur">dur</a></li>},
+               'path ok w/o slash');
 
        my $slash = $req . '/';
        my $r2 = $cb->(GET($slash));
@@ -19,7 +20,7 @@ test_psgi($test->{app}, sub {
        my $slash_body = dechunk($r2);
        like($slash_body, qr{href="\./dur\">dur</a></li>}, 'path ok w/ slash');
 
-       $req = 'http://example.com/test.git/plain/foo.txt';
+       $req = 'http://example.com/test.git/plain/master/foo.txt';
        my $blob = $cb->(GET($req));
        like($blob->header('Content-Type'), qr!\Atext/plain\b!,
                'got text/plain blob');
index 531f914c83d5d43f7b934d5336ecdeba7d13de41..d91cfdc998c1788212f5a5eec97471fba7a33014 100644 (file)
@@ -7,11 +7,11 @@ my $test = require './t/repobrowse_common_git.perl';
 test_psgi($test->{app}, sub {
        my ($cb) = @_;
 
-       my $req = 'http://example.com/test.git/tree/dir';
+       my $req = 'http://example.com/test.git/tree/HEAD/dir';
        my $res = $cb->(GET($req));
        is(200, $res->code, 'got 200 response from dir');
        my $noslash_body = dechunk($res);
-       like($noslash_body, qr{href="dir/dur\?id=\w+">dur/</a>},
+       like($noslash_body, qr{href="dir/dur">dur/</a>},
                'path ok w/o slash');
 
        my $slash = $req . '/';
@@ -19,7 +19,7 @@ test_psgi($test->{app}, sub {
        is(301, $r2->code, 'got 301 response from dir with slash');
        is($req, $r2->header('Location'), 'redirected w/o slash');
 
-       $req = 'http://example.com/test.git/tree/foo.txt';
+       $req = 'http://example.com/test.git/tree/master/foo.txt';
        my $blob = $cb->(GET($req));
        is($blob->header('Content-Type'), 'text/html; charset=UTF-8',
                'got text/html blob');