Minimally working snapshot action.
Zachary Stevens [Thu, 19 Nov 2009 23:19:31 +0000 (23:19 +0000)]
lib/Gitalist/Controller/Root.pm
lib/Gitalist/Git/Object/Commit.pm
lib/Gitalist/Git/Project.pm
lib/Gitalist/Git/Util.pm

index 17c8750..287c5f9 100644 (file)
@@ -457,8 +457,15 @@ sub patches : Local {
 }
 
 sub snapshot : Local {
-    # FIXME - implement snapshot
-    Carp::croak "Not implemented.";
+    my ($self, $c) = @_;
+    my $format = $c->req->param('snapshot_format') || 'tar';
+    die unless $format;
+    my $commit = $self->_get_object($c);
+    $c->response->status(200);
+    $c->response->headers->header( 'Content-Disposition' =>
+                                       'attachment; filename=export.tgz');
+
+    $c->response->body($commit->snapshot($format));
 }
 
 =head2 auto
index 5a125f6..752b930 100644 (file)
@@ -8,6 +8,7 @@ class Gitalist::Git::Object::Commit
         use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
         use Moose::Autobox;
         use List::MoreUtils qw/any zip/;
+        use Gitalist::Util qw(to_utf8);
         our $SHA1RE = qr/[0-9a-fA-F]{40}/;
 
         has '+type' => ( default => 'commit' );
@@ -79,6 +80,18 @@ class Gitalist::Git::Object::Commit
             return \@difftree, [$self->_parse_diff(@out)];
         }
 
+method snapshot ( NonEmptySimpleStr $format ) {
+#    return unless (qw/tar zip/->any($format));
+    my $name = $self->project->name;
+    $name =~ s,([^/])/*\.git$,$1,;
+    my $filename = to_utf8($name);
+    $filename .= "-$self->sha1.$format";
+    $name =~ s/\047/\047\\\047\047/g;
+
+    my @cmd = ('archive', "--format=$format", "--prefix=$name", $self->sha1);
+    return $self->_run_cmd_fh(@cmd);
+}
+
         ## Private methods
         # gitweb uses the following sort of command for diffing merges:
         # /home/dbrook/apps/bin/git --git-dir=/home/dbrook/dev/app/.git diff-tree -r -M --no-commit-id --patch-with-raw --full-index --cc 316cf158df3f6207afbae7270bcc5ba0 --
index 5129f12..5ef414d 100644 (file)
@@ -238,6 +238,19 @@ Returns a list of revs for the given head ($sha1).
         return @revs;
     }
 
+=head2 snapshot($head?, $format)
+
+Generate an archived snapshot of the repository.
+Returns a filehandle to read from.
+
+=cut
+
+method snapshot (Gitalist::Git::Object :$commit,
+                 NonEmptySimpleStr :$format
+               ) {
+               return $commit->snapshot;
+           }
+
 =head2 diff($commit, $patch?, $parent?, $file?)
 
 Generate a diff from a given L<Gitalist::Git::Object>.
index c5d26ab..966c144 100644 (file)
@@ -48,11 +48,12 @@ EOR
     }
 
     method run_cmd_fh (@args) {
-        my ($out, $err) = (geniosym, geniosym);
+        my ($in, $out, $err) = (geniosym, geniosym, geniosym);
         unshift @args, ('--git-dir' => $self->gitdir)
             if $self->has_project;
+#        print STDERR 'RUNNING: ', $self->_git, qq[ @args], $/;
         run [$self->_git, @args],
-            undef,
+            '<pipe', $in,
             '>pipe', $out,
             '2>pipe', $err
                 or die "cmd returned *?";