From: Eric Wong Date: Sun, 28 Feb 2016 03:35:07 +0000 (+0000) Subject: repobrowse: git commit is more callback driven X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5940f0cab7017aeefeb5df272b0a73897ce175c2;p=thirdparty%2Fpublic-inbox.git 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... --- diff --git a/lib/PublicInbox/RepobrowseGitCommit.pm b/lib/PublicInbox/RepobrowseGitCommit.pm index edc277176..156e3e222 100644 --- a/lib/PublicInbox/RepobrowseGitCommit.pm +++ b/lib/PublicInbox/RepobrowseGitCommit.pm @@ -23,7 +23,12 @@ use constant GIT_FMT => '--pretty=format:'.join('%n', '%t', '%p', '%D', '%b%x00'); sub git_commit_stream { - my ($self, $req, $q, $H, $log, $fh) = @_; + my ($self, $req) = @_; + my $log = $req->{log}; + my $H = <$log>; + defined $H or return git_commit_404($req); + my $fh = delete($req->{res})->([200, ['Content-Type'=>'text/html']]); + $req->{fh} = $fh; chomp(my $h = <$log>); # abbreviated commit my $l; chomp(my $s = utf8_html($l = <$log>)); # subject @@ -38,6 +43,7 @@ sub git_commit_stream { my $git = $req->{repo_info}->{git}; my $rel = $req->{relcmd}; + my $q = $req->{'q'}; my $qs = $q->qs(id => $h); chomp $H; my $x = $self->html_start($req, $s) . "\n" . @@ -146,34 +152,47 @@ sub call_git_commit { } my $git = $req->{repo_info}->{git}; - my @cmd = (qw(show -z --numstat -p --encoding=UTF-8 - --no-notes --no-color -c), $git->abbrev); - - 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) unless defined $H; + my $cmd = [ qw(show -z --numstat -p --encoding=UTF-8 + --no-notes --no-color -c), + $git->abbrev, GIT_FMT, $id, '--' ]; + $req->{log} = $git->popen($cmd, undef, { 2 => $git->err_begin }); + $req->{end} = sub { + $req->{cb} = $req->{end} = undef; + if (my $fh = delete $req->{fh}) { + $fh->close; + } elsif (my $res = delete $req->{res}) { + $res->(r(500)); + } + if (my $log = delete $req->{log}) { + $log->close; # _may_ be Danga::Socket::close + } + # zero the error file for now, be careful about printing + # $id to psgi.errors w/o sanitizing... + $git->err; + }; + $req->{'q'} = $q; + $req->{cb} = sub { # read git-show output and stream to client + git_commit_stream($self, $req); + $req->{end}->(); + }; sub { - my ($res) = @_; # Plack callback - my $fh = $res->([200, ['Content-Type'=>'text/html']]); - git_commit_stream($self, $req, $q, $H, $log, $fh); - $fh->close; + $req->{res} = $_[0]; + $req->{cb}->(); } } sub git_commit_404 { - my ($req, $q) = @_; + my ($req) = @_; my $x = 'Missing commit or path'; my $pfx = "$req->{relcmd}commit"; my $try = 'try'; $x = "$x
$x\n\n";
-	my $qs = $q->qs(id => '');
+	my $qs = $req->{'q'}->qs(id => '');
 	$x .= "$try the latest commit in HEAD\n";
 	$x .= '
'; - [ 404, ['Content-Type'=>'text/html'], [ $x ] ]; + delete($req->{res})->([404, ['Content-Type'=>'text/html'], [ $x ]]); } sub git_show_diffstat { diff --git a/t/repobrowse_git_commit.t b/t/repobrowse_git_commit.t index f13cd909e..969a0b5e8 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();