gitprep / templates / smart-http / info-refs.html.ep /
36025d0 8 years ago
1 contributor
87 lines | 2.432kb
<%
  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->reply->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;
    }
  }
%>