Merge pull request #4484 from reitermarkus/nested-unpack-strategy
Add support for nested archives.
This commit is contained in:
commit
c47d51519e
@ -15,6 +15,50 @@ RSpec.shared_examples "#extract" do |children: []|
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe UnpackStrategy do
|
||||||
|
describe "#extract_nestedly" do
|
||||||
|
subject(:strategy) { described_class.detect(path) }
|
||||||
|
|
||||||
|
let(:unpack_dir) { mktmpdir }
|
||||||
|
|
||||||
|
context "when extracting a GZIP nested in a BZIP2" do
|
||||||
|
let(:file_name) { "file" }
|
||||||
|
let(:path) {
|
||||||
|
dir = mktmpdir
|
||||||
|
|
||||||
|
(dir/"file").write "This file was inside a GZIP inside a BZIP2."
|
||||||
|
system "gzip", dir.children.first
|
||||||
|
system "bzip2", dir.children.first
|
||||||
|
|
||||||
|
dir.children.first
|
||||||
|
}
|
||||||
|
|
||||||
|
it "can extract nested archives" do
|
||||||
|
strategy.extract_nestedly(to: unpack_dir)
|
||||||
|
|
||||||
|
expect(File.read(unpack_dir/file_name)).to eq("This file was inside a GZIP inside a BZIP2.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when extracting a directory with nested directories" do
|
||||||
|
let(:directories) { "A/B/C" }
|
||||||
|
let(:path) {
|
||||||
|
(mktmpdir/"file.tar").tap do |path|
|
||||||
|
mktmpdir do |dir|
|
||||||
|
(dir/directories).mkpath
|
||||||
|
system "tar", "-c", "-f", path, "-C", dir, "A/"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
it "does not recurse into nested directories" do
|
||||||
|
strategy.extract_nestedly(to: unpack_dir)
|
||||||
|
expect(Pathname.glob(unpack_dir/"**/*")).to include unpack_dir/directories
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe UncompressedUnpackStrategy do
|
describe UncompressedUnpackStrategy do
|
||||||
let(:path) {
|
let(:path) {
|
||||||
(mktmpdir/"test").tap do |path|
|
(mktmpdir/"test").tap do |path|
|
||||||
|
@ -67,6 +67,25 @@ class UnpackStrategy
|
|||||||
unpack_dir.mkpath
|
unpack_dir.mkpath
|
||||||
extract_to_dir(unpack_dir, basename: basename)
|
extract_to_dir(unpack_dir, basename: basename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def extract_nestedly(to: nil, basename: nil)
|
||||||
|
Dir.mktmpdir do |tmp_unpack_dir|
|
||||||
|
tmp_unpack_dir = Pathname(tmp_unpack_dir)
|
||||||
|
|
||||||
|
extract(to: tmp_unpack_dir, basename: basename)
|
||||||
|
|
||||||
|
children = tmp_unpack_dir.children
|
||||||
|
|
||||||
|
if children.count == 1 && !children.first.directory?
|
||||||
|
s = self.class.detect(children.first)
|
||||||
|
|
||||||
|
s.extract_nestedly(to: to, basename: basename)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
DirectoryUnpackStrategy.new(tmp_unpack_dir).extract(to: to)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class DirectoryUnpackStrategy < UnpackStrategy
|
class DirectoryUnpackStrategy < UnpackStrategy
|
||||||
@ -82,6 +101,8 @@ class DirectoryUnpackStrategy < UnpackStrategy
|
|||||||
end
|
end
|
||||||
|
|
||||||
class UncompressedUnpackStrategy < UnpackStrategy
|
class UncompressedUnpackStrategy < UnpackStrategy
|
||||||
|
alias extract_nestedly extract
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
def extract_to_dir(unpack_dir, basename:)
|
||||||
@ -166,7 +187,7 @@ class CompressUnpackStrategy < TarUnpackStrategy
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class XzUnpackStrategy < UncompressedUnpackStrategy
|
class XzUnpackStrategy < UnpackStrategy
|
||||||
def self.can_extract?(path:, magic_number:)
|
def self.can_extract?(path:, magic_number:)
|
||||||
magic_number.match?(/\A\xFD7zXZ\x00/n)
|
magic_number.match?(/\A\xFD7zXZ\x00/n)
|
||||||
end
|
end
|
||||||
@ -175,7 +196,7 @@ class XzUnpackStrategy < UncompressedUnpackStrategy
|
|||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
def extract_to_dir(unpack_dir, basename:)
|
||||||
super
|
super
|
||||||
safe_system Formula["xz"].opt_bin/"xz", "-d", "-q", "-T0", unpack_dir/basename
|
safe_system Formula["xz"].opt_bin/"unxz", "-q", "-T0", unpack_dir/basename
|
||||||
extract_nested_tar(unpack_dir, basename: basename)
|
extract_nested_tar(unpack_dir, basename: basename)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -192,7 +213,7 @@ class XzUnpackStrategy < UncompressedUnpackStrategy
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Bzip2UnpackStrategy < UncompressedUnpackStrategy
|
class Bzip2UnpackStrategy < UnpackStrategy
|
||||||
def self.can_extract?(path:, magic_number:)
|
def self.can_extract?(path:, magic_number:)
|
||||||
magic_number.match?(/\ABZh/n)
|
magic_number.match?(/\ABZh/n)
|
||||||
end
|
end
|
||||||
@ -200,12 +221,12 @@ class Bzip2UnpackStrategy < UncompressedUnpackStrategy
|
|||||||
private
|
private
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
def extract_to_dir(unpack_dir, basename:)
|
||||||
super
|
FileUtils.cp path, unpack_dir/basename, preserve: true
|
||||||
safe_system "bunzip2", "-q", unpack_dir/basename
|
safe_system "bunzip2", "-q", unpack_dir/basename
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class GzipUnpackStrategy < UncompressedUnpackStrategy
|
class GzipUnpackStrategy < UnpackStrategy
|
||||||
def self.can_extract?(path:, magic_number:)
|
def self.can_extract?(path:, magic_number:)
|
||||||
magic_number.match?(/\A\037\213/n)
|
magic_number.match?(/\A\037\213/n)
|
||||||
end
|
end
|
||||||
@ -213,12 +234,12 @@ class GzipUnpackStrategy < UncompressedUnpackStrategy
|
|||||||
private
|
private
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
def extract_to_dir(unpack_dir, basename:)
|
||||||
super
|
FileUtils.cp path, unpack_dir/basename, preserve: true
|
||||||
safe_system "gunzip", "-q", "-N", unpack_dir/basename
|
safe_system "gunzip", "-q", "-N", unpack_dir/basename
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LzipUnpackStrategy < UncompressedUnpackStrategy
|
class LzipUnpackStrategy < UnpackStrategy
|
||||||
def self.can_extract?(path:, magic_number:)
|
def self.can_extract?(path:, magic_number:)
|
||||||
magic_number.match?(/\ALZIP/n)
|
magic_number.match?(/\ALZIP/n)
|
||||||
end
|
end
|
||||||
@ -226,7 +247,7 @@ class LzipUnpackStrategy < UncompressedUnpackStrategy
|
|||||||
private
|
private
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
def extract_to_dir(unpack_dir, basename:)
|
||||||
super
|
FileUtils.cp path, unpack_dir/basename, preserve: true
|
||||||
safe_system Formula["lzip"].opt_bin/"lzip", "-d", "-q", unpack_dir/basename
|
safe_system Formula["lzip"].opt_bin/"lzip", "-d", "-q", unpack_dir/basename
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -271,12 +292,6 @@ class GitUnpackStrategy < DirectoryUnpackStrategy
|
|||||||
def self.can_extract?(path:, magic_number:)
|
def self.can_extract?(path:, magic_number:)
|
||||||
super && (path/".git").directory?
|
super && (path/".git").directory?
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:)
|
|
||||||
FileUtils.cp_r path.children, unpack_dir, preserve: true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class SubversionUnpackStrategy < DirectoryUnpackStrategy
|
class SubversionUnpackStrategy < DirectoryUnpackStrategy
|
||||||
|
Loading…
x
Reference in New Issue
Block a user