diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index 5530683523..498c3bc885 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -10,7 +10,6 @@ require "hbc/caskroom" require "hbc/checkable" require "hbc/cli" require "hbc/cask_dependencies" -require "hbc/container" require "hbc/download" require "hbc/download_strategy" require "hbc/exceptions" @@ -18,7 +17,6 @@ require "hbc/installer" require "hbc/macos" require "hbc/pkg" require "hbc/staged" -require "system_command" require "hbc/topological_hash" require "hbc/utils" require "hbc/verify" diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb index 1cbe49cf27..df1bc9b6a8 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact.rb @@ -10,7 +10,6 @@ require "hbc/artifact/internet_plugin" require "hbc/artifact/audio_unit_plugin" require "hbc/artifact/vst_plugin" require "hbc/artifact/vst3_plugin" -require "hbc/artifact/nested_container" require "hbc/artifact/pkg" require "hbc/artifact/postflight_block" require "hbc/artifact/preflight_block" diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb index 0771054689..86643b90d4 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb @@ -29,9 +29,6 @@ module Hbc # The `uninstall` stanza should be run first, as it may # depend on other artifacts still being installed. Uninstall, - # We want to extract nested containers before we - # handle any other artifacts. - NestedContainer, Installer, [ App, diff --git a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb deleted file mode 100644 index 23ff9cc9b5..0000000000 --- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb +++ /dev/null @@ -1,36 +0,0 @@ -require "hbc/artifact/abstract_artifact" - -module Hbc - module Artifact - class NestedContainer < AbstractArtifact - attr_reader :path - - def initialize(cask, path) - super(cask) - @path = cask.staged_path.join(path) - end - - def install_phase(**options) - extract(**options) - end - - private - - def summarize - path.relative_path_from(cask.staged_path).to_s - end - - def extract(verbose: nil, **_) - container = Container.for_path(path) - - unless container - raise CaskError, "Aw dang, could not identify nested container at '#{source}'" - end - - ohai "Extracting nested container #{path.relative_path_from(cask.staged_path)}" - container.new(cask, path).extract(to: cask.staged_path, verbose: verbose) - FileUtils.remove_entry_secure(path) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 9ed6f68a96..4e9e489457 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -113,8 +113,7 @@ module Hbc end add_error "at least one name stanza is required" if cask.name.empty? # TODO: specific DSL knowledge should not be spread around in various files like this - # TODO: nested_container should not still be a pseudo-artifact at this point - installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap, :nested_container].include?(k) } + installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap].include?(k) } add_error "at least one activatable artifact stanza is required" if installable_artifacts.empty? end diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb deleted file mode 100644 index 8c5d2b4018..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container.rb +++ /dev/null @@ -1,79 +0,0 @@ -require "hbc/utils" - -require "hbc/container/base" -require "hbc/container/air" -require "hbc/container/bzip2" -require "hbc/container/cab" -require "hbc/container/dmg" -require "hbc/container/self_extracting_executable" -require "hbc/container/executable" -require "hbc/container/generic_unar" -require "hbc/container/gzip" -require "hbc/container/lzma" -require "hbc/container/naked" -require "hbc/container/otf" -require "hbc/container/pkg" -require "hbc/container/seven_zip" -require "hbc/container/sit" -require "hbc/container/svn_repository" -require "hbc/container/tar" -require "hbc/container/ttf" -require "hbc/container/rar" -require "hbc/container/xar" -require "hbc/container/xz" -require "hbc/container/zip" - -module Hbc - class Container - def self.autodetect_containers - [ - Pkg, - Ttf, - Otf, - Air, - SelfExtractingExecutable, - Cab, - Dmg, - SevenZip, - Sit, - Rar, - Zip, - Xar, # need to be before tar as tar can also list xar - Tar, # or compressed tar (bzip2/gzip/lzma/xz) - Bzip2, # pure bzip2 - Gzip, # pure gzip - Lzma, # pure lzma - Xz, # pure xz - Executable, - SvnRepository, - ] - # for explicit use only (never autodetected): - # Hbc::Container::Naked - # Hbc::Container::GenericUnar - end - - def self.for_path(path) - odebug "Determining which containers to use based on filetype" - - magic_number = if path.directory? - "" - else - File.binread(path, 262) || "" - end - - autodetect_containers.find do |c| - odebug "Checking container class #{c}" - c.can_extract?(path: path, magic_number: magic_number) - end - end - - def self.from_type(type) - odebug "Determining which containers to use based on 'container :type'" - begin - const_get(type.to_s.split("_").map(&:capitalize).join) - rescue NameError - nil - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/air.rb b/Library/Homebrew/cask/lib/hbc/container/air.rb deleted file mode 100644 index 71f9d63cb9..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/air.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Air < Base - def self.can_extract?(path:, magic_number:) - path.extname == ".air" - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!( - "/Applications/Utilities/Adobe AIR Application Installer.app/Contents/MacOS/Adobe AIR Application Installer", - args: ["-silent", "-location", unpack_dir, path], - ) - end - - def dependencies - @dependencies ||= [CaskLoader.load("adobe-air")] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/base.rb b/Library/Homebrew/cask/lib/hbc/container/base.rb deleted file mode 100644 index 192ae9cb78..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/base.rb +++ /dev/null @@ -1,54 +0,0 @@ -module Hbc - class Container - class Base - extend Predicable - - attr_reader :path - - def initialize(cask, path, nested: false) - @cask = cask - @path = path - end - - def extract(to: nil, basename: nil, verbose: false) - basename ||= path.basename - unpack_dir = Pathname(to || Dir.pwd).expand_path - unpack_dir.mkpath - extract_to_dir(unpack_dir, basename: basename, verbose: verbose) - end - - def extract_nested_inside(dir, to:, verbose: false) - children = Pathname.new(dir).children - - nested_container = children[0] - - unless children.count == 1 && - !nested_container.directory? && - @cask.artifacts.none? { |a| a.is_a?(Artifact::NestedContainer) } && - extract_nested_container(nested_container, to: to, verbose: verbose) - - children.each do |src| - dest = @cask.staged_path.join(src.basename) - FileUtils.rm_r(dest) if dest.exist? - FileUtils.mv(src, dest) - end - end - end - - def extract_nested_container(source, to:, verbose: false) - container = Container.for_path(source) - - return false unless container - - ohai "Extracting nested container #{source.basename}" - container.new(@cask, source).extract(to: to, verbose: verbose) - - true - end - - def dependencies - [] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb b/Library/Homebrew/cask/lib/hbc/container/bzip2.rb deleted file mode 100644 index 579fabb088..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Bzip2 < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\ABZh/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - Dir.mktmpdir do |tmp_unpack_dir| - tmp_unpack_dir = Pathname(tmp_unpack_dir) - - FileUtils.cp path, tmp_unpack_dir/basename, preserve: true - system_command!("bunzip2", args: ["--quiet", "--", tmp_unpack_dir/basename]) - - extract_nested_inside(tmp_unpack_dir, to: unpack_dir) - end - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/cab.rb b/Library/Homebrew/cask/lib/hbc/container/cab.rb deleted file mode 100644 index d88e0d96cd..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/cab.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Cab < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\A(MSCF|MZ)/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("cabextract", - args: ["-d", unpack_dir, "--", path], - env: { "PATH" => PATH.new(Formula["cabextract"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["cabextract"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/dmg.rb b/Library/Homebrew/cask/lib/hbc/container/dmg.rb deleted file mode 100644 index 1ce9845df6..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/dmg.rb +++ /dev/null @@ -1,152 +0,0 @@ -require "tempfile" - -require "hbc/container/base" - -module Hbc - class Container - class Dmg < Base - def self.can_extract?(path:, magic_number:) - imageinfo = system_command("/usr/bin/hdiutil", - # realpath is a failsafe against unusual filenames - args: ["imageinfo", path.realpath], - print_stderr: false).stdout - - !imageinfo.empty? - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - mount(verbose: verbose) do |mounts| - begin - raise "No mounts found in '#{path}'; perhaps it is a bad disk image?" if mounts.empty? - mounts.each do |mount| - extract_mount(mount, to: unpack_dir) - end - ensure - mounts.each(&method(:eject)) - end - end - end - - def mount(verbose: false) - # realpath is a failsafe against unusual filenames - realpath = path.realpath - path = realpath - - Dir.mktmpdir do |unpack_dir| - without_eula = system_command("/usr/bin/hdiutil", - args: ["attach", "-plist", "-nobrowse", "-readonly", "-noidme", "-mountrandom", unpack_dir, path], - input: "qn\n", - print_stderr: false) - - # If mounting without agreeing to EULA succeeded, there is none. - plist = if without_eula.success? - without_eula.plist - else - cdr_path = Pathname.new(unpack_dir).join("#{path.basename(".dmg")}.cdr") - - system_command!("/usr/bin/hdiutil", args: ["convert", "-quiet", "-format", "UDTO", "-o", cdr_path, path]) - - with_eula = system_command!("/usr/bin/hdiutil", - args: ["attach", "-plist", "-nobrowse", "-readonly", "-noidme", "-mountrandom", unpack_dir, cdr_path]) - - if verbose && !(eula_text = without_eula.stdout).empty? - ohai "Software License Agreement for '#{path}':" - puts eula_text - end - - with_eula.plist - end - - yield mounts_from_plist(plist) - end - end - - def eject(mount) - # realpath is a failsafe against unusual filenames - mountpath = Pathname.new(mount).realpath - - begin - tries ||= 3 - - return unless mountpath.exist? - - if tries > 1 - system_command!("/usr/sbin/diskutil", - args: ["eject", mountpath], - print_stderr: false) - else - system_command!("/usr/sbin/diskutil", - args: ["unmount", "force", mountpath], - print_stderr: false) - end - rescue ErrorDuringExecution => e - raise e if (tries -= 1).zero? - sleep 1 - retry - end - end - - private - - def extract_mount(mount, to:) - Tempfile.open(["", ".bom"]) do |bomfile| - bomfile.close - - Tempfile.open(["", ".list"]) do |filelist| - filelist.puts(bom_filelist_from_path(mount)) - filelist.close - - system_command!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) - system_command!("/usr/bin/ditto", args: ["--bom", bomfile.path, "--", mount, to]) - end - end - end - - def bom_filelist_from_path(mount) - # We need to use `find` here instead of Ruby in order to properly handle - # file names containing special characters, such as “e” + “´” vs. “é”. - system_command("/usr/bin/find", args: [".", "-print0"], chdir: mount, print_stderr: false) - .stdout - .split("\0") - .reject { |path| skip_path?(mount, path) } - .join("\n") - end - - def skip_path?(mount, path) - path = Pathname(path.sub(%r{\A\./}, "")) - dmg_metadata?(path) || system_dir_symlink?(mount, path) - end - - # unnecessary DMG metadata - DMG_METADATA_FILES = Set.new %w[ - .background - .com.apple.timemachine.donotpresent - .com.apple.timemachine.supported - .DocumentRevisions-V100 - .DS_Store - .fseventsd - .MobileBackups - .Spotlight-V100 - .TemporaryItems - .Trashes - .VolumeIcon.icns - ].freeze - - def dmg_metadata?(path) - relative_root = path.sub(%r{/.*}, "") - DMG_METADATA_FILES.include?(relative_root.basename.to_s) - end - - def system_dir_symlink?(mount, path) - full_path = Pathname(mount).join(path) - # symlinks to system directories (commonly to /Applications) - full_path.symlink? && MacOS.system_dir?(full_path.readlink) - end - - def mounts_from_plist(plist) - return [] unless plist.respond_to?(:fetch) - plist.fetch("system-entities", []).map { |e| e["mount-point"] }.compact - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/executable.rb b/Library/Homebrew/cask/lib/hbc/container/executable.rb deleted file mode 100644 index 4f2ebdcc97..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/executable.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "hbc/container/naked" -require "vendor/macho/macho" - -module Hbc - class Container - class Executable < Naked - def self.can_extract?(path:, magic_number:) - return true if magic_number.match?(/\A#!\s*\S+/n) - - begin - path.file? && MachO.open(path).header.executable? - rescue MachO::MagicError - false - end - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb b/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb deleted file mode 100644 index 0844057528..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class GenericUnar < Base - def self.can_extract?(path:, magic_number:) - false - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("unar", - args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", path], - env: { "PATH" => PATH.new(Formula["unar"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["unar"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/gzip.rb b/Library/Homebrew/cask/lib/hbc/container/gzip.rb deleted file mode 100644 index 5f1715eabf..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/gzip.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Gzip < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\A\037\213/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - Dir.mktmpdir do |tmp_unpack_dir| - tmp_unpack_dir = Pathname(tmp_unpack_dir) - - FileUtils.cp path, tmp_unpack_dir/basename, preserve: true - system_command!("gunzip", args: ["--quiet", "--name", "--", tmp_unpack_dir/basename]) - - extract_nested_inside(tmp_unpack_dir, to: unpack_dir) - end - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/lzma.rb b/Library/Homebrew/cask/lib/hbc/container/lzma.rb deleted file mode 100644 index 0f656bfe68..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/lzma.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Lzma < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\A\]\000\000\200\000/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("/usr/bin/ditto", args: ["--", path, unpack_dir]) - system_command!("unlzma", - args: ["-q", "--", Pathname(unpack_dir).join(basename)], - env: { "PATH" => PATH.new(Formula["unlzma"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["unlzma"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/naked.rb b/Library/Homebrew/cask/lib/hbc/container/naked.rb deleted file mode 100644 index 680ca45f89..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/naked.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Naked < Base - def self.can_extract?(path:, magic_number:) - false - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("/usr/bin/ditto", args: ["--", path, unpack_dir/basename]) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/otf.rb b/Library/Homebrew/cask/lib/hbc/container/otf.rb deleted file mode 100644 index d8aa9dbcbe..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/otf.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "hbc/container/naked" - -module Hbc - class Container - class Otf < Naked - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\AOTTO/n) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/pkg.rb b/Library/Homebrew/cask/lib/hbc/container/pkg.rb deleted file mode 100644 index 98f250c949..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/pkg.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "hbc/container/naked" - -module Hbc - class Container - class Pkg < Naked - def self.can_extract?(path:, magic_number:) - path.extname.match?(/\A.m?pkg\Z/) && - (path.directory? || magic_number.match?(/\Axar!/n)) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/rar.rb b/Library/Homebrew/cask/lib/hbc/container/rar.rb deleted file mode 100644 index 27bb0def4b..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/rar.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Rar < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\ARar!/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("unrar", - args: ["x", "-inul", path, unpack_dir], - env: { "PATH" => PATH.new(Formula["unrar"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["unrar"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/self_extracting_executable.rb b/Library/Homebrew/cask/lib/hbc/container/self_extracting_executable.rb deleted file mode 100644 index e620c510d3..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/self_extracting_executable.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "hbc/container/generic_unar" - -module Hbc - class Container - class SelfExtractingExecutable < GenericUnar - def self.can_extract?(path:, magic_number:) - return false unless magic_number.match?(/\AMZ/n) - - SystemCommand.run("file", - args: [path], - print_stderr: false).stdout.include?("self-extracting") - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb b/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb deleted file mode 100644 index 876b647a4f..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class SevenZip < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\A7z\xBC\xAF\x27\x1C/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("7zr", - args: ["x", "-y", "-bd", "-bso0", path, "-o#{unpack_dir}"], - env: { "PATH" => PATH.new(Formula["p7zip"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["p7zip"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/sit.rb b/Library/Homebrew/cask/lib/hbc/container/sit.rb deleted file mode 100644 index 3a22b48ab9..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/sit.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "hbc/container/generic_unar" - -module Hbc - class Container - class Sit < GenericUnar - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\AStuffIt/n) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/svn_repository.rb b/Library/Homebrew/cask/lib/hbc/container/svn_repository.rb deleted file mode 100644 index 16fc13cc4d..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/svn_repository.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Hbc - class Container - class SvnRepository < Base - def self.can_extract?(path:, magic_number:) - (path/".svn").directory? - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("svn", args: ["export", "--force", path, unpack_dir]) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/tar.rb b/Library/Homebrew/cask/lib/hbc/container/tar.rb deleted file mode 100644 index 8f40a54cdd..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/tar.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Tar < Base - def self.can_extract?(path:, magic_number:) - return true if magic_number.match?(/\A.{257}ustar/n) - - # Check if `tar` can list the contents, then it can also extract it. - IO.popen(["tar", "tf", path], err: File::NULL) do |stdout| - !stdout.read(1).nil? - end - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("tar", args: ["xf", path, "-C", unpack_dir]) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/ttf.rb b/Library/Homebrew/cask/lib/hbc/container/ttf.rb deleted file mode 100644 index 3a64c796a2..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/ttf.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "hbc/container/naked" - -module Hbc - class Container - class Ttf < Naked - def self.can_extract?(path:, magic_number:) - # TrueType Font - magic_number.match?(/\A\000\001\000\000\000/n) || - # Truetype Font Collection - magic_number.match?(/\Attcf/n) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/xar.rb b/Library/Homebrew/cask/lib/hbc/container/xar.rb deleted file mode 100644 index b688a8f542..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/xar.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Xar < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\Axar!/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("xar", args: ["-x", "-f", @path, "-C", unpack_dir]) - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/xz.rb b/Library/Homebrew/cask/lib/hbc/container/xz.rb deleted file mode 100644 index c5b00ecfb7..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/xz.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Xz < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\A\xFD7zXZ\x00/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - system_command!("/usr/bin/ditto", args: ["--", path, unpack_dir]) - system_command!("unxz", - args: ["-q", "--", unpack_dir/basename], - env: { "PATH" => PATH.new(Formula["xz"].opt_bin, ENV["PATH"]) }) - end - - def dependencies - @dependencies ||= [Formula["xz"]] - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/container/zip.rb b/Library/Homebrew/cask/lib/hbc/container/zip.rb deleted file mode 100644 index 98afd0f838..0000000000 --- a/Library/Homebrew/cask/lib/hbc/container/zip.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "hbc/container/base" - -module Hbc - class Container - class Zip < Base - def self.can_extract?(path:, magic_number:) - magic_number.match?(/\APK(\003\004|\005\006)/n) - end - - def extract_to_dir(unpack_dir, basename:, verbose:) - Dir.mktmpdir do |tmp_unpack_dir| - system_command!("/usr/bin/ditto", args: ["-x", "-k", "--", path, tmp_unpack_dir]) - - extract_nested_inside(tmp_unpack_dir, to: unpack_dir) - end - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb index 5ed0fb5e99..cee83b1347 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl.rb @@ -172,16 +172,8 @@ module Hbc end def container(*args) - # TODO: remove this constraint, and instead merge multiple container stanzas set_unique_stanza(:container, args.empty?) do - begin - DSL::Container.new(*args).tap do |container| - # TODO: remove this backward-compatibility section after removing nested_container - if container&.nested - artifacts.add(Artifact::NestedContainer.new(cask, container.nested)) - end - end - end + DSL::Container.new(*args) end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 2472c88e49..9174cca5ea 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,5 +1,3 @@ -require "system_command" - module Hbc class DSL class Appcast diff --git a/Library/Homebrew/cask/lib/hbc/dsl/container.rb b/Library/Homebrew/cask/lib/hbc/dsl/container.rb index caaf25bcaf..ef2c8d2c38 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/container.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/container.rb @@ -1,4 +1,4 @@ -require "hbc/container" +require "unpack_strategy" module Hbc class DSL @@ -19,7 +19,7 @@ module Hbc end return if type.nil? - return unless Hbc::Container.from_type(type).nil? + return unless UnpackStrategy.from_type(type).nil? raise "invalid container type: #{type.inspect}" end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 5e16eb234b..342313b0b9 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -1,6 +1,7 @@ require "rubygems" require "formula_installer" +require "unpack_strategy" require "hbc/cask_dependencies" require "hbc/staged" @@ -148,17 +149,7 @@ module Hbc def primary_container @primary_container ||= begin - container = if @cask.container&.type - Container.from_type(@cask.container.type) - else - Container.for_path(@downloaded_path) - end - - unless container - raise CaskError, "Uh oh, could not figure out how to unpack '#{@downloaded_path}'." - end - - container.new(@cask, @downloaded_path) + UnpackStrategy.detect(@downloaded_path, type: @cask.container&.type) end end @@ -168,7 +159,18 @@ module Hbc odebug "Using container class #{primary_container.class} for #{@downloaded_path}" basename = CGI.unescape(File.basename(@cask.url.path)) - primary_container.extract(to: @cask.staged_path, basename: basename, verbose: verbose?) + + if nested_container = @cask.container&.nested + Dir.mktmpdir do |tmpdir| + tmpdir = Pathname(tmpdir) + primary_container.extract(to: tmpdir, basename: basename, verbose: verbose?) + + UnpackStrategy.detect(tmpdir/nested_container) + .extract_nestedly(to: @cask.staged_path, verbose: verbose?) + end + else + primary_container.extract_nestedly(to: @cask.staged_path, basename: basename, verbose: verbose?) + end end def install_artifacts diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index 14458727cb..10fab11f4f 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -20,6 +20,8 @@ require "messages" require "pp" require "extend/ARGV" +require "system_command" + ARGV.extend(HomebrewArgvExtension) HOMEBREW_PRODUCT = ENV["HOMEBREW_PRODUCT"] diff --git a/Library/Homebrew/system_command.rb b/Library/Homebrew/system_command.rb index a57c0513cc..c49d773a90 100644 --- a/Library/Homebrew/system_command.rb +++ b/Library/Homebrew/system_command.rb @@ -1,10 +1,12 @@ require "open3" +require "ostruct" require "vendor/plist/plist" require "shellwords" require "extend/io" require "extend/hash_validator" using HashValidator +require "extend/predicable" def system_command(*args) SystemCommand.run(*args) @@ -27,18 +29,15 @@ class SystemCommand def run! @merged_output = [] - @processed_output = { stdout: "", stderr: "" } odebug command.shelljoin each_output_line do |type, line| case type when :stdout puts line.chomp if print_stdout? - processed_output[:stdout] << line @merged_output << [:stdout, line] when :stderr $stderr.puts Formatter.error(line.chomp) if print_stderr? - processed_output[:stderr] << line @merged_output << [:stderr, line] end end @@ -70,7 +69,7 @@ class SystemCommand private - attr_reader :executable, :args, :input, :options, :processed_output, :processed_status, :env + attr_reader :executable, :args, :input, :options, :env attr_predicate :sudo?, :print_stdout?, :print_stderr?, :must_succeed? @@ -93,9 +92,9 @@ class SystemCommand end def assert_success - return if processed_status&.success? + return if @status.success? raise ErrorDuringExecution.new(command, - status: processed_status, + status: @status, output: @merged_output) end @@ -121,7 +120,10 @@ class SystemCommand raw_stdin.close_write each_line_from [raw_stdout, raw_stderr], &b - @processed_status = raw_wait_thr.value + @status = raw_wait_thr.value + rescue SystemCallError => e + @status = $CHILD_STATUS + @merged_output << [:stderr, e.message] end def write_input_to(raw_stdin) @@ -151,10 +153,11 @@ class SystemCommand end def result - Result.new(command, - processed_output[:stdout], - processed_output[:stderr], - processed_status.exitstatus) + output = @merged_output.each_with_object(stdout: "", stderr: "") do |(type, line), hash| + hash[type] << line + end + + Result.new(command, output[:stdout], output[:stderr], @status.exitstatus) end class Result diff --git a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb deleted file mode 100644 index 92486fc7f8..0000000000 --- a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe Hbc::Artifact::NestedContainer, :cask do - describe "install" do - it "extracts the specified paths as containers" do - cask = Hbc::CaskLoader.load(cask_path("nested-app")).tap do |c| - InstallHelper.install_without_artifacts(c) - end - - cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact| - artifact.install_phase(command: NeverSudoSystemCommand, force: false) - end - - expect(cask.staged_path.join("MyNestedApp.app")).to be_a_directory - end - end -end diff --git a/Library/Homebrew/test/cask/container/dmg_spec.rb b/Library/Homebrew/test/cask/container/dmg_spec.rb deleted file mode 100644 index 7eee7c49fc..0000000000 --- a/Library/Homebrew/test/cask/container/dmg_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -describe Hbc::Container::Dmg, :cask do - describe "#mount" do - let(:transmission) { Hbc::CaskLoader.load(cask_path("local-transmission")) } - subject(:dmg) { described_class.new(transmission, Pathname(transmission.url.path)) } - - it "does not store nil mounts for dmgs with extra data" do - dmg.mount do |mounts| - begin - expect(mounts).not_to include nil - ensure - mounts.each(&dmg.public_method(:eject)) - end - end - end - end -end diff --git a/Library/Homebrew/test/cask/container/naked_spec.rb b/Library/Homebrew/test/cask/container/naked_spec.rb deleted file mode 100644 index 1acdb7a069..0000000000 --- a/Library/Homebrew/test/cask/container/naked_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -describe Hbc::Container::Naked, :cask do - it "saves files with spaces in them from uris with encoded spaces" do - cask = Hbc::Cask.new("spacey") do - url "http://example.com/kevin%20spacey.pkg" - version "1.2" - end - - path = Pathname("/tmp/downloads/kevin-spacey.pkg") - expected_destination = cask.staged_path.join("kevin spacey.pkg") - - container = Hbc::Container::Naked.new(cask, path) - - expect(container).to receive(:system_command!) - .with("/usr/bin/ditto", args: ["--", path, expected_destination]) - - container.extract(to: cask.staged_path, basename: "kevin spacey.pkg") - end -end diff --git a/Library/Homebrew/test/system_command_spec.rb b/Library/Homebrew/test/system_command_spec.rb index f57d22f612..0b74d1fbfe 100644 --- a/Library/Homebrew/test/system_command_spec.rb +++ b/Library/Homebrew/test/system_command_spec.rb @@ -208,4 +208,12 @@ describe SystemCommand do expect(described_class.run("tool", env: { "PATH" => path }).stdout).to include "Hello, world!" end end + + describe "#run" do + it "does not raise a `SystemCallError` when the executable does not exist" do + expect { + described_class.run("non_existent_executable") + }.not_to raise_error + end + end end diff --git a/Library/Homebrew/test/unpack_strategy/dmg_spec.rb b/Library/Homebrew/test/unpack_strategy/dmg_spec.rb new file mode 100644 index 0000000000..a572ea3a08 --- /dev/null +++ b/Library/Homebrew/test/unpack_strategy/dmg_spec.rb @@ -0,0 +1,10 @@ +require_relative "shared_examples" + +describe UnpackStrategy::Dmg, :needs_macos do + describe "#mount" do + let(:path) { TEST_FIXTURE_DIR/"cask/container.dmg" } + + include_examples "UnpackStrategy::detect" + include_examples "#extract", children: ["container"] + end +end diff --git a/Library/Homebrew/unpack_strategy.rb b/Library/Homebrew/unpack_strategy.rb index b341292cdf..154724ec0a 100644 --- a/Library/Homebrew/unpack_strategy.rb +++ b/Library/Homebrew/unpack_strategy.rb @@ -5,15 +5,23 @@ module UnpackStrategy def self.strategies @strategies ||= [ + Pkg, + Ttf, + Otf, + Air, + Executable, + SelfExtractingExecutable, Jar, LuaRock, MicrosoftOfficeXml, Zip, + Dmg, Xar, Compress, Tar, - Gzip, Bzip2, + Gzip, + Lzma, Xz, Lzip, Git, @@ -22,14 +30,29 @@ module UnpackStrategy Cvs, Fossil, Bazaar, + Cab, P7Zip, + Sit, Rar, Lha, ].freeze end private_class_method :strategies - def self.detect(path, ref_type: nil, ref: nil) + def self.from_type(type) + type = { + naked: :uncompressed, + seven_zip: :p7zip, + }.fetch(type, type) + + begin + const_get(type.to_s.split("_").map(&:capitalize).join) + rescue NameError + nil + end + end + + def self.from_path(path) magic_number = if path.directory? "" else @@ -50,6 +73,11 @@ module UnpackStrategy 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) end @@ -86,26 +114,41 @@ module UnpackStrategy Directory.new(tmp_unpack_dir).extract(to: to, verbose: verbose) end end + + def dependencies + [] + end end +require "unpack_strategy/air" require "unpack_strategy/bazaar" require "unpack_strategy/bzip2" +require "unpack_strategy/cab" require "unpack_strategy/compress" require "unpack_strategy/cvs" require "unpack_strategy/directory" +require "unpack_strategy/dmg" +require "unpack_strategy/executable" require "unpack_strategy/fossil" +require "unpack_strategy/generic_unar" 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/lzma" require "unpack_strategy/mercurial" require "unpack_strategy/microsoft_office_xml" +require "unpack_strategy/otf" require "unpack_strategy/p7zip" +require "unpack_strategy/pkg" require "unpack_strategy/rar" +require "unpack_strategy/self_extracting_executable" +require "unpack_strategy/sit" require "unpack_strategy/subversion" require "unpack_strategy/tar" +require "unpack_strategy/ttf" require "unpack_strategy/uncompressed" require "unpack_strategy/xar" require "unpack_strategy/xz" diff --git a/Library/Homebrew/unpack_strategy/air.rb b/Library/Homebrew/unpack_strategy/air.rb new file mode 100644 index 0000000000..4fd819c888 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/air.rb @@ -0,0 +1,22 @@ +module UnpackStrategy + class Air + include UnpackStrategy + + def self.can_extract?(path:, magic_number:) + path.extname == ".air" + end + + def dependencies + @dependencies ||= [Hbc::CaskLoader.load("adobe-air")] + end + + private + + def extract_to_dir(unpack_dir, basename:, verbose:) + system_command!( + "/Applications/Utilities/Adobe AIR Application Installer.app/Contents/MacOS/Adobe AIR Application Installer", + args: ["-silent", "-location", unpack_dir, path], + ) + end + end +end diff --git a/Library/Homebrew/unpack_strategy/bzip2.rb b/Library/Homebrew/unpack_strategy/bzip2.rb index aa401368ce..60378b7003 100644 --- a/Library/Homebrew/unpack_strategy/bzip2.rb +++ b/Library/Homebrew/unpack_strategy/bzip2.rb @@ -11,7 +11,7 @@ module UnpackStrategy def extract_to_dir(unpack_dir, basename:, verbose:) FileUtils.cp path, unpack_dir/basename, preserve: true quiet_flags = verbose ? [] : ["-q"] - safe_system "bunzip2", *quiet_flags, unpack_dir/basename + system_command! "bunzip2", args: [*quiet_flags, unpack_dir/basename] end end end diff --git a/Library/Homebrew/unpack_strategy/cab.rb b/Library/Homebrew/unpack_strategy/cab.rb new file mode 100644 index 0000000000..1daf219f4a --- /dev/null +++ b/Library/Homebrew/unpack_strategy/cab.rb @@ -0,0 +1,19 @@ +module UnpackStrategy + class Cab + include UnpackStrategy + + def self.can_extract?(path:, magic_number:) + magic_number.match?(/\A(MSCF|MZ)/n) + end + + def extract_to_dir(unpack_dir, basename:, verbose:) + system_command! "cabextract", + args: ["-d", unpack_dir, "--", path], + env: { "PATH" => PATH.new(Formula["cabextract"].opt_bin, ENV["PATH"]) } + end + + def dependencies + @dependencies ||= [Formula["cabextract"]] + end + end +end diff --git a/Library/Homebrew/unpack_strategy/dmg.rb b/Library/Homebrew/unpack_strategy/dmg.rb new file mode 100644 index 0000000000..1068c93486 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/dmg.rb @@ -0,0 +1,158 @@ +require "tempfile" + +module UnpackStrategy + class Dmg + include UnpackStrategy + + module Bom + DMG_METADATA = Set.new %w[ + .background + .com.apple.timemachine.donotpresent + .com.apple.timemachine.supported + .DocumentRevisions-V100 + .DS_Store + .fseventsd + .MobileBackups + .Spotlight-V100 + .TemporaryItems + .Trashes + .VolumeIcon.icns + ].freeze + private_constant :DMG_METADATA + + refine Pathname do + def dmg_metadata? + DMG_METADATA.include?(cleanpath.ascend.to_a.last.to_s) + end + + # symlinks to system directories (commonly to /Applications) + def system_dir_symlink? + symlink? && MacOS.system_dir?(readlink) + end + + def bom + # We need to use `find` here instead of Ruby in order to properly handle + # file names containing special characters, such as “e” + “´” vs. “é”. + system_command("find", args: [".", "-print0"], chdir: self, print_stderr: false) + .stdout + .split("\0") + .reject { |path| Pathname(path).dmg_metadata? } + .reject { |path| (self/path).system_dir_symlink? } + .join("\n") + end + end + end + private_constant :Bom + + using Bom + + class Mount + include UnpackStrategy + + def eject + tries ||= 3 + + return unless path.exist? + + if tries > 1 + system_command! "diskutil", + args: ["eject", path], + print_stderr: false + else + system_command! "diskutil", + args: ["unmount", "force", path], + print_stderr: false + end + rescue ErrorDuringExecution => e + raise e if (tries -= 1).zero? + sleep 1 + retry + end + + private + + def extract_to_dir(unpack_dir, basename:, verbose:) + Tempfile.open(["", ".bom"]) do |bomfile| + bomfile.close + + Tempfile.open(["", ".list"]) do |filelist| + filelist.puts(path.bom) + filelist.close + + system_command! "mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path] + end + + system_command! "ditto", args: ["--bom", bomfile.path, "--", path, unpack_dir] + end + end + end + private_constant :Mount + + def self.can_extract?(path:, magic_number:) + imageinfo = system_command("hdiutil", + args: ["imageinfo", path], + print_stderr: false).stdout + + !imageinfo.empty? + end + + private + + def extract_to_dir(unpack_dir, basename:, verbose:) + mount(verbose: verbose) do |mounts| + raise "No mounts found in '#{path}'; perhaps it is a bad disk image?" if mounts.empty? + + mounts.each do |mount| + mount.extract(to: unpack_dir) + end + end + end + + def mount(verbose: false) + Dir.mktmpdir do |mount_dir| + mount_dir = Pathname(mount_dir) + + without_eula = system_command("hdiutil", + args: ["attach", "-plist", "-nobrowse", "-readonly", "-noidme", "-mountrandom", mount_dir, path], + input: "qn\n", + print_stderr: false) + + # If mounting without agreeing to EULA succeeded, there is none. + plist = if without_eula.success? + without_eula.plist + else + cdr_path = mount_dir/path.basename.sub_ext(".cdr") + + system_command!("hdiutil", args: ["convert", "-quiet", "-format", "UDTO", "-o", cdr_path, path]) + + with_eula = system_command!( + "/usr/bin/hdiutil", + args: ["attach", "-plist", "-nobrowse", "-readonly", "-noidme", "-mountrandom", mount_dir, cdr_path], + ) + + if verbose && !(eula_text = without_eula.stdout).empty? + ohai "Software License Agreement for '#{path}':" + puts eula_text + end + + with_eula.plist + end + + mounts = if plist.respond_to?(:fetch) + plist.fetch("system-entities", []) + .map { |entity| entity["mount-point"] } + .compact + .map { |path| Mount.new(path) } + else + [] + end + + begin + yield mounts + ensure + mounts.each(&:eject) + end + end + end + end +end diff --git a/Library/Homebrew/unpack_strategy/executable.rb b/Library/Homebrew/unpack_strategy/executable.rb new file mode 100644 index 0000000000..85964fcd06 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/executable.rb @@ -0,0 +1,17 @@ +require_relative "uncompressed" + +require "vendor/macho/macho" + +module UnpackStrategy + class Executable < Uncompressed + def self.can_extract?(path:, magic_number:) + return true if magic_number.match?(/\A#!\s*\S+/n) + + begin + path.file? && MachO.open(path).header.executable? + rescue MachO::NotAMachOError + false + end + end + end +end diff --git a/Library/Homebrew/unpack_strategy/fossil.rb b/Library/Homebrew/unpack_strategy/fossil.rb index e72908c401..49b480ceab 100644 --- a/Library/Homebrew/unpack_strategy/fossil.rb +++ b/Library/Homebrew/unpack_strategy/fossil.rb @@ -7,7 +7,7 @@ module UnpackStrategy # 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'" - Utils.popen_read("sqlite3", path, query).to_i == 1 + system_command("sqlite3", args: [path, query]).stdout.to_i == 1 end private @@ -19,9 +19,10 @@ module UnpackStrategy [] end - with_env "PATH" => PATH.new(Formula["fossil"].opt_bin, ENV["PATH"]) do - safe_system "fossil", "open", path, *args, chdir: unpack_dir - end + system_command! "fossil", + args: ["open", path, *args], + chdir: unpack_dir, + env: { "PATH" => PATH.new(Formula["fossil"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/generic_unar.rb b/Library/Homebrew/unpack_strategy/generic_unar.rb new file mode 100644 index 0000000000..3b11df94a4 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/generic_unar.rb @@ -0,0 +1,21 @@ +module UnpackStrategy + class GenericUnar + include UnpackStrategy + + def self.can_extract?(path:, magic_number:) + false + end + + def dependencies + @dependencies ||= [Formula["unar"]] + end + + private + + def extract_to_dir(unpack_dir, basename:, verbose:) + system_command! "unar", + args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", path], + env: { "PATH" => PATH.new(Formula["unar"].opt_bin, ENV["PATH"]) } + end + end +end diff --git a/Library/Homebrew/unpack_strategy/gzip.rb b/Library/Homebrew/unpack_strategy/gzip.rb index e83feccfe3..6ae5517603 100644 --- a/Library/Homebrew/unpack_strategy/gzip.rb +++ b/Library/Homebrew/unpack_strategy/gzip.rb @@ -11,7 +11,8 @@ module UnpackStrategy def extract_to_dir(unpack_dir, basename:, verbose:) FileUtils.cp path, unpack_dir/basename, preserve: true quiet_flags = verbose ? [] : ["-q"] - safe_system "gunzip", *quiet_flags, "-N", unpack_dir/basename + system_command! "gunzip", + args: [*quiet_flags, "-N", "--", unpack_dir/basename] end end end diff --git a/Library/Homebrew/unpack_strategy/lha.rb b/Library/Homebrew/unpack_strategy/lha.rb index b5d7f8b16b..9f71e75613 100644 --- a/Library/Homebrew/unpack_strategy/lha.rb +++ b/Library/Homebrew/unpack_strategy/lha.rb @@ -13,7 +13,9 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system Formula["lha"].opt_bin/"lha", "xq2w=#{unpack_dir}", path + system_command! "lha", + args: ["xq2w=#{unpack_dir}", path], + env: { "PATH" => PATH.new(Formula["lha"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/lzip.rb b/Library/Homebrew/unpack_strategy/lzip.rb index 5454423269..21200c556d 100644 --- a/Library/Homebrew/unpack_strategy/lzip.rb +++ b/Library/Homebrew/unpack_strategy/lzip.rb @@ -15,7 +15,9 @@ module UnpackStrategy def extract_to_dir(unpack_dir, basename:, verbose:) FileUtils.cp path, unpack_dir/basename, preserve: true quiet_flags = verbose ? [] : ["-q"] - safe_system Formula["lzip"].opt_bin/"lzip", "-d", *quiet_flags, unpack_dir/basename + system_command! "lzip", + args: ["-d", *quiet_flags, unpack_dir/basename], + env: { "PATH" => PATH.new(Formula["lzip"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/lzma.rb b/Library/Homebrew/unpack_strategy/lzma.rb new file mode 100644 index 0000000000..f759b0cb66 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/lzma.rb @@ -0,0 +1,21 @@ +module UnpackStrategy + class Lzma + include UnpackStrategy + + def self.can_extract?(path:, magic_number:) + magic_number.match?(/\A\]\000\000\200\000/n) + end + + def extract_to_dir(unpack_dir, basename:, verbose:) + FileUtils.cp path, unpack_dir/basename, preserve: true + quiet_flags = verbose ? [] : ["-q"] + system_command! "unlzma", + args: [*quiet_flags, "--", unpack_dir/basename], + env: { "PATH" => PATH.new(Formula["xz"].opt_bin, ENV["PATH"]) } + end + + def dependencies + @dependencies ||= [Formula["xz"]] + end + end +end diff --git a/Library/Homebrew/unpack_strategy/mercurial.rb b/Library/Homebrew/unpack_strategy/mercurial.rb index 8f71fdc95e..518878fdb2 100644 --- a/Library/Homebrew/unpack_strategy/mercurial.rb +++ b/Library/Homebrew/unpack_strategy/mercurial.rb @@ -9,9 +9,9 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - with_env "PATH" => PATH.new(Formula["mercurial"].opt_bin, ENV["PATH"]) do - safe_system "hg", "--cwd", path, "archive", "--subrepos", "-y", "-t", "files", unpack_dir - end + system_command! "hg", + args: ["--cwd", path, "archive", "--subrepos", "-y", "-t", "files", unpack_dir], + env: { "PATH" => PATH.new(Formula["mercurial"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/otf.rb b/Library/Homebrew/unpack_strategy/otf.rb new file mode 100644 index 0000000000..f8f4ee531f --- /dev/null +++ b/Library/Homebrew/unpack_strategy/otf.rb @@ -0,0 +1,9 @@ +require_relative "uncompressed" + +module UnpackStrategy + class Otf < Uncompressed + def self.can_extract?(path:, magic_number:) + magic_number.match?(/\AOTTO/n) + end + end +end diff --git a/Library/Homebrew/unpack_strategy/p7zip.rb b/Library/Homebrew/unpack_strategy/p7zip.rb index c299756601..4a8d7d093b 100644 --- a/Library/Homebrew/unpack_strategy/p7zip.rb +++ b/Library/Homebrew/unpack_strategy/p7zip.rb @@ -13,7 +13,9 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system "7zr", "x", "-y", "-bd", "-bso0", path, "-o#{unpack_dir}" + system_command! "7zr", + args: ["x", "-y", "-bd", "-bso0", path, "-o#{unpack_dir}"], + env: { "PATH" => PATH.new(Formula["p7zip"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/pkg.rb b/Library/Homebrew/unpack_strategy/pkg.rb new file mode 100644 index 0000000000..dceee1ef56 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/pkg.rb @@ -0,0 +1,10 @@ +require_relative "uncompressed" + +module UnpackStrategy + class Pkg < Uncompressed + def self.can_extract?(path:, magic_number:) + path.extname.match?(/\A.m?pkg\Z/) && + (path.directory? || magic_number.match?(/\Axar!/n)) + end + end +end diff --git a/Library/Homebrew/unpack_strategy/rar.rb b/Library/Homebrew/unpack_strategy/rar.rb index 326caeffe0..d7ecbbf64a 100644 --- a/Library/Homebrew/unpack_strategy/rar.rb +++ b/Library/Homebrew/unpack_strategy/rar.rb @@ -13,7 +13,9 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system Formula["unrar"].opt_bin/"unrar", "x", "-inul", path, unpack_dir + system_command! "unrar", + args: ["x", "-inul", path, unpack_dir], + env: { "PATH" => PATH.new(Formula["unrar"].opt_bin, ENV["PATH"]) } end end end diff --git a/Library/Homebrew/unpack_strategy/self_extracting_executable.rb b/Library/Homebrew/unpack_strategy/self_extracting_executable.rb new file mode 100644 index 0000000000..a7de316716 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/self_extracting_executable.rb @@ -0,0 +1,13 @@ +require_relative "generic_unar" + +module UnpackStrategy + class SelfExtractingExecutable < GenericUnar + def self.can_extract?(path:, magic_number:) + return false unless magic_number.match?(/\AMZ/n) + + system_command("file", + args: [path], + print_stderr: false).stdout.include?("self-extracting") + end + end +end diff --git a/Library/Homebrew/unpack_strategy/sit.rb b/Library/Homebrew/unpack_strategy/sit.rb new file mode 100644 index 0000000000..48098bb8cb --- /dev/null +++ b/Library/Homebrew/unpack_strategy/sit.rb @@ -0,0 +1,9 @@ +require_relative "generic_unar" + +module UnpackStrategy + class Sit < GenericUnar + def self.can_extract?(path:, magic_number:) + magic_number.match?(/\AStuffIt/n) + end + end +end diff --git a/Library/Homebrew/unpack_strategy/subversion.rb b/Library/Homebrew/unpack_strategy/subversion.rb index a1937183b1..02599f01e2 100644 --- a/Library/Homebrew/unpack_strategy/subversion.rb +++ b/Library/Homebrew/unpack_strategy/subversion.rb @@ -9,7 +9,7 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system "svn", "export", "--force", path, unpack_dir + system_command! "svn", args: ["export", "--force", path, unpack_dir] end end end diff --git a/Library/Homebrew/unpack_strategy/tar.rb b/Library/Homebrew/unpack_strategy/tar.rb index a8865ec3e9..704e3890f4 100644 --- a/Library/Homebrew/unpack_strategy/tar.rb +++ b/Library/Homebrew/unpack_strategy/tar.rb @@ -14,7 +14,7 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system "tar", "xf", path, "-C", unpack_dir + system_command! "tar", args: ["xf", path, "-C", unpack_dir] end end end diff --git a/Library/Homebrew/unpack_strategy/ttf.rb b/Library/Homebrew/unpack_strategy/ttf.rb new file mode 100644 index 0000000000..8d1421a106 --- /dev/null +++ b/Library/Homebrew/unpack_strategy/ttf.rb @@ -0,0 +1,12 @@ +require_relative "uncompressed" + +module UnpackStrategy + class Ttf < Uncompressed + def self.can_extract?(path:, magic_number:) + # TrueType Font + magic_number.match?(/\A\000\001\000\000\000/n) || + # Truetype Font Collection + magic_number.match?(/\Attcf/n) + end + end +end diff --git a/Library/Homebrew/unpack_strategy/xar.rb b/Library/Homebrew/unpack_strategy/xar.rb index c78233f4f5..b631aba77d 100644 --- a/Library/Homebrew/unpack_strategy/xar.rb +++ b/Library/Homebrew/unpack_strategy/xar.rb @@ -9,7 +9,7 @@ module UnpackStrategy private def extract_to_dir(unpack_dir, basename:, verbose:) - safe_system "xar", "-x", "-f", path, "-C", unpack_dir + system_command! "xar", args: ["-x", "-f", path, "-C", unpack_dir] end end end diff --git a/Library/Homebrew/unpack_strategy/xz.rb b/Library/Homebrew/unpack_strategy/xz.rb index a629de237b..c7f418cede 100644 --- a/Library/Homebrew/unpack_strategy/xz.rb +++ b/Library/Homebrew/unpack_strategy/xz.rb @@ -15,7 +15,9 @@ module UnpackStrategy def extract_to_dir(unpack_dir, basename:, verbose:) FileUtils.cp path, unpack_dir/basename, preserve: true quiet_flags = verbose ? [] : ["-q"] - safe_system Formula["xz"].opt_bin/"unxz", *quiet_flags, "-T0", unpack_dir/basename + system_command! "unxz", + args: [*quiet_flags, "-T0", "--", unpack_dir/basename], + env: { "PATH" => PATH.new(Formula["xz"].opt_bin, ENV["PATH"]) } extract_nested_tar(unpack_dir) end diff --git a/Library/Homebrew/unpack_strategy/zip.rb b/Library/Homebrew/unpack_strategy/zip.rb index c5544a30c8..df3a0c1220 100644 --- a/Library/Homebrew/unpack_strategy/zip.rb +++ b/Library/Homebrew/unpack_strategy/zip.rb @@ -10,7 +10,7 @@ module UnpackStrategy def extract_to_dir(unpack_dir, basename:, verbose:) quiet_flags = verbose ? [] : ["-qq"] - safe_system "unzip", *quiet_flags, path, "-d", unpack_dir + system_command! "unzip", args: [*quiet_flags, path, "-d", unpack_dir] end end end