Explorar o código

Dpkg::Source::Compressor: handle on-the-fly compression

* scripts/Dpkg/Source/Compressor.pm: This new module knows how
to compress/uncompress streams of data. It supports all the
compression types defined in Dpkg::Compression.
Raphael Hertzog %!s(int64=18) %!d(string=hai) anos
pai
achega
6057d6b501
Modificáronse 3 ficheiros con 176 adicións e 2 borrados
  1. 5 2
      scripts/Dpkg/Compression.pm
  2. 169 0
      scripts/Dpkg/Source/Compressor.pm
  3. 2 0
      scripts/po/POTFILES.in

+ 5 - 2
scripts/Dpkg/Compression.pm

@@ -4,11 +4,14 @@ use strict;
 use warnings;
 use warnings;
 
 
 use base qw(Exporter);
 use base qw(Exporter);
-our @EXPORT = qw(@comp_supported %comp_supported %comp_ext $comp_regex);
+our @EXPORT = qw(@comp_supported %comp_supported %comp_ext $comp_regex
+		 %comp_prog %comp_decomp_prog);
 
 
 our @comp_supported = qw(gzip bzip2 lzma);
 our @comp_supported = qw(gzip bzip2 lzma);
 our %comp_supported = map { $_ => 1 } @comp_supported;
 our %comp_supported = map { $_ => 1 } @comp_supported;
-our %comp_ext = ( gzip => 'gz', bzip2 => 'bz2', lzma => 'lzma' );
+our %comp_ext = (gzip => 'gz', bzip2 => 'bz2', lzma => 'lzma');
 our $comp_regex = '(?:gz|bz2|lzma)';
 our $comp_regex = '(?:gz|bz2|lzma)';
+our %comp_prog = (gzip => 'gzip', bzip2 => 'bzip2', lzma => 'lzma');
+our %comp_decomp_prog = (gzip => 'gunzip', bzip2 => 'bunzip2', lzma => 'unlzma');
 
 
 1;
 1;

+ 169 - 0
scripts/Dpkg/Source/Compressor.pm

