From: Eric Wong Date: Sun, 3 Jan 2016 11:19:32 +0000 (+0000) Subject: repobrowse: tree nav is consistent between blobs/trees X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5d06fc05c32cc229c078eb3ca1f4c2003f0251a6;p=thirdparty%2Fpublic-inbox.git repobrowse: tree nav is consistent between blobs/trees We use the same path: header at the top and allow jumping back to the tree when displaying blobs. --- diff --git a/lib/PublicInbox/RepoBrowseGitTree.pm b/lib/PublicInbox/RepoBrowseGitTree.pm index b361a9c08..7cab58c98 100644 --- a/lib/PublicInbox/RepoBrowseGitTree.pm +++ b/lib/PublicInbox/RepoBrowseGitTree.pm @@ -14,6 +14,8 @@ my %GIT_MODE = ( '160000' => 'g', # commit (gitlink) ); +my $BINARY_MSG = "Binary file, save using the 'plain' link above"; + sub git_tree_stream { my ($self, $req, $res) = @_; # res: Plack callback my @extra = @{$req->{extra}}; @@ -40,7 +42,7 @@ sub git_tree_stream { if ($type eq 'tree') { git_tree_show($req, $fh, $git, $hex, $q); } elsif ($type eq 'blob') { - git_blob_show($fh, $git, $hex); + git_blob_show($req, $fh, $git, $hex, $q); } else { # TODO } @@ -53,17 +55,40 @@ sub call_git_tree { sub { git_tree_stream($self, $req, @_) }; } -sub git_blob_binary { - my ($fh) = @_; - $fh->write('
Binary file cannot be displayed
'); +sub cur_path { + my ($req, $q) = @_; + my $qs = $q->qs; + my @ex = @{$req->{extra}} or return 'root'; + my $s; + + my $rel = $req->{relcmd}; + # avoid relative paths, here, we don't want to propagate + # trailing-slash URLs although we tolerate them + $s = "root/"; + my $cur = pop @ex; + my @t; + $s .= join('/', (map { + push @t, $_; + my $e = PublicInbox::Hval->utf8($_, join('/', @t)); + my $ep = $e->as_path; + my $eh = $e->as_html; + "$eh"; + } @ex), ''.utf8_html($cur).''); } sub git_blob_show { - my ($fh, $git, $hex) = @_; + my ($req, $fh, $git, $hex, $q) = @_; # 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 $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{
path: $t\n\nblob: $hex (plain)};
+
 	$git->cat_file($hex, sub {
 		my ($cat, $left) = @_; # $$left == $size
 		$to_read = $$left if $to_read > $$left;
@@ -71,9 +96,11 @@ sub git_blob_show {
 		return unless defined($r) && $r > 0;
 		$$left -= $r;
 
-		return git_blob_binary($fh) if (index($buf, "\0") >= 0);
-
-		$fh->write('
');
+		if (index($buf, "\0") >= 0) {
+			$fh->write("$h\n$BINARY_MSG
"); + return; + } + $fh->write($h . '
');
 		$text_p = 1;
 
 		while (1) {
@@ -105,38 +132,23 @@ sub git_tree_show {
 	my ($req, $fh, $git, $hex, $q) = @_;
 	$fh->write('
');
 	my $ls = $git->popen(qw(ls-tree --abbrev=16 -l -z), $hex);
-	local $/ = "\0";
+	my $t = cur_path($req, $q);
 	my $pfx;
+	$fh->write("path: $t\n\n");
 	my $qs = $q->qs;
-	my @ex = @{$req->{extra}};
-	my $rel = $req->{relcmd};
-	my $t;
-	if (@ex) {
-		$t = "root/";
-		my $cur = pop @ex;
-		my @t;
-		$t .= join('/', (map {
-			push @t, $_;
-			my $e = PublicInbox::Hval->utf8($_, join('/', @t));
-			my $ep = $e->as_path;
-			my $eh = $e->as_html;
-			"$eh";
-		} @ex), ''.utf8_html($cur).'');
-		push @ex, $cur;
-	} else {
-		$t = 'root';
-	}
-	$fh->write("$t\n");
 
 	if ($req->{tslash}) {
 		$pfx = './';
-	} elsif (@ex) {
-		$pfx = $ex[-1] . '/';
+	} elsif (defined(my $last = $req->{extra}->[-1])) {
+		$pfx = PublicInbox::Hval->utf8($last)->as_path . '/';
 	} else {
 		$pfx = 'tree/';
 	}
 
-	my $plain_pfx = join('/', "${rel}plain", @{$req->{extra}}, '');
+	my $plain_pfx = join('/', "$req->{relcmd}plain", @{$req->{extra}}, '');
+	$plain_pfx = PublicInbox::Hval->utf8($plain_pfx)->as_path;
+	local $/ = "\0";
+	$fh->write("mode\t\t\tsize\tname\n");
 	while (defined(my $l = <$ls>)) {
 		chomp $l;
 		my ($m, $t, $x, $s, $path) =
@@ -154,9 +166,11 @@ sub git_tree_show {
 		elsif ($m eq 'd') { $path = "$path/" }
 		elsif ($m eq 'x') { $path = "$path" }
 		elsif ($m eq 'l') { $path = "$path" }
+		$s =~ s/\s+//g;
 
-		$fh->write(qq($m log raw) .
-			qq( $s $path\n));
+		$fh->write(qq($m\tlog ).
+			qq(plain) .
+			qq(\t$s\t$path\n));
 	}
 	$fh->write('
'); } diff --git a/t/repobrowse_git_tree.t b/t/repobrowse_git_tree.t new file mode 100644 index 000000000..52df0492a --- /dev/null +++ b/t/repobrowse_git_tree.t @@ -0,0 +1,35 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +use strict; +use warnings; +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 $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/}, + 'path ok w/o slash'); + + my $slash = $req . '/'; + my $r2 = $cb->(GET($slash)); + is(200, $r2->code, 'got 200 response from dir'); + my $slash_body = dechunk($r2); + like($slash_body, qr{href="\./dur\?id=\w+\">dur/}, + 'path ok w/ slash'); + + $req = 'http://example.com/test.git/tree/foo.txt'; + my $blob = $cb->(GET($req)); + is($blob->header('Content-Type'), 'text/html; charset=UTF-8', + 'got text/html blob'); + + my $body = dechunk($blob); + foreach (qw(----- hello world)) { + ok(index($body, $_) >= 0, "substring $_ in body"); + } +}); + +done_testing();