Skip to content

Commit

Permalink
use libarchive by preference
Browse files Browse the repository at this point in the history
Signed-off-by: Thom May <[email protected]>
  • Loading branch information
Thom May committed Apr 25, 2018
1 parent aea48e9 commit 3a3b971
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ source "https://rubygems.org"
# Specify your gem's dependencies in mixlib-archive.gemspec
gemspec

gem "ffi-libarchive"

group(:changelog) do
gem "github_changelog_generator", git: "https://github.com/chef/github-changelog-generator"
end
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

0 comments on commit 3a3b971

Please sign in to comment.