Merge pull request #4552 from reitermarkus/reorder-unpack-strategies
Reorder unpack strategies.
This commit is contained in:
commit
4183dd3564
@ -47,8 +47,11 @@ class AbstractDownloadStrategy
|
|||||||
# chdir into the newly-unpacked directory.
|
# chdir into the newly-unpacked directory.
|
||||||
# Unlike {Resource#stage}, this does not take a block.
|
# Unlike {Resource#stage}, this does not take a block.
|
||||||
def stage
|
def stage
|
||||||
UnpackStrategy.detect(cached_location, ref_type: @ref_type, ref: @ref)
|
UnpackStrategy.detect(cached_location,
|
||||||
|
extension_only: true,
|
||||||
|
ref_type: @ref_type, ref: @ref)
|
||||||
.extract_nestedly(basename: basename_without_params,
|
.extract_nestedly(basename: basename_without_params,
|
||||||
|
extension_only: true,
|
||||||
verbose: ARGV.verbose? && !shutup)
|
verbose: ARGV.verbose? && !shutup)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,36 +1,60 @@
|
|||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
|
module Magic
|
||||||
# length of the longest regex (currently Tar)
|
# length of the longest regex (currently Tar)
|
||||||
MAX_MAGIC_NUMBER_LENGTH = 262
|
MAX_MAGIC_NUMBER_LENGTH = 262
|
||||||
private_constant :MAX_MAGIC_NUMBER_LENGTH
|
|
||||||
|
refine Pathname do
|
||||||
|
def magic_number
|
||||||
|
@magic_number ||= if directory?
|
||||||
|
""
|
||||||
|
else
|
||||||
|
binread(MAX_MAGIC_NUMBER_LENGTH) || ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_type
|
||||||
|
@file_type ||= system_command("file", args: ["-b", self], print_stderr: false)
|
||||||
|
.stdout.chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
def zipinfo
|
||||||
|
@zipinfo ||= system_command("zipinfo", args: ["-1", self], print_stderr: false)
|
||||||
|
.stdout
|
||||||
|
.encode(Encoding::UTF_8, invalid: :replace)
|
||||||
|
.split("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private_constant :Magic
|
||||||
|
|
||||||
def self.strategies
|
def self.strategies
|
||||||
@strategies ||= [
|
@strategies ||= [
|
||||||
Pkg,
|
Tar, # needs to be before Bzip2/Gzip/Xz/Lzma
|
||||||
Ttf,
|
|
||||||
Otf,
|
|
||||||
Air,
|
|
||||||
Executable,
|
|
||||||
SelfExtractingExecutable,
|
|
||||||
Jar,
|
|
||||||
LuaRock,
|
|
||||||
MicrosoftOfficeXml,
|
|
||||||
Zip,
|
|
||||||
Dmg,
|
|
||||||
Xar,
|
|
||||||
Compress,
|
|
||||||
Tar,
|
|
||||||
Bzip2,
|
|
||||||
Gzip,
|
Gzip,
|
||||||
Lzma,
|
Lzma,
|
||||||
Xz,
|
Xz,
|
||||||
Lzip,
|
Lzip,
|
||||||
|
Air, # needs to be before Zip
|
||||||
|
Jar, # needs to be before Zip
|
||||||
|
LuaRock, # needs to be before Zip
|
||||||
|
MicrosoftOfficeXml, # needs to be before Zip
|
||||||
|
Zip,
|
||||||
|
Pkg, # needs to be before Xar
|
||||||
|
Xar,
|
||||||
|
Ttf,
|
||||||
|
Otf,
|
||||||
Git,
|
Git,
|
||||||
Mercurial,
|
Mercurial,
|
||||||
Subversion,
|
Subversion,
|
||||||
Cvs,
|
Cvs,
|
||||||
|
SelfExtractingExecutable, # needs to be before Cab
|
||||||
|
Cab,
|
||||||
|
Executable,
|
||||||
|
Dmg, # needs to be before Bzip2
|
||||||
|
Bzip2,
|
||||||
Fossil,
|
Fossil,
|
||||||
Bazaar,
|
Bazaar,
|
||||||
Cab,
|
Compress,
|
||||||
P7Zip,
|
P7Zip,
|
||||||
Sit,
|
Sit,
|
||||||
Rar,
|
Rar,
|
||||||
@ -42,6 +66,7 @@ module UnpackStrategy
|
|||||||
def self.from_type(type)
|
def self.from_type(type)
|
||||||
type = {
|
type = {
|
||||||
naked: :uncompressed,
|
naked: :uncompressed,
|
||||||
|
nounzip: :uncompressed,
|
||||||
seven_zip: :p7zip,
|
seven_zip: :p7zip,
|
||||||
}.fetch(type, type)
|
}.fetch(type, type)
|
||||||
|
|
||||||
@ -52,32 +77,30 @@ module UnpackStrategy
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_path(path)
|
def self.from_extension(extension)
|
||||||
magic_number = if path.directory?
|
strategies.sort_by { |s| s.extensions.map(&:length).max(0) }
|
||||||
""
|
.reverse
|
||||||
|
.detect { |s| s.extensions.any? { |ext| extension.end_with?(ext) } }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.from_magic(path)
|
||||||
|
strategies.detect { |s| s.can_extract?(path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.detect(path, extension_only: false, type: nil, ref_type: nil, ref: nil)
|
||||||
|
strategy = from_type(type) if type
|
||||||
|
|
||||||
|
if extension_only
|
||||||
|
strategy ||= from_extension(path.extname)
|
||||||
|
strategy ||= strategies.select { |s| s < Directory || s == Fossil }
|
||||||
|
.detect { |s| s.can_extract?(path) }
|
||||||
else
|
else
|
||||||
File.binread(path, MAX_MAGIC_NUMBER_LENGTH) || ""
|
strategy ||= from_magic(path)
|
||||||
|
strategy ||= from_extension(path.extname)
|
||||||
end
|
end
|
||||||
|
|
||||||
strategy = strategies.detect do |s|
|
strategy ||= Uncompressed
|
||||||
s.can_extract?(path: path, magic_number: magic_number)
|
|
||||||
end
|
|
||||||
|
|
||||||
# This is so that bad files produce good error messages.
|
|
||||||
strategy ||= case path.extname
|
|
||||||
when ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz", ".tar.xz", ".txz"
|
|
||||||
Tar
|
|
||||||
when ".zip"
|
|
||||||
Zip
|
|
||||||
else
|
|
||||||
Uncompressed
|
|
||||||
end
|
|
||||||
|
|
||||||
strategy
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.detect(path, type: nil, ref_type: nil, ref: nil)
|
|
||||||
strategy = type ? from_type(type) : from_path(path)
|
|
||||||
strategy.new(path, ref_type: ref_type, ref: ref)
|
strategy.new(path, ref_type: ref_type, ref: ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -96,7 +119,7 @@ module UnpackStrategy
|
|||||||
extract_to_dir(unpack_dir, basename: basename, verbose: verbose)
|
extract_to_dir(unpack_dir, basename: basename, verbose: verbose)
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_nestedly(to: nil, basename: nil, verbose: false)
|
def extract_nestedly(to: nil, basename: nil, verbose: false, extension_only: false)
|
||||||
Dir.mktmpdir do |tmp_unpack_dir|
|
Dir.mktmpdir do |tmp_unpack_dir|
|
||||||
tmp_unpack_dir = Pathname(tmp_unpack_dir)
|
tmp_unpack_dir = Pathname(tmp_unpack_dir)
|
||||||
|
|
||||||
@ -105,9 +128,9 @@ module UnpackStrategy
|
|||||||
children = tmp_unpack_dir.children
|
children = tmp_unpack_dir.children
|
||||||
|
|
||||||
if children.count == 1 && !children.first.directory?
|
if children.count == 1 && !children.first.directory?
|
||||||
s = UnpackStrategy.detect(children.first)
|
s = UnpackStrategy.detect(children.first, extension_only: extension_only)
|
||||||
|
|
||||||
s.extract_nestedly(to: to, verbose: verbose)
|
s.extract_nestedly(to: to, verbose: verbose, extension_only: extension_only)
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,15 @@ module UnpackStrategy
|
|||||||
class Air
|
class Air
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
path.extname == ".air"
|
|
||||||
|
def self.extensions
|
||||||
|
[".air"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
mime_type = "application/vnd.adobe.air-application-installer-package+zip"
|
||||||
|
path.magic_number.match?(/.{59}#{Regexp.escape(mime_type)}/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
|
|||||||
@ -2,7 +2,9 @@ require_relative "directory"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Bazaar < Directory
|
class Bazaar < Directory
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
super && (path/".bzr").directory?
|
super && (path/".bzr").directory?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Bzip2
|
class Bzip2
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\ABZh/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".bz2"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\ABZh/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Cab
|
class Cab
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\AMSCF/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".cab"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\AMSCF/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||||
|
|||||||
@ -2,8 +2,14 @@ require_relative "tar"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Compress < Tar
|
class Compress < Tar
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A\037\235/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".compress"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A\037\235/n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,7 +2,9 @@ require_relative "directory"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Cvs < Directory
|
class Cvs < Directory
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
super && (path/"CVS").directory?
|
super && (path/"CVS").directory?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,7 +2,13 @@ module UnpackStrategy
|
|||||||
class Directory
|
class Directory
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.extensions
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
path.directory?
|
path.directory?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ module UnpackStrategy
|
|||||||
class Dmg
|
class Dmg
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
|
using Magic
|
||||||
|
|
||||||
module Bom
|
module Bom
|
||||||
DMG_METADATA = Set.new %w[
|
DMG_METADATA = Set.new %w[
|
||||||
.background
|
.background
|
||||||
@ -83,12 +85,18 @@ module UnpackStrategy
|
|||||||
end
|
end
|
||||||
|
|
||||||
system_command! "ditto", args: ["--bom", bomfile.path, "--", path, unpack_dir]
|
system_command! "ditto", args: ["--bom", bomfile.path, "--", path, unpack_dir]
|
||||||
|
|
||||||
|
FileUtils.chmod "u+w", Pathname.glob(unpack_dir/"**/*").reject(&:symlink?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
private_constant :Mount
|
private_constant :Mount
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
def self.extensions
|
||||||
|
[".dmg"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
imageinfo = system_command("hdiutil",
|
imageinfo = system_command("hdiutil",
|
||||||
args: ["imageinfo", path],
|
args: ["imageinfo", path],
|
||||||
print_stderr: false).stdout
|
print_stderr: false).stdout
|
||||||
|
|||||||
@ -2,8 +2,15 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Executable < Uncompressed
|
class Executable < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A#!\s*\S+/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".sh", ".bash"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A#!\s*\S+/n) ||
|
||||||
|
path.magic_number.match?(/\AMZ/n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Fossil
|
class Fossil
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return false unless magic_number.match?(/\ASQLite format 3\000/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
return false unless path.magic_number.match?(/\ASQLite format 3\000/n)
|
||||||
|
|
||||||
# Fossil database is made up of artifacts, so the `artifact` table must exist.
|
# Fossil database is made up of artifacts, so the `artifact` table must exist.
|
||||||
query = "select count(*) from sqlite_master where type = 'view' and name = 'artifact'"
|
query = "select count(*) from sqlite_master where type = 'view' and name = 'artifact'"
|
||||||
|
|||||||
@ -2,7 +2,13 @@ module UnpackStrategy
|
|||||||
class GenericUnar
|
class GenericUnar
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.extensions
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(_path)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,9 @@ require_relative "directory"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Git < Directory
|
class Git < Directory
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
super && (path/".git").directory?
|
super && (path/".git").directory?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Gzip
|
class Gzip
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A\037\213/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".gz"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A\037\213/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -2,14 +2,17 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Jar < Uncompressed
|
class Jar < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return false unless Zip.can_extract?(path: path, magic_number: magic_number)
|
|
||||||
|
def self.extensions
|
||||||
|
[".apk", ".jar"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
return false unless Zip.can_extract?(path)
|
||||||
|
|
||||||
# Check further if the ZIP is a JAR/WAR.
|
# Check further if the ZIP is a JAR/WAR.
|
||||||
out, = Open3.capture3("zipinfo", "-1", path)
|
path.zipinfo.include?("META-INF/MANIFEST.MF")
|
||||||
out.encode(Encoding::UTF_8, invalid: :replace)
|
|
||||||
.split("\n")
|
|
||||||
.include?("META-INF/MANIFEST.MF")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Lha
|
class Lha
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A..-(lh0|lh1|lz4|lz5|lzs|lh\\40|lhd|lh2|lh3|lh4|lh5)-/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".lha", ".lzh"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A..-(lh0|lh1|lz4|lz5|lzs|lh\\40|lhd|lh2|lh3|lh4|lh5)-/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
|
|||||||
@ -2,14 +2,17 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class LuaRock < Uncompressed
|
class LuaRock < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return false unless Zip.can_extract?(path: path, magic_number: magic_number)
|
|
||||||
|
def self.extensions
|
||||||
|
[".rock"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
return false unless Zip.can_extract?(path)
|
||||||
|
|
||||||
# Check further if the ZIP is a LuaRocks package.
|
# Check further if the ZIP is a LuaRocks package.
|
||||||
out, = Open3.capture3("zipinfo", "-1", path)
|
path.zipinfo.grep(%r{\A[^/]+.rockspec\Z}).any?
|
||||||
out.encode(Encoding::UTF_8, invalid: :replace)
|
|
||||||
.split("\n")
|
|
||||||
.any? { |line| line.match?(%r{\A[^/]+.rockspec\Z}) }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Lzip
|
class Lzip
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\ALZIP/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".lz"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\ALZIP/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Lzma
|
class Lzma
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A\]\000\000\200\000/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".lzma"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A\]\000\000\200\000/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||||
|
|||||||
@ -2,7 +2,9 @@ require_relative "directory"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Mercurial < Directory
|
class Mercurial < Directory
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
super && (path/".hg").directory?
|
super && (path/".hg").directory?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,22 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class MicrosoftOfficeXml < Uncompressed
|
class MicrosoftOfficeXml < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return false unless Zip.can_extract?(path: path, magic_number: magic_number)
|
|
||||||
|
def self.extensions
|
||||||
|
[
|
||||||
|
".doc", ".docx",
|
||||||
|
".ppt", ".pptx",
|
||||||
|
".xls", ".xlsx"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
return false unless Zip.can_extract?(path)
|
||||||
|
|
||||||
# Check further if the ZIP is a Microsoft Office XML document.
|
# Check further if the ZIP is a Microsoft Office XML document.
|
||||||
magic_number.match?(/\APK\003\004/n) &&
|
path.magic_number.match?(/\APK\003\004/n) &&
|
||||||
magic_number.match?(%r{\A.{30}(\[Content_Types\]\.xml|_rels/\.rels)}n)
|
path.magic_number.match?(%r{\A.{30}(\[Content_Types\]\.xml|_rels/\.rels)}n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Otf < Uncompressed
|
class Otf < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\AOTTO/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".otf"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\AOTTO/n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class P7Zip
|
class P7Zip
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A7z\xBC\xAF\x27\x1C/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".7z"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A7z\xBC\xAF\x27\x1C/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
|
|||||||
@ -2,9 +2,15 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Pkg < Uncompressed
|
class Pkg < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.extensions
|
||||||
|
[".pkg", ".mkpg"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
path.extname.match?(/\A.m?pkg\Z/) &&
|
path.extname.match?(/\A.m?pkg\Z/) &&
|
||||||
(path.directory? || magic_number.match?(/\Axar!/n))
|
(path.directory? || path.magic_number.match?(/\Axar!/n))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Rar
|
class Rar
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\ARar!/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".rar"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\ARar!/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
|
|||||||
@ -2,12 +2,15 @@ require_relative "generic_unar"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class SelfExtractingExecutable < GenericUnar
|
class SelfExtractingExecutable < GenericUnar
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return false unless magic_number.match?(/\AMZ/n)
|
|
||||||
|
|
||||||
system_command("file",
|
def self.extensions
|
||||||
args: [path],
|
[]
|
||||||
print_stderr: false).stdout.include?("self-extracting")
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\AMZ/n) &&
|
||||||
|
path.file_type.include?("self-extracting archive")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ require_relative "generic_unar"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Sit < GenericUnar
|
class Sit < GenericUnar
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\AStuffIt/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".sit"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\AStuffIt/n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,7 +2,9 @@ require_relative "directory"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Subversion < Directory
|
class Subversion < Directory
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
super && (path/".svn").directory?
|
super && (path/".svn").directory?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,24 @@ module UnpackStrategy
|
|||||||
class Tar
|
class Tar
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
return true if magic_number.match?(/\A.{257}ustar/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[
|
||||||
|
".tar",
|
||||||
|
".tbz", ".tbz2", ".tar.bz2",
|
||||||
|
".tgz", ".tar.gz",
|
||||||
|
".tlz", ".tar.lz",
|
||||||
|
".txz", ".tar.xz"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
return true if path.magic_number.match?(/\A.{257}ustar/n)
|
||||||
|
|
||||||
|
unless [Bzip2, Gzip, Lzip, Xz].any? { |s| s.can_extract?(path) }
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
# Check if `tar` can list the contents, then it can also extract it.
|
# Check if `tar` can list the contents, then it can also extract it.
|
||||||
IO.popen(["tar", "tf", path], err: File::NULL) do |stdout|
|
IO.popen(["tar", "tf", path], err: File::NULL) do |stdout|
|
||||||
@ -14,7 +30,17 @@ module UnpackStrategy
|
|||||||
private
|
private
|
||||||
|
|
||||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||||
system_command! "tar", args: ["xf", path, "-C", unpack_dir]
|
Dir.mktmpdir do |tmpdir|
|
||||||
|
tar_path = path
|
||||||
|
|
||||||
|
if DependencyCollector.tar_needs_xz_dependency? && Xz.can_extract?(path)
|
||||||
|
tmpdir = Pathname(tmpdir)
|
||||||
|
Xz.new(path).extract(to: tmpdir)
|
||||||
|
tar_path = tmpdir.children.first
|
||||||
|
end
|
||||||
|
|
||||||
|
system_command! "tar", args: ["xf", tar_path, "-C", unpack_dir]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,11 +2,17 @@ require_relative "uncompressed"
|
|||||||
|
|
||||||
module UnpackStrategy
|
module UnpackStrategy
|
||||||
class Ttf < Uncompressed
|
class Ttf < Uncompressed
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
|
|
||||||
|
def self.extensions
|
||||||
|
[".ttc", ".ttf"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
# TrueType Font
|
# TrueType Font
|
||||||
magic_number.match?(/\A\000\001\000\000\000/n) ||
|
path.magic_number.match?(/\A\000\001\000\000\000/n) ||
|
||||||
# Truetype Font Collection
|
# Truetype Font Collection
|
||||||
magic_number.match?(/\Attcf/n)
|
path.magic_number.match?(/\Attcf/n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,7 +2,9 @@ module UnpackStrategy
|
|||||||
class Uncompressed
|
class Uncompressed
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
alias extract_nestedly extract
|
def extract_nestedly(extension_only: false, **options)
|
||||||
|
extract(**options)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Xar
|
class Xar
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\Axar!/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".xar"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\Axar!/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Xz
|
class Xz
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\A\xFD7zXZ\x00/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".xz"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\A\xFD7zXZ\x00/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
def dependencies
|
||||||
@ -18,19 +24,6 @@ module UnpackStrategy
|
|||||||
system_command! "unxz",
|
system_command! "unxz",
|
||||||
args: [*quiet_flags, "-T0", "--", unpack_dir/basename],
|
args: [*quiet_flags, "-T0", "--", unpack_dir/basename],
|
||||||
env: { "PATH" => PATH.new(Formula["xz"].opt_bin, ENV["PATH"]) }
|
env: { "PATH" => PATH.new(Formula["xz"].opt_bin, ENV["PATH"]) }
|
||||||
extract_nested_tar(unpack_dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
def extract_nested_tar(unpack_dir)
|
|
||||||
return unless DependencyCollector.tar_needs_xz_dependency?
|
|
||||||
return if (children = unpack_dir.children).count != 1
|
|
||||||
return if (tar = children.first).extname != ".tar"
|
|
||||||
|
|
||||||
Dir.mktmpdir do |tmpdir|
|
|
||||||
tmpdir = Pathname(tmpdir)
|
|
||||||
FileUtils.mv tar, tmpdir/tar.basename
|
|
||||||
Tar.new(tmpdir/tar.basename).extract(to: unpack_dir)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,8 +2,14 @@ module UnpackStrategy
|
|||||||
class Zip
|
class Zip
|
||||||
include UnpackStrategy
|
include UnpackStrategy
|
||||||
|
|
||||||
def self.can_extract?(path:, magic_number:)
|
using Magic
|
||||||
magic_number.match?(/\APK(\003\004|\005\006)/n)
|
|
||||||
|
def self.extensions
|
||||||
|
[".zip"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_extract?(path)
|
||||||
|
path.magic_number.match?(/\APK(\003\004|\005\006)/n)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user