From: Raphael Hertzog Date: Fri, 15 Feb 2008 15:10:55 +0000 (+0100) Subject: Dpkg::Source::Compressor: handle on-the-fly compression X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6057d6b50124c5ba2b7c3efb95b6ed205b1e50de;p=dpkg 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. --- diff --git a/scripts/Dpkg/Compression.pm b/scripts/Dpkg/Compression.pm index 7c1947b9..7d7c1738 100644 --- a/scripts/Dpkg/Compression.pm +++ b/scripts/Dpkg/Compression.pm @@ -4,11 +4,14 @@ use strict; use warnings; 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 = 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_prog = (gzip => 'gzip', bzip2 => 'bzip2', lzma => 'lzma'); +our %comp_decomp_prog = (gzip => 'gunzip', bzip2 => 'bunzip2', lzma => 'unlzma'); 1; diff --git a/scripts/Dpkg/Source/Compressor.pm b/scripts/Dpkg/Source/Compressor.pm new file mode 100644 index 00000000..0fb2349c --- /dev/null +++ b/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; diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in index 240ff28f..1ca810de 100644 --- a/scripts/po/POTFILES.in +++ b/scripts/po/POTFILES.in @@ -26,6 +26,8 @@ scripts/Dpkg/IPC.pm scripts/Dpkg/Shlibs.pm scripts/Dpkg/Shlibs/Objdump.pm scripts/Dpkg/Shlibs/SymbolFile.pm +scripts/Dpkg/Source/Compressor.pm +scripts/Dpkg/Source/VCS/git.pm scripts/Dpkg/Substvars.pm scripts/Dpkg/Vars.pm scripts/Dpkg/Version.pm