Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

On top of seveas/snapshot, allow one to specify a custom snapshot generator #41

Open
wants to merge 2 commits into from

1 participant

@seveas

At perl5.git.perl.org we use a special snapshot generator that creates
and includes a .patch file used in tests. This patch allows us to use it
within gitalist. The generator itself is also included as an example.

seveas added some commits
@seveas seveas 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
723a8f6
@seveas seveas Allow one to specify a custom snapshot generator
At perl5.git.perl.org we use a special snapshot generator that creates
and includes a .patch file used in tests. This patch allows us to use it
within gitalist. The generator itself is also included as an example.
5063e1b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 28, 2012
  1. @seveas

    Snapshot improvements

    seveas authored
    - 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
  2. @seveas

    Allow one to specify a custom snapshot generator

    seveas authored
    At perl5.git.perl.org we use a special snapshot generator that creates
    and includes a .patch file used in tests. This patch allows us to use it
    within gitalist. The generator itself is also included as an example.
This page is out of date. Refresh to see the latest.
View
1  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).
View
8 gitalist.conf
@@ -20,3 +20,11 @@ sitename "A Gitalist"
<patches>
max = 16
</patches>
+
+<snapshot>
+ format = tar.bz2
+ tmpdir = /tmp/gitalist/snapshot
+# This command can be used instead of git archive to generate the snapshot
+# It must understand --git-dir, --output, --prefix and --format
+# custom_snapshot = /usr/local/bin/my_snapshot.pl
+</snapshot>
View
11 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
View
53 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,56 @@ 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/", "--output=$local_ga_filename", $sha1);
+ if(my $custom = Gitalist->config->{snapshot}->{custom_snapshot}) {
+ shift @cmd;
+ unshift @cmd, ($custom, '--git-dir' => $self->path);
+ require IPC::Run;
+ IPC::Run::run [ @cmd ], \my($in, $out, $err);
+ }
+ else {
+ $self->run_cmd(@cmd);
+ }
+ if($compressors->exists($format)) {
+ run [$compressors->{$format}, $local_ga_filename];
+ }
+ }
+
+ return ($mimetypes->{$format}, $filename, $local_filename);
}
method reflog (@logargs) {
View
1  root/fragment/repository/shortlog.tt2
@@ -33,6 +33,7 @@
<a href="[% c.uri_for_action("/ref/commit", [Repository.name, line.sha1]) %]" title="Commit details" class="button commit">commit</a>
<a href="[% c.uri_for_action("/ref/diff_fancy", [Repository.name, line.sha1]) %]" title="Commit difference" class="button diff">commitdiff</a>
<a href="[% c.uri_for_action("/ref/tree", [Repository.name, line.sha1]) %]" title="Tree" class="button tree">tree</a>
+ <a href="[% c.uri_for_action("/ref/snapshot", [Repository.name, line.sha1]) %]" title="Snapshot" class="button snapshot">snapshot</a>
</td>
</tr>
[% END %]
View
5 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{
View
95 script/snapshot_example.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+#
+# This is an example of a custom snapshot generator for gitweb/gitalist. It is
+# in active use by the perl 5 porters on perl5.git.perl.org.
+#
+# It doesn't do much, it only adds a .patch file with patch info as used by the
+# perl build/test process.
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use POSIX qw(strftime);
+use IPC::Cmd qw(run);
+use Data::Dumper;
+use File::Spec;
+use File::Basename;
+use version;
+
+$ENV{PATH}="/usr/local/bin:/bin/:/usr/bin";
+
+my $format = 'tar';
+my $output;
+my $git_dir;
+my $prefix;
+
+my $result = GetOptions(
+ 'format=s' => \$format,
+ 'output=s', => \$output,
+ 'git-dir=s', => \$git_dir,
+ 'prefix=s', => \$prefix,
+);
+my $sha1 = $ARGV[0];
+
+# Get commit info:
+# - branch name. If it's on multiple, prefer the name blead, then maint-*, then others
+my $branches;
+my $res = scalar run(
+ command => [ "git", "--git-dir", $git_dir, "branch", "--contains", $sha1, '--all' ],
+ buffer => \$branches,
+);
+chomp($branches);
+my @branches = sort branchcmp (map { s/^..//; $_ } split(/\n/, $branches));
+my $branch = $branches[0];
+$branch =~ s![/ ]!-!g;
+
+# - Abbreviated commit and timestamp
+my ($sha1_abbrev,$timestamp);
+$res = scalar run(
+ command => [ "git", "--git-dir", $git_dir, "log", '--pretty=format:%h,%ct', '-1', $sha1 ],
+ buffer => \$sha1_abbrev,
+);
+($sha1_abbrev, $timestamp) = split /,/, $sha1_abbrev;
+
+# - And describe output
+my $describe;
+$res = scalar run(
+ command => [ "git", "--git-dir", $git_dir, 'describe', $sha1 ],
+ buffer => \$describe,
+);
+if(!$res) {
+ $describe = "";
+}
+chomp($describe);
+
+# Now create the base snapshot
+run(
+ command => ["git", "--git-dir", $git_dir, "archive",
+ "--format", $format, "--prefix", $prefix,
+ "--output", $output, $sha1],
+);
+
+# And add the .patch file
+my $patch = File::Spec->catfile(dirname($output), "$sha1_abbrev.patch");
+open(my $fh, ">", $patch);
+print $fh join(" ", $branch, isotime($timestamp), $sha1, $describe);
+run(
+ command => ["tar", "-f", $output, '--transform', "s,.*$sha1_abbrev,$prefix,",
+ "--owner=root", "--group=root", "--mode=664", "--append", $patch]
+);
+
+# Done :-)
+
+sub branchcmp {
+ return -1 if ($a eq 'blead');
+ return 1 if ($b eq 'blead');
+ return -1 if ($a =~ /^maint/ && $b !~ /^maint/);
+ return 1 if ($a =~ /^maint/ && $b !~ /^maint/);
+ return $a cmp $b if ($a !~ /^maint/ && $b !~ /^maint/);
+ $a =~ s/maint-([0-9.]+).*/$1/;
+ $b =~ s/maint-([0-9.]+).*/$1/;
+ return version->parse($a) <=> version->parse($b);
+}
+
+sub isotime { strftime "%Y-%m-%d.%H:%M:%S",gmtime(shift||time) }
Something went wrong with that request. Please try again.