class Mixlib::Archive::Tar
Constants
- TAR_LONGLINK
Attributes
archive[R]
options[R]
Public Class Methods
new(archive, options = {})
click to toggle source
# File lib/mixlib/archive/tar.rb, line 13 def initialize(archive, options = {}) @archive = archive @options = options end
Public Instance Methods
create(files, gzip: false)
click to toggle source
Creates an archive with the given set of files
Parameters¶ ↑
- gzip<Boolean>
-
should the archive be gzipped?
# File lib/mixlib/archive/tar.rb, line 72 def create(files, gzip: false) tgt_dir = File.dirname(archive) target = Tempfile.new(File.basename(archive), tgt_dir) target.binmode Gem::Package::TarWriter.new(target) do |tar| files.each do |fn| mode = File.stat(fn).mode if File.symlink?(fn) target = File.readlink(fn) tar.add_symlink(fn, target, mode) elsif File.directory?(fn) tar.mkdir(fn, mode) elsif File.file?(fn) file = File.open(fn, "rb") tar.add_file(fn, mode) do |io| io.write(file.read) end file.close end end end target.close if gzip Zlib::GzipWriter.open(archive, Zlib::BEST_COMPRESSION) do |gz| gz.mtime = File.mtime(target.path) gz.orig_name = File.basename(archive) File.open(target.path) do |file| while (chunk = file.read(16 * 1024)) gz.write(chunk) end end end else FileUtils.mv(target.path, archive) end ensure target.close unless target.closed? end
extract(destination, perms: true, ignore: [])
click to toggle source
Extracts the archive to the given destination
Parameters¶ ↑
- perms<Boolean>
-
should the extracter use permissions from the archive.
- ignore
-
an array of matches of file paths to ignore
# File lib/mixlib/archive/tar.rb, line 23 def extract(destination, perms: true, ignore: []) # (http://stackoverflow.com/a/31310593/506908) ignore_re = Regexp.union(ignore) reader do |tar| dest = nil tar.each do |entry| if entry.full_name == TAR_LONGLINK dest = File.join(destination, entry.read.strip) next end if entry.full_name =~ ignore_re Mixlib::Archive::Log.warn "ignoring entry #{entry.full_name}" next end dest ||= File.expand_path(File.join(destination, entry.full_name)) parent = File.dirname(dest) FileUtils.mkdir_p(parent) if entry.directory? || (entry.header.typeflag == "" && entry.full_name.end_with?("/")) File.delete(dest) if File.file?(dest) if perms FileUtils.mkdir_p(dest, mode: entry.header.mode, verbose: false) else FileUtils.mkdir_p(dest, verbose: false) end elsif entry.file? || (entry.header.typeflag == "" && !entry.full_name.end_with?("/")) FileUtils.rm_rf(dest) if File.directory?(dest) File.open(dest, "wb") do |f| f.print(entry.read) end FileUtils.chmod(entry.header.mode, dest, verbose: false) if perms elsif entry.header.typeflag == "2" # handle symlink File.symlink(entry.header.linkname, dest) else Mixlib::Archive::Log.warn "unknown tar entry: #{entry.full_name} type: #{entry.header.typeflag}" end dest = nil end end end
Private Instance Methods
is_gzip_file?(path)
click to toggle source
# File lib/mixlib/archive/tar.rb, line 115 def is_gzip_file?(path) # You cannot write "\x1F\x8B" because the default encoding of # ruby >= 1.9.3 is UTF-8 and 8B is an invalid in UTF-8. IO.binread(path, 2) == [0x1F, 0x8B].pack("C*") end
is_tar_archive?(io)
click to toggle source
tar's magic is at byte 257 and is “ustar0” OLDGNU_MAGIC “ustar 0” /* 7 chars and a null */
# File lib/mixlib/archive/tar.rb, line 123 def is_tar_archive?(io) !(read_tar_magic(io) =~ /ustar\s{0,2}\x00/).nil? end
read_tar_magic(io)
click to toggle source
# File lib/mixlib/archive/tar.rb, line 127 def read_tar_magic(io) io.rewind magic = Array(io.read(512).bytes[257..264]).pack("C*") io.rewind magic end
reader(&block)
click to toggle source
# File lib/mixlib/archive/tar.rb, line 134 def reader(&block) raw = File.open(archive, "rb") file = if is_gzip_file?(archive) Mixlib::Archive::Log.debug "gzip file detected" Zlib::GzipReader.wrap(raw) else raw end raise Mixlib::Archive::TarError, "Unrecognized archive format" unless is_tar_archive?(file) Gem::Package::TarReader.new(file, &block) ensure if file file.close unless file.closed? file = nil # rubocop:disable Lint/UselessAssignment end if raw raw.close unless raw.closed? raw = nil # rubocop:disable Lint/UselessAssignment end end