From 3e79993321bd0e5a12b104730638eb87947ec86b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 22 Dec 2015 21:56:36 +0000 Subject: repobrowse: add git helper for unquoting We need to parse diffs with all manner of funky file names :< --- t/repobrowse_git.t | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 t/repobrowse_git.t (limited to 't') diff --git a/t/repobrowse_git.t b/t/repobrowse_git.t new file mode 100644 index 00000000..eeda90a3 --- /dev/null +++ b/t/repobrowse_git.t @@ -0,0 +1,11 @@ +# Copyright (C) 2015 all contributors +# License: AGPL-3.0+ (https://www.gnu.org/licenses/agpl-3.0.txt) +use strict; +use warnings; +use Test::More; +use PublicInbox::RepoBrowseGit qw(git_unquote); + +is("foo\nbar", git_unquote('"foo\\nbar"'), 'unquoted newline'); +is("Eléanor", git_unquote('"El\\303\\251anor"'), 'unquoted octal'); + +done_testing(); -- cgit v1.2.3-24-ge0c7 From e82a365d610f4939767c219fd3d642915cd1826c Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 31 Dec 2015 21:16:39 +0000 Subject: git: add support for qx wrapper This lets us one-line git commands easily like ``, but without having to remember --git-dir or escape arguments. --- t/git.t | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 't') diff --git a/t/git.t b/t/git.t index 0f3dbae3..d7b20d0d 100644 --- a/t/git.t +++ b/t/git.t @@ -129,6 +129,14 @@ if (1) { local $/; is($all, <$fh>, 'entire read matches'); }; + + my $ref = $gcf->qx(qw(cat-file blob), $buf); + is($all, $ref, 'qx read giant single string'); + + my @ref = $gcf->qx(qw(cat-file blob), $buf); + is($all, join('', @ref), 'qx returned array when wanted'); + my $nl = scalar @ref; + ok($nl > 1, "qx returned array length of $nl"); } done_testing(); -- cgit v1.2.3-24-ge0c7 From 2e84aabd2d81868ce1ed909a2b04103ec3c7e622 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 3 Jan 2016 04:18:58 +0000 Subject: repobrowse: add "plain" endpoint for cgit URI compat This is similar to the "blob" endpoint, except it shows trees as a directory. --- t/repobrowse_common_git.perl | 67 ++++++++++++++++++++++++++++++++++++++++++++ t/repobrowse_git_plain.t | 28 ++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 t/repobrowse_common_git.perl create mode 100644 t/repobrowse_git_plain.t (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl new file mode 100644 index 00000000..869ab382 --- /dev/null +++ b/t/repobrowse_common_git.perl @@ -0,0 +1,67 @@ +#!/usr/bin/perl -w +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +use strict; +use warnings; +use Test::More; +use Data::Dumper; +use File::Temp qw/tempdir/; +use Cwd qw/getcwd/; +my @mods = qw(HTTP::Request::Common Plack::Request Plack::Test URI::Escape); +foreach my $mod (@mods) { + eval "require $mod"; + plan skip_all => "$mod missing for $0" if $@; +} + +sub dechunk ($) { + my ($res) = @_; + my $s = $res->content; + if (lc($res->header('Transfer-Encoding')) eq 'chunked') { + my $rv = ''; + while ($s =~ s/\A([a-f0-9]+)\r\n//i) { # no comment support :x + my $n = hex($1) or last; + $rv .= substr($s, 0, $n); + $s = substr($s, $n); + $s =~ s/\A\r\n// or die "broken parsing in $s\n"; + } + $s =~ s/\A\r\n// or die "broken end parsing in $s\n"; + $s = $rv; + } + $s; +} + +use_ok $_ foreach @mods; +my $git_dir = tempdir(CLEANUP => 1); +my $psgi = "examples/repobrowse.psgi"; +my $app; +ok(-f $psgi, 'psgi example for repobrowse.psgi found'); +{ + is(system(qw(git init -q --bare), $git_dir), 0, 'created git directory'); + my @cmd = ('git', "--git-dir=$git_dir", 'fast-import', '--quiet'); + my $fi_data = getcwd().'/t/git.fast-import-data'; + ok(-r $fi_data, "fast-import data readable (or run test at top level)"); + my $pid = fork; + defined $pid or die "fork failed: $!\n"; + if ($pid == 0) { + open STDIN, '<', $fi_data or die "open $fi_data: $!\n"; + exec @cmd; + die "failed exec: ",join(' ', @cmd),": $!\n"; + } + waitpid $pid, 0; + is($?, 0, 'fast-import succeeded'); + my $repo_config = "$git_dir/pi_repo_config"; + my $fh; + ok((open $fh, '>', $repo_config and + print $fh '[repo "test.git"]', "\n", + "\t", "path = $git_dir", "\n" and + close $fh), 'created repo config'); + local $ENV{PI_REPO_CONFIG} = $repo_config; + ok($app = require $psgi, 'loaded PSGI app'); +} + +# return value +bless { + psgi => $psgi, + git_dir => $git_dir, + app => $app, +}, 'RepoBrowse::TestGit'; diff --git a/t/repobrowse_git_plain.t b/t/repobrowse_git_plain.t new file mode 100644 index 00000000..23c9e0f5 --- /dev/null +++ b/t/repobrowse_git_plain.t @@ -0,0 +1,28 @@ +# 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/plain/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}, '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\">dur}, 'path ok w/ slash'); + + $req = 'http://example.com/test.git/plain/foo.txt'; + my $blob = $cb->(GET($req)); + is($blob->header('Content-Type'), 'text/plain', 'got text/plain blob'); + is($blob->content, "-----\nhello\nworld\n", 'raw blob passed'); +}); + +done_testing(); -- cgit v1.2.3-24-ge0c7 From 5d06fc05c32cc229c078eb3ca1f4c2003f0251a6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 3 Jan 2016 11:19:32 +0000 Subject: 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. --- t/repobrowse_git_tree.t | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 t/repobrowse_git_tree.t (limited to 't') diff --git a/t/repobrowse_git_tree.t b/t/repobrowse_git_tree.t new file mode 100644 index 00000000..52df0492 --- /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(); -- cgit v1.2.3-24-ge0c7 From 6867976f298441eefbc75af1bb04027f1a69efae Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 5 Jan 2016 11:09:38 +0000 Subject: t/git.t: add tests for detecting failures We need to ensure failure detection works. --- t/git.t | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 't') diff --git a/t/git.t b/t/git.t index d7b20d0d..e09a4d01 100644 --- a/t/git.t +++ b/t/git.t @@ -139,4 +139,29 @@ if (1) { ok($nl > 1, "qx returned array length of $nl"); } +{ + my $git = PublicInbox::Git->new($dir); + open my $tmperr, '>&', \*STDERR or die "dup stderr failed: $!\n"; + + open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; + my $err = $git->popen(qw(cat-file blob non-existent)); + my @out = <$err>; + my $close_ret = close $err; + my $close_err = $?; + open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; + is(join('', @out), '', 'no output on stdout on error'); + isnt($close_err, 0, 'close set $? on bad command'); + ok(!$close_ret, 'close returned error on bad command'); + + open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; + $err = $git->popen(qw(tag -l)); + @out = <$err>; + $close_ret = close $err; + $close_err = $?; + open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; + is(join('', @out), '', 'no output on stdout on error'); + ok(!$close_err, 'close clobbered $? on empty output'); + ok($close_ret, 'close returned error on empty output'); +} + done_testing(); -- cgit v1.2.3-24-ge0c7 From 1e7a2bbd2c7b0c1d5f989c0e225d22276055eff1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 12 Jan 2016 21:32:33 +0000 Subject: repobrowse: change Perl capitalization to "Repobrowse" We mainly call it "repobrowse" (all lowercase), so do not imply it is two separate words by capitalizing "Browse". --- t/repobrowse_common_git.perl | 2 +- t/repobrowse_git.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl index 869ab382..96763d9d 100644 --- a/t/repobrowse_common_git.perl +++ b/t/repobrowse_common_git.perl @@ -64,4 +64,4 @@ bless { psgi => $psgi, git_dir => $git_dir, app => $app, -}, 'RepoBrowse::TestGit'; +}, 'Repobrowse::TestGit'; diff --git a/t/repobrowse_git.t b/t/repobrowse_git.t index eeda90a3..6ae7475b 100644 --- a/t/repobrowse_git.t +++ b/t/repobrowse_git.t @@ -3,7 +3,7 @@ use strict; use warnings; use Test::More; -use PublicInbox::RepoBrowseGit qw(git_unquote); +use PublicInbox::RepobrowseGit qw(git_unquote); is("foo\nbar", git_unquote('"foo\\nbar"'), 'unquoted newline'); is("Eléanor", git_unquote('"El\\303\\251anor"'), 'unquoted octal'); -- cgit v1.2.3-24-ge0c7 From be3e0f48796ddb342d4eeb4838c5eedb9aaf79b9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 15 Jan 2016 22:04:30 +0000 Subject: repobrowse: redirect w/o trailing slashes for humans For human-visible HTML pages, avoid the trailing slash as that can reduce cache hits in both the server (using varnish) and clients. Typical web browsers are all capable of following 301 redirects without difficulty or human interaction. We do not redirect for endpoints which may be consumed by automated tools as that may cause compatibility problems. For example, curl(1) does not automatically follow redirects and needs the "-L" flag to do so. --- t/repobrowse_git_tree.t | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 't') diff --git a/t/repobrowse_git_tree.t b/t/repobrowse_git_tree.t index 52df0492..205022a9 100644 --- a/t/repobrowse_git_tree.t +++ b/t/repobrowse_git_tree.t @@ -16,10 +16,8 @@ test_psgi($test->{app}, sub { 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'); + 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'; my $blob = $cb->(GET($req)); -- cgit v1.2.3-24-ge0c7 From 940a4d5f32ae0bed0e39da852dacf44798d7c623 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Jan 2016 05:52:34 +0000 Subject: rename PI_REPO_CONFIG => PI_REPOBROWSE_CONFIG We want to use 'repobrowse' terminology consistently despite it being longer. Furthermore, "repo-config" is an old git command (nowadays git-config(1)) which may confuse some old git users. --- t/repobrowse_common_git.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl index 96763d9d..80f1973e 100644 --- a/t/repobrowse_common_git.perl +++ b/t/repobrowse_common_git.perl @@ -49,13 +49,13 @@ ok(-f $psgi, 'psgi example for repobrowse.psgi found'); } waitpid $pid, 0; is($?, 0, 'fast-import succeeded'); - my $repo_config = "$git_dir/pi_repo_config"; + my $repobrowse_config = "$git_dir/pi_repobrowse_config"; my $fh; - ok((open $fh, '>', $repo_config and + ok((open $fh, '>', $repobrowse_config and print $fh '[repo "test.git"]', "\n", "\t", "path = $git_dir", "\n" and - close $fh), 'created repo config'); - local $ENV{PI_REPO_CONFIG} = $repo_config; + close $fh), 'created repobrowse config'); + local $ENV{PI_REPOBROWSE_CONFIG} = $repobrowse_config; ok($app = require $psgi, 'loaded PSGI app'); } -- cgit v1.2.3-24-ge0c7 From fa8e2e7e001d7585d6e41c254ee4443a1672bca5 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 18 Jan 2016 21:16:14 +0000 Subject: hval: routines for attribute escaping We'll use HTML attributes + anchor links to link to filenames in coming commits. --- t/hval.t | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 t/hval.t (limited to 't') diff --git a/t/hval.t b/t/hval.t new file mode 100644 index 00000000..f824752c --- /dev/null +++ b/t/hval.t @@ -0,0 +1,20 @@ +# Copyright (C) 2015 all contributors +# License: AGPL-3.0+ (https://www.gnu.org/licenses/agpl-3.0.txt) +use strict; +use warnings; +use Test::More; +use PublicInbox::Hval qw(to_attr from_attr); + +foreach my $s ('Hello/World.pm', 'Zcat', 'hello world.c', 'Eléanor', '$at') { + my $attr = to_attr($s); + is(from_attr($attr), $s, "$s => $attr => $s round trips"); +} + +{ + my $bad = eval { to_attr('foo//bar') }; + my $err = $@; + ok(!$bad, 'double-slash rejected'); + like($err, qr/invalid filename:/, 'got exception message'); +} + +done_testing(); -- cgit v1.2.3-24-ge0c7 From 66ad0a45c58ed63ec16a35f41f3eda7cb8917c50 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 18 Jan 2016 23:44:40 +0000 Subject: repobrowse: display text/plain as UTF-8 We'll be UTF-8 imperialists for now and assume all of our textual output is UTF-8 for the benefit of browsers. --- t/repobrowse_git_plain.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 't') diff --git a/t/repobrowse_git_plain.t b/t/repobrowse_git_plain.t index 23c9e0f5..27347f70 100644 --- a/t/repobrowse_git_plain.t +++ b/t/repobrowse_git_plain.t @@ -21,7 +21,8 @@ test_psgi($test->{app}, sub { $req = 'http://example.com/test.git/plain/foo.txt'; my $blob = $cb->(GET($req)); - is($blob->header('Content-Type'), 'text/plain', 'got text/plain blob'); + like($blob->header('Content-Type'), qr!\Atext/plain\b!, + 'got text/plain blob'); is($blob->content, "-----\nhello\nworld\n", 'raw blob passed'); }); -- cgit v1.2.3-24-ge0c7 From b3bc0d722aacdad5ac5e8ee7c32bda9c87d3052b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 20 Jan 2016 22:17:37 +0000 Subject: repobrowse: fix redirects with query string We need to preserve the query string to avoid breakage. --- t/repobrowse.t | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 t/repobrowse.t (limited to 't') diff --git a/t/repobrowse.t b/t/repobrowse.t new file mode 100644 index 00000000..de8a7952 --- /dev/null +++ b/t/repobrowse.t @@ -0,0 +1,21 @@ +# 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($res->code, 301, 'got 301 with trailing slash'); + is($res->header('Location'), $req, 'redirected without tslash'); + + my $q = '?id=deadbeef'; + + $res = $cb->(GET($req . "/$q")); + is($res->code, 301, 'got 301 with trailing slash + query string'); + is($res->header('Location'), $req.$q, 'redirected without tslash'); +}); + +done_testing(); -- cgit v1.2.3-24-ge0c7 From f08dc18b4f5b3aa7a43bfa9ce754b23028f5babb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 20 Jan 2016 22:35:23 +0000 Subject: repobrowse: commits with path redirect to root with anchor 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. --- t/repobrowse_git_commit.t | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 t/repobrowse_git_commit.t (limited to 't') diff --git a/t/repobrowse_git_commit.t b/t/repobrowse_git_commit.t new file mode 100644 index 00000000..f13cd909 --- /dev/null +++ b/t/repobrowse_git_commit.t @@ -0,0 +1,23 @@ +# 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 $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(); -- cgit v1.2.3-24-ge0c7 From 74bdccb25e66298c3f9c81af0f611ad3adfc5a01 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 29 Jan 2016 03:23:39 +0000 Subject: repobrowse: implement Atom feed Mostly following cgit, except we do not serve redundant text-only output which wastes bandwidth and doesn't preserve pre-formatting layout which is critical to some messages. --- t/repobrowse_git_atom.t | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 t/repobrowse_git_atom.t (limited to 't') diff --git a/t/repobrowse_git_atom.t b/t/repobrowse_git_atom.t new file mode 100644 index 00000000..2525effd --- /dev/null +++ b/t/repobrowse_git_atom.t @@ -0,0 +1,39 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +use strict; +use warnings; +my $have_xml_feed = eval { require XML::Feed; 1 }; +my $test = require './t/repobrowse_common_git.perl'; +use Test::More; + +test_psgi($test->{app}, sub { + my ($cb) = @_; + my $req = 'http://example.com/test.git/atom'; + my $res = $cb->(GET($req)); + is($res->code, 200, 'got 200'); + is($res->header('Content-Type'), 'application/atom+xml', + 'got correct Content-Type'); + my $body = dechunk($res); + SKIP: { + skip 'XML::Feed missing', 2 unless $have_xml_feed; + my $p = XML::Feed->parse(\$body); + is($p->format, "Atom", "parsed atom feed"); + is(scalar $p->entries, 6, "parsed six entries"); + } + + $res = $cb->(GET($req . '/')); + my $sl = dechunk($res); + is($body, $sl, 'slash returned identical to non-trailing slash'); + + $res = $cb->(GET($req . '/foo.txt')); + is($res->code, 200, 'got 200'); + $body = dechunk($res); + SKIP: { + skip 'XML::Feed missing', 2 unless $have_xml_feed; + my $p = XML::Feed->parse(\$body); + is($p->format, "Atom", "parsed atom feed"); + is(scalar $p->entries, 4, "parsed 4 entries"); + } +}); + +done_testing(); -- cgit v1.2.3-24-ge0c7 From 64d131a6b4435289f8876b20510a6d80d4dde418 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 3 Mar 2016 03:12:12 +0000 Subject: git: support an error tmpfile for stashing stderr output This should allow us to avoid polluting stderr output when HTTP clients inevitably request broken revisions. --- t/git.t | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 't') diff --git a/t/git.t b/t/git.t index e09a4d01..e7a3c9ea 100644 --- a/t/git.t +++ b/t/git.t @@ -141,27 +141,25 @@ if (1) { { my $git = PublicInbox::Git->new($dir); - open my $tmperr, '>&', \*STDERR or die "dup stderr failed: $!\n"; - open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; - my $err = $git->popen(qw(cat-file blob non-existent)); + my $err = $git->popen([qw(cat-file blob non-existent)], undef, + { 2 => $git->err_begin }); my @out = <$err>; my $close_ret = close $err; my $close_err = $?; - open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; is(join('', @out), '', 'no output on stdout on error'); isnt($close_err, 0, 'close set $? on bad command'); ok(!$close_ret, 'close returned error on bad command'); + isnt($git->err, '', 'got stderr output'); - open STDERR, '>', '/dev/null' or die "redirect stderr failed: $!\n"; - $err = $git->popen(qw(tag -l)); + $err = $git->popen([qw(tag -l)], undef, { 2 => $git->err_begin }); @out = <$err>; $close_ret = close $err; $close_err = $?; - open STDERR, '>&', $tmperr or die "restore stderr failed: $!\n"; is(join('', @out), '', 'no output on stdout on error'); ok(!$close_err, 'close clobbered $? on empty output'); ok($close_ret, 'close returned error on empty output'); + is($git->err, '', 'no stderr output'); } done_testing(); -- cgit v1.2.3-24-ge0c7 From 5940f0cab7017aeefeb5df272b0a73897ce175c2 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 28 Feb 2016 03:35:07 +0000 Subject: repobrowse: git commit is more callback driven We'll be moving to Danga::Socket for giant diff generation in future commits. So this is a step towards being more callback-driven... --- t/repobrowse_git_commit.t | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 't') diff --git a/t/repobrowse_git_commit.t b/t/repobrowse_git_commit.t index f13cd909..969a0b5e 100644 --- a/t/repobrowse_git_commit.t +++ b/t/repobrowse_git_commit.t @@ -18,6 +18,14 @@ test_psgi($test->{app}, sub { 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'); + + $res = $cb->(GET($req)); + is($res->code, 200, 'got proper 200 response for default'); + my $body = dechunk($res); + like($body, qr!\z!, 'response body finished'); + + $res = $cb->(GET($req.$q)); + is($res->code, 404, 'got 404 response for default'); }); done_testing(); -- cgit v1.2.3-24-ge0c7 From 541b8a4e14c471d4746bfda597691155dae0f960 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 5 Mar 2016 07:47:10 +0000 Subject: repobrowse: shorten env name to REPOBROWSE_CONFIG ...From PI_REPOBROWSE_CONFIG. The "PI_" prefix is a bit too long and "repobrowse" is nearly an independent project at this point from a user-perspective. --- t/repobrowse_common_git.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl index 80f1973e..116ae5ab 100644 --- a/t/repobrowse_common_git.perl +++ b/t/repobrowse_common_git.perl @@ -55,7 +55,7 @@ ok(-f $psgi, 'psgi example for repobrowse.psgi found'); print $fh '[repo "test.git"]', "\n", "\t", "path = $git_dir", "\n" and close $fh), 'created repobrowse config'); - local $ENV{PI_REPOBROWSE_CONFIG} = $repobrowse_config; + local $ENV{REPOBROWSE_CONFIG} = $repobrowse_config; ok($app = require $psgi, 'loaded PSGI app'); } -- cgit v1.2.3-24-ge0c7 From 2722ba03b74a782c0f64c7a6b1d09b7b82ff5478 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 7 Mar 2016 08:10:55 +0000 Subject: repobrowse: git fallback allows smart cloning We can reuse the existing code for cloning ssoma repositories to serve normal git repos for repobrowse. Also, this finally adds a test to fallback to dumb cloning when http.uploadPack is disabled for the git repository to save CPU/memory on the host machine. --- t/repobrowse_common_git.perl | 6 +-- t/repobrowse_git_fallback.t | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 t/repobrowse_git_fallback.t (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl index 116ae5ab..9c62a261 100644 --- a/t/repobrowse_common_git.perl +++ b/t/repobrowse_common_git.perl @@ -4,7 +4,6 @@ use strict; use warnings; use Test::More; -use Data::Dumper; use File::Temp qw/tempdir/; use Cwd qw/getcwd/; my @mods = qw(HTTP::Request::Common Plack::Request Plack::Test URI::Escape); @@ -31,8 +30,9 @@ sub dechunk ($) { } use_ok $_ foreach @mods; -my $git_dir = tempdir(CLEANUP => 1); +my $git_dir = tempdir('repobrowse-XXXXXX', CLEANUP => 1, TMPDIR => 1); my $psgi = "examples/repobrowse.psgi"; +my $repobrowse_config = "$git_dir/repobrowse_config"; my $app; ok(-f $psgi, 'psgi example for repobrowse.psgi found'); { @@ -49,7 +49,6 @@ ok(-f $psgi, 'psgi example for repobrowse.psgi found'); } waitpid $pid, 0; is($?, 0, 'fast-import succeeded'); - my $repobrowse_config = "$git_dir/pi_repobrowse_config"; my $fh; ok((open $fh, '>', $repobrowse_config and print $fh '[repo "test.git"]', "\n", @@ -64,4 +63,5 @@ bless { psgi => $psgi, git_dir => $git_dir, app => $app, + repobrowse_config => $repobrowse_config, }, 'Repobrowse::TestGit'; diff --git a/t/repobrowse_git_fallback.t b/t/repobrowse_git_fallback.t new file mode 100644 index 00000000..99f2ee70 --- /dev/null +++ b/t/repobrowse_git_fallback.t @@ -0,0 +1,87 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +use strict; +use warnings; +use Test::More; +my $test = require './t/repobrowse_common_git.perl'; +foreach my $mod (qw(Danga::Socket HTTP::Parser::XS HTTP::Date HTTP::Status)) { + eval "require $mod"; + plan skip_all => "$mod missing for repobrowse_git_fallback.t" if $@; +} +use File::Temp qw/tempdir/; +use Cwd qw/getcwd/; +use IO::Socket; +use Fcntl qw(F_SETFD); +use POSIX qw(dup2); +my $tmpdir = tempdir('repobrowse_git_fallback-XXXXXX', TMPDIR => 1, CLEANUP => 1); +my $err = "$tmpdir/stderr.log"; +my $out = "$tmpdir/stdout.log"; +my $httpd = 'blib/script/public-inbox-httpd'; +my $psgi = getcwd() . '/' . $test->{psgi}; +my %opts = ( + LocalAddr => '127.0.0.1', + ReuseAddr => 1, + Proto => 'tcp', + Type => SOCK_STREAM, + Listen => 1024, +); +my $sock = IO::Socket::INET->new(%opts); +my $pid; +END { kill 'TERM', $pid if defined $pid }; +my $spawn_httpd = sub { + $pid = fork; + if ($pid == 0) { + # pretend to be systemd: + dup2(fileno($sock), 3) or die "dup2 failed: $!\n"; + my $t = IO::Handle->new_from_fd(3, 'r'); + $t->fcntl(F_SETFD, 0); + $ENV{REPOBROWSE_CONFIG} = $test->{repobrowse_config}; + $ENV{LISTEN_PID} = $$; + $ENV{LISTEN_FDS} = 1; + exec $httpd, '-W0', $psgi; + # exec $httpd, '-W0', "--stdout=$out", "--stderr=$err", $psgi; + die "FAIL: $!\n"; + } + ok(defined $pid, 'forked httpd process successfully'); +}; + +$spawn_httpd->(); + +{ + my $host = $sock->sockhost; + my $port = $sock->sockport; + my $url = "http://$host:$port/test.git"; + is(system(qw(git clone -q --mirror), $url, "$tmpdir/smart.git"), + 0, 'smart clone successful'); + is(system('git', "--git-dir=$tmpdir/smart.git", 'fsck'), 0, 'fsck OK'); + + is(system('git', "--git-dir=$test->{git_dir}", + qw(config http.uploadpack 0)), 0, 'disabled smart HTTP'); + is(system('git', "--git-dir=$test->{git_dir}", + qw(update-server-info)), 0, 'enable dumb HTTP'); + is(system(qw(git clone -q --mirror), $url, "$tmpdir/dumb.git"), + 0, 'dumb clone successful'); + is(system('git', "--git-dir=$tmpdir/dumb.git", 'fsck'), 0, 'fsck dumb OK'); + + # allow reading description file + my %conn = ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', + Type => SOCK_STREAM); + my $conn = IO::Socket::INET->new(%conn); + ok($conn, "connected for description check"); + $conn->write("GET /test.git/description HTTP/1.0\r\n\r\n"); + ok($conn->read(my $buf, 8192), 'read response'); + my ($head, $body) = split(/\r\n\r\n/, $buf, 2); + like($head, qr!\AHTTP/1\.0 200 !s, 'got 200 response for description'); + + $conn = IO::Socket::INET->new(%conn); + ok($conn, "connected for range check"); + $conn->write("GET /test.git/description HTTP/1.0\r\n" . + "Range: bytes=5-\r\n\r\n"); + ok($conn->read($buf, 8192), 'read partial response'); + my ($h2, $b2) = split(/\r\n\r\n/, $buf, 2); + like($h2, qr!\AHTTP/1\.0 206 !s, 'got 206 response for range'); + is($b2, substr($body, 5), 'substring matches on 206'); +} + +done_testing(); +1; -- cgit v1.2.3-24-ge0c7 From 278706bf0ab1ce134e0f742791fa904692660ab8 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 8 Mar 2016 04:36:17 +0000 Subject: tests: consolidate repobrowse + httpd integration Use Plack::Test::ExternalServer to simplify our test code and prepare to add more tests for future changes. Add a check for patch generation while we're at it, since patch generation may use our internal "pi.async" API. --- t/repobrowse_git_fallback.t | 87 --------------------------------- t/repobrowse_git_httpd.t | 116 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 87 deletions(-) delete mode 100644 t/repobrowse_git_fallback.t create mode 100644 t/repobrowse_git_httpd.t (limited to 't') diff --git a/t/repobrowse_git_fallback.t b/t/repobrowse_git_fallback.t deleted file mode 100644 index 99f2ee70..00000000 --- a/t/repobrowse_git_fallback.t +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2016 all contributors -# License: AGPL-3.0+ -use strict; -use warnings; -use Test::More; -my $test = require './t/repobrowse_common_git.perl'; -foreach my $mod (qw(Danga::Socket HTTP::Parser::XS HTTP::Date HTTP::Status)) { - eval "require $mod"; - plan skip_all => "$mod missing for repobrowse_git_fallback.t" if $@; -} -use File::Temp qw/tempdir/; -use Cwd qw/getcwd/; -use IO::Socket; -use Fcntl qw(F_SETFD); -use POSIX qw(dup2); -my $tmpdir = tempdir('repobrowse_git_fallback-XXXXXX', TMPDIR => 1, CLEANUP => 1); -my $err = "$tmpdir/stderr.log"; -my $out = "$tmpdir/stdout.log"; -my $httpd = 'blib/script/public-inbox-httpd'; -my $psgi = getcwd() . '/' . $test->{psgi}; -my %opts = ( - LocalAddr => '127.0.0.1', - ReuseAddr => 1, - Proto => 'tcp', - Type => SOCK_STREAM, - Listen => 1024, -); -my $sock = IO::Socket::INET->new(%opts); -my $pid; -END { kill 'TERM', $pid if defined $pid }; -my $spawn_httpd = sub { - $pid = fork; - if ($pid == 0) { - # pretend to be systemd: - dup2(fileno($sock), 3) or die "dup2 failed: $!\n"; - my $t = IO::Handle->new_from_fd(3, 'r'); - $t->fcntl(F_SETFD, 0); - $ENV{REPOBROWSE_CONFIG} = $test->{repobrowse_config}; - $ENV{LISTEN_PID} = $$; - $ENV{LISTEN_FDS} = 1; - exec $httpd, '-W0', $psgi; - # exec $httpd, '-W0', "--stdout=$out", "--stderr=$err", $psgi; - die "FAIL: $!\n"; - } - ok(defined $pid, 'forked httpd process successfully'); -}; - -$spawn_httpd->(); - -{ - my $host = $sock->sockhost; - my $port = $sock->sockport; - my $url = "http://$host:$port/test.git"; - is(system(qw(git clone -q --mirror), $url, "$tmpdir/smart.git"), - 0, 'smart clone successful'); - is(system('git', "--git-dir=$tmpdir/smart.git", 'fsck'), 0, 'fsck OK'); - - is(system('git', "--git-dir=$test->{git_dir}", - qw(config http.uploadpack 0)), 0, 'disabled smart HTTP'); - is(system('git', "--git-dir=$test->{git_dir}", - qw(update-server-info)), 0, 'enable dumb HTTP'); - is(system(qw(git clone -q --mirror), $url, "$tmpdir/dumb.git"), - 0, 'dumb clone successful'); - is(system('git', "--git-dir=$tmpdir/dumb.git", 'fsck'), 0, 'fsck dumb OK'); - - # allow reading description file - my %conn = ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', - Type => SOCK_STREAM); - my $conn = IO::Socket::INET->new(%conn); - ok($conn, "connected for description check"); - $conn->write("GET /test.git/description HTTP/1.0\r\n\r\n"); - ok($conn->read(my $buf, 8192), 'read response'); - my ($head, $body) = split(/\r\n\r\n/, $buf, 2); - like($head, qr!\AHTTP/1\.0 200 !s, 'got 200 response for description'); - - $conn = IO::Socket::INET->new(%conn); - ok($conn, "connected for range check"); - $conn->write("GET /test.git/description HTTP/1.0\r\n" . - "Range: bytes=5-\r\n\r\n"); - ok($conn->read($buf, 8192), 'read partial response'); - my ($h2, $b2) = split(/\r\n\r\n/, $buf, 2); - like($h2, qr!\AHTTP/1\.0 206 !s, 'got 206 response for range'); - is($b2, substr($body, 5), 'substring matches on 206'); -} - -done_testing(); -1; diff --git a/t/repobrowse_git_httpd.t b/t/repobrowse_git_httpd.t new file mode 100644 index 00000000..a9eb0aab --- /dev/null +++ b/t/repobrowse_git_httpd.t @@ -0,0 +1,116 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +# +# Integration test for public-inbox-httpd and (git) repobrowse +# since we may use some special APIs not available in other servers +use strict; +use warnings; +use Test::More; +foreach my $mod (qw(Danga::Socket HTTP::Parser::XS HTTP::Date HTTP::Status + Plack::Test::ExternalServer)) { + eval "require $mod"; + plan skip_all => "$mod missing for repobrowse_git_httpd.t" if $@; +} +my $test = require './t/repobrowse_common_git.perl'; +$Plack::Test::Impl = 'ExternalServer'; +use File::Temp qw/tempdir/; +use Cwd qw/getcwd/; +use IO::Socket; +use Fcntl qw(F_SETFD); +use POSIX qw(dup2); +my $tmpdir = tempdir('repobrowse_git_httpd-XXXXXX', TMPDIR => 1, CLEANUP => 1); +my $err = "$tmpdir/stderr.log"; +my $out = "$tmpdir/stdout.log"; +my $httpd = 'blib/script/public-inbox-httpd'; +my $psgi = getcwd() . '/' . $test->{psgi}; +my %opts = ( + LocalAddr => '127.0.0.1', + ReuseAddr => 1, + Proto => 'tcp', + Type => SOCK_STREAM, + Listen => 1024, +); +my $sock = IO::Socket::INET->new(%opts); +my $host = $sock->sockhost; +my $port = $sock->sockport; +my $uri = "http://$host:$port/"; +my $pid; +END { kill 'TERM', $pid if defined $pid }; +my $spawn_httpd = sub { + $pid = fork; + if ($pid == 0) { + # pretend to be systemd: + dup2(fileno($sock), 3) or die "dup2 failed: $!\n"; + my $t = IO::Handle->new_from_fd(3, 'r'); + $t->fcntl(F_SETFD, 0); + $ENV{REPOBROWSE_CONFIG} = $test->{repobrowse_config}; + $ENV{LISTEN_PID} = $$; + $ENV{LISTEN_FDS} = 1; + exec $httpd, '-W0', $psgi; + # exec $httpd, '-W0', "--stdout=$out", "--stderr=$err", $psgi; + die "FAIL: $!\n"; + } + ok(defined $pid, 'forked httpd process successfully'); +}; + +$spawn_httpd->(); + +{ # git clone tests + my $url = $uri . 'test.git'; + is(system(qw(git clone -q --mirror), $url, "$tmpdir/smart.git"), + 0, 'smart clone successful'); + is(system('git', "--git-dir=$tmpdir/smart.git", 'fsck'), 0, 'fsck OK'); + is(system('git', "--git-dir=$test->{git_dir}", + qw(config http.uploadpack 0)), 0, 'disabled smart HTTP'); + is(system('git', "--git-dir=$test->{git_dir}", + qw(update-server-info)), 0, 'enable dumb HTTP'); + is(system(qw(git clone -q --mirror), $url, "$tmpdir/dumb.git"), + 0, 'dumb clone successful'); + is(system('git', "--git-dir=$tmpdir/dumb.git", 'fsck'), + 0, 'fsck dumb OK'); +} + +test_psgi(uri => $uri, client => sub { + my ($cb) = @_; + my $res = $cb->(GET($uri . 'test.git/info/refs')); + is(200, $res->code, 'got info/refs'); + + $res = $cb->(GET($uri . 'best.git/info/refs')); + is(404, $res->code, 'bad request fails'); + + $res = $cb->(GET($uri . 'test.git/patch')); + is(200, $res->code, 'got patch'); + is('text/plain; charset=UTF-8', $res->header('Content-Type'), + 'got proper content-type with patch'); + + # ignore signature from git-format-patch: + my ($patch, undef) = split(/\n-- \n/s, $res->content); + my ($exp, undef) = split(/\n-- \n/s, + `cd "$test->{git_dir}" && \ + git format-patch -1 -M --stdout HEAD`); + is($patch, $exp, 'patch content matches expected'); +}); + +{ + # allow reading description file + my %conn = ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', + Type => SOCK_STREAM); + my $conn = IO::Socket::INET->new(%conn); + ok($conn, "connected for description check"); + $conn->write("GET /test.git/description HTTP/1.0\r\n\r\n"); + ok($conn->read(my $buf, 8192), 'read response'); + my ($head, $body) = split(/\r\n\r\n/, $buf, 2); + like($head, qr!\AHTTP/1\.0 200 !s, 'got 200 response for description'); + + $conn = IO::Socket::INET->new(%conn); + ok($conn, "connected for range check"); + $conn->write("GET /test.git/description HTTP/1.0\r\n" . + "Range: bytes=5-\r\n\r\n"); + ok($conn->read($buf, 8192), 'read partial response'); + my ($h2, $b2) = split(/\r\n\r\n/, $buf, 2); + like($h2, qr!\AHTTP/1\.0 206 !s, 'got 206 response for range'); + is($b2, substr($body, 5), 'substring matches on 206'); +} + +done_testing(); +1; -- cgit v1.2.3-24-ge0c7 From 78951743029a1d0074ff447c612b2750a83623e5 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 12 Mar 2016 03:41:12 +0000 Subject: examples/repobrowse.psgi: disable Chunked response by default It seems incompatible with Starman and probably confuses other HTTP/1.0-only servers, too. Our -httpd will respect it and requires it for persistent connections. Followup-to: dca2724e0aeb ("examples: disable Chunked response in PSGI example") --- t/repobrowse_common_git.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/repobrowse_common_git.perl b/t/repobrowse_common_git.perl index 9c62a261..cd8ce582 100644 --- a/t/repobrowse_common_git.perl +++ b/t/repobrowse_common_git.perl @@ -15,7 +15,7 @@ foreach my $mod (@mods) { sub dechunk ($) { my ($res) = @_; my $s = $res->content; - if (lc($res->header('Transfer-Encoding')) eq 'chunked') { + if (lc($res->header('Transfer-Encoding') || '') eq 'chunked') { my $rv = ''; while ($s =~ s/\A([a-f0-9]+)\r\n//i) { # no comment support :x my $n = hex($1) or last; -- cgit v1.2.3-24-ge0c7 From 07ba708d4d52f25f371b72801f0b00458944d634 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 5 Apr 2016 03:31:31 +0000 Subject: test: disable warning for Plack::Test::Impl Not sure of a better way around this, but the Plack::Test manpage documents this variable so it should be supported. --- t/repobrowse_git_httpd.t | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 't') diff --git a/t/repobrowse_git_httpd.t b/t/repobrowse_git_httpd.t index a9eb0aab..baa7be59 100644 --- a/t/repobrowse_git_httpd.t +++ b/t/repobrowse_git_httpd.t @@ -12,7 +12,10 @@ foreach my $mod (qw(Danga::Socket HTTP::Parser::XS HTTP::Date HTTP::Status plan skip_all => "$mod missing for repobrowse_git_httpd.t" if $@; } my $test = require './t/repobrowse_common_git.perl'; -$Plack::Test::Impl = 'ExternalServer'; +{ + no warnings 'once'; + $Plack::Test::Impl = 'ExternalServer'; +} use File::Temp qw/tempdir/; use Cwd qw/getcwd/; use IO::Socket; -- cgit v1.2.3-24-ge0c7 From 25b49fc37121d8584b84b44b20c910ef43c44950 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 4 Apr 2016 21:09:19 +0000 Subject: repobrowse: snapshot support for cgit compatibility We currently do not display links to snapshots, but may in the future (optionally, like cgit). However, support snapshots for compatibility reasons in case people had cached URLs or auto-generated them somewhere. We won't natively support xz and bzip2 just yet, but will document (at least in comments) how to enable these expensive compression schemes via git-config(1). Also, support disabling certain archive types to twart URL guessing or old cached links from spiders burning bandwidth. In retrospect, enabling snapshots for my own cgit views was a bad idea since it wastes bandwidth from crawlers and is is often not useful for users with maintainer-built files (e.g. "configure" from "configure.ac" for autoconf, where only the latter is stored in git and the former is generated in release tarballs). --- t/repobrowse_git_httpd.t | 18 ++++++++++++++++++ t/repobrowse_git_snapshot.t | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 t/repobrowse_git_snapshot.t (limited to 't') diff --git a/t/repobrowse_git_httpd.t b/t/repobrowse_git_httpd.t index baa7be59..3e52b1b5 100644 --- a/t/repobrowse_git_httpd.t +++ b/t/repobrowse_git_httpd.t @@ -115,5 +115,23 @@ test_psgi(uri => $uri, client => sub { is($b2, substr($body, 5), 'substring matches on 206'); } +test_psgi(uri => $uri, client => sub { + my ($cb) = @_; + my $res = $cb->(GET($uri . 'test.git/snapshot/test-master.tar.gz')); + is(200, $res->code, 'got gzipped tarball'); + my $got = "$tmpdir/got.tar.gz"; + my $exp = "$tmpdir/exp.tar.gz"; + open my $fh, '>', $got or die "open got.tar.gz: $!"; + print $fh $res->content; + close $fh or die "close failed: $!"; + $res = undef; + my $rc = system('git', "--git-dir=$test->{git_dir}", + qw(archive --prefix=test-master/ --format=tar.gz), + '-o', $exp, 'master'); + is(0, $rc, 'git-archive generated check correctly'); + is(0, system('cmp', $got, $exp), 'got expected gzipped tarball'); + +}); + done_testing(); 1; diff --git a/t/repobrowse_git_snapshot.t b/t/repobrowse_git_snapshot.t new file mode 100644 index 00000000..b608459e --- /dev/null +++ b/t/repobrowse_git_snapshot.t @@ -0,0 +1,46 @@ +# 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, $rc, $res); + + $req = 'http://example.com/test.git/snapshot/test-master.tar.gz'; + $res = $cb->(GET($req)); + is($res->code, 200, 'got 200 response from $NAME-master-tar.gz'); + is($res->header('Content-Type'), 'application/x-gzip', + 'Content-Type is as expected'); + + $req = 'http://example.com/test.git/snapshot/test-nonexistent.tar.gz'; + $res = $cb->(GET($req)); + is($res->code, 404, 'got 404 for non-existent'); + + $rc = system('git', "--git-dir=$test->{git_dir}", 'tag', '-a', + '-m', 'annotated tag!', 'v1.0.0'); + is($rc, 0, 'created annotated 1.0.0 tag'); + $req = 'http://example.com/test.git/snapshot/test-1.0.0.tar.gz'; + $res = $cb->(GET($req)); + is($res->code, 200, 'got 200 response for tag'); + is($res->header('Content-Type'), 'application/x-gzip', + 'Content-Type is as expected'); + is($res->header('Content-Disposition'), + 'inline; filename="test-1.0.0.tar.gz"', + 'Content-Disposition is as expected'); + + $rc = system('git', "--git-dir=$test->{git_dir}", 'tag', + '-m', 'lightweight tag!', 'v2.0.0'); + is($rc, 0, 'created lightweight 2.0.0 tag'); + $req = 'http://example.com/test.git/snapshot/test-2.0.0.tar.gz'; + $res = $cb->(GET($req)); + is($res->code, 200, 'got 200 response for tag'); + is($res->header('Content-Type'), 'application/x-gzip', + 'Content-Type is as expected'); + is($res->header('Content-Disposition'), + 'inline; filename="test-2.0.0.tar.gz"', + 'Content-Disposition is as expected'); +}); + +done_testing(); -- cgit v1.2.3-24-ge0c7 From 2d4c8a36a10acfb14da50dae7f61f06c593803cb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 21 May 2016 07:11:49 +0000 Subject: t/repobrowse_git_tree.t: fix test for lack of bold Fixes: dac5d97d6042 ("repobrowse: do not bold directory names in tree view") --- t/repobrowse_git_tree.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 't') diff --git a/t/repobrowse_git_tree.t b/t/repobrowse_git_tree.t index 205022a9..531f914c 100644 --- a/t/repobrowse_git_tree.t +++ b/t/repobrowse_git_tree.t @@ -11,7 +11,7 @@ test_psgi($test->{app}, sub { 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/}, + like($noslash_body, qr{href="dir/dur\?id=\w+">dur/}, 'path ok w/o slash'); my $slash = $req . '/'; -- cgit v1.2.3-24-ge0c7 From 6cdb0221d18b2caed4d0caebf7c20d6eb159497d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 21 May 2016 07:13:18 +0000 Subject: t/repobrowse_git_httpd.t: ensure signature exists for split I've started using "format.signature=" for an empty signature on some of my machines to save a few lines. --- t/repobrowse_git_httpd.t | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 't') diff --git a/t/repobrowse_git_httpd.t b/t/repobrowse_git_httpd.t index 3e52b1b5..005ab173 100644 --- a/t/repobrowse_git_httpd.t +++ b/t/repobrowse_git_httpd.t @@ -88,9 +88,10 @@ test_psgi(uri => $uri, client => sub { # ignore signature from git-format-patch: my ($patch, undef) = split(/\n-- \n/s, $res->content); + + my $cmd = 'format-patch --signature=git -1 -M --stdout HEAD'; my ($exp, undef) = split(/\n-- \n/s, - `cd "$test->{git_dir}" && \ - git format-patch -1 -M --stdout HEAD`); + `git --git-dir=$test->{git_dir} $cmd`); is($patch, $exp, 'patch content matches expected'); }); -- cgit v1.2.3-24-ge0c7