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;
# Smart HTTP
if ($service eq 'git-upload-pack' || $service eq 'git-receive-pack') {
my $service_cmd = $service;
substr($service_cmd, 0, 4, '');
my $rep = $git->rep($user, $project);
my @cmd = $git->cmd($user, $project, $service_cmd, '--stateless-rpc', '--advertise-refs', $rep);
my ($cout, $cerr) = (Symbol::gensym, Symbol::gensym);
my $pid = IPC::Open3::open3(my $cin, $cout, $cerr, @cmd );
close $cin;
my ( $refs, $err, $buf ) = ( '', '', '' );
my $s = IO::Select->new($cout, $cerr);
my $buffer_size = $ENV{GITPREP_SMART_HTTP_BUFFER_SIZE};
while (my @ready = $s->can_read) {
for my $handle (@ready) {
while (sysread($handle, $buf, $buffer_size)) {
if ($handle == $cerr) {
$err .= $buf;
}
else {
$refs .= $buf;
}
}
$s->remove($handle) if eof($handle);
}
}
close $cout;
close $cerr;
waitpid($pid, 0);
if ($err) {
app->log->error($err);
$self->render_exception($err);
return;
}
$self->res->headers->content_type("application/x-$service-advertisement");
# Data start
my $message = "# service=$service\n";
my $data = sprintf( '%04x', length($message) + 4 ) . $message . '0000' . $refs;
$self->render(data => $data);
return;
}
# Dumb HTTP
else {
# Update server info
my @cmd = $git->cmd($user, $project, 'update-server-info');
open my $fh, '-|', @cmd
or die "Can't open pipe for @cmd:$!";
close $fh
or die "Can't close pipe for @cmd:$!";
my $content_type = 'text/plain; charset=UTF-8';
my $rep_home = app->git->rep_home;
my $file = "$rep_home/$user/$project.git/info/refs";
if (-f $file) {
my $asset = Mojo::Asset::File->new(path => $file);
my $content = $asset->slurp;
$content = '' unless defined $content;
$self->res->headers->content_type($content_type);
$self->res->headers->content_length(length $content);
$self->res->body($content);
$self->res->code(200);
$self->rendered;
return;
}
else {
$self->res->code(404);
$self->rendered;
return;
}
}
%>