gitprep / templates / smart-http / service.html.ep /
Yuki Kimoto remove cmd_rep
8d3561f 8 years ago
1 contributor
72 lines | 1.654kb
<%
  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;
%>