2018-07-23 20:59:21 +02:00
|
|
|
module UnpackStrategy
|
|
|
|
# length of the longest regex (currently Tar)
|
2018-07-01 23:35:29 +02:00
|
|
|
MAX_MAGIC_NUMBER_LENGTH = 262
|
|
|
|
private_constant :MAX_MAGIC_NUMBER_LENGTH
|
|
|
|
|
|
|
|
def self.strategies
|
|
|
|
@strategies ||= [
|
2018-07-23 20:59:21 +02:00
|
|
|
Jar,
|
|
|
|
LuaRock,
|
|
|
|
MicrosoftOfficeXml,
|
|
|
|
Zip,
|
|
|
|
Xar,
|
|
|
|
Compress,
|
|
|
|
Tar,
|
|
|
|
Gzip,
|
|
|
|
Bzip2,
|
|
|
|
Xz,
|
|
|
|
Lzip,
|
|
|
|
Git,
|
|
|
|
Mercurial,
|
|
|
|
Subversion,
|
|
|
|
Cvs,
|
|
|
|
Fossil,
|
|
|
|
Bazaar,
|
|
|
|
P7Zip,
|
|
|
|
Rar,
|
|
|
|
Lha,
|
2018-07-01 23:35:29 +02:00
|
|
|
].freeze
|
|
|
|
end
|
|
|
|
private_class_method :strategies
|
|
|
|
|
2018-07-09 22:11:26 +02:00
|
|
|
def self.detect(path, ref_type: nil, ref: nil)
|
2018-07-01 23:35:29 +02:00
|
|
|
magic_number = if path.directory?
|
|
|
|
""
|
|
|
|
else
|
2018-07-09 20:04:33 +02:00
|
|
|
File.binread(path, MAX_MAGIC_NUMBER_LENGTH) || ""
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
strategy = strategies.detect do |s|
|
|
|
|
s.can_extract?(path: path, magic_number: magic_number)
|
|
|
|
end
|
|
|
|
|
|
|
|
# This is so that bad files produce good error messages.
|
|
|
|
strategy ||= case path.extname
|
2018-07-09 20:04:33 +02:00
|
|
|
when ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz", ".tar.xz", ".txz"
|
2018-07-23 20:59:21 +02:00
|
|
|
Tar
|
2018-07-01 23:35:29 +02:00
|
|
|
when ".zip"
|
2018-07-23 20:59:21 +02:00
|
|
|
Zip
|
2018-07-01 23:35:29 +02:00
|
|
|
else
|
2018-07-23 20:59:21 +02:00
|
|
|
Uncompressed
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
|
|
|
|
2018-07-09 22:11:26 +02:00
|
|
|
strategy.new(path, ref_type: ref_type, ref: ref)
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :path
|
|
|
|
|
2018-07-09 22:11:26 +02:00
|
|
|
def initialize(path, ref_type: nil, ref: nil)
|
2018-07-01 23:35:29 +02:00
|
|
|
@path = Pathname(path).expand_path
|
2018-07-09 22:11:26 +02:00
|
|
|
@ref_type = ref_type
|
|
|
|
@ref = ref
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
|
|
|
|
2018-07-21 16:52:27 +02:00
|
|
|
def extract(to: nil, basename: nil, verbose: false)
|
2018-07-09 20:04:33 +02:00
|
|
|
basename ||= path.basename
|
2018-07-01 23:35:29 +02:00
|
|
|
unpack_dir = Pathname(to || Dir.pwd).expand_path
|
|
|
|
unpack_dir.mkpath
|
2018-07-21 16:52:27 +02:00
|
|
|
extract_to_dir(unpack_dir, basename: basename, verbose: verbose)
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
2018-07-16 19:00:49 +02:00
|
|
|
|
2018-07-21 16:52:27 +02:00
|
|
|
def extract_nestedly(to: nil, basename: nil, verbose: false)
|
2018-07-16 19:00:49 +02:00
|
|
|
Dir.mktmpdir do |tmp_unpack_dir|
|
|
|
|
tmp_unpack_dir = Pathname(tmp_unpack_dir)
|
|
|
|
|
2018-07-21 16:52:27 +02:00
|
|
|
extract(to: tmp_unpack_dir, basename: basename, verbose: verbose)
|
2018-07-16 19:00:49 +02:00
|
|
|
|
|
|
|
children = tmp_unpack_dir.children
|
|
|
|
|
2018-07-16 20:10:22 +02:00
|
|
|
if children.count == 1 && !children.first.directory?
|
2018-07-23 20:59:21 +02:00
|
|
|
s = UnpackStrategy.detect(children.first)
|
2018-07-16 19:00:49 +02:00
|
|
|
|
2018-07-21 16:52:27 +02:00
|
|
|
s.extract_nestedly(to: to, verbose: verbose)
|
2018-07-16 19:00:49 +02:00
|
|
|
next
|
|
|
|
end
|
|
|
|
|
2018-07-23 20:59:21 +02:00
|
|
|
Directory.new(tmp_unpack_dir).extract(to: to, verbose: verbose)
|
2018-07-16 19:00:49 +02:00
|
|
|
end
|
|
|
|
end
|
2018-07-01 23:35:29 +02:00
|
|
|
end
|
|
|
|
|
2018-07-23 20:59:21 +02:00
|
|
|
require "unpack_strategy/bazaar"
|
|
|
|
require "unpack_strategy/bzip2"
|
|
|
|
require "unpack_strategy/compress"
|
|
|
|
require "unpack_strategy/cvs"
|
|
|
|
require "unpack_strategy/directory"
|
|
|
|
require "unpack_strategy/fossil"
|
|
|
|
require "unpack_strategy/git"
|
|
|
|
require "unpack_strategy/gzip"
|
|
|
|
require "unpack_strategy/jar"
|
|
|
|
require "unpack_strategy/lha"
|
|
|
|
require "unpack_strategy/lua_rock"
|
|
|
|
require "unpack_strategy/lzip"
|
|
|
|
require "unpack_strategy/mercurial"
|
|
|
|
require "unpack_strategy/microsoft_office_xml"
|
|
|
|
require "unpack_strategy/p7zip"
|
|
|
|
require "unpack_strategy/rar"
|
|
|
|
require "unpack_strategy/subversion"
|
|
|
|
require "unpack_strategy/tar"
|
|
|
|
require "unpack_strategy/uncompressed"
|
|
|
|
require "unpack_strategy/xar"
|
|
|
|
require "unpack_strategy/xz"
|
|
|
|
require "unpack_strategy/zip"
|