Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use libarchive by preference #17

Merged
merged 1 commit into from
Apr 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ sudo: false
language: ruby
cache: bundler

addons:
apt:
packages:
- libarchive-dev

matrix:
include:
- rvm: 2.3.6
- rvm: 2.4.3
- rvm: 2.5.0
- rvm: 2.4.4
- rvm: 2.5.1
- rvm: ruby-head
allow_failures:
- rvm: ruby-head
Expand Down
4 changes: 1 addition & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ source "https://rubygems.org"
# Specify your gem's dependencies in mixlib-archive.gemspec
gemspec

group(:changelog) do
gem "github_changelog_generator", git: "https://github.com/chef/github-changelog-generator"
end
gem "ffi-libarchive"
10 changes: 8 additions & 2 deletions lib/mixlib/archive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ def initialize(archive, empty: false)
@empty = empty

archive = File.expand_path(archive)
# for now we only support Tar format archives.
@archiver = Mixlib::Archive::Tar.new(archive)
begin
# we prefer to use libarchive, which supports a great big pile o' stuff
require "mixlib/archive/lib_archive"
@archiver = Mixlib::Archive::LibArchive.new(archive)
rescue LoadError
# but if we can't use that, we'll fall back to ruby's native tar implementation
@archiver = Mixlib::Archive::Tar.new(archive)
end
end

class Log
Expand Down
63 changes: 63 additions & 0 deletions lib/mixlib/archive/lib_archive.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require "ffi-libarchive"

module Mixlib
class Archive
class LibArchive
attr_reader :options
attr_reader :archive

def initialize(archive, options = {})
@archive = archive
@options = options
end

# Extracts the archive to the given +destination+
#
# === Parameters
# perms<Boolean>:: should the extracter use permissions from the archive.
# ignore[Array]:: an array of matches of file paths to ignore
def extract(destination, perms: true, ignore: [])
ignore_re = Regexp.union(ignore)
flags = perms ? ::Archive::EXTRACT_PERM : nil
Dir.chdir(destination) do
reader = ::Archive::Reader.open_filename(@archive)

reader.each_entry do |entry|
if entry.pathname =~ ignore_re
Mixlib::Archive::Log.warn "ignoring entry #{entry.pathname}"
next
end

reader.extract(entry, flags.to_i)
end
reader.close
end
end

# Creates an archive with the given set of +files+
#
# === Parameters
# gzip<Boolean>:: should the archive be gzipped?
def create(files, gzip: false)
compression = gzip ? ::Archive::COMPRESSION_GZIP : ::Archive::COMPRESSION_NONE
# "PAX restricted" will use PAX extensions when it has to, but will otherwise
# use ustar for maximum compatibility
format = ::Archive::FORMAT_TAR_PAX_RESTRICTED

::Archive.write_open_filename(archive, compression, format) do |tar|
files.each do |fn|
tar.new_entry do |entry|
entry.pathname = fn
entry.copy_stat(fn)
tar.write_header(entry)
if File.file?(fn)
content = File.read(fn)
tar.write_data(content)
end
end
end
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/mixlib/archive/tar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ def reader(&block)
ensure
if file
file.close unless file.closed?
file = nil
file = nil # rubocop:disable Lint/UselessAssignment
end
if raw
raw.close unless raw.closed?
raw = nil
raw = nil # rubocop:disable Lint/UselessAssignment
end
end

Expand Down
15 changes: 9 additions & 6 deletions spec/mixlib/archive_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

describe Mixlib::Archive do
let(:target) { "../fixtures/foo.tar" }
let (:destination) { Dir.mktmpdir }
let (:files) { %w{ file dir/file new_file.rb } }
let(:destination) { ::Dir.mktmpdir }
let(:files) { %w{ file dir/file new_file.rb } }

let (:archive) { described_class.new(target) }
let (:archiver) { double(Mixlib::Archive::Tar, extract: true) }
let(:archive) { described_class.new(target) }
let(:tar_archiver) { double(Mixlib::Archive::Tar, extract: true) }
let(:archiver) { double(Mixlib::Archive::LibArchive, extract: true) }

before do
allow(File).to receive(:expand_path).and_call_original
allow(Mixlib::Archive::Tar).to receive(:new).with(any_args).and_return(archiver)
allow(Mixlib::Archive::LibArchive).to receive(:new).with(any_args).and_return(archiver)
end

after do
Expand All @@ -31,11 +33,12 @@
before do
end

it "with the correct archiver" do
it "with the default archiver" do
expect(File).to receive(:expand_path).with(target).and_return(expanded_target)
expect(Mixlib::Archive::Tar).to receive(:new).with(expanded_target)
expect(Mixlib::Archive::LibArchive).to receive(:new).with(expanded_target)
described_class.new(target)
end

end
end

Expand Down
3 changes: 3 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "tmpdir"
require "mixlib/archive"
require "mixlib/archive/tar"
require "mixlib/archive/lib_archive"