Showing 2 changed files with 11 additions and 301 deletions
+2 -295
lib/Gitprep/SmartHTTP.pm
... ...
@@ -14,63 +14,10 @@ has buffer_size => 8192;
14 14
 
15 15
 our $VERSION = '0.05';
16 16
 my @SERVICES = (
17
-    [ 'POST', 'service_rpc', qr{(.*?)/git-upload-pack$},  'upload-pack' ],
18
-    [ 'POST', 'service_rpc', qr{(.*?)/git-receive-pack$}, 'receive-pack' ],
19
-
20
-    [ 'GET', 'get_info_refs',    qr{(.*?)/info/refs$} ],
21
-    [ 'GET', 'get_text_file',    qr{(.*?)/HEAD$} ],
22
-    [ 'GET', 'get_text_file',    qr{(.*?)/objects/info/alternates$} ],
23
-    [ 'GET', 'get_text_file',    qr{(.*?)/objects/info/http-alternates$} ],
24
-    [ 'GET', 'get_info_packs',   qr{(.*?)/objects/info/packs$} ],
25
-    [ 'GET', 'get_loose_object', qr{(.*?)/objects/[0-9a-f]{2}/[0-9a-f]{38}$} ],
26
-    [
27
-        'GET', 'get_pack_file', qr{(.*?)/objects/pack/pack-[0-9a-f]{40}\.pack$}
28
-    ],
29
-    [ 'GET', 'get_idx_file', qr{(.*?)/objects/pack/pack-[0-9a-f]{40}\.idx$} ],
17
+  [ 'POST', 'service_rpc', qr{(.*?)/git-upload-pack$},  'upload-pack' ],
18
+  [ 'POST', 'service_rpc', qr{(.*?)/git-receive-pack$}, 'receive-pack' ],
30 19
 );
31 20
 
32
-sub get_service {
33
-    my $self = shift;
34
-    my $req  = shift;
35
-
36
-    my $service = $req->param('service');
37
-    return unless $service;
38
-    return unless substr( $service, 0, 4 ) eq 'git-';
39
-    $service =~ s/git-//g;
40
-    return $service;
41
-}
42
-
43
-sub match_routing {
44
-    my $self = shift;
45
-    my $req  = shift;
46
-
47
-    my ( $cmd, $path, $file, $rpc );
48
-    for my $s (@SERVICES) {
49
-        my $match = $s->[2];
50
-        if ( $req->path_info =~ /$match/ ) {
51
-            return ('not_allowed') if $s->[0] ne uc( $req->method );
52
-            $cmd  = $s->[1];
53
-            $path = $1;
54
-            $file = $req->path_info;
55
-            $file =~ s|\Q$path/\E||;
56
-            $rpc = $s->[3];
57
-            return ( $cmd, $path, $file, $rpc );
58
-        }
59
-    }
60
-    return ();
61
-}
62
-
63
-sub get_git_repo_dir {
64
-    my $self = shift;
65
-    my $path = shift;
66
-
67
-    my $root = $self->root || `pwd`;
68
-    chomp $root;
69
-    $path = catdir( $root, $path );
70
-    return $path if ( -d $path );
71
-    return;
72
-}
73
-
74 21
 sub service_rpc {
75 22
     my $self = shift;
76 23
     my $args = shift;
... ...
@@ -146,244 +93,4 @@ sub service_rpc {
146 93
       }
147 94
 }
148 95
 
