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")
|
Dependency.new("xz", tags) unless which("xz")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def zstd_dep_if_needed(tags)
|
||||||
|
Dependency.new("zstd", tags) unless which("zstd")
|
||||||
|
end
|
||||||
|
|
||||||
def unzip_dep_if_needed(tags)
|
def unzip_dep_if_needed(tags)
|
||||||
Dependency.new("unzip", tags) unless which("unzip")
|
Dependency.new("unzip", tags) unless which("unzip")
|
||||||
end
|
end
|
||||||
@ -171,6 +175,7 @@ class DependencyCollector
|
|||||||
def parse_url_spec(url, tags)
|
def parse_url_spec(url, tags)
|
||||||
case File.extname(url)
|
case File.extname(url)
|
||||||
when ".xz" then xz_dep_if_needed(tags)
|
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 ".zip" then unzip_dep_if_needed(tags)
|
||||||
when ".bz2" then bzip2_dep_if_needed(tags)
|
when ".bz2" then bzip2_dep_if_needed(tags)
|
||||||
when ".lha", ".lzh" then Dependency.new("lha", 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
|
bottle_ext, = HOMEBREW_BOTTLES_EXTNAME_REGEX.match(basename).to_a
|
||||||
return bottle_ext if bottle_ext
|
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
|
return archive_ext if archive_ext
|
||||||
|
|
||||||
# Don't treat version numbers as extname.
|
# 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
|
def self.strategies
|
||||||
@strategies ||= [
|
@strategies ||= [
|
||||||
Tar, # Needs to be before Bzip2/Gzip/Xz/Lzma.
|
Tar, # Needs to be before Bzip2/Gzip/Xz/Lzma/Zstd.
|
||||||
Pax,
|
Pax,
|
||||||
Gzip,
|
Gzip,
|
||||||
Dmg, # Needs to be before Bzip2/Xz/Lzma.
|
Dmg, # Needs to be before Bzip2/Xz/Lzma.
|
||||||
Lzma,
|
Lzma,
|
||||||
Xz,
|
Xz,
|
||||||
|
Zstd,
|
||||||
Lzip,
|
Lzip,
|
||||||
Air, # Needs to be before `Zip`.
|
Air, # Needs to be before `Zip`.
|
||||||
Jar, # 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/xar"
|
||||||
require "unpack_strategy/xz"
|
require "unpack_strategy/xz"
|
||||||
require "unpack_strategy/zip"
|
require "unpack_strategy/zip"
|
||||||
|
require "unpack_strategy/zstd"
|
||||||
|
@ -20,14 +20,15 @@ module UnpackStrategy
|
|||||||
".tbz", ".tbz2", ".tar.bz2",
|
".tbz", ".tbz2", ".tar.bz2",
|
||||||
".tgz", ".tar.gz",
|
".tgz", ".tar.gz",
|
||||||
".tlzma", ".tar.lzma",
|
".tlzma", ".tar.lzma",
|
||||||
".txz", ".tar.xz"
|
".txz", ".tar.xz",
|
||||||
|
".tar.zst"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.can_extract?(path)
|
def self.can_extract?(path)
|
||||||
return true if path.magic_number.match?(/\A.{257}ustar/n)
|
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.
|
# 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)
|
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) }
|
sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) }
|
||||||
def extract_to_dir(unpack_dir, basename:, verbose:)
|
def extract_to_dir(unpack_dir, basename:, verbose:)
|
||||||
Dir.mktmpdir do |tmpdir|
|
Dir.mktmpdir do |tmpdir|
|
||||||
tar_path = path
|
tar_path = if DependencyCollector.tar_needs_xz_dependency? && Xz.can_extract?(path)
|
||||||
|
subextract(Xz, Pathname(tmpdir), verbose)
|
||||||
if DependencyCollector.tar_needs_xz_dependency? && Xz.can_extract?(path)
|
elsif Zstd.can_extract?(path)
|
||||||
tmpdir = Pathname(tmpdir)
|
subextract(Zstd, Pathname(tmpdir), verbose)
|
||||||
Xz.new(path).extract(to: tmpdir, verbose: verbose)
|
else
|
||||||
tar_path = tmpdir.children.first
|
path
|
||||||
end
|
end
|
||||||
|
|
||||||
system_command! "tar",
|
system_command! "tar",
|
||||||
@ -54,5 +55,13 @@ module UnpackStrategy
|
|||||||
verbose: verbose
|
verbose: verbose
|
||||||
end
|
end
|
||||||
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
|
||||||
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