diff options
author | Eric Wong <e@80x24.org> | 2016-12-13 21:56:39 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2016-12-14 00:22:55 +0000 |
commit | 00488f0cfe9f81d04cd65d09ea783e860c937401 (patch) | |
tree | 24e4d9282d5e7098fc6cbdcc9d5615c46513661f /lib/PublicInbox/RepobrowseGitBlob.pm | |
parent | f9d4f28d9761011d3c7ffad9e2c9d1e54b65c519 (diff) | |
parent | 6cdb0221d18b2caed4d0caebf7c20d6eb159497d (diff) | |
download | public-inbox-00488f0cfe9f81d04cd65d09ea783e860c937401.tar.gz |
* origin/repobrowse: (98 commits) t/repobrowse_git_httpd.t: ensure signature exists for split t/repobrowse_git_tree.t: fix test for lack of bold repobrowse: fix alignment of gitlink entries repobrowse: show invalid type for tree views repobrowse: do not bold directory names in tree view repobrowse: reduce checks for response fh repobrowse: larger, short-lived buffer for reading patches repobrowse: reduce risk of callback reference cycles repobrowse: snapshot support for cgit compatibility test: disable warning for Plack::Test::Impl repobrowse: avoid confusing linkification for "diff" repobrowse: git commit view uses pi-httpd.async repobrowse: more consistent variable naming for /commit/ repobrowse: show roughly equivalent "diff-tree" invocation repobrowse: reduce local variables for state management repobrowse: summary handles multiple README types repobrowse: remove bold decorations from diff view repobrowse: common git diff parsing code repobrowse: implement diff view for compatibility examples/repobrowse.psgi: disable Chunked response by default ...
Diffstat (limited to 'lib/PublicInbox/RepobrowseGitBlob.pm')
-rw-r--r-- | lib/PublicInbox/RepobrowseGitBlob.pm | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/lib/PublicInbox/RepobrowseGitBlob.pm b/lib/PublicInbox/RepobrowseGitBlob.pm new file mode 100644 index 00000000..f2b38a0c --- /dev/null +++ b/lib/PublicInbox/RepobrowseGitBlob.pm @@ -0,0 +1,79 @@ +# Copyright (C) 2015-2016 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# Show a blob as-is +package PublicInbox::RepobrowseGitBlob; +use strict; +use warnings; +use base qw(PublicInbox::RepobrowseBase); +use base qw(Exporter); +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::RepobrowseGitQuery->new($req->{cgi}); + my $id = $q->{id}; + $id eq '' and $id = 'HEAD'; + + if (length(my $expath = $req->{expath})) { + $id .= ":$expath"; + } + my ($cat, $hex, $type, $size) = $git->cat_file_begin($id); + return unless defined $cat; + + my ($r, $buf); + my $left = $size; + if ($type eq 'blob') { + $type = git_blob_mime_type($self, $req, $cat, \$buf, \$left); + } elsif ($type eq 'commit' || $type eq 'tag') { + $type = 'text/plain; charset=UTF-8'; + } else { + $type = 'application/octet-stream'; + } + git_blob_stream_response($git, $cat, $size, $type, $buf, $left); +} + +sub git_blob_mime_type { + my ($self, $req, $cat, $buf, $left) = @_; + my $base = $req->{extra}->[-1]; + my $type = $self->mime_type($base) if defined $base; + return $type if $type; + + my $to_read = 8000; # git uses this size to detect binary files + $to_read = $$left if $to_read > $$left; + my $r = read($cat, $$buf, $to_read); + if (!defined $r || $r <= 0) { + my $git = $req->{repo_info}->{git}; + $git->cat_file_finish($$left); + return; + } + $$left -= $r; + (index($buf, "\0") < 0) ? 'text/plain; charset=UTF-8' + : 'application/octet-stream'; +} + +sub git_blob_stream_response { + my ($git, $cat, $size, $type, $buf, $left) = @_; + + sub { + my ($res) = @_; + my $to_read = 8192; + eval { + my $fh = $res->([ 200, ['Content-Length' => $size, + 'Content-Type' => $type]]); + $fh->write($buf) if defined $buf; + while ($left > 0) { + $to_read = $left if $to_read > $left; + my $r = read($cat, $buf, $to_read); + last if (!defined $r || $r <= 0); + $left -= $r; + $fh->write($buf); + } + $fh->close; + }; + $git->cat_file_finish($left); + } +} + +1; |