1 contributor
<%
use IPC::Open3 ();
use Symbol ();
use IO::Select ();
my $service = param('service');
my $user = param('user');
my $project = param('project');
my $git = app->git;
my $rep_info = app->rep_info($user, $project);
my $rep_git_dir = $rep_info->{git_dir};
my @cmd = $git->cmd(app->rep_info($user, $project), $service, '--stateless-rpc', $rep_git_dir);
# Command
my ($cout, $cerr) = (Symbol::gensym, Symbol::gensym);
my $pid = IPC::Open3::open3(my $cin, $cout, $cerr, @cmd);
my $pos = 0;
my $content = $self->req->content;
while (1) {
my $chunk = $content->get_body_chunk($pos);
last unless defined $chunk;
my $length = length $chunk;
last unless $length;
print $cin $chunk;
$pos += $length;
}
close $cin;
# Response
$self->res->headers->content_type("application/x-git-$service-result");
$self->render_later;
# Write
my $s = IO::Select->new($cout, $cerr);
my $buffer_size = $ENV{GITPREP_SMART_HTTP_BUFFER_SIZE};
my $error;
my @ready;
my $cb;
$cb = sub {
my $c = shift;
if (@ready = $s->can_read) {
my $output = '';
for my $handle (@ready) {
if (sysread($handle, my $buf, $buffer_size)) {
if ($handle == $cerr) {
$error .= $buf;
}
else {
$output .= $buf;
}
}
else {
$s->remove($handle);
}
}
$c->write_chunk($output, $cb);
}
else {
$c->finish;
waitpid($pid, 0);
$c->app->log->error($c->url_for . ": $error") if defined $error;
undef $cb;
return;
}
};
$self->$cb;
%>