# Copyright (C) 2015-2016 all contributors
# License: AGPL-3.0+
package PublicInbox::RepoGitRaw;
use strict;
use warnings;
use base qw(PublicInbox::RepoBase);
use PublicInbox::Hval qw(utf8_html);
use PublicInbox::Qspawn;
my $MAX_ASYNC = 65536;
my $BIN_DETECT = 8000;
sub git_raw_check_res ($$$) {
my ($self, $req, $res) = @_;
sub {
my ($info) = @_;
my ($hex, $type, $size) = @$info;
if (!defined $type || $type eq 'missing') {
return $res->($self->rt(404, 'plain', 'Not Found'));
}
my $ct;
if ($type eq 'blob') {
my $base = $req->{extra}->[-1];
$ct = $self->mime_type($base) if defined $base;
$ct ||= 'text/plain; charset=UTF-8' if !$size;
} elsif ($type eq 'commit' || $type eq 'tag') {
$ct = 'text/plain; charset=UTF-8';
} elsif ($type eq 'tree') {
return git_tree_raw($self, $req, $res, $hex);
} else {
$ct = 'application/octet-stream';
}
$size > $MAX_ASYNC and
return show_big($self, $req, $res, $ct, $info);
# buffer small files in full
my $buf = '';
$req->{-repo}->{git}->cat_async($req->{env}, $hex, sub {
my ($r) = @_;
return if ref($r) ne 'SCALAR';
$buf .= $$r;
return if bytes::length($buf) < $size;
$ct ||= index($buf, "\0") >= 0 ?
'application/octet-stream' :
'text/plain; charset=UTF-8';
$res->([200, ['Content-Type', $ct,
'Content-Length', $size ],
[ $buf ]]);
});
}
}
sub call_git_raw {
my ($self, $req) = @_;
my $repo = $req->{-repo};
my $obj = $req->{tip} || $repo->tip;
my $expath = $req->{expath};
$obj .= ":$expath" if $expath ne '';
sub {
my ($res) = @_;
$repo->{git}->check_async($req->{env}, $obj,
git_raw_check_res($self, $req, $res));
}
}
sub git_tree_sed ($) {
my ($req) = @_;
my $buf = '';
my $end = '';
my $pfx = $req->{tpfx};
sub { # $_[0] = buffer or undef
my $dst = delete $req->{tstart} || '';
my @files;
if (defined $_[0]) {
@files = split(/\0/, $buf .= $_[0]);
$buf = pop @files if scalar @files;
} else {
@files = split(/\0/, $buf);
$end = '