149
-sub get_info_refs {
150
-    my $self = shift;
151
-    my $args = shift;
152
-
153
-    my $req     = $args->{req};
154
-    my $service = $self->get_service($req);
155
-    if ( $self->has_access( $args->{req}, $service ) ) {
156
-        my @cmd =
157
-          $self->git_command( $service, '--stateless-rpc', '--advertise-refs',
158
-            '.' );
159
-
160
-        my ( $cout, $cerr ) = ( gensym, gensym );
161
-        my $pid = open3( my $cin, $cout, $cerr, @cmd );
162
-        close $cin;
163
-        my ( $refs, $err, $buf ) = ( '', '', '' );
164
-        my $s = IO::Select->new( $cout, $cerr );
165
-        while ( my @ready = $s->can_read ) {
166
-            for my $handle (@ready) {
167
-                while ( sysread( $handle, $buf, BUFFER_SIZE ) ) {
168
-                    if ( $handle == $cerr ) {
169
-                        $err .= $buf;
170
-                    }
171
-                    else {
172
-                        $refs .= $buf;
173
-                    }
174
-                }
175
-                $s->remove($handle) if eof($handle);
176
-            }
177
-        }
178
-        close $cout;
179
-        close $cerr;
180
-        waitpid( $pid, 0 );
181
-
182
-        if ($err) {
183
-            $req->env->{'psgi.errors'}->print("git command failed: $err");
184
-            return $self->return_400;
185
-        }
186
-
187
-        my $res = $req->new_response(200);
188
-        $res->headers(
189
-            [
190
-                'Content-Type' =>
191
-                  sprintf( 'application/x-git-%s-advertisement', $service ),
192
-            ]
193
-        );
194
-        my $body =
195
-          pkt_write("# service=git-${service}\n") . pkt_flush() . $refs;
196
-        $res->body($body);
197
-        return $res->finalize;
198
-    }
199
-    else {
200
-        return $self->dumb_info_refs($args);
201
-    }
202
-}
203
-
204
-sub dumb_info_refs {
205
-    my $self = shift;
206
-    my $args = shift;
207
-    $self->update_server_info;
208
-    $self->send_file( $args, "text/plain; charset=utf-8" );
209
-}
210
-
211
-sub get_info_packs {
212
-    my $self = shift;
213
-    my $args = shift;
214
-    $self->send_file( $args, "text/plain; charset=utf-8" );
215
-}
216
-
217
-sub get_loose_object {
218
-    my $self = shift;
219
-    my $args = shift;
220
-    $self->send_file( $args, "application/x-git-loose-object" );
221
-}
222
-
223
-sub get_pack_file {
224
-    my $self = shift;
225
-    my $args = shift;
226
-    $self->send_file( $args, "application/x-git-packed-objects" );
227
-}
228
-
229
-sub get_idx_file {
230
-    my $self = shift;
231
-    my $args = shift;
232
-    $self->send_file( $args, "application/x-git-packed-objects-toc" );
233
-}
234
-
235
-sub get_text_file {
236
-    my $self = shift;
237
-    my $args = shift;
238
-    $self->send_file( $args, "text/plain" );
239
-}
240
-
241
-sub update_server_info {
242
-    my $self = shift;
243
-    system( $self->git_command('update-server-info') );
244
-}
245
-
246
-sub git_command {
247
-    my $self     = shift;
248
-    my @commands = @_;
249
-    my $git_bin  = $self->git_path;
250
-    return ( $git_bin, @commands );
251
-}
252
-
253
-sub has_access {
254
-    my $self = shift;
255
-    my ( $req, $rpc, $check_content_type ) = @_;
256
-
257
-    if (   $check_content_type
258
-        && $req->content_type ne
259
-        sprintf( "application/x-git-%s-request", $rpc ) )
260
-    {
261
-        return;
262
-    }
263
-
264
-    return if !$rpc;
265
-    return $self->received_pack if $rpc eq 'receive-pack';
266
-    return $self->upload_pack   if $rpc eq 'upload-pack';
267
-    return;
268
-}
269
-
270
-sub send_file {
271
-    my $self = shift;
272
-    my ( $args, $content_type ) = @_;
273
-
274
-    my $file = $args->{reqfile};
275
-    return $self->return_404 unless -e $file;
276
-
277
-    my @stat = stat $file;
278
-    my $res  = $args->{req}->new_response(200);
279
-    $res->headers(
280
-        [
281
-            'Content-Type'  => $content_type,
282
-            'Last-Modified' => HTTP::Date::time2str( $stat[9] ),
283
-            'Expires'       => 'Fri, 01 Jan 1980 00:00:00 GMT',
284
-            'Pragma'        => 'no-cache',
285
-            'Cache-Control' => 'no-cache, max-age=0, must-revalidate',
286
-        ]
287
-    );
288
-
289
-    if ( $stat[7] ) {
290
-        $res->header( 'Content-Length' => $stat[7] );
291
-    }
292
-    open my $fh, "<:raw", $file
293
-      or return $self->return_403;
294
-
295
-    Plack::Util::set_io_path( $fh, Cwd::realpath($file) );
296
-    $res->body($fh);
297
-    $res->finalize;
298
-}
299
-
300
-sub pkt_flush {
301
-  my $self = shift;
302
-  
303
-  return '0000';
304
-}
305
-
306
-sub pkt_write {
307
-  my $self = shift;
308
-  my $str = shift;
309
-  return sprintf( '%04x', length($str) + 4 ) . $str;
310
-}
311
-
312
-sub return_not_allowed {
313
-    my $self = shift;
314
-    my $env  = shift;
315
-    if ( $env->{SERVER_PROTOCOL} eq 'HTTP/1.1' ) {
316
-        return [
317
-            405, [ 'Content-Type' => 'text/plain', 'Content-Length' => 18 ],
318
-            ['Method Not Allowed']
319
-        ];
320
-    }
321
-    else {
322
-        return [
323
-            400, [ 'Content-Type' => 'text/plain', 'Content-Length' => 11 ],
324
-            ['Bad Request']
325
-        ];
326
-    }
327
-}
328
-
329
-sub return_403 {
330
-    my $self = shift;
331
-    return [
332
-        403, [ 'Content-Type' => 'text/plain', 'Content-Length' => 9 ],
333
-        ['Forbidden']
334
-    ];
335
-}
336
-
337
-sub return_400 {
338
-    my $self = shift;
339
-    return [
340
-        400, [ 'Content-Type' => 'text/plain', 'Content-Length' => 11 ],
341
-        ['Bad Request']
342
-    ];
343
-}
344
-
345
-sub return_404 {
346
-    my $self = shift;
347
-    return [
348
-        404, [ 'Content-Type' => 'text/plain', 'Content-Length' => 9 ],
349
-        ['Not Found']
350
-    ];
351
-}
352
-
353 96
 1;
