modularize the delta writing code
authorJoey Hess <joey@kitenet.net>
Sat, 24 Jul 2010 00:57:51 +0000 (20:57 -0400)
committerJoey Hess <joey@kitenet.net>
Sat, 24 Jul 2010 00:57:51 +0000 (20:57 -0400)
This will make it easy to add support for flat deltas, etc.

Pristine/Tar/Delta.pm
Pristine/Tar/Delta/Tarball.pm [new file with mode: 0644]
pristine-bz2
pristine-gz
pristine-tar

index 50ecf76..c5e6572 100644 (file)
@@ -1,21 +1,38 @@
 #!/usr/bin/perl
 # pristine-tar delta file library
+# See delta-format.txt for details about the contents of delta files.
 package Pristine::Tar::Delta;
 
 use Pristine::Tar;
 use warnings;
 use strict;
-use File::Basename;
 
-# See delta-format.txt for details about the contents of delta files.
-#
-# Some of the delta contents are treated as files. Things not listed here
-# are treated as fields with short values.
+# Checks if a field of a delta should be stored in the delta hash using
+# a filename. (Normally the hash stores the whole field value, but
+# using filenames makes sense for a few fields.)
 my %delta_files=map { $_ => 1 } qw(manifest delta wrapper);
+sub is_filename {
+       my $field=shift;
+       return $delta_files{$field};
+}
 
