From 723a8f6521044e7de3208f15e58a88fed9b6a8ca Mon Sep 17 00:00:00 2001 From: Dennis Kaarsemaker Date: Fri, 27 Jul 2012 23:44:43 +0200 Subject: [PATCH] Snapshot improvements - Snapshots are now stored on disk so they can be reused, tmpwatch can be used to clean up - .tar.{gz,xz,bz2} snapshots are now supported - Snapshot dir and format are configurable in the gitalist config - shortlog/longlog now contain links to snapshots, defaulting to bz2 - Use the abbreviated sha1 in the snapshot filename and directory name like gitweb does --- ISSUES | 1 - gitalist.conf | 5 +++ lib/Gitalist/Controller/Ref.pm | 11 ++++--- lib/Gitalist/Git/Repository.pm | 45 ++++++++++++++++++++++----- root/fragment/repository/shortlog.tt2 | 1 + root/static/css/core.css | 5 ++- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/ISSUES b/ISSUES index 74d64a7..4b66700 100644 --- a/ISSUES +++ b/ISSUES @@ -4,4 +4,3 @@ * Gitweb compat URIs are borked - there were some I just wholesale ripped out. Put back.. * Sort out commitdiff so conflicted merges have an equivalent display to gitweb (d7f39bebabeb31ce9a7b4f1b6f3db9f391b78c3e as a reference) * Need to sanitise the input ... -* The snapshot action does not properly support tgz - requests for this format will receive a tar. tbz2 is not supported at all (yet). diff --git a/gitalist.conf b/gitalist.conf index 7de94a7..8445655 100644 --- a/gitalist.conf +++ b/gitalist.conf @@ -20,3 +20,8 @@ sitename "A Gitalist" max = 16 + + + format = tar.bz2 + tmpdir = /tmp/gitalist/snapshot + diff --git a/lib/Gitalist/Controller/Ref.pm b/lib/Gitalist/Controller/Ref.pm index 46def57..e927ea6 100644 --- a/lib/Gitalist/Controller/Ref.pm +++ b/lib/Gitalist/Controller/Ref.pm @@ -49,15 +49,18 @@ Provides a snapshot of a given commit. sub snapshot : Chained('find') PathPart('snapshot') Args() { my ($self, $c, $format) = @_; - $format ||= 'tgz'; + $format ||= Gitalist->config->{snapshot}{format} || "tar.bz2"; my @snap = $c->stash->{Repository}->snapshot( sha1 => $c->stash->{Commit}->sha1, format => $format ); $c->response->status(200); - $c->response->headers->header( 'Content-Disposition' => - "attachment; filename=$snap[0]"); - $c->response->body($snap[1]); + $c->response->content_type($snap[0]); + $c->response->content_length(-s $snap[2]); + $c->response->headers->header('Content-Disposition' => + "attachment; filename=$snap[1]"); + open(my $fh, '<', $snap[2]); + $c->response->body($fh); } =head2 patch diff --git a/lib/Gitalist/Git/Repository.pm b/lib/Gitalist/Git/Repository.pm index c6981bd..a42b34c 100644 --- a/lib/Gitalist/Git/Repository.pm +++ b/lib/Gitalist/Git/Repository.pm @@ -12,6 +12,9 @@ class Gitalist::Git::Repository with (Gitalist::Git::HasUtils, Gitalist::Git::Se use aliased 'DateTime' => 'DT'; use List::MoreUtils qw/any zip/; use Encode qw/decode/; + use IPC::Run qw/run/; + use File::Spec qw/catfile/; + use File::Path qw/mkpath/; use if $^O ne 'MSWin32' => 'I18N::Langinfo', qw/langinfo CODESET/; @@ -150,20 +153,48 @@ class Gitalist::Git::Repository with (Gitalist::Git::HasUtils, Gitalist::Git::Se NonEmptySimpleStr :$format ) { # TODO - only valid formats are 'tar' and 'zip' - my $formats = { tgz => 'tar', zip => 'zip' }; + my $formats = { + 'tar.gz' => 'tar', + 'tar.bz2' => 'tar', + zip => 'zip', + }; + my $compressors = { + 'tar.gz' => 'gzip', + 'tar.bz2' => 'bzip2', + 'tar.xz' => 'xz', + }; + my $mimetypes = { + 'tar.gz' => 'application/x-gzip', + 'tar.bz2' => 'application/x-bzip2', + 'tar.xz' => 'application/octet-stream', + }; unless ($formats->exists($format)) { die("No such format: $format"); } - $format = $formats->{$format}; + my $ga_format = $formats->{$format}; my $name = $self->name; $name =~ s,([^/])/*\.git$,$1,; - my $filename = $name; - $filename .= "-$sha1.$format"; + my $sha1_abbrev = $self->run_cmd(('log', '--pretty=format:%h', '-1', $sha1)); + my $filename = "$name-$sha1_abbrev.$format"; + my $ga_filename = "$name-$sha1_abbrev.$ga_format"; $name =~ s/\047/\047\\\047\047/g; - my @cmd = ('archive', "--format=$format", "--prefix=$name/", $sha1); - return ($filename, $self->run_cmd_fh(@cmd)); - # TODO - support compressed archives + my $local_dir = Gitalist->config->{snapshot}{tmpdir} || "/tmp/gitalist/snapshot"; + $local_dir = File::Spec->catfile($local_dir, substr($sha1,0,2), substr($sha1,0,4)); + my $local_filename = File::Spec->catfile($local_dir, $filename); + my $local_ga_filename = File::Spec->catfile($local_dir, $ga_filename); + if(!-e $local_filename) { + if(! -e $local_dir) { + mkpath($local_dir, 0, 0755); + } + my @cmd = ('archive', "--format=$ga_format", "--prefix=$name-$sha1_abbrev/", $sha1, "--output=$local_ga_filename"); + $self->run_cmd(@cmd); + if($compressors->exists($format)) { + run [$compressors->{$format}, $local_ga_filename]; + } + } + + return ($mimetypes->{$format}, $filename, $local_filename); } method reflog (@logargs) { diff --git a/root/fragment/repository/shortlog.tt2 b/root/fragment/repository/shortlog.tt2 index e0d687c..f982a94 100755 --- a/root/fragment/repository/shortlog.tt2 +++ b/root/fragment/repository/shortlog.tt2 @@ -33,6 +33,7 @@ commit commitdiff tree + snapshot [% END %] diff --git a/root/static/css/core.css b/root/static/css/core.css index 98411b1..84d0c79 100755 --- a/root/static/css/core.css +++ b/root/static/css/core.css @@ -258,6 +258,9 @@ a.longlog{ a.blob{ background:transparent url([% c.uri_for('/static/i/icons/blob.png') %]) no-repeat; } +a.snapshot{ + background:transparent url([% c.uri_for('/static/i/icons/blob.png') %]) no-repeat; +} a.blame{ background:transparent url([% c.uri_for('/static/i/icons/blame.png') %]) no-repeat; } @@ -444,7 +447,7 @@ BUT the final width needs to be set with javascript based on the parent element */ .action-list{ - width:120px; + width:160px; } .diff-tree{