... | ... |
@@ -653,10 +653,16 @@ sub last_activity { |
653 | 653 |
} |
654 | 654 |
|
655 | 655 |
sub object_type { |
656 |
- my ($self, $project, $cid) = @_; |
|
656 |
+ my ($self, $user, $project, $cid) = @_; |
|
657 | 657 |
|
658 |
- # Get object type (command "git cat-file") |
|
659 |
- my @cmd = ($self->cmd($project), 'cat-file', '-t', $cid); |
|
658 |
+ # Get object type |
|
659 |
+ my @cmd = $self->_cmd( |
|
660 |
+ $user, |
|
661 |
+ $project, |
|
662 |
+ 'cat-file', |
|
663 |
+ '-t', |
|
664 |
+ $cid |
|
665 |
+ ); |
|
660 | 666 |
open my $fh, '-|', @cmd or return; |
661 | 667 |
my $type = $self->dec(scalar <$fh>); |
662 | 668 |
close $fh or return; |
... | ... |
@@ -1,82 +0,0 @@ |
1 |
-package Gitprep::Main; |
|
2 |
-use Mojo::Base 'Mojolicious::Controller'; |
|
3 |
-use File::Basename 'dirname'; |
|
4 |
-use Carp 'croak'; |
|
5 |
-use Gitprep::API; |
|
6 |
- |
|
7 |
-sub archive { |
|
8 |
- my $self = shift; |
|
9 |
- |
|
10 |
- # API |
|
11 |
- my $api = Gitprep::API->new($self); |
|
12 |
- |
|
13 |
- # Parameter |
|
14 |
- my $user = $self->param('user'); |
|
15 |
- my $project = $self->param('project'); |
|
16 |
- my $root_ns = $api->root_ns($self->config->{root}); |
|
17 |
- my $rep_ns = "$root_ns/$user/$project.git"; |
|
18 |
- my $rep = "/$rep_ns"; |
|
19 |
- my $rev = $self->param('rev'); |
|
20 |
- my $archive_type = $self->stash('archive_type'); |
|
21 |
- my $content_type; |
|
22 |
- my $format; |
|
23 |
- my $ext; |
|
24 |
- if ($archive_type eq 'tar') { |
|
25 |
- $format = 'tar'; |
|
26 |
- $ext = 'tar.gz'; |
|
27 |
- $content_type = 'application/x-tar'; |
|
28 |
- } |
|
29 |
- elsif ($archive_type eq 'zip') { |
|
30 |
- $format = 'zip'; |
|
31 |
- $ext = 'zip'; |
|
32 |
- $content_type = 'application/zip'; |
|
33 |
- } |
|
34 |
- |
|
35 |
- # Git |
|
36 |
- my $git = $self->app->git; |
|
37 |
- |
|
38 |
- # Object type |
|
39 |
- my $type = $git->object_type($rep, "$rev^{}"); |
|
40 |
- if (!$type) { croak 404, 'Object does not exist' } |
|
41 |
- elsif ($type eq 'blob') { croak 400, 'Object is not a tree-ish' } |
|
42 |
- |
|
43 |
- my $name = "$project-$rev"; |
|
44 |
- my $file = "$name.$ext"; |
|
45 |
- |
|
46 |
- my $cmd = $self->_quote_command( |
|
47 |
- $git->cmd($rep), 'archive', "--format=$format", "--prefix=$name/", $rev |
|
48 |
- ); |
|
49 |
- if ($archive_type eq 'tar') { |
|
50 |
- $cmd .= ' | ' . $self->_quote_command('gzip', '-n'); |
|
51 |
- } |
|
52 |
- $file =~ s/(["\\])/\\$1/g; |
|
53 |
- |
|
54 |
- open my $fh, '-|', $cmd |
|
55 |
- or croak 'Execute git-archive failed'; |
|
56 |
- |
|
57 |
- # Write chunk |
|
58 |
- $self->res->headers->content_type($content_type); |
|
59 |
- $self->res->headers->content_disposition(qq/attachment; filename="$file"/); |
|
60 |
- my $cb; |
|
61 |
- $cb = sub { |
|
62 |
- my $c = shift; |
|
63 |
- my $size = 500 * 1024; |
|
64 |
- my $length = sysread($fh, my $buffer, $size); |
|
65 |
- unless ($length) { |
|
66 |
- close $fh; |
|
67 |
- undef $cb; |
|
68 |
- $c->finish; |
|
69 |
- return; |
|
70 |
- } |
|
71 |
- $c->write_chunk($buffer, $cb); |
|
72 |
- }; |
|
73 |
- $self->$cb; |
|
74 |
-} |
|
75 |
- |
|
76 |
-sub _quote_command { |
|
77 |
- my $self = shift; |
|
78 |
- return join(' ', |
|
79 |
- map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ); |
|
80 |
-} |
|
81 |
- |
|
82 |
-1; |
... | ... |
@@ -0,0 +1,74 @@ |
1 |
+<% |
|
2 |
+ # API |
|
3 |
+ my $api = $self->gitprep_api; |
|
4 |
+ |
|
5 |
+ # Parameter |
|
6 |
+ my $user = param('user'); |
|
7 |
+ my $project = param('project'); |
|
8 |
+ my $rev = param('rev'); |
|
9 |
+ my $archive_type = stash('archive_type'); |
|
10 |
+ my $content_type; |
|
11 |
+ my $format; |
|
12 |
+ my $ext; |
|
13 |
+ if ($archive_type eq 'tar') { |
|
14 |
+ $format = 'tar'; |
|
15 |
+ $ext = 'tar.gz'; |
|
16 |
+ $content_type = 'application/x-tar'; |
|
17 |
+ } |
|
18 |
+ elsif ($archive_type eq 'zip') { |
|
19 |
+ $format = 'zip'; |
|
20 |
+ $ext = 'zip'; |
|
21 |
+ $content_type = 'application/zip'; |
|
22 |
+ } |
|
23 |
+ |
|
24 |
+ # Git |
|
25 |
+ my $git = app->git; |
|
26 |
+ |
|
27 |
+ # Object type |
|
28 |
+ my $type = $git->object_type($user, $project, "$rev^{}"); |
|
29 |
+ if (!$type) { $api->croak('Object does not exist') } |
|
30 |
+ elsif ($type eq 'blob') { $api->croak('Object is not a tree-ish') } |
|
31 |
+ |
|
32 |
+ my $name = "$project-$rev"; |
|
33 |
+ my $file = "$name.$ext"; |
|
34 |
+ my $quote = sub { |
|
35 |
+ return join(' ', |
|
36 |
+ map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ |
|
37 |
+ ); |
|
38 |
+ }; |
|
39 |
+ my $cmd = $quote->( |
|
40 |
+ $git->_cmd( |
|
41 |
+ $user, |
|
42 |
+ $project, |
|
43 |
+ 'archive', |
|
44 |
+ "--format=$format", |
|
45 |
+ "--prefix=$name/", |
|
46 |
+ $rev |
|
47 |
+ ) |
|
48 |
+ ); |
|
49 |
+ if ($archive_type eq 'tar') { |
|
50 |
+ $cmd .= ' | ' . $quote->('gzip', '-n'); |
|
51 |
+ } |
|
52 |
+ $file =~ s/(["\\])/\\$1/g; |
|
53 |
+ |
|
54 |
+ open my $fh, '-|', $cmd |
|
55 |
+ or $api->croak('Execute git-archive failed'); |
|
56 |
+ |
|
57 |
+ # Write chunk |
|
58 |
+ $self->res->headers->content_type($content_type); |
|
59 |
+ $self->res->headers->content_disposition(qq/attachment; filename="$file"/); |
|
60 |
+ my $cb; |
|
61 |
+ $cb = sub { |
|
62 |
+ my $c = shift; |
|
63 |
+ my $size = 500 * 1024; |
|
64 |
+ my $length = sysread($fh, my $buffer, $size); |
|
65 |
+ unless ($length) { |
|
66 |
+ close $fh; |
|
67 |
+ undef $cb; |
|
68 |
+ $c->finish; |
|
69 |
+ return; |
|
70 |
+ } |
|
71 |
+ $c->write_chunk($buffer, $cb); |
|
72 |
+ }; |
|
73 |
+ $self->$cb; |
|
74 |
+%> |