unpack_strategy: add zstd
This commit is contained in:
parent
109f24fd60
commit
fe9a039774
@ -81,6 +81,10 @@ class DependencyCollector
|
||||
Dependency.new("xz", tags) unless which("xz")
|
||||
end
|
||||
|
||||
def zstd_dep_if_needed(tags)
|
||||
Dependency.new("zstd", tags) unless which("zstd")
|
||||
end
|
||||
|
||||
def unzip_dep_if_needed(tags)
|
||||
Dependency.new("unzip", tags) unless which("unzip")
|
||||
end
|
||||
@ -171,6 +175,7 @@ class DependencyCollector
|
||||
def parse_url_spec(url, tags)
|
||||
case File.extname(url)
|
||||
when ".xz" then xz_dep_if_needed(tags)
|
||||
when ".zst" then zstd_dep_if_needed(tags)
|
||||
when ".zip" then unzip_dep_if_needed(tags)
|
||||
when ".bz2" then bzip2_dep_if_needed(tags)
|
||||
when ".lha", ".lzh" then Dependency.new("lha", tags)
|
||||
|
@ -231,7 +231,7 @@ class Pathname
|
||||
bottle_ext, = HOMEBREW_BOTTLES_EXTNAME_REGEX.match(basename).to_a
|
||||
return bottle_ext if bottle_ext
|
||||
|
||||
archive_ext = basename[/(\.(tar|cpio|pax)\.(gz|bz2|lz|xz|Z))\Z/, 1]
|
||||
archive_ext = basename[/(\.(tar|cpio|pax)\.(gz|bz2|lz|xz|zst|Z))\Z/, 1]
|
||||
return archive_ext if archive_ext
|
||||
|
||||
# Don't treat version numbers as extname.
|
||||
|
BIN
Library/Homebrew/test/support/fixtures/cask/container.tar.zst
Normal file
BIN
Library/Homebrew/test/support/fixtures/cask/container.tar.zst
Normal file
Binary file not shown.
10
Library/Homebrew/test/unpack_strategy/zstd_spec.rb
Normal file
10
Library/Homebrew/test/unpack_strategy/zstd_spec.rb
Normal file
@ -0,0 +1,10 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "shared_examples"
|
||||
|
||||
describe UnpackStrategy::Zstd do
|
||||
let(:path) { TEST_FIXTURE_DIR/"cask/container.tar.zst" }
|
||||
|
||||
include_examples "UnpackStrategy::detect"
|
||||
end
|
@ -44,12 +44,13 @@ module UnpackStrategy
|
||||
|
||||
def self.strategies
|
||||
@strategies ||= [
|
||||
Tar, # Needs to be before Bzip2/Gzip/Xz/Lzma.
|
||||
Tar, # Needs to be before Bzip2/Gzip/Xz/Lzma/Zstd.
|
||||
Pax,
|
||||
Gzip,
|
||||
Dmg, # Needs to be before Bzip2/Xz/Lzma.
|
||||
Lzma,
|
||||
Xz,
|
||||
Zstd,
|
||||
Lzip,
|
||||
Air, # Needs to be before `Zip`.
|
||||
Jar, # Needs to be before `Zip`.
|
||||
@ -203,3 +204,4 @@ require "unpack_strategy/uncompressed"
|
||||
require "unpack_strategy/xar"
|
||||
require "unpack_strategy/xz"
|
||||
require "unpack_strategy/zip"
|
||||
require "unpack_strategy/zstd"
|
||||
|
@ -20,14 +20,15 @@ module UnpackStrategy
|
||||
".tbz", ".tbz2", ".tar.bz2",
|
||||
".tgz", ".tar.gz",
|
||||
".tlzma", ".tar.lzma",
|
||||
".txz", ".tar.xz"
|
||||
".txz", ".tar.xz",
|
||||
".tar.zst"
|
||||
]
|
||||
end
|
||||
|
||||
def self.can_extract?(path)
|
||||
return true if path.magic_number.match?(/\A.{257}ustar/n)
|
||||
|
||||
return false unless [Bzip2, Gzip, Lzip, Xz].any? { |s| s.can_extract?(path) }
|
||||
return false unless [Bzip2, Gzip, Lzip, Xz, Zstd].any? { |s| s.can_extract?(path) }
|
||||
|
||||
# Check if `tar` can list the contents, then it can also extract it.
|
||||
stdout, _, status = system_command("tar", args: ["--list", "--file", path], print_stderr: false)
|
||||
@ -39,12 +40,12 @@ module UnpackStrategy
|
||||
sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) }
|
||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||
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, verbose: verbose)
|
||||
tar_path = tmpdir.children.first
|
||||
tar_path = if DependencyCollector.tar_needs_xz_dependency? && Xz.can_extract?(path)
|
||||
subextract(Xz, Pathname(tmpdir), verbose)
|
||||
elsif Zstd.can_extract?(path)
|
||||
subextract(Zstd, Pathname(tmpdir), verbose)
|
||||
else
|
||||
path
|
||||
end
|
||||
|
||||
system_command! "tar",
|
||||
@ -54,5 +55,13 @@ module UnpackStrategy
|
||||
verbose: verbose
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(extractor: T.any(T.class_of(Xz), T.class_of(Zstd)), dir: Pathname, verbose: T::Boolean).returns(Pathname)
|
||||
}
|
||||
def subextract(extractor, dir, verbose)
|
||||
extractor.new(path).extract(to: dir, verbose: verbose)
|
||||
T.must(dir.children.first)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
38
Library/Homebrew/unpack_strategy/zstd.rb
Normal file
38
Library/Homebrew/unpack_strategy/zstd.rb
Normal file
@ -0,0 +1,38 @@
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
module UnpackStrategy
|
||||
# Strategy for unpacking zstd archives.
|
||||
class Zstd
|
||||
extend T::Sig
|
||||
|
||||
include UnpackStrategy
|
||||
|
||||
using Magic
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def self.extensions
|
||||
[".zst"]
|
||||
end
|
||||
|
||||
def self.can_extract?(path)
|
||||
path.magic_number.match?(/\x28\xB5\x2F\xFD/n)
|
||||
end
|
||||
|
||||
def dependencies
|
||||
@dependencies ||= [Formula["zstd"]]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) }
|
||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||
FileUtils.cp path, unpack_dir/basename, preserve: true
|
||||
quiet_flags = verbose ? [] : ["-q"]
|
||||
system_command! "unzstd",
|
||||
args: [*quiet_flags, "-T0", "--", unpack_dir/basename],
|
||||
env: { "PATH" => PATH.new(Formula["zstd"].opt_bin, ENV["PATH"]) },
|
||||
verbose: verbose
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user