From c8c2779c1811cefc55b712b943bb4ab5103b0a30 Mon Sep 17 00:00:00 2001 From: Andrew Parker Date: Mon, 8 Apr 2013 14:54:37 -0700 Subject: [PATCH] (#13542) Unvendor Minitar We've decided that minitar is a non-trivial library and so should not be placed inside the codebase. Instead it will be brought in through package dependencies. --- Gemfile | 1 + .../module_tool/applications/builder.rb | 4 +- .../module_tool/applications/unpacker.rb | 4 +- lib/puppet/module_tool/shared_behaviors.rb | 2 +- lib/puppet/util/archive/tar/minitar.rb | 1015 ----------------- .../util/archive/tar/minitar/command.rb | 822 ------------- .../module_tool/applications/unpacker_spec.rb | 6 +- .../unit/module_tool/shared_behaviors_spec.rb | 2 +- 8 files changed, 10 insertions(+), 1846 deletions(-) delete mode 100644 lib/puppet/util/archive/tar/minitar.rb delete mode 100644 lib/puppet/util/archive/tar/minitar/command.rb diff --git a/Gemfile b/Gemfile index 9a05ae28a..aa9219205 100644 --- a/Gemfile +++ b/Gemfile @@ -32,6 +32,7 @@ group(:development, :test) do gem "sqlite3" gem "stomp" gem "tzinfo" + gem "minitar" end platforms :mswin, :mingw do diff --git a/lib/puppet/module_tool/applications/builder.rb b/lib/puppet/module_tool/applications/builder.rb index 215840c60..fc14e7a62 100644 --- a/lib/puppet/module_tool/applications/builder.rb +++ b/lib/puppet/module_tool/applications/builder.rb @@ -1,5 +1,5 @@ require 'zlib' -require 'puppet/util/archive/tar/minitar' +require 'archive/tar/minitar' require 'pathname' module Puppet::ModuleTool @@ -43,7 +43,7 @@ module Puppet::ModuleTool def create_module_tar_gz(module_tar_gz) module_tar_gz.dirname.mkdir rescue nil Zlib::GzipWriter.open(module_tar_gz) do |gzip| - Puppet::Util::Archive::Tar::Minitar::Writer.open(gzip) do |tar| + Archive::Tar::Minitar::Writer.open(gzip) do |tar| add_metadata(tar) Dir.foreach(@path) do |file| case File.basename(file) diff --git a/lib/puppet/module_tool/applications/unpacker.rb b/lib/puppet/module_tool/applications/unpacker.rb index 7e03684df..0a52eb6e2 100644 --- a/lib/puppet/module_tool/applications/unpacker.rb +++ b/lib/puppet/module_tool/applications/unpacker.rb @@ -1,5 +1,5 @@ require 'zlib' -require 'puppet/util/archive/tar/minitar' +require 'archive/tar/minitar' require 'pathname' module Puppet::ModuleTool @@ -37,7 +37,7 @@ module Puppet::ModuleTool begin begin Zlib::GzipReader.open(@filename) do |gzip| - Puppet::Util::Archive::Tar::Minitar::Reader.open(gzip) do |tar| + Archive::Tar::Minitar::Reader.open(gzip) do |tar| tar.each do |entry| destination_file = Pathname.new(entry.full_name).cleanpath if destination_file.absolute? || diff --git a/lib/puppet/module_tool/shared_behaviors.rb b/lib/puppet/module_tool/shared_behaviors.rb index b3d06adcd..5be695da8 100644 --- a/lib/puppet/module_tool/shared_behaviors.rb +++ b/lib/puppet/module_tool/shared_behaviors.rb @@ -703,7 +703,7 @@ module Puppet::ModuleTool::Shared raise MissingPackageError, :action => @action, :requested_package => File.expand_path(name) unless File.file?(name) begin Zlib::GzipReader.open(name) do |gzip| - Puppet::Util::Archive::Tar::Minitar::Reader.open(gzip) do |tar| + Archive::Tar::Minitar::Reader.open(gzip) do |tar| tar.each do |entry| name_components = entry.full_name.split('/', 3) next unless (name_components.length == 2 && name_components.last == 'metadata.json') diff --git a/lib/puppet/util/archive/tar/minitar.rb b/lib/puppet/util/archive/tar/minitar.rb deleted file mode 100644 index ca72ca053..000000000 --- a/lib/puppet/util/archive/tar/minitar.rb +++ /dev/null @@ -1,1015 +0,0 @@ -#!/usr/bin/env ruby -# embed the code in puppet under the Puppet::Util namesapce -module Puppet -module Util - -#-- -# Archive::Tar::Minitar 0.5.2 -# Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler -# -# This program is based on and incorporates parts of RPA::Package from -# rpa-base (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and has been -# adapted to be more generic by Austin. -# -# It is licensed under the GNU General Public Licence or Ruby's licence. -# -# $Id$ -#++ - -module Archive; end -module Archive::Tar; end - - # = Archive::Tar::PosixHeader - # Implements the POSIX tar header as a Ruby class. The structure of - # the POSIX tar header is: - # - # struct tarfile_entry_posix - # { // pack/unpack - # char name[100]; // ASCII (+ Z unless filled) a100/Z100 - # char mode[8]; // 0 padded, octal, null a8 /A8 - # char uid[8]; // ditto a8 /A8 - # char gid[8]; // ditto a8 /A8 - # char size[12]; // 0 padded, octal, null a12 /A12 - # char mtime[12]; // 0 padded, octal, null a12 /A12 - # char checksum[8]; // 0 padded, octal, null, space a8 /A8 - # char typeflag[1]; // see below a /a - # char linkname[100]; // ASCII + (Z unless filled) a100/Z100 - # char magic[6]; // "ustar\0" a6 /A6 - # char version[2]; // "00" a2 /A2 - # char uname[32]; // ASCIIZ a32 /Z32 - # char gname[32]; // ASCIIZ a32 /Z32 - # char devmajor[8]; // 0 padded, octal, null a8 /A8 - # char devminor[8]; // 0 padded, octal, null a8 /A8 - # char prefix[155]; // ASCII (+ Z unless filled) a155/Z155 - # }; - # - # The +typeflag+ may be one of the following known values: - # - # "0":: Regular file. NULL should be treated as a synonym, for - # compatibility purposes. - # "1":: Hard link. - # "2":: Symbolic link. - # "3":: Character device node. - # "4":: Block device node. - # "5":: Directory. - # "6":: FIFO node. - # "7":: Reserved. - # - # POSIX indicates that "A POSIX-compliant implementation must treat any - # unrecognized typeflag value as a regular file." -class Archive::Tar::PosixHeader - FIELDS = %w(name mode uid gid size mtime checksum typeflag linkname) + - %w(magic version uname gname devmajor devminor prefix) - - FIELDS.each { |field| attr_reader field.intern } - - HEADER_PACK_FORMAT = "a100a8a8a8a12a12a7aaa100a6a2a32a32a8a8a155" - HEADER_UNPACK_FORMAT = "Z100A8A8A8A12A12A8aZ100A6A2Z32Z32A8A8Z155" - - # Creates a new PosixHeader from a data stream. - def self.new_from_stream(stream, long_name = nil) - data = stream.read(512) - fields = data.unpack(HEADER_UNPACK_FORMAT) - name = fields.shift - mode = fields.shift.oct - uid = fields.shift.oct - gid = fields.shift.oct - size = fields.shift.oct - mtime = fields.shift.oct - checksum = fields.shift.oct - typeflag = fields.shift - linkname = fields.shift - magic = fields.shift - version = fields.shift.oct - uname = fields.shift - gname = fields.shift - devmajor = fields.shift.oct - devminor = fields.shift.oct - prefix = fields.shift - - empty = (data == "\0" * 512) - - if typeflag == 'L' && name == '././@LongLink' - long_name = stream.read(512).rstrip - return new_from_stream(stream, long_name) - end - - new(:name => long_name || name, - :mode => mode, :uid => uid, :gid => gid, - :size => size, :mtime => mtime, :checksum => checksum, - :typeflag => typeflag, :magic => magic, :version => version, - :uname => uname, :gname => gname, :devmajor => devmajor, - :devminor => devminor, :prefix => prefix, :empty => empty) - end - - # Creates a new PosixHeader. A PosixHeader cannot be created unless the - # #name, #size, #prefix, and #mode are provided. - def initialize(vals) - unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] - raise ArgumentError - end - - vals[:mtime] ||= 0 - vals[:checksum] ||= "" - vals[:typeflag] ||= "0" - vals[:magic] ||= "ustar" - vals[:version] ||= "00" - - FIELDS.each do |field| - instance_variable_set("@#{field}", vals[field.intern]) - end - @empty = vals[:empty] - end - - def empty? - @empty - end - - def to_s - update_checksum - header(@checksum) - end - - # Update the checksum field. - def update_checksum - hh = header(" " * 8) - @checksum = oct(calculate_checksum(hh), 6) - end - - private - def oct(num, len) - if num.nil? - "\0" * (len + 1) - else - "%0#{len}o" % num - end - end - - def calculate_checksum(hdr) - hdr.unpack("C*").inject { |aa, bb| aa + bb } - end - - def header(chksum) - arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11), - oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version, - uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix] - str = arr.pack(HEADER_PACK_FORMAT) - str + "\0" * ((512 - str.size) % 512) - end -end - -require 'fileutils' -require 'find' - - # = Archive::Tar::Minitar 0.5.2 - # Archive::Tar::Minitar is a pure-Ruby library and command-line - # utility that provides the ability to deal with POSIX tar(1) archive - # files. The implementation is based heavily on Mauricio Ferna'ndez's - # implementation in rpa-base, but has been reorganised to promote - # reuse in other projects. - # - # This tar class performs a subset of all tar (POSIX tape archive) - # operations. We can only deal with typeflags 0, 1, 2, and 5 (see - # Archive::Tar::PosixHeader). All other typeflags will be treated as - # normal files. - # - # NOTE::: support for typeflags 1 and 2 is not yet implemented in this - # version. - # - # This release is version 0.5.2. The library can only handle files and - # directories at this point. A future version will be expanded to - # handle symbolic links and hard links in a portable manner. The - # command line utility, minitar, can only create archives, extract - # from archives, and list archive contents. - # - # == Synopsis - # Using this library is easy. The simplest case is: - # - # require 'zlib' - # require 'archive/tar/minitar' - # include Archive::Tar - # - # # Packs everything that matches Find.find('tests') - # File.open('test.tar', 'wb') { |tar| Minitar.pack('tests', tar) } - # # Unpacks 'test.tar' to 'x', creating 'x' if necessary. - # Minitar.unpack('test.tar', 'x') - # - # A gzipped tar can be written with: - # - # tgz = Zlib::GzipWriter.new(File.open('test.tgz', 'wb')) - # # Warning: tgz will be closed! - # Minitar.pack('tests', tgz) - # - # tgz = Zlib::GzipReader.new(File.open('test.tgz', 'rb')) - # # Warning: tgz will be closed! - # Minitar.unpack(tgz, 'x') - # - # As the case above shows, one need not write to a file. However, it - # will sometimes require that one dive a little deeper into the API, - # as in the case of StringIO objects. Note that I'm not providing a - # block with Minitar::Output, as Minitar::Output#close automatically - # closes both the Output object and the wrapped data stream object. - # - # begin - # sgz = Zlib::GzipWriter.new(StringIO.new("")) - # tar = Output.new(sgz) - # Find.find('tests') do |entry| - # Minitar.pack_file(entry, tar) - # end - # ensure - # # Closes both tar and sgz. - # tar.close - # end - # - # == Copyright - # Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler - # - # This program is based on and incorporates parts of RPA::Package from - # rpa-base (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and - # has been adapted to be more generic by Austin. - # - # 'minitar' contains an adaptation of Ruby/ProgressBar by Satoru - # Takabayashi , copyright 2001 - 2004. - # - # This program is free software. It may be redistributed and/or - # modified under the terms of the GPL version 2 (or later) or Ruby's - # licence. -module Archive::Tar::Minitar - VERSION = "0.5.4" - - # The exception raised when a wrapped data stream class is expected to - # respond to #rewind or #pos but does not. - class NonSeekableStream < StandardError; end - # The exception raised when a block is required for proper operation of - # the method. - class BlockRequired < ArgumentError; end - # The exception raised when operations are performed on a stream that has - # previously been closed. - class ClosedStream < StandardError; end - # The exception raised when a filename exceeds 256 bytes in length, - # the maximum supported by the standard Tar format. - class FileNameTooLong < StandardError; end - # The exception raised when a data stream ends before the amount of data - # expected in the archive's PosixHeader. - class UnexpectedEOF < StandardError; end - - # The class that writes a tar format archive to a data stream. - class Writer - # A stream wrapper that can only be written to. Any attempt to read - # from this restricted stream will result in a NameError being thrown. - class RestrictedStream - def initialize(anIO) - @io = anIO - end - - def write(data) - @io.write(data) - end - end - - # A RestrictedStream that also has a size limit. - class BoundedStream < Archive::Tar::Minitar::Writer::RestrictedStream - # The exception raised when the user attempts to write more data to - # a BoundedStream than has been allocated. - class FileOverflow < RuntimeError; end - - # The maximum number of bytes that may be written to this data - # stream. - attr_reader :limit - # The current total number of bytes written to this data stream. - attr_reader :written - - def initialize(io, limit) - @io = io - @limit = limit - @written = 0 - end - - def write(data) - raise FileOverflow if (data.size + @written) > @limit - @io.write(data) - @written += data.size - data.size - end - end - - # With no associated block, +Writer::open+ is a synonym for - # +Writer::new+. If the optional code block is given, it will be - # passed the new _writer_ as an argument and the Writer object will - # automatically be closed when the block terminates. In this instance, - # +Writer::open+ returns the value of the block. - def self.open(anIO) - writer = Writer.new(anIO) - - return writer unless block_given? - - begin - res = yield writer - ensure - writer.close - end - - res - end - - # Creates and returns a new Writer object. - def initialize(anIO) - @io = anIO - @closed = false - end - - # Adds a file to the archive as +name+. +opts+ must contain the - # following values: - # - # :mode:: The Unix file permissions mode value. - # :size:: The size, in bytes. - # - # +opts+ may contain the following values: - # - # :uid: The Unix file owner user ID number. - # :gid: The Unix file owner group ID number. - # :mtime:: The *integer* modification time value. - # - # It will not be possible to add more than opts[:size] bytes - # to the file. - def add_file_simple(name, opts = {}) # :yields BoundedStream: - raise Archive::Tar::Minitar::BlockRequired unless block_given? - raise Archive::Tar::ClosedStream if @closed - - name, prefix = split_name(name) - - header = { :name => name, :mode => opts[:mode], :mtime => opts[:mtime], - :uname => opts[:uname], :gname => opts[:gname], - :size => opts[:size], :gid => opts[:gid], :uid => opts[:uid], - :prefix => prefix } - header = Archive::Tar::PosixHeader.new(header).to_s - @io.write(header) - - os = BoundedStream.new(@io, opts[:size]) - yield os - # FIXME: what if an exception is raised in the block? - - min_padding = opts[:size] - os.written - @io.write("\0" * min_padding) - remainder = (512 - (opts[:size] % 512)) % 512 - @io.write("\0" * remainder) - end - - # Adds a file to the archive as +name+. +opts+ must contain the - # following value: - # - # :mode:: The Unix file permissions mode value. - # - # +opts+ may contain the following values: - # - # :uid: The Unix file owner user ID number. - # :gid: The Unix file owner group ID number. - # :mtime:: The *integer* modification time value. - # - # The file's size will be determined from the amount of data written - # to the stream. - # - # For #add_file to be used, the Archive::Tar::Minitar::Writer must be - # wrapping a stream object that is seekable (e.g., it responds to - # #pos=). Otherwise, #add_file_simple must be used. - # - # +opts+ may be modified during the writing to the stream. - def add_file(name, opts = {}) # :yields RestrictedStream, +opts+: - raise Archive::Tar::Minitar::BlockRequired unless block_given? - raise Archive::Tar::Minitar::ClosedStream if @closed - raise Archive::Tar::Minitar::NonSeekableStream unless @io.respond_to?(:pos=) - - name, prefix = split_name(name) - init_pos = @io.pos - @io.write("\0" * 512) # placeholder for the header - - yield RestrictedStream.new(@io), opts - # FIXME: what if an exception is raised in the block? - - size = @io.pos - (init_pos + 512) - remainder = (512 - (size % 512)) % 512 - @io.write("\0" * remainder) - - final_pos = @io.pos - @io.pos = init_pos - - header = { :name => name, :mode => opts[:mode], :mtime => opts[:mtime], - :uname => opts[:uname], :gname => opts[:gname], - :size => size, :gid => opts[:gid], :uid => opts[:uid], - :prefix => prefix } - header = Archive::Tar::PosixHeader.new(header).to_s - @io.write(header) - @io.pos = final_pos - end - - # Add a symlink to the tar. - def add_symlink(name, target, opts = {}) - raise ClosedStream if @closed - name, prefix = split_name(name) - header = { :name => name, :mode => opts[:mode] || 0777, - :uname => opts[:uname], :gname => opts[:gname], - :typeflag => "2", :size => 0, - :prefix => prefix, :linkname => target } - header = Archive::Tar::PosixHeader.new(header).to_s - @io.write(header) - nil - end - - # Creates a directory in the tar. - def mkdir(name, opts = {}) - raise ClosedStream if @closed - name, prefix = split_name(name) - header = { :name => name, :mode => opts[:mode], :typeflag => "5", - :uname => opts[:uname], :gname => opts[:gname], - :size => 0, :gid => opts[:gid], :uid => opts[:uid], - :mtime => opts[:mtime], :prefix => prefix } - header = Archive::Tar::PosixHeader.new(header).to_s - @io.write(header) - nil - end - - # Passes the #flush method to the wrapped stream, used for buffered - # streams. - def flush - raise ClosedStream if @closed - @io.flush if @io.respond_to?(:flush) - end - - # Closes the Writer. - def close - return if @closed - @io.write("\0" * 1024) - @closed = true - end - - private - def split_name(name) - raise FileNameTooLong if name.size > 256 - if name.size <= 100 - prefix = "" - else - parts = name.split(/\//) - newname = parts.pop - - nxt = "" - - loop do - nxt = parts.pop - break if newname.size + 1 + nxt.size > 100 - newname = "#{nxt}/#{newname}" - end - - prefix = (parts + [nxt]).join("/") - - name = newname - - raise FileNameTooLong if name.size > 100 || prefix.size > 155 - end - return name, prefix - end - end - - # The class that reads a tar format archive from a data stream. The data - # stream may be sequential or random access, but certain features only work - # with random access data streams. - class Reader - # This marks the EntryStream closed for reading without closing the - # actual data stream. - module InvalidEntryStream - def read(len = nil); raise ClosedStream; end - def getc; raise ClosedStream; end - def rewind; raise ClosedStream; end - end - - # EntryStreams are pseudo-streams on top of the main data stream. - class EntryStream - Archive::Tar::PosixHeader::FIELDS.each do |field| - attr_reader field.intern - end - - def initialize(header, anIO) - @io = anIO - @name = header.name - @mode = header.mode - @uid = header.uid - @gid = header.gid - @size = header.size - @mtime = header.mtime - @checksum = header.checksum - @typeflag = header.typeflag - @linkname = header.linkname - @magic = header.magic - @version = header.version - @uname = header.uname - @gname = header.gname - @devmajor = header.devmajor - @devminor = header.devminor - @prefix = header.prefix - @read = 0 - @orig_pos = @io.pos - end - - # Reads +len+ bytes (or all remaining data) from the entry. Returns - # +nil+ if there is no more data to read. - def read(len = nil) - return nil if @read >= @size - len ||= @size - @read - max_read = [len, @size - @read].min - ret = @io.read(max_read) - @read += ret.size - ret - end - - # Reads one byte from the entry. Returns +nil+ if there is no more data - # to read. - def getc - return nil if @read >= @size - ret = @io.getc - @read += 1 if ret - ret - end - - # Returns +true+ if the entry represents a directory. - def directory? - @typeflag == "5" - end - alias_method :directory, :directory? - - # Returns +true+ if the entry represents a symbolic link. - def symlink? - @typeflag == "2" - end - alias_method :symlink, :symlink? - - # Returns +true+ if the entry represents a plain file. - def file? - @typeflag == "0" or @typeflag == "\0" - end - alias_method :file, :file? - - # Returns +true+ if the current read pointer is at the end of the - # EntryStream data. - def eof? - @read >= @size - end - - # Returns the current read pointer in the EntryStream. - def pos - @read - end - - # Sets the current read pointer to the beginning of the EntryStream. - def rewind - raise NonSeekableStream unless @io.respond_to?(:pos=) - @io.pos = @orig_pos - @read = 0 - end - - def bytes_read - @read - end - - # Returns the full and proper name of the entry. - def full_name - if @prefix != "" - File.join(@prefix, @name) - else - @name - end - end - - # Closes the entry. - def close - invalidate - end - - private - def invalidate - extend InvalidEntryStream - end - end - - # With no associated block, +Reader::open+ is a synonym for - # +Reader::new+. If the optional code block is given, it will be passed - # the new _writer_ as an argument and the Reader object will - # automatically be closed when the block terminates. In this instance, - # +Reader::open+ returns the value of the block. - def self.open(anIO) - reader = Reader.new(anIO) - - return reader unless block_given? - - begin - res = yield reader - ensure - reader.close - end - - res - end - - # Creates and returns a new Reader object. - def initialize(anIO) - @io = anIO - @init_pos = anIO.pos - end - - # Iterates through each entry in the data stream. - def each(&block) - each_entry(&block) - end - - # Resets the read pointer to the beginning of data stream. Do not call - # this during a #each or #each_entry iteration. This only works with - # random access data streams that respond to #rewind and #pos. - def rewind - if @init_pos == 0 - raise NonSeekableStream unless @io.respond_to?(:rewind) - @io.rewind - else - raise NonSeekableStream unless @io.respond_to?(:pos=) - @io.pos = @init_pos - end - end - - # Iterates through each entry in the data stream. - def each_entry - loop do - return if @io.eof? - - header = Archive::Tar::PosixHeader.new_from_stream(@io) - return if header.empty? - - entry = EntryStream.new(header, @io) - size = entry.size - - yield entry - - skip = (512 - (size % 512)) % 512 - - if @io.respond_to?(:seek) - # avoid reading... - @io.seek(size - entry.bytes_read, IO::SEEK_CUR) - else - pending = size - entry.bytes_read - while pending > 0 - bread = @io.read([pending, 4096].min).size - raise UnexpectedEOF if @io.eof? - pending -= bread - end - end - @io.read(skip) # discard trailing zeros - # make sure nobody can use #read, #getc or #rewind anymore - entry.close - end - end - - def close - end - end - - # Wraps a Archive::Tar::Minitar::Reader with convenience methods and - # wrapped stream management; Input only works with random access data - # streams. See Input::new for details. - class Input - include Enumerable - - # With no associated block, +Input::open+ is a synonym for - # +Input::new+. If the optional code block is given, it will be passed - # the new _writer_ as an argument and the Input object will - # automatically be closed when the block terminates. In this instance, - # +Input::open+ returns the value of the block. - def self.open(input) - stream = Input.new(input) - return stream unless block_given? - - begin - res = yield stream - ensure - stream.close - end - - res - end - - # Creates a new Input object. If +input+ is a stream object that responds - # to #read), then it will simply be wrapped. Otherwise, one will be - # created and opened using Kernel#open. When Input#close is called, the - # stream object wrapped will be closed. - def initialize(input) - if input.respond_to?(:read) - @io = input - else - @io = open(input, "rb") - end - @tarreader = Archive::Tar::Minitar::Reader.new(@io) - end - - # Iterates through each entry and rewinds to the beginning of the stream - # when finished. - def each(&block) - @tarreader.each { |entry| yield entry } - ensure - @tarreader.rewind - end - - # Extracts the current +entry+ to +destdir+. If a block is provided, it - # yields an +action+ Symbol, the full name of the file being extracted - # (+name+), and a Hash of statistical information (+stats+). - # - # The +action+ will be one of: - # :dir:: The +entry+ is a directory. - # :file_start:: The +entry+ is a file; the extract of the - # file is just beginning. - # :file_progress:: Yielded every 4096 bytes during the extract - # of the +entry+. - # :file_done:: Yielded when the +entry+ is completed. - # - # The +stats+ hash contains the following keys: - # :current:: The current total number of bytes read in the - # +entry+. - # :currinc:: The current number of bytes read in this read - # cycle. - # :entry:: The entry being extracted; this is a - # Reader::EntryStream, with all methods thereof. - def extract_entry(destdir, entry) # :yields action, name, stats: - stats = { - :current => 0, - :currinc => 0, - :entry => entry - } - - if entry.directory? - dest = File.join(destdir, entry.full_name) - - yield :dir, entry.full_name, stats if block_given? - - if Archive::Tar::Minitar.dir?(dest) - begin - FileUtils.chmod(entry.mode, dest) - rescue Exception - nil - end - else - FileUtils.mkdir_p(dest, :mode => entry.mode) - FileUtils.chmod(entry.mode, dest) - end - - fsync_dir(dest) - fsync_dir(File.join(dest, "..")) - return - else # it's a file - destdir = File.join(destdir, File.dirname(entry.full_name)) - FileUtils.mkdir_p(destdir, :mode => 0755) - - destfile = File.join(destdir, File.basename(entry.full_name)) - FileUtils.chmod(0600, destfile) rescue nil # Errno::ENOENT - - yield :file_start, entry.full_name, stats if block_given? - - File.open(destfile, "wb", entry.mode) do |os| - loop do - data = entry.read(4096) - break unless data - - stats[:currinc] = os.write(data) - stats[:current] += stats[:currinc] - - yield :file_progress, entry.full_name, stats if block_given? - end - os.fsync - end - - FileUtils.chmod(entry.mode, destfile) - fsync_dir(File.dirname(destfile)) - fsync_dir(File.join(File.dirname(destfile), "..")) - - yield :file_done, entry.full_name, stats if block_given? - end - end - - # Returns the Reader object for direct access. - def tar - @tarreader - end - - # Closes the Reader object and the wrapped data stream. - def close - @io.close - @tarreader.close - end - - private - def fsync_dir(dirname) - # make sure this hits the disc - dir = open(dirname, 'rb') - dir.fsync - rescue # ignore IOError if it's an unpatched (old) Ruby - nil - ensure - dir.close if dir rescue nil - end - end - - # Wraps a Archive::Tar::Minitar::Writer with convenience methods and - # wrapped stream management; Output only works with random access data - # streams. See Output::new for details. - class Output - # With no associated block, +Output::open+ is a synonym for - # +Output::new+. If the optional code block is given, it will be passed - # the new _writer_ as an argument and the Output object will - # automatically be closed when the block terminates. In this instance, - # +Output::open+ returns the value of the block. - def self.open(output) - stream = Output.new(output) - return stream unless block_given? - - begin - res = yield stream - ensure - stream.close - end - - res - end - - # Creates a new Output object. If +output+ is a stream object that - # responds to #read), then it will simply be wrapped. Otherwise, one will - # be created and opened using Kernel#open. When Output#close is called, - # the stream object wrapped will be closed. - def initialize(output) - if output.respond_to?(:write) - @io = output - else - @io = ::File.open(output, "wb") - end - @tarwriter = Archive::Tar::Minitar::Writer.new(@io) - end - - # Returns the Writer object for direct access. - def tar - @tarwriter - end - - # Closes the Writer object and the wrapped data stream. - def close - @tarwriter.close - @io.close - end - end - - class << self - # Tests if +path+ refers to a directory. Fixes an apparently - # corrupted stat() call on Windows. - def dir?(path) - File.directory?((path[-1] == ?/) ? path : "#{path}/") - end - - # A convenience method for wrapping Archive::Tar::Minitar::Input.open - # (mode +r+) and Archive::Tar::Minitar::Output.open (mode +w+). No other - # modes are currently supported. - def open(dest, mode = "r", &block) - case mode - when "r" - Input.open(dest, &block) - when "w" - Output.open(dest, &block) - else - raise "Unknown open mode for Archive::Tar::Minitar.open." - end - end - - # A convenience method to packs the file provided. +entry+ may either be - # a filename (in which case various values for the file (see below) will - # be obtained from File#stat(entry) or a Hash with the fields: - # - # :name:: The filename to be packed into the tarchive. - # *REQUIRED*. - # :mode:: The mode to be applied. - # :uid:: The user owner of the file. (Ignored on Windows.) - # :gid:: The group owner of the file. (Ignored on Windows.) - # :mtime:: The modification Time of the file. - # - # During packing, if a block is provided, #pack_file yields an +action+ - # Symol, the full name of the file being packed, and a Hash of - # statistical information, just as with - # Archive::Tar::Minitar::Input#extract_entry. - # - # The +action+ will be one of: - # :dir:: The +entry+ is a directory. - # :file_start:: The +entry+ is a file; the extract of the - # file is just beginning. - # :file_progress:: Yielded every 4096 bytes during the extract - # of the +entry+. - # :file_done:: Yielded when the +entry+ is completed. - # - # The +stats+ hash contains the following keys: - # :current:: The current total number of bytes read in the - # +entry+. - # :currinc:: The current number of bytes read in this read - # cycle. - # :name:: The filename to be packed into the tarchive. - # *REQUIRED*. - # :mode:: The mode to be applied. - # :uid:: The user owner of the file. (+nil+ on Windows.) - # :gid:: The group owner of the file. (+nil+ on Windows.) - # :mtime:: The modification Time of the file. - def pack_file(entry, outputter) #:yields action, name, stats: - outputter = outputter.tar if outputter.kind_of?(Archive::Tar::Minitar::Output) - - stats = {} - - if entry.kind_of?(Hash) - name = entry[:name] - - entry.each { |kk, vv| stats[kk] = vv unless vv.nil? } - else - name = entry - end - - name = name.sub(%r{\./}, '') - stat = File.stat(name) - stats[:mode] ||= stat.mode - stats[:mtime] ||= stat.mtime - stats[:size] = stat.size - - if RUBY_PLATFORM =~ /win32/ - stats[:uid] = nil - stats[:gid] = nil - else - stats[:uid] ||= stat.uid - stats[:gid] ||= stat.gid - end - - case - when File.file?(name) - outputter.add_file_simple(name, stats) do |os| - stats[:current] = 0 - yield :file_start, name, stats if block_given? - File.open(name, "rb") do |ff| - until ff.eof? - stats[:currinc] = os.write(ff.read(4096)) - stats[:current] += stats[:currinc] - yield :file_progress, name, stats if block_given? - end - end - yield :file_done, name, stats if block_given? - end - when dir?(name) - yield :dir, name, stats if block_given? - outputter.mkdir(name, stats) - else - raise "Don't yet know how to pack this type of file." - end - end - - # A convenience method to pack files specified by +src+ into +dest+. If - # +src+ is an Array, then each file detailed therein will be packed into - # the resulting Archive::Tar::Minitar::Output stream; if +recurse_dirs+ - # is true, then directories will be recursed. - # - # If +src+ is an Array, it will be treated as the argument to Find.find; - # all files matching will be packed. - def pack(src, dest, recurse_dirs = true, &block) - Output.open(dest) do |outp| - if src.kind_of?(Array) - src.each do |entry| - pack_file(entry, outp, &block) - if dir?(entry) and recurse_dirs - Dir["#{entry}/**/**"].each do |ee| - pack_file(ee, outp, &block) - end - end - end - else - Find.find(src) do |entry| - pack_file(entry, outp, &block) - end - end - end - end - - # A convenience method to unpack files from +src+ into the directory - # specified by +dest+. Only those files named explicitly in +files+ - # will be extracted. - def unpack(src, dest, files = [], &block) - Input.open(src) do |inp| - if File.exist?(dest) and (not dir?(dest)) - raise "Can't unpack to a non-directory." - elsif not File.exist?(dest) - FileUtils.mkdir_p(dest) - end - - inp.each do |entry| - if files.empty? or files.include?(entry.full_name) - inp.extract_entry(dest, entry, &block) - end - end - end - end - end -end - -# end of embeding under the Puppet::Util namesapce -end -end diff --git a/lib/puppet/util/archive/tar/minitar/command.rb b/lib/puppet/util/archive/tar/minitar/command.rb deleted file mode 100644 index c7689e4b2..000000000 --- a/lib/puppet/util/archive/tar/minitar/command.rb +++ /dev/null @@ -1,822 +0,0 @@ -#!/usr/bin/env ruby -# embed the code in puppet under the Puppet::Util namesapce -module Puppet -module Util - -#-- -# Archive::Tar::Baby 0.5.2 -# Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler -# This is free software with ABSOLUTELY NO WARRANTY. -# -# This program is based on and incorporates parts of RPA::Package from -# rpa-base (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and has been -# adapted to be more generic by Austin. -# -# This file contains an adaptation of Ruby/ProgressBar by Satoru -# Takabayashi , copyright 2001 - 2004. -# -# It is licensed under the GNU General Public Licence or Ruby's licence. -# -# $Id$ -#++ - -require 'zlib' - -# TODO: add -# TODO: delete ??? - -require 'optparse' -require 'ostruct' -require 'fileutils' - -module Archive::Tar::Minitar::Command - class ProgressBar - VERSION = "0.8" - - attr_accessor :total - attr_accessor :title - - def initialize (title, total, out = STDERR) - @title = title - @total = total - @out = out - @bar_width = 80 - @bar_mark = "o" - @current = 0 - @previous = 0 - @is_finished = false - @start_time = Time.now - @previous_time = @start_time - @title_width = 14 - @format = "%-#{@title_width}s %3d%% %s %s" - @format_arguments = [:title, :percentage, :bar, :stat] - show - end - - private - def convert_bytes (bytes) - if bytes < 1024 - sprintf("%6dB", bytes) - elsif bytes < 1024 * 1000 # 1000kb - sprintf("%5.1fKB", bytes.to_f / 1024) - elsif bytes < 1024 * 1024 * 1000 # 1000mb - sprintf("%5.1fMB", bytes.to_f / 1024 / 1024) - else - sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024) - end - end - - def transfer_rate - bytes_per_second = @current.to_f / (Time.now - @start_time) - sprintf("%s/s", convert_bytes(bytes_per_second)) - end - - def bytes - convert_bytes(@current) - end - - def format_time (t) - t = t.to_i - sec = t % 60 - min = (t / 60) % 60 - hour = t / 3600 - sprintf("%02d:%02d:%02d", hour, min, sec); - end - - # ETA stands for Estimated Time of Arrival. - def eta - if @current == 0 - "ETA: --:--:--" - else - elapsed = Time.now - @start_time - eta = elapsed * @total / @current - elapsed; - sprintf("ETA: %s", format_time(eta)) - end - end - - def elapsed - elapsed = Time.now - @start_time - sprintf("Time: %s", format_time(elapsed)) - end - - def stat - if @is_finished then elapsed else eta end - end - - def stat_for_file_transfer - if @is_finished then - sprintf("%s %s %s", bytes, transfer_rate, elapsed) - else - sprintf("%s %s %s", bytes, transfer_rate, eta) - end - end - - def eol - if @is_finished then "\n" else "\r" end - end - - def bar - len = percentage * @bar_width / 100 - sprintf("|%s%s|", @bar_mark * len, " " * (@bar_width - len)) - end - - def percentage(value = nil) - if @total.zero? - 100 - else - (value || @current) * 100 / @total - end - end - - def title - @title[0,(@title_width - 1)] + ":" - end - - def get_width - # FIXME: I don't know how portable it is. - default_width = 80 - # begin - # tiocgwinsz = 0x5413 - # data = [0, 0, 0, 0].pack("SSSS") - # if @out.ioctl(tiocgwinsz, data) >= 0 then - # rows, cols, xpixels, ypixels = data.unpack("SSSS") - # if cols >= 0 then cols else default_width end - # else - # default_width - # end - # rescue Exception - # default_width - # end - end - - def show - arguments = @format_arguments.map {|method| send(method) } - line = sprintf(@format, *arguments) - - width = get_width - if line.length == width - 1 - @out.print(line + eol) - elsif line.length >= width - @bar_width = [@bar_width - (line.length - width + 1), 0].max - if @bar_width == 0 then @out.print(line + eol) else show end - else # line.length < width - 1 - @bar_width += width - line.length + 1 - show - end - @previous_time = Time.now - end - - def show_progress - if @total.zero? - cur_percentage = 100 - prev_percentage = 0 - else - cur_percentage = (@current * 100 / @total).to_i - prev_percentage = (@previous * 100 / @total).to_i - end - - if cur_percentage > prev_percentage || - Time.now - @previous_time >= 1 || - @is_finished - show - end - end - - public - def file_transfer_mode - @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer] - end - - def format= (format) - @format = format - end - - def format_arguments= (arguments) - @format_arguments = arguments - end - - def finish - @current = @total - @is_finished = true - show_progress - end - - def halt - @is_finished = true - show_progress - end - - def set (count) - if count < 0 || count > @total - raise "invalid count: #{count} (total: #{@total})" - end - @current = count - show_progress - @previous = @current - end - - def inc (step = 1) - @current += step - @current = @total if @current > @total - show_progress - @previous = @current - end - - def inspect - "(ProgressBar: #{@current}/#{@total})" - end - end - - class CommandPattern - class AbstractCommandError < Exception; end - class UnknownCommandError < RuntimeError; end - class CommandAlreadyExists < RuntimeError; end - - class << self - def add(command) - command = command.new if command.kind_of?(Class) - - @commands ||= {} - if @commands.has_key?(command.name) - raise CommandAlreadyExists - else - @commands[command.name] = command - end - - if command.respond_to?(:altname) - unless @commands.has_key?(command.altname) - @commands[command.altname] = command - end - end - end - - def <<(command) - add(command) - end - - attr_accessor :default - def default=(command) #:nodoc: - if command.kind_of?(CommandPattern) - @default = command - elsif command.kind_of?(Class) - @default = command.new - elsif @commands.has_key?(command) - @default = @commands[command] - else - raise UnknownCommandError - end - end - - def command?(command) - @commands.has_key?(command) - end - - def command(command) - if command?(command) - @commands[command] - else - @default - end - end - - def [](cmd) - self.command(cmd) - end - - def default_ioe(ioe = {}) - ioe[:input] ||= $stdin - ioe[:output] ||= $stdout - ioe[:error] ||= $stderr - ioe - end - end - - def [](args, opts = {}, ioe = {}) - call(args, opts, ioe) - end - - def name - raise AbstractCommandError - end - - def call(args, opts = {}, ioe = {}) - raise AbstractCommandError - end - - def help - raise AbstractCommandError - end - end - - class CommandHelp < CommandPattern - def name - "help" - end - - def call(args, opts = {}, ioe = {}) - ioe = CommandPattern.default_ioe(ioe) - - help_on = args.shift - - if CommandPattern.command?(help_on) - ioe[:output] << CommandPattern[help_on].help - elsif help_on == "commands" - ioe[:output] << <<-EOH -The commands known to minitar are: - - minitar create Creates a new tarfile. - minitar extract Extracts files from a tarfile. - minitar list Lists files in the tarfile. - -All commands accept the options --verbose and --progress, which are -mutually exclusive. In "minitar list", --progress means the same as ---verbose. - - --verbose, -V Performs the requested command verbosely. - --progress, -P Shows a progress bar, if appropriate, for the action - being performed. - - EOH - else - ioe[:output] << "Unknown command: #{help_on}\n" unless help_on.nil? or help_on.empty? - ioe[:output] << self.help - end - - 0 - end - - def help - help = <<-EOH -This is a basic help message containing pointers to more information on -how to use this command-line tool. Try: - - minitar help commands list all 'minitar' commands - minitar help show help on - (e.g., 'minitar help create') - EOH - end -# minitar add Adds a file to an existing tarfile. -# minitar delete Deletes a file from an existing tarfile. - end - - class CommandCreate < CommandPattern - def name - "create" - end - - def altname - "cr" - end - - def call(args, opts = {}, ioe = {}) - argv = [] - - while (arg = args.shift) - case arg - when '--compress', '-z' - opts[:compress] = true - else - argv << arg - end - end - - if argv.size < 2 - ioe[:output] << "Not enough arguments.\n\n" - CommandPattern["help"][["create"]] - return 255 - end - - output = argv.shift - if '-' == output - opts[:name] = "STDOUT" - output = ioe[:output] - opts[:output] = ioe[:error] - else - opts[:name] = output - output = File.open(output, "wb") - opts[:output] = ioe[:output] - end - - if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:compress] - output = Zlib::GzipWriter.new(output) - end - - files = [] - if argv.include?("--") - # Read stdin for the list of files. - files = "" - files << ioe[:input].read while not ioe[:input].eof? - files = files.split(/\r\n|\n|\r/) - args.delete("--") - end - - files << argv.to_a - files.flatten! - - if opts[:verbose] - watcher = lambda do |action, name, stats| - opts[:output] << "#{name}\n" if action == :dir or action == :file_done - end - finisher = lambda { opts[:output] << "\n" } - elsif opts[:progress] - progress = ProgressBar.new(opts[:name], 1) - watcher = lambda do |action, name, stats| - case action - when :file_start, :dir - progress.title = File.basename(name) - if action == :dir - progress.total += 1 - progress.inc - else - progress.total += stats[:size] - end - when :file_progress - progress.inc(stats[:currinc]) - end - end - finisher = lambda do - progress.title = opts[:name] - progress.finish - end - else - watcher = nil - finisher = lambda { } - end - - Archive::Tar::Minitar.pack(files, output, &watcher) - finisher.call - 0 - ensure - output.close if output and not output.closed? - end - - def help - help = <<-EOH - minitar create [OPTIONS] + - -Creates a new tarfile. If the tarfile is named .tar.gz or .tgz, then it -will be compressed automatically. If the tarfile is "-", then it will be -output to standard output (stdout) so that minitar may be piped. - -The files or directories that will be packed into the tarfile are -specified after the name of the tarfile itself. Directories will be -processed recursively. If the token "--" is found in the list of files -to be packed, additional filenames will be read from standard input -(stdin). If any file is not found, the packaging will be halted. - -create Options: - --compress, -z Compresses the tarfile with gzip. - - EOH - end - end - - class CommandExtract < CommandPattern - def name - "extract" - end - - def altname - "ex" - end - - def call(args, opts = {}, ioe = {}) - argv = [] - output = nil - dest = "." - files = [] - - while (arg = args.shift) - case arg - when '--uncompress', '-z' - opts[:uncompress] = true - when '--pipe' - opts[:output] = ioe[:error] - output = ioe[:output] - when '--output', '-o' - dest = args.shift - else - argv << arg - end - end - - if argv.size < 1 - ioe[:output] << "Not enough arguments.\n\n" - CommandPattern["help"][["extract"]] - return 255 - end - - input = argv.shift - if '-' == input - opts[:name] = "STDIN" - input = ioe[:input] - else - opts[:name] = input - input = File.open(input, "rb") - end - - if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress] - input = Zlib::GzipReader.new(input) - end - - files << argv.to_a - files.flatten! - - if opts[:verbose] - watcher = lambda do |action, name, stats| - opts[:output] << "#{name}\n" if action == :dir or action == :file_done - end - finisher = lambda { opts[:output] << "\n" } - elsif opts[:progress] - progress = ProgressBar.new(opts[:name], 1) - watcher = lambda do |action, name, stats| - case action - when :file_start, :dir - progress.title = File.basename(name) - if action == :dir - progress.total += 1 - progress.inc - else - progress.total += stats[:entry].size - end - when :file_progress - progress.inc(stats[:currinc]) - end - end - finisher = lambda do - progress.title = opts[:name] - progress.finish - end - else - watcher = nil - finisher = lambda { } - end - - if output.nil? - Archive::Tar::Minitar.unpack(input, dest, files, &watcher) - finisher.call - else - Archive::Tar::Minitar::Input.open(input) do |inp| - inp.each do |entry| - stats = { - :mode => entry.mode, - :mtime => entry.mtime, - :size => entry.size, - :gid => entry.gid, - :uid => entry.uid, - :current => 0, - :currinc => 0, - :entry => entry - } - - if files.empty? or files.include?(entry.full_name) - if entry.directory? - puts "Directory: #{entry.full_name}" - watcher[:dir, dest, stats] unless watcher.nil? - else - puts "File: #{entry.full_name}" - watcher[:file_start, destfile, stats] unless watcher.nil? - loop do - data = entry.read(4096) - break unless data - stats[:currinc] = output.write(data) - stats[:current] += stats[:currinc] - - watcher[:file_progress, name, stats] unless watcher.nil? - end - watcher[:file_done, name, stats] unless watcher.nil? - end - end - end - end - end - - 0 - end - - def help - help = <<-EOH - minitar extract [OPTIONS] [+] - -Extracts files from an existing tarfile. If the tarfile is named .tar.gz -or .tgz, then it will be uncompressed automatically. If the tarfile is -"-", then it will be read from standard input (stdin) so that minitar -may be piped. - -The files or directories that will be extracted from the tarfile are -specified after the name of the tarfile itself. Directories will be -processed recursively. Files must be specified in full. A file -"foo/bar/baz.txt" cannot simply be specified by specifying "baz.txt". -Any file not found will simply be skipped and an error will be reported. - -extract Options: - --uncompress, -z Uncompresses the tarfile with gzip. - --pipe Emits the extracted files to STDOUT for piping. - --output, -o Extracts the files to the specified directory. - - EOH - end - end - - class CommandList < CommandPattern - def name - "list" - end - - def altname - "ls" - end - - def modestr(mode) - s = "---" - s[0] = ?r if (mode & 4) == 4 - s[1] = ?w if (mode & 2) == 2 - s[2] = ?x if (mode & 1) == 1 - s - end - - def call(args, opts = {}, ioe = {}) - argv = [] - output = nil - dest = "." - files = [] - opts[:field] = "name" - - while (arg = args.shift) - case arg - when '--sort', '-S' - opts[:sort] = true - opts[:field] = args.shift - when '--reverse', '-R' - opts[:reverse] = true - opts[:sort] = true - when '--uncompress', '-z' - opts[:uncompress] = true - when '-l' - opts[:verbose] = true - else - argv << arg - end - end - - if argv.size < 1 - ioe[:output] << "Not enough arguments.\n\n" - CommandPattern["help"][["list"]] - return 255 - end - - input = argv.shift - if '-' == input - opts[:name] = "STDIN" - input = ioe[:input] - else - opts[:name] = input - input = File.open(input, "rb") - end - - if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress] - input = Zlib::GzipReader.new(input) - end - - files << argv.to_a - files.flatten! - - if opts[:verbose] or opts[:progress] - format = "%10s %4d %8s %8s %8d %12s %s" - datefmt = "%b %d %Y" - timefmt = "%b %d %H:%M" - fields = %w(permissions inodes user group size date fullname) - else - format = "%s" - fields = %w(fullname) - end - - opts[:field] = opts[:field].intern - opts[:field] = :full_name if opts[:field] == :name - - output = [] - - Archive::Tar::Minitar::Input.open(input) do |inp| - today = Time.now - oneyear = Time.mktime(today.year - 1, today.month, today.day) - inp.each do |entry| - value = format % fields.map do |ff| - case ff - when "permissions" - s = entry.directory? ? "d" : "-" - s << modestr(entry.mode / 0100) - s << modestr(entry.mode / 0010) - s << modestr(entry.mode) - when "inodes" - entry.size / 512 - when "user" - entry.uname || entry.uid || 0 - when "group" - entry.gname || entry.gid || 0 - when "size" - entry.size - when "date" - if Time.at(entry.mtime) > (oneyear) - Time.at(entry.mtime).strftime(timefmt) - else - Time.at(entry.mtime).strftime(datefmt) - end - when "fullname" - entry.full_name - end - end - - if opts[:sort] - output << [entry.send(opts[:field]), value] - else - ioe[:output] << value << "\n" - end - - end - end - - if opts[:sort] - output = output.sort { |a, b| a[0] <=> b[0] } - if opts[:reverse] - output.reverse_each { |oo| ioe[:output] << oo[1] << "\n" } - else - output.each { |oo| ioe[:output] << oo[1] << "\n" } - end - end - - 0 - end - - def help - help = <<-EOH - minitar list [OPTIONS] [+] - -Lists files in an existing tarfile. If the tarfile is named .tar.gz or -.tgz, then it will be uncompressed automatically. If the tarfile is "-", -then it will be read from standard input (stdin) so that minitar may be -piped. - -If --verbose or --progress is specified, then the file list will be -similar to that produced by the Unix command "ls -l". - -list Options: - --uncompress, -z Uncompresses the tarfile with gzip. - --sort [], -S Sorts the list of files by the specified - field. The sort defaults to the filename. - --reverse, -R Reverses the sort. - -l Lists the files in detail. - -Sort Fields: - name, mtime, size - - EOH - end - end - - CommandPattern << CommandHelp - CommandPattern << CommandCreate - CommandPattern << CommandExtract - CommandPattern << CommandList -# CommandPattern << CommandAdd -# CommandPattern << CommandDelete - - def self.run(argv, input = $stdin, output = $stdout, error = $stderr) - ioe = { - :input => input, - :output => output, - :error => error, - } - opts = { } - - if argv.include?("--version") - output << <<-EOB -minitar #{Archive::Tar::Minitar::VERSION} - Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler - This is free software with ABSOLUTELY NO WARRANTY. - - see http://rubyforge.org/projects/ruwiki for more information - EOB - end - - if argv.include?("--verbose") or argv.include?("-V") - opts[:verbose] = true - argv.delete("--verbose") - argv.delete("-V") - end - - if argv.include?("--progress") or argv.include?("-P") - opts[:progress] = true - opts[:verbose] = false - argv.delete("--progress") - argv.delete("-P") - end - - command = CommandPattern[(argv.shift or "").downcase] - command ||= CommandPattern["help"] - return command[argv, opts, ioe] - end -end - -# end of embeding under the Puppet::Util namesapce -end -end diff --git a/spec/unit/module_tool/applications/unpacker_spec.rb b/spec/unit/module_tool/applications/unpacker_spec.rb index b4512d231..07842642f 100644 --- a/spec/unit/module_tool/applications/unpacker_spec.rb +++ b/spec/unit/module_tool/applications/unpacker_spec.rb @@ -35,12 +35,12 @@ describe Puppet::ModuleTool::Applications::Unpacker do FileUtils.stubs(:mv) end - it "should attempt to open the file with Zlib::GzipReader and process the yielded stream with Puppet::Util::Archive::Tar::Minitar::Reader" do + it "should attempt to open the file with Zlib::GzipReader and process the yielded stream with Archive::Tar::Minitar::Reader" do pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do - tar = mock('Puppet::Util::Archive::Tar::Minitar::Reader') + tar = mock('Archive::Tar::Minitar::Reader') tar.expects(:each) gzip = mock('Zlib::GzipReader') - Puppet::Util::Archive::Tar::Minitar::Reader.expects(:open).with(gzip).yields(tar) + Archive::Tar::Minitar::Reader.expects(:open).with(gzip).yields(tar) Zlib::GzipReader.expects(:open).with(Pathname.new(filename)).yields(gzip) unpacker.run end diff --git a/spec/unit/module_tool/shared_behaviors_spec.rb b/spec/unit/module_tool/shared_behaviors_spec.rb index d2579abe8..b8bbc83b1 100644 --- a/spec/unit/module_tool/shared_behaviors_spec.rb +++ b/spec/unit/module_tool/shared_behaviors_spec.rb @@ -130,7 +130,7 @@ describe Puppet::ModuleTool::Shared do before do Zlib::GzipWriter.open(stdlib_pkg) do |gzip| - Puppet::Util::Archive::Tar::Minitar::Writer.open(gzip) do |tar| + Archive::Tar::Minitar::Writer.open(gzip) do |tar| serialized_metadata = PSON.pretty_generate(metadata) tar.add_file_simple('baz/metadata.json', :mode => 0644,