354
-__END__
355
-
356
-=head1 NAME
357
-
358
-  Plack::App::GitSmartHttp - Git Smart HTTP Server PSGI(Plack) Implementation
359
-
360
-=head1 SYNOPSIS
361
-
362
-  use Plack::App::GitSmartHttp;
363
-
364
-  Plack::App::GitSmartHttp->new(
365
-      root          => '/var/git/repos',
366
-      git_path      => '/usr/bin/git',
367
-      upload_pack   => 1,
368
-      received_pack => 1
369
-  )->to_app;
370
-
371
-=head1 DESCRIPTION
372
-
373
-  Plack::App::GitSmartHttp is Git Smart HTTP Server PSGI(Plack) Implementation.
374
-
375
-=head1 AUTHOR
376
-
377
-  Ryuzo Yamamoto E<lt>ryuzo.yamamoto@gmail.comE<gt>
378
-
379
-=head1 SEE ALSO
380
-
381
-  Smart HTTP Transport : <http://progit.org/2010/03/04/smart-http.html>
382
-  Grack : <https://github.com/schacon/grack>
383
-
384
-=head1 LICENSE
385
-
386
-This library is free software; you can redistribute it and/or modify
387
-it under the same terms as Perl itself.
388
-
389
-=cut
+9 -6
templates/smart-http/info-refs.html.ep
... ...
@@ -7,7 +7,8 @@
7 7
   my $project = param('project');
8 8
   my $git = app->git;
9 9
   my $sh = app->smart_http;
10
-
10
+  
11
+  # Smart HTTP
11 12
   if ($service eq 'git-upload-pack') {
12 13
     
13 14
     my $rep = $git->rep($user, $project);
... ...
@@ -44,15 +45,17 @@
44 45
     
45 46
     $self->res->headers->content_type('application/x-git-upload-pack-advertisement');
46 47
     
47
-    my $data =
48
-      $sh->pkt_write("# service=git-upload-pack\n") . $sh->pkt_flush() . $refs;
49
-    
50
-    warn $data;
48
+    # Data start
49
+    my $message = "# service=git-upload-pack\n";
50
+    my $data = sprintf( '%04x', length($message) + 4 ) . $message . '0000' . $refs;
51 51
     
52 52
     $self->render(data => $data);
53 53
     return;
54 54
   }
55
+  # Dumb HTTP
55 56
   else {
56
-    $sh->dumb_info_refs;
57
+    $git->cmd($user, $project, 'update-server-info');
58
+    $self->render_static("../data/rep/$user/$project.git/info/refs");
59
+    return;
57 60
   }
58 61
 %>