-# After the filename to create, this takes a hashref containing
-# the contents of the delta file to create.
+sub handler {
+       my $action=shift;
+       my $type=shift;
+       
+       my $class="Pristine::Tar::Delta::$type";
+       eval "use $class";
+       if ($@) {
+               error "unsupported delta file format $type";
+       }
+       $class->$action(@_);
+}
+
+# After the type of delta and the file to create (which can be "-"
+# to send it to stdout), this takes a hashref containing the contents of
+# the delta to write.
 sub write {
+       my $type=shift;
        my $deltafile=shift;
        my $delta=shift;
 
@@ -26,19 +43,8 @@ sub write {
                $stdout=1;
                $deltafile="$tempdir/tmpout";
        }
-
-       foreach my $field (keys %$delta) {
-               if ($delta_files{$field}) {
-                       link($delta->{$field}, "$tempdir/$field") || die "link $tempdir/$field: $!";
-               }
-               else {
-                       open (my $out, ">", "$tempdir/$field") || die "$tempdir/$field: $!";
-                       print $out $delta->{$field}."\n";
-                       close $out;
-               }
-       }
-
-       doit("tar", "czf", $deltafile, "-C", $tempdir, keys %$delta);
+       
+       handler('write', $type, $deltafile, $delta);
 
        if ($stdout) {
                doit("cat", $deltafile);
@@ -50,6 +56,7 @@ sub write {
 
 # Returns a hashref of the contents of the delta.
 sub read {
+       my $type=shift;
        my $deltafile=shift;
        
        my $tempdir=tempdir();
@@ -63,30 +70,12 @@ sub read {
                }
                close $out;
        }
-       doit("tar", "xf", File::Spec->rel2abs($deltafile), "-C", $tempdir);
-       unlink($deltafile) if $stdin;
 
-       my %delta;
-       foreach my $file (glob("$tempdir/*")) {
-               if (-f $file) {
-                       my $field=basename($file);
-                       if ($delta_files{$field}) {
-                               $delta{$field}=$file;
-                       }
-                       else {
-                               open (my $in, "<", $file) || die "$file: $!";
-                               {
-                                       local $/=undef;
-                                       $delta{$field}=<$in>;
-                               }
-                               chomp $delta{$field};
-                               close $in;
-                       }
-               }
-       }
-       # TODO read all files
+       my $delta=handler('read', $type, $deltafile);
        
-       return \%delta;
+       unlink($deltafile) if $stdin;
+
+       return $delta;
 }
 
 # Checks the type, maxversion, minversion of a delta hashref.
diff --git a/Pristine/Tar/Delta/Tarball.pm b/Pristine/Tar/Delta/Tarball.pm
new file mode 100644 (file)
index 0000000..ab38935
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+# pristine-tar delta files formatted as tarballs
+package Pristine::Tar::Delta::Tarball;
+
+use Pristine::Tar;
+use Pristine::Tar::Delta;
+use File::Basename;
+use warnings;
+use strict;
+
+sub write {
+       my $class=shift;
+       my $deltafile=shift;
+       my $delta=shift;
+
+       my $tempdir=tempdir();
+
+       foreach my $field (keys %$delta) {
+               if (Pristine::Tar::Delta::is_filename($field)) {
+                       link($delta->{$field}, "$tempdir/$field") || die "link $tempdir/$field: $!";
+               }
+               else {
+                       open (my $out, ">", "$tempdir/$field") || die "$tempdir/$field: $!";
+                       print $out $delta->{$field}."\n";
+                       close $out;
+               }
+       }
+
+       doit("tar", "czf", $deltafile, "-C", $tempdir, keys %$delta);
+
+       return $delta;
+}
+
+sub read {
+       my $class=shift;
+       my $deltafile=shift;
+       
+       my $tempdir=tempdir();
+       doit("tar", "xf", File::Spec->rel2abs($deltafile), "-C", $tempdir);
+
+       my %delta;
+       foreach my $file (glob("$tempdir/*")) {
+               if (-f $file) {
+                       my $field=basename($file);
+                       if (Pristine::Tar::Delta::is_filename($field)) {
+                               $delta{$field}=$file;
+                       }
+                       else {
+                               open (my $in, "<", $file) || die "$file: $!";
+                               {
+                                       local $/=undef;
+                                       $delta{$field}=<$in>;
+                               }
+                               chomp $delta{$field};
+                               close $in;
+                       }
+               }
+       }
+       
+       return \%delta;
+}
+
+1
index ed55fb6..1c69c91 100755 (executable)
@@ -244,7 +244,7 @@ sub genbz2 {
        my $deltafile=shift;
        my $file=shift;
 
-       my $delta=Pristine::Tar::Delta::read($deltafile);
+       my $delta=Pristine::Tar::Delta::read(Tarball => $deltafile);
        Pristine::Tar::Delta::assert($delta, type => "bz2", maxversion => 2, 
                fields => [qw{params program}]);
 
@@ -276,7 +276,7 @@ sub gendelta {
 
        my ($program, @params) = reproducebzip2($bzip2file);
 
-       Pristine::Tar::Delta::write($deltafile, {
+       Pristine::Tar::Delta::write(Tarball => $deltafile, {
                version => '2.0',
                type => 'bz2',
                params => "@params",
index 7356d37..9687c49 100755 (executable)
@@ -267,7 +267,7 @@ sub gengz {
        my $deltafile=shift;
        my $file=shift;
 
-       my $delta=Pristine::Tar::Delta::read($deltafile);
+       my $delta=Pristine::Tar::Delta::read(Tarball => $deltafile);
        Pristine::Tar::Delta::assert($delta, type => "gz", maxversion => 3,
                fields => [qw{params filename timestamp}]);
 
@@ -312,7 +312,7 @@ sub gendelta {
        my ($filename, $timestamp, $xdelta, @params)=
                reproducegz($gzfile, $tempdir, "$tempdir/test");
        
-       Pristine::Tar::Delta::write($deltafile, {
+       Pristine::Tar::Delta::write(Tarball => $deltafile, {
                version => (defined $xdelta ? "3.0" : "2.0"),
                type => 'gz',
                params => "@params",
index 82d9045..a741b92 100755 (executable)
@@ -327,7 +327,7 @@ sub gentar {
        my $tarball=shift;
        my %opts=@_;
 
-       my $delta=Pristine::Tar::Delta::read($deltafile);
+       my $delta=Pristine::Tar::Delta::read(Tarball => $deltafile);
        Pristine::Tar::Delta::assert($delta, type => "tar", maxversion => 2,
                minversion => 2, fields => [qw{manifest delta}]);
 
@@ -338,7 +338,7 @@ sub gentar {
        doit("xdelta", "patch", $delta->{delta}, $recreatetarball, $out);
 
        if (defined $delta->{wrapper}) {
-               my $delta_wrapper=Pristine::Tar::Delta::read($delta->{wrapper});
+               my $delta_wrapper=Pristine::Tar::Delta::read(Tarball => $delta->{wrapper});
                if ($delta_wrapper->{type} eq 'gz') {
                        doit("pristine-gz", 
                                ($verbose ? "-v" : "--no-verbose"),
@@ -457,7 +457,7 @@ sub gendelta {
                error "xdelta failed with return code $ret";
        }
 
-       Pristine::Tar::Delta::write($deltafile, {
+       Pristine::Tar::Delta::write(Tarball => $deltafile, {
                version => 2,
                type => 'tar',
                %delta,