@@ -0,0 +1,169 @@
+package Dpkg::Source::Compressor;
+
+use strict;
+use warnings;
+
+use Dpkg::Compression;
+use Dpkg::Gettext;
+use Dpkg::IPC;
+use Dpkg::ErrorHandling qw(error syserr warning);
+
+use POSIX;
+
+our $default_compression = "gzip";
+our $default_compression_level = 9;
+
+sub new {
+    my ($this, %args) = @_;
+    my $class = ref($this) || $this;
+    my $self = {
+	"compression" => $default_compression,
+	"compression_level" => $default_compression_level,
+    };
+    bless $self, $class;
+    if (exists $args{"compression"}) {
+	$self->set_compression($args{"compression"});
+    }
+    if (exists $args{"compression_level"}) {
+	$self->set_compression_level($args{"compression_level"});
+    }
+    if (exists $args{"filename"}) {
+	$self->set_filename($args{"filename"});
+    }
+    if (exists $args{"uncompressed_filename"}) {
+	$self->set_uncompressed_filename($args{"uncompressed_filename"});
+    }
+    return $self;
+}
+
+sub set_compression {
+    my ($self, $method) = @_;
+    error(_g("%s is not a supported compression method"), $method)
+	    unless $comp_supported{$method};
+    $self->{"compression"} = $method;
+}
+
+sub set_compression_level {
+    my ($self, $level) = @_;
+    error(_g("%s is not a compression level"), $level)
+            unless $level =~ /^([1-9]|fast|best)$/;
+    $self->{"compression_level"} = $level;
+}
+
+sub set_filename {
+    my ($self, $filename) = @_;
+    # Identify compression from filename
+    my $found = 0;
+    foreach my $comp (@comp_supported) {
+	if ($filename =~ /^(.*)\.\Q$comp_ext{$comp}\E$/) {
+	    $found = 1;
+	    $self->set_compression($comp);
+	    $self->set_uncompressed_filename($1);
+	    last;
+	}
+    }
+    error(_g("unknown compression type on file %s"), $filename) unless $found;
+}
+
+sub get_filename {
+    my $self = shift;
+    return $self->{"uncompressed_filename"} . "." .
+	   $comp_ext{$self->{"compression"}};
+}
+
+sub set_uncompressed_filename {
+    my ($self, $filename) = @_;
+    warning(_g("uncompressed filename %s has an extension of a compressed file"),
+	    $filename) if $filename =~ /\.$comp_regex$/;
+    $self->{"uncompressed_filename"} = $filename;
+}
+
+sub wait_end_process {
+    my ($self) = @_;
+    wait_child($self->{"pid"}, cmdline => $self->{"cmdline"});
+    delete $self->{"pid"};
+    delete $self->{"cmdline"};
+}
+
+sub close_in_child {
+    my ($self, $fd) = @_;
+    if (not $self->{"close_in_child"}) {
+	$self->{"close_in_child"} = [];
+    }
+    push @{$self->{"close_in_child"}}, $fd;
+}
+
+sub get_compress_cmdline {
+    my ($self) = @_;
+    # Define the program invocation
+    my @prog = ($comp_prog{$self->{"compression"}});
+    my $level = "-" . $self->{"compression_level"};
+    $level = "--" . $self->{"compression_level"}
+	    if $self->{"compression_level"} =~ m/best|fast/;
+    push @prog, $level;
+    return @prog;
+}
+
+sub get_uncompress_cmdline {
+    my ($self) = @_;
+    return ($comp_decomp_prog{$self->{"compression"}});
+}
+
+sub compress_from_fd_to_file {
+    my ($self, $fd, $filename) = @_;
+    $filename ||= $self->get_filename();
+    error(_g("Dpkg::Source::Compressor can only start one subprocess at a time"))
+	    if $self->{"pid"};
+    my @prog = $self->get_compress_cmdline();
+    $self->{"cmdline"} = "@prog";
+    $self->{"pid"} = fork_and_exec(
+	    'exec' => \@prog,
+	    from_handle => $fd,
+	    to_file => $filename,
+	    close_in_child => $self->{"close_in_child"}
+    );
+}
+
+sub compress_from_pipe_to_file {
+    my ($self, $filename) = @_;
+    $filename ||= $self->get_filename();
+    # Open pipe
+    pipe(my $read_fh, my $write_fh) ||
+	    syserr(_g("pipe for %s"), $comp_prog{$self->{"compression"}});
+    binmode($write_fh);
+    $self->close_in_child($write_fh);
+    # Start the process
+    $self->compress_from_fd_to_file($read_fh, $filename);
+    return $write_fh;
+}
+
+sub uncompress_from_file_to_fd {
+    my ($self, $filename, $fd) = @_;
+    $filename ||= $self->get_filename();
+    error(_g("Dpkg::Source::Compressor can only start one subprocess at a time"))
+	    if $self->{"pid"};
+    my @prog = $self->get_uncompress_cmdline();
+    $self->{"cmdline"} = "@prog";
+    $self->{"pid"} = fork_and_exec(
+	    'exec' => \@prog,
+	    from_file => $filename,
+	    to_handle => $fd,
+	    close_in_child => $self->{"close_in_child"}
+    );
+}
+
+sub uncompress_from_file_to_pipe {
+    my ($self, $filename) = @_;
+    $filename ||= $self->get_filename();
+    # Open output pipe
+    pipe(my $read_fh, my $write_fh) ||
+	    syserr(_g("pipe for %s"), $self->{"cmdline"});
+    binmode($read_fh);
+    $self->close_in_child($read_fh);
+    # Start the process
+    $self->uncompress_from_file_to_fd($filename, $write_fh);
+    # Return the read side of the pipe
+    return $read_fh;
+}
+
+1;

+ 2 - 0
scripts/po/POTFILES.in

@@ -26,6 +26,8 @@ scripts/Dpkg/IPC.pm
 scripts/Dpkg/Shlibs.pm
 scripts/Dpkg/Shlibs.pm
 scripts/Dpkg/Shlibs/Objdump.pm
 scripts/Dpkg/Shlibs/Objdump.pm
 scripts/Dpkg/Shlibs/SymbolFile.pm
 scripts/Dpkg/Shlibs/SymbolFile.pm
+scripts/Dpkg/Source/Compressor.pm
+scripts/Dpkg/Source/VCS/git.pm
 scripts/Dpkg/Substvars.pm
 scripts/Dpkg/Substvars.pm
 scripts/Dpkg/Vars.pm
 scripts/Dpkg/Vars.pm
 scripts/Dpkg/Version.pm
 scripts/Dpkg/Version.pm