Skip to content

Commit

Permalink
Fix up creating archives
Browse files Browse the repository at this point in the history
Signed-off-by: Thom May <thom@chef.io>
  • Loading branch information
Thom May committed Apr 27, 2018
1 parent accafd0 commit ba40dab
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 5 deletions.
6 changes: 6 additions & 0 deletions lib/mixlib/archive.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
require "mixlib/archive/tar"
require "mixlib/archive/version"
require "mixlib/log"
require "find"

module Mixlib
class Archive
attr_reader :archiver
alias_method :extractor, :archiver

def self.archive_directory(path, archive, gzip: false, format: :tar, compression: :none)
targets = Find.find(path).collect { |fn| fn }
new(archive).create(targets, gzip: gzip)
end

def initialize(archive, empty: false)
@empty = empty

Expand Down
28 changes: 25 additions & 3 deletions lib/mixlib/archive/lib_archive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def initialize(archive, options = {})
def extract(destination, perms: true, ignore: [])
ignore_re = Regexp.union(ignore)
flags = perms ? ::Archive::EXTRACT_PERM : nil
FileUtils.mkdir_p(destination)
Dir.chdir(destination) do
reader = ::Archive::Reader.open_filename(@archive)

Expand Down Expand Up @@ -47,17 +48,38 @@ def create(files, gzip: false)
::Archive.write_open_filename(archive, compression, format) do |tar|
files.each do |fn|
tar.new_entry do |entry|
content = nil
entry.pathname = fn
entry.copy_stat(fn)
tar.write_header(entry)
stat = File.lstat(fn)
if File.file?(fn)
content = File.read(fn)
tar.write_data(content)
entry.size = content.size
end
entry.mode = stat.mode
entry.filetype = resolve_type(stat.ftype)
entry.atime = stat.atime
entry.mtime = stat.mtime
entry.symlink = File.readlink(fn) if File.symlink?(fn)
tar.write_header(entry)

tar.write_data(content) unless content.nil?
end
end
end
end

def resolve_type(type)
case type
when "characterSpecial"
::Archive::Entry::CHARACTER_SPECIAL
when "blockSpecial"
::Archive::Entry::BLOCK_SPECIAL
when "link"
::Archive::Entry::SYMBOLIC_LINK
else
::Archive::Entry.const_get(type.upcase)
end
end
end
end
end
9 changes: 7 additions & 2 deletions lib/mixlib/archive/tar.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "rubygems/package"
require "tempfile"
require "zlib"

module Mixlib
Expand Down Expand Up @@ -85,10 +86,14 @@ def create(files, gzip: false)

target.close
if gzip
Zlib::GzipWriter.open(archive) do |gz|
Zlib::GzipWriter.open(archive, Zlib::BEST_COMPRESSION) do |gz|
gz.mtime = File.mtime(target.path)
gz.orig_name = File.basename(archive)
gz.write IO.binread(target.path)
File.open(target.path) do |file|
while (chunk = file.read(16 * 1024))
gz.write(chunk)
end
end
end
else
FileUtils.mv(target.path, archive)
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/fixture_a
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fixture_a
1 change: 1 addition & 0 deletions spec/fixtures/fixture_b
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fixture_b
1 change: 1 addition & 0 deletions spec/fixtures/fixture_c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fixture_c
57 changes: 57 additions & 0 deletions spec/mixlib/lib_archive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
require "spec_helper"

describe Mixlib::Archive::LibArchive do
let(:tar_archive) { "#{fixtures_path}/test.tar" }
let(:tgz_archive) { "#{fixtures_path}/test.tgz" }
let(:tar_gz_archive) { "#{fixtures_path}/test.tar.gz" }

let(:extraction) { lambda { |f| } }

let(:destination) { Dir.mktmpdir }

let(:gzip_header) { [0x1F, 0x8B].pack("C*") }

before do
allow(IO).to receive(:binread).and_return(nil)
end

after do
FileUtils.remove_entry destination
end

describe "#reader"

describe "#create" do
let(:test_root) { Dir.mktmpdir(nil) }
let(:archive_path) { File.join(test_root, "test.tar.gz") }
let(:file_paths) { %w{ . .. fixture_a fixture_b fixture_c } }

context "using the correct options" do
it "requests the correct tar format" do
expect(::Archive).to receive(:write_open_filename).with(archive_path, 0, ::Archive::FORMAT_TAR_PAX_RESTRICTED)
Mixlib::Archive::LibArchive.new(archive_path).create([])
end

it "requests gzip compression" do
expect(::Archive).to receive(:write_open_filename).with(archive_path, ::Archive::COMPRESSION_GZIP, ::Archive::FORMAT_TAR_PAX_RESTRICTED)
Mixlib::Archive::LibArchive.new(archive_path).create([], gzip: true)
end

it "requests no compression" do
expect(::Archive).to receive(:write_open_filename).with(archive_path, ::Archive::COMPRESSION_NONE, ::Archive::FORMAT_TAR_PAX_RESTRICTED)
Mixlib::Archive::LibArchive.new(archive_path).create([], gzip: false)
end
end

it "creates a tarball" do
Dir.chdir(fixtures_path) do
Mixlib::Archive::LibArchive.new(archive_path).create(file_paths, gzip: true)
end
expect(File.file?(archive_path)).to be true
target = File.join(test_root, "target")
Mixlib::Archive::LibArchive.new(archive_path).extract(target)
expect(Dir.entries(target)).to match_array file_paths
end

end
end
17 changes: 17 additions & 0 deletions spec/mixlib/tar_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,21 @@
end

end

describe "#create" do
let(:test_root) { Dir.mktmpdir(nil) }
let(:archive_path) { File.join(test_root, "test.tar.gz") }
let(:file_paths) { %w{ . .. fixture_a fixture_b fixture_c } }

it "creates a tarball" do
Dir.chdir(fixtures_path) do
Mixlib::Archive::Tar.new(archive_path).create(file_paths, gzip: true)
end
expect(File.file?(archive_path)).to be true
target = File.join(test_root, "target")
Mixlib::Archive::LibArchive.new(archive_path).extract(target, ignore: %w{ . .. })
expect(Dir.entries(target)).to match_array file_paths
end

end
end
15 changes: 15 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@
require "mixlib/archive"
require "mixlib/archive/tar"
require "mixlib/archive/lib_archive"

module Fixtures
def fixtures_path
spec_root.join("fixtures")
end

def spec_root
Pathname.new(File.expand_path(File.dirname(__FILE__)))
end
end

RSpec.configure do |config|
config.raise_errors_for_deprecations!
config.include Fixtures
end

0 comments on commit ba40dab

Please sign in to comment.