aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/cask
diff options
context:
space:
mode:
authorBen Muschol2017-09-27 16:36:10 -0400
committerGitHub2017-09-27 16:36:10 -0400
commit2d6bd0400785b5fb061f793f70736f12e6ec8231 (patch)
treefd0abc8937fc85fb49714ad9dc4a3735fa58242f /Library/Homebrew/cask
parentfe5c885da0b8b69a5de74647e4181b137acb835f (diff)
parentcb139ca381cb7f00a4dfdc21482515f103aed417 (diff)
downloadbrew-2d6bd0400785b5fb061f793f70736f12e6ec8231.tar.bz2
Merge branch 'master' into check-for-master-no-refactor
Diffstat (limited to 'Library/Homebrew/cask')
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact.rb9
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/base.rb)43
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb46
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb)141
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/artifact.rb31
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/binary.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/installer.rb97
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/moved.rb52
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb28
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/pkg.rb61
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/relocated.rb82
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/suite.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb58
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/zap.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/audit.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask_loader.rb19
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb47
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/cat.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/edit.rb19
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/fetch.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/info.rb12
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/install.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb26
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb74
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/list.rb14
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/reinstall.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/search.rb21
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/uninstall.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/zap.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/naked.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl.rb131
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/installer.rb32
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/version.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb24
-rw-r--r--Library/Homebrew/cask/lib/hbc/staged.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/system_command.rb2
42 files changed, 614 insertions, 573 deletions
diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb
index 074d15017..cb15ec051 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact.rb
@@ -33,7 +33,7 @@ module Hbc
# We want to extract nested containers before we
# handle any other artifacts.
#
- TYPES = [
+ CLASSES = [
PreflightBlock,
Uninstall,
NestedContainer,
@@ -60,12 +60,9 @@ module Hbc
Zap,
].freeze
- def self.for_cask(cask, options = {})
+ def self.for_cask(cask)
odebug "Determining which artifacts are present in Cask #{cask}"
-
- TYPES
- .select { |klass| klass.me?(cask) }
- .map { |klass| klass.new(cask, options) }
+ CLASSES.flat_map { |klass| klass.for_cask(cask) }
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
index ae15552a4..1b18cc6e7 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
@@ -1,34 +1,28 @@
module Hbc
module Artifact
- class Base
+ class AbstractArtifact
extend Predicable
- def self.artifact_name
- @artifact_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
+ def self.english_name
+ @english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
end
- def self.artifact_english_name
- @artifact_english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
+ def self.english_article
+ @english_article ||= (english_name =~ /^[aeiou]/i) ? "an" : "a"
end
- def self.artifact_english_article
- @artifact_english_article ||= (artifact_english_name =~ /^[aeiou]/i) ? "an" : "a"
+ def self.dsl_key
+ @dsl_key ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
end
- def self.artifact_dsl_key
- @artifact_dsl_key ||= artifact_name.to_sym
+ def self.dirmethod
+ @dirmethod ||= "#{dsl_key}dir".to_sym
end
- def self.artifact_dirmethod
- @artifact_dirmethod ||= "#{artifact_name}dir".to_sym
+ def self.for_cask(cask)
+ cask.artifacts[dsl_key].to_a
end
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any?
- end
-
- attr_reader :force
-
# TODO: this sort of logic would make more sense in dsl.rb, or a
# constructor called from dsl.rb, so long as that isn't slow.
def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
@@ -63,17 +57,14 @@ module Hbc
[executable, arguments]
end
- def summary
- {}
- end
+ attr_reader :cask
- attr_predicate :force?, :verbose?
-
- def initialize(cask, command: SystemCommand, force: false, verbose: false)
+ def initialize(cask)
@cask = cask
- @command = command
- @force = force
- @verbose = verbose
+ end
+
+ def to_s
+ "#{summarize} (#{self.class.english_name})"
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
index be3050acb..4e8edbc11 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
@@ -1,39 +1,51 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class AbstractFlightBlock < Base
- def self.artifact_dsl_key
+ class AbstractFlightBlock < AbstractArtifact
+ def self.dsl_key
super.to_s.sub(/_block$/, "").to_sym
end
- def self.uninstall_artifact_dsl_key
- artifact_dsl_key.to_s.prepend("uninstall_").to_sym
+ def self.uninstall_dsl_key
+ dsl_key.to_s.prepend("uninstall_").to_sym
end
- def self.class_for_dsl_key(dsl_key)
- Object.const_get("Hbc::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}")
+ def self.for_cask(cask)
+ [dsl_key, uninstall_dsl_key].flat_map do |key|
+ [*cask.artifacts[key]].map { |block| new(cask, key => block) }
+ end
end
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any? ||
- cask.artifacts[uninstall_artifact_dsl_key].any?
+ attr_reader :directives
+
+ def initialize(cask, **directives)
+ super(cask)
+ @directives = directives
end
- def install_phase
- abstract_phase(self.class.artifact_dsl_key)
+ def install_phase(**)
+ abstract_phase(self.class.dsl_key)
end
- def uninstall_phase
- abstract_phase(self.class.uninstall_artifact_dsl_key)
+ def uninstall_phase(**)
+ abstract_phase(self.class.uninstall_dsl_key)
end
private
+ def class_for_dsl_key(dsl_key)
+ namespace = self.class.name.to_s.sub(/::.*::.*$/, "")
+ self.class.const_get("#{namespace}::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}")
+ end
+
def abstract_phase(dsl_key)
- @cask.artifacts[dsl_key].each do |block|
- self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block)
- end
+ return if (block = directives[dsl_key]).nil?
+ class_for_dsl_key(dsl_key).new(cask).instance_eval(&block)
+ end
+
+ def summarize
+ directives.keys.map(&:to_s).join(", ")
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb
index d92644150..badd549ce 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb
@@ -1,11 +1,11 @@
require "pathname"
require "timeout"
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class UninstallBase < Base
+ class AbstractUninstall < AbstractArtifact
ORDERED_DIRECTIVES = [
:early_script,
:launchctl,
@@ -20,26 +20,42 @@ module Hbc
:rmdir,
].freeze
- def dispatch_uninstall_directives
- directives_set = @cask.artifacts[stanza]
+ def self.from_args(cask, **directives)
+ new(cask, directives)
+ end
+
+ attr_reader :directives
+
+ def initialize(cask, directives)
+ super(cask)
+ directives[:signal] = [*directives[:signal]].flatten.each_slice(2).to_a
+ @directives = directives
+ end
+
+ def to_h
+ directives.to_h
+ end
+
+ def summarize
+ to_h.map { |key, val| [*val].map { |v| "#{key.inspect} => #{v.inspect}" }.join(", ") }.join(", ")
+ end
+
+ private
+
+ def dispatch_uninstall_directives(**options)
ohai "Running #{stanza} process for #{@cask}; your password may be necessary"
- directives_set.each do |directives|
- warn_for_unknown_directives(directives)
- end
+ warn_for_unknown_directives(directives)
ORDERED_DIRECTIVES.each do |directive_sym|
- directives_set.select { |h| h.key?(directive_sym) }.each do |directives|
- args = directives[directive_sym]
- send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args))
- end
+ next unless directives.key?(directive_sym)
+ args = directives[directive_sym]
+ send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args), **options)
end
end
- private
-
def stanza
- self.class.artifact_dsl_key
+ self.class.dsl_key
end
def warn_for_unknown_directives(directives)
@@ -51,18 +67,18 @@ module Hbc
# Preserve prior functionality of script which runs first. Should rarely be needed.
# :early_script should not delete files, better defer that to :script.
# If Cask writers never need :early_script it may be removed in the future.
- def uninstall_early_script(directives)
- uninstall_script(directives, directive_name: :early_script)
+ def uninstall_early_script(directives, **options)
+ uninstall_script(directives, directive_name: :early_script, **options)
end
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
- def uninstall_launchctl(*services)
+ def uninstall_launchctl(*services, command: nil, **_)
services.each do |service|
ohai "Removing launchctl service #{service}"
[false, true].each do |with_sudo|
- plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout
+ plist_status = command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout
if plist_status =~ /^\{/
- @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
+ command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
sleep 1
end
paths = ["/Library/LaunchAgents/#{service}.plist",
@@ -70,38 +86,38 @@ module Hbc
paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo
paths = paths.map { |elt| Pathname(elt) }.select(&:exist?)
paths.each do |path|
- @command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo)
+ command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo)
end
# undocumented and untested: pass a path to uninstall :launchctl
next unless Pathname(service).exist?
- @command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo)
- @command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo)
+ command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo)
+ command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo)
sleep 1
end
end
end
- def running_processes(bundle_id)
- @command.run!("/bin/launchctl", args: ["list"]).stdout.lines
- .map { |line| line.chomp.split("\t") }
- .map { |pid, state, id| [pid.to_i, state.to_i, id] }
- .select do |fields|
- next if fields[0].zero?
- fields[2] =~ /^#{Regexp.escape(bundle_id)}($|\.\d+)/
- end
+ def running_processes(bundle_id, command: nil)
+ command.run!("/bin/launchctl", args: ["list"]).stdout.lines
+ .map { |line| line.chomp.split("\t") }
+ .map { |pid, state, id| [pid.to_i, state.to_i, id] }
+ .select do |fields|
+ next if fields[0].zero?
+ fields[2] =~ /^#{Regexp.escape(bundle_id)}($|\.\d+)/
+ end
end
# :quit/:signal must come before :kext so the kext will not be in use by a running process
- def uninstall_quit(*bundle_ids)
+ def uninstall_quit(*bundle_ids, command: nil, **_)
bundle_ids.each do |bundle_id|
ohai "Quitting application ID #{bundle_id}"
- next if running_processes(bundle_id).empty?
- @command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
+ next if running_processes(bundle_id, command: command).empty?
+ command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
begin
Timeout.timeout(3) do
Kernel.loop do
- break if running_processes(bundle_id).empty?
+ break if running_processes(bundle_id, command: command).empty?
end
end
rescue Timeout::Error
@@ -111,15 +127,15 @@ module Hbc
end
# :signal should come after :quit so it can be used as a backup when :quit fails
- def uninstall_signal(*signals)
- signals.flatten.each_slice(2) do |pair|
+ def uninstall_signal(*signals, command: nil, **_)
+ signals.each do |pair|
unless pair.size == 2
- raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must consist of 2 elements.")
+ raise CaskInvalidError.new(cask, "Each #{stanza} :signal must consist of 2 elements.")
end
signal, bundle_id = pair
ohai "Signalling '#{signal}' to application ID '#{bundle_id}'"
- pids = running_processes(bundle_id).map(&:first)
+ pids = running_processes(bundle_id, command: command).map(&:first)
next unless pids.any?
# Note that unlike :quit, signals are sent from the current user (not
# upgraded to the superuser). This is a todo item for the future, but
@@ -133,10 +149,10 @@ module Hbc
end
end
- def uninstall_login_item(*login_items)
+ def uninstall_login_item(*login_items, command: nil, **_)
login_items.each do |name|
ohai "Removing login item #{name}"
- @command.run!("/usr/bin/osascript",
+ command.run!("/usr/bin/osascript",
args: ["-e", %Q(tell application "System Events" to delete every login item whose name is "#{name}")],
sudo: false)
sleep 1
@@ -144,23 +160,24 @@ module Hbc
end
# :kext should be unloaded before attempting to delete the relevant file
- def uninstall_kext(*kexts)
+ def uninstall_kext(*kexts, command: nil, **_)
kexts.each do |kext|
ohai "Unloading kernel extension #{kext}"
- is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout
+ is_loaded = command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout
if is_loaded.length > 1
- @command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true)
+ command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true)
sleep 1
end
- @command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
+ command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
ohai "Removing kernel extension #{kext_path}"
- @command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
+ command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
end
end
end
# :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted
- def uninstall_script(directives, directive_name: :script)
+ def uninstall_script(directives, directive_name: :script, force: false, command: nil, **_)
+ # TODO: Create a common `Script` class to run this and Artifact::Installer.
executable, script_arguments = self.class.read_script_arguments(directives,
"uninstall",
{ must_succeed: true, sudo: false },
@@ -168,25 +185,25 @@ module Hbc
directive_name)
ohai "Running uninstall script #{executable}"
- raise CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
- executable_path = @cask.staged_path.join(executable)
+ raise CaskInvalidError.new(cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
+ executable_path = cask.staged_path.join(executable)
unless executable_path.exist?
message = "uninstall script #{executable} does not exist"
- raise CaskError, "#{message}." unless force?
+ raise CaskError, "#{message}." unless force
opoo "#{message}, skipping."
return
end
- @command.run("/bin/chmod", args: ["--", "+x", executable_path])
- @command.run(executable_path, script_arguments)
+ command.run("/bin/chmod", args: ["--", "+x", executable_path])
+ command.run(executable_path, script_arguments)
sleep 1
end
- def uninstall_pkgutil(*pkgs)
+ def uninstall_pkgutil(*pkgs, command: nil, **_)
ohai "Uninstalling packages:"
pkgs.each do |regex|
- Hbc::Pkg.all_matching(regex, @command).each do |pkg|
+ Hbc::Pkg.all_matching(regex, command).each do |pkg|
puts pkg.package_id
pkg.uninstall
end
@@ -215,28 +232,28 @@ module Hbc
end
end
- def uninstall_delete(*paths)
+ def uninstall_delete(*paths, command: nil, **_)
return if paths.empty?
ohai "Removing files:"
each_resolved_path(:delete, paths) do |path, resolved_paths|
puts path
- @command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
+ command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
end
end
- def uninstall_trash(*paths)
+ def uninstall_trash(*paths, **options)
return if paths.empty?
resolved_paths = each_resolved_path(:trash, paths).to_a
ohai "Trashing files:"
puts resolved_paths.map(&:first)
- trash_paths(*resolved_paths.flat_map(&:last))
+ trash_paths(*resolved_paths.flat_map(&:last), **options)
end
- def trash_paths(*paths)
- @command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
+ def trash_paths(*paths, command: nil, **_)
+ command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
on run argv
repeat with i from 1 to (count argv)
set item i of argv to (item i of argv as POSIX file)
@@ -260,7 +277,7 @@ module Hbc
EOS
end
- def uninstall_rmdir(*directories)
+ def uninstall_rmdir(*directories, command: nil, **_)
return if directories.empty?
ohai "Removing directories if empty:"
@@ -268,10 +285,10 @@ module Hbc
puts path
resolved_paths.select(&:directory?).each do |resolved_path|
if (ds_store = resolved_path.join(".DS_Store")).exist?
- @command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
+ command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
end
- @command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
+ command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
index b42db877d..0f37afade 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
@@ -5,21 +5,32 @@ require "hbc/utils/hash_validator"
module Hbc
module Artifact
class Artifact < Moved
- def self.artifact_english_name
+ def self.english_name
"Generic Artifact"
end
- def self.artifact_dirmethod
- :appdir
- end
+ def self.from_args(cask, *args)
+ source_string, target_hash = args
+
+ if source_string.nil?
+ raise CaskInvalidError.new(cask.token, "no source given for #{english_name}")
+ end
+
+ unless target_hash.is_a?(Hash)
+ raise CaskInvalidError.new(cask.token, "target required for #{english_name} '#{source_string}'")
+ end
- def load_specification(artifact_spec)
- source_string, target_hash = artifact_spec
- raise CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil?
- @source = @cask.staged_path.join(source_string)
- raise CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash)
target_hash.extend(HashValidator).assert_valid_keys(:target)
- @target = Pathname.new(target_hash[:target])
+
+ new(cask, source_string, **target_hash)
+ end
+
+ def self.resolve_target(target)
+ Pathname(target)
+ end
+
+ def initialize(cask, source, target: nil)
+ super(cask, source, target: target)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
index 7178c2af6..68f4b074d 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
@@ -3,13 +3,13 @@ require "hbc/artifact/symlinked"
module Hbc
module Artifact
class Binary < Symlinked
- def link
- super
+ def link(command: nil, **options)
+ super(command: command, **options)
return if source.executable?
if source.writable?
FileUtils.chmod "+x", source
else
- @command.run!("/bin/chmod", args: ["+x", source], sudo: true)
+ command.run!("/bin/chmod", args: ["+x", source], sudo: true)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
index be857696e..588bcabd5 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
@@ -1,29 +1,82 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class Installer < Base
- def install_phase
- @cask.artifacts[self.class.artifact_dsl_key].each do |artifact|
- if artifact.manual
- puts <<-EOS.undent
- To complete the installation of Cask #{@cask}, you must also
- run the installer at
-
- '#{@cask.staged_path.join(artifact.manual)}'
-
- EOS
- else
- executable, script_arguments = self.class.read_script_arguments(artifact.script,
- self.class.artifact_dsl_key.to_s,
- { must_succeed: true, sudo: false },
- print_stdout: true)
- ohai "Running #{self.class.artifact_dsl_key} script #{executable}"
- raise CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil?
- executable_path = @cask.staged_path.join(executable)
- @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path)
- @command.run(executable_path, script_arguments)
+ class Installer < AbstractArtifact
+ VALID_KEYS = Set.new [
+ :manual,
+ :script,
+ ]
+
+ module ManualInstaller
+ def install_phase(**)
+ puts <<-EOS.undent
+ To complete the installation of Cask #{cask}, you must also
+ run the installer at
+
+ '#{path}'
+ EOS
+ end
+ end
+
+ module ScriptInstaller
+ def install_phase(command: nil, **_)
+ ohai "Running #{self.class.dsl_key} script '#{path.relative_path_from(cask.staged_path)}'"
+ FileUtils.chmod "+x", path unless path.executable?
+ command.run(path, **args)
+ end
+ end
+
+ def self.from_args(cask, **args)
+ raise CaskInvalidError.new(cask, "'installer' stanza requires an argument.") if args.empty?
+
+ if args.key?(:script) && !args[:script].respond_to?(:key?)
+ if args.key?(:executable)
+ raise CaskInvalidError.new(cask, "'installer' stanza gave arguments for both :script and :executable.")
end
+
+ args[:executable] = args[:script]
+ args.delete(:script)
+ args = { script: args }
+ end
+
+ unless args.keys.count == 1
+ raise CaskInvalidError.new(cask, "invalid 'installer' stanza: Only one of #{VALID_KEYS.inspect} is permitted.")
+ end
+
+ args.extend(HashValidator).assert_valid_keys(*VALID_KEYS)
+ new(cask, **args)
+ end
+
+ attr_reader :path, :args
+
+ def initialize(cask, **args)
+ super(cask)
+
+ if args.key?(:manual)
+ @path = cask.staged_path.join(args[:manual])
+ @args = []
+ extend(ManualInstaller)
+ return
+ end
+
+ path, @args = self.class.read_script_arguments(
+ args[:script], self.class.dsl_key.to_s, { must_succeed: true, sudo: false }, print_stdout: true
+ )
+ raise CaskInvalidError.new(cask, "#{self.class.dsl_key} missing executable") if path.nil?
+
+ path = Pathname(path)
+ @path = path.absolute? ? path : cask.staged_path.join(path)
+ extend(ScriptInstaller)
+ end
+
+ def summarize
+ path.relative_path_from(cask.staged_path).to_s
+ end
+
+ def to_h
+ { path: path.relative_path_from(cask.staged_path).to_s }.tap do |h|
+ h[:args] = args unless is_a?(ManualInstaller)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
index 3fe969c0c..ba1c8e907 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
@@ -4,63 +4,61 @@ module Hbc
module Artifact
class Moved < Relocated
def self.english_description
- "#{artifact_english_name}s"
+ "#{english_name}s"
end
- def install_phase
- each_artifact(&method(:move))
+ def install_phase(**options)
+ move(**options)
end
- def uninstall_phase
- each_artifact(&method(:delete))
+ def uninstall_phase(**options)
+ delete(**options)
+ end
+
+ def summarize_installed
+ if target.exist?
+ "#{printable_target} (#{target.abv})"
+ else
+ Formatter.error(printable_target, label: "Missing #{self.class.english_name}")
+ end
end
private
- def move
+ def move(force: false, command: nil, **options)
if Utils.path_occupied?(target)
- message = "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'"
- raise CaskError, "#{message}." unless force?
+ message = "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'"
+ raise CaskError, "#{message}." unless force
opoo "#{message}; overwriting."
- delete
+ delete(force: force, command: command, **options)
end
unless source.exist?
- raise CaskError, "It seems the #{self.class.artifact_english_name} source '#{source}' is not there."
+ raise CaskError, "It seems the #{self.class.english_name} source '#{source}' is not there."
end
- ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
+ ohai "Moving #{self.class.english_name} '#{source.basename}' to '#{target}'."
target.dirname.mkpath
if target.parent.writable?
FileUtils.move(source, target)
else
- SystemCommand.run("/bin/mv", args: [source, target], sudo: true)
+ command.run("/bin/mv", args: [source, target], sudo: true)
end
- add_altname_metadata target, source.basename.to_s
+ add_altname_metadata(target, source.basename, command: command)
end
- def delete
- ohai "Removing #{self.class.artifact_english_name} '#{target}'."
- raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}." if MacOS.undeletable?(target)
+ def delete(force: false, command: nil, **_)
+ ohai "Removing #{self.class.english_name} '#{target}'."
+ raise CaskError, "Cannot remove undeletable #{self.class.english_name}." if MacOS.undeletable?(target)
return unless Utils.path_occupied?(target)
if target.parent.writable? && !force
target.rmtree
else
- Utils.gain_permissions_remove(target, command: @command)
- end
- end
-
- def summarize_artifact(artifact_spec)
- load_specification artifact_spec
-
- if target.exist?
- "#{printable_target} (#{target.abv})"
- else
- Formatter.error(printable_target, label: "Missing #{self.class.artifact_english_name}")
+ Utils.gain_permissions_remove(target, command: command)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
index 84253ea30..81adf9029 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
@@ -1,23 +1,31 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class NestedContainer < Base
- def install_phase
- @cask.artifacts[:nested_container].each { |container| extract(container) }
+ 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
- def extract(container_relative_path)
- source = @cask.staged_path.join(container_relative_path)
- container = Container.for_path(source, @command)
+ private
+
+ def extract(command: nil, verbose: nil, **_)
+ container = Container.for_path(path, command)
unless container
raise CaskError, "Aw dang, could not identify nested container at '#{source}'"
end
- ohai "Extracting nested container #{source.basename}"
- container.new(@cask, source, @command, verbose: verbose?).extract
- FileUtils.remove_entry_secure(source)
+ ohai "Extracting nested container #{path.relative_path_from(cask.staged_path)}"
+ container.new(cask, path, command, verbose: verbose).extract
+ FileUtils.remove_entry_secure(path)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
index be0a6be71..0967fd99d 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
@@ -1,4 +1,4 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
require "hbc/utils/hash_validator"
@@ -6,62 +6,57 @@ require "vendor/plist/plist"
module Hbc
module Artifact
- class Pkg < Base
+ class Pkg < AbstractArtifact
attr_reader :pkg_relative_path
- def self.artifact_dsl_key
- :pkg
+ def self.from_args(cask, path, **options)
+ options.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
+ new(cask, path, **options)
end
- def load_pkg_description(pkg_description)
- @pkg_relative_path = pkg_description.shift
- @pkg_install_opts = pkg_description.shift
- begin
- if @pkg_install_opts.respond_to?(:keys)
- @pkg_install_opts.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
- elsif @pkg_install_opts
- raise
- end
- raise if pkg_description.nil?
- rescue StandardError
- raise CaskInvalidError.new(@cask, "Bad pkg stanza")
- end
+ attr_reader :path, :options
+
+ def initialize(cask, path, **options)
+ super(cask)
+ @path = cask.staged_path.join(path)
+ @options = options
end
- def pkg_install_opts(opt)
- @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys)
+ def summarize
+ path.relative_path_from(cask.staged_path).to_s
end
- def install_phase
- @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) }
+ def install_phase(**options)
+ run_installer(**options)
end
- def run_installer(pkg_description)
- load_pkg_description pkg_description
- ohai "Running installer for #{@cask}; your password may be necessary."
+ private
+
+ def run_installer(command: nil, verbose: false, **options)
+ ohai "Running installer for #{cask}; your password may be necessary."
ohai "Package installers may write to any location; options such as --appdir are ignored."
- source = @cask.staged_path.join(pkg_relative_path)
- unless source.exist?
- raise CaskError, "pkg source file not found: '#{source}'"
+ unless path.exist?
+ raise CaskError, "pkg source file not found: '#{path.relative_path_from(cask.staged_path)}'"
end
args = [
- "-pkg", source,
+ "-pkg", path,
"-target", "/"
]
- args << "-verboseR" if verbose?
- args << "-allowUntrusted" if pkg_install_opts :allow_untrusted
+ args << "-verboseR" if verbose
+ args << "-allowUntrusted" if options.fetch(:allow_untrusted, false)
with_choices_file do |choices_path|
args << "-applyChoiceChangesXML" << choices_path if choices_path
- @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
+ command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
end
end
def with_choices_file
- return yield nil unless pkg_install_opts(:choices)
+ choices = options.fetch(:choices, {})
+ return yield nil if choices.empty?
Tempfile.open(["choices", ".xml"]) do |file|
begin
- file.write Plist::Emit.dump(pkg_install_opts(:choices))
+ file.write Plist::Emit.dump(choices)
file.close
yield file.path
ensure
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
index a44f8ae3a..87f120934 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
@@ -3,7 +3,7 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Prefpane < Moved
- def self.artifact_english_name
+ def self.english_name
"Preference Pane"
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
index ee41de2fe..298714d89 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
@@ -3,22 +3,24 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Qlplugin < Moved
- def self.artifact_english_name
+ def self.english_name
"QuickLook Plugin"
end
- def install_phase
- super
- reload_quicklook
+ def install_phase(**options)
+ super(**options)
+ reload_quicklook(**options)
end
- def uninstall_phase
- super
- reload_quicklook
+ def uninstall_phase(**options)
+ super(**options)
+ reload_quicklook(**options)
end
- def reload_quicklook
- @command.run!("/usr/bin/qlmanage", args: ["-r"])
+ private
+
+ def reload_quicklook(command: nil, **_)
+ command.run!("/usr/bin/qlmanage", args: ["-r"])
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
index 4dba46c9d..540699630 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
@@ -1,65 +1,79 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
require "hbc/utils/hash_validator"
module Hbc
module Artifact
- class Relocated < Base
- def summary
- {
- english_description: self.class.english_description,
- contents: @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact,
- }
+ class Relocated < AbstractArtifact
+ def self.from_args(cask, *args)
+ source_string, target_hash = args
+
+ if target_hash
+ raise CaskInvalidError unless target_hash.respond_to?(:keys)
+ target_hash.extend(HashValidator).assert_valid_keys(:target)
+ end
+
+ target_hash ||= {}
+
+ new(cask, source_string, **target_hash)
+ end
+
+ def self.resolve_target(target)
+ Hbc.public_send(dirmethod).join(target)
end
attr_reader :source, :target
- def printable_target
- target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
+ def initialize(cask, source, target: nil)
+ super(cask)
+
+ @source_string = source.to_s
+ @target_string = target.to_s
+ source = cask.staged_path.join(source)
+ @source = source
+ target ||= source.basename
+ @target = self.class.resolve_target(target)
end
+ def to_a
+ [@source_string].tap do |ary|
+ ary << { target: @target_string } unless @target_string.empty?
+ end
+ end
+
+ def summarize
+ target_string = @target_string.empty? ? "" : " -> #{@target_string}"
+ "#{@source_string}#{target_string}"
+ end
+
+ private
+
ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze
# Try to make the asset searchable under the target name. Spotlight
# respects this attribute for many filetypes, but ignores it for App
# bundles. Alfred 2.2 respects it even for App bundles.
- def add_altname_metadata(file, altname)
- return if altname.casecmp(file.basename).zero?
+ def add_altname_metadata(file, altname, command: nil)
+ return if altname.to_s.casecmp(file.basename.to_s).zero?
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
- altnames = @command.run("/usr/bin/xattr",
- args: ["-p", ALT_NAME_ATTRIBUTE, file.to_s],
+ altnames = command.run("/usr/bin/xattr",
+ args: ["-p", ALT_NAME_ATTRIBUTE, file],
print_stderr: false).stdout.sub(/\A\((.*)\)\Z/, '\1')
odebug "Existing metadata is: '#{altnames}'"
altnames.concat(", ") unless altnames.empty?
altnames.concat(%Q("#{altname}"))
altnames = "(#{altnames})"
- # Some packges are shipped as u=rx (e.g. Bitcoin Core)
- @command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
+ # Some packages are shipped as u=rx (e.g. Bitcoin Core)
+ command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
- @command.run!("/usr/bin/xattr",
+ command.run!("/usr/bin/xattr",
args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file],
print_stderr: false)
end
- def each_artifact
- @cask.artifacts[self.class.artifact_dsl_key].each do |artifact|
- load_specification(artifact)
- yield
- end
- end
-
- def load_specification(artifact_spec)
- source_string, target_hash = artifact_spec
- raise CaskInvalidError if source_string.nil?
- @source = @cask.staged_path.join(source_string)
- if target_hash
- raise CaskInvalidError unless target_hash.respond_to?(:keys)
- target_hash.extend(HashValidator).assert_valid_keys(:target)
- @target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target])
- else
- @target = Hbc.send(self.class.artifact_dirmethod).join(source.basename)
- end
+ def printable_target
+ target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
index 1122c1d02..8c32a52d0 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
@@ -1,10 +1,22 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class StageOnly < Base
- def self.artifact_dsl_key
- :stage_only
+ class StageOnly < AbstractArtifact
+ def self.from_args(cask, *args)
+ if args != [true]
+ raise CaskInvalidError.new(cask.token, "'stage_only' takes only a single argument: true")
+ end
+
+ new(cask)
+ end
+
+ def initialize(cask)
+ super(cask)
+ end
+
+ def to_a
+ [true]
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
index 35251f70c..59ae58cf1 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
@@ -3,11 +3,11 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Suite < Moved
- def self.artifact_english_name
+ def self.english_name
"App Suite"
end
- def self.artifact_dirmethod
+ def self.dirmethod
:appdir
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
index 16715fe81..3726ebb5c 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
@@ -8,58 +8,56 @@ module Hbc
end
def self.english_description
- "#{artifact_english_name} #{link_type_english_name}s"
+ "#{english_name} #{link_type_english_name}s"
end
- def install_phase
- each_artifact(&method(:link))
+ def install_phase(**options)
+ link(**options)
end
- def uninstall_phase
- each_artifact(&method(:unlink))
+ def uninstall_phase(**options)
+ unlink(**options)
+ end
+
+ def summarize_installed
+ if target.symlink? && target.exist? && target.readlink.exist?
+ "#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
+ else
+ string = if target.symlink?
+ "#{printable_target} -> #{target.readlink}"
+ else
+ printable_target
+ end
+
+ Formatter.error(string, label: "Broken Link")
+ end
end
private
- def link
+ def link(**options)
unless source.exist?
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source '#{source}' is not there."
end
if target.exist? && !target.symlink?
- raise CaskError, "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking."
+ raise CaskError, "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'; not linking."
end
- ohai "Linking #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
- create_filesystem_link(source, target)
+ ohai "Linking #{self.class.english_name} '#{source.basename}' to '#{target}'."
+ create_filesystem_link(**options)
end
- def unlink
+ def unlink(**)
return unless target.symlink?
- ohai "Unlinking #{self.class.artifact_english_name} '#{target}'."
+ ohai "Unlinking #{self.class.english_name} '#{target}'."
target.delete
end
- def create_filesystem_link(source, target)
+ def create_filesystem_link(command: nil, **_)
target.dirname.mkpath
- @command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
- add_altname_metadata source, target.basename.to_s
- end
-
- def summarize_artifact(artifact_spec)
- load_specification artifact_spec
-
- if target.symlink? && target.exist? && target.readlink.exist?
- "#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
- else
- string = if target.symlink?
- "#{printable_target} -> #{target.readlink}"
- else
- printable_target
- end
-
- Formatter.error(string, label: "Broken Link")
- end
+ command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
+ add_altname_metadata(source, target.basename, command: command)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
index 5a3dc098d..2bbf82862 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
@@ -1,10 +1,10 @@
-require "hbc/artifact/uninstall_base"
+require "hbc/artifact/abstract_uninstall"
module Hbc
module Artifact
- class Uninstall < UninstallBase
- def uninstall_phase
- dispatch_uninstall_directives
+ class Uninstall < AbstractUninstall
+ def uninstall_phase(**options)
+ dispatch_uninstall_directives(**options)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
index cdfe2531d..31ff54d20 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
@@ -1,10 +1,10 @@
-require "hbc/artifact/uninstall_base"
+require "hbc/artifact/abstract_uninstall"
module Hbc
module Artifact
- class Zap < UninstallBase
- def zap_phase
- dispatch_uninstall_directives
+ class Zap < AbstractUninstall
+ def zap_phase(**options)
+ dispatch_uninstall_directives(**options)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb
index b8bb6ab81..03d8cce82 100644
--- a/Library/Homebrew/cask/lib/hbc/audit.rb
+++ b/Library/Homebrew/cask/lib/hbc/audit.rb
@@ -214,12 +214,10 @@ module Hbc
end
def check_generic_artifacts
- cask.artifacts[:artifact].each do |source, target_hash|
- unless target_hash.is_a?(Hash) && target_hash[:target]
- add_error "target required for generic artifact #{source}"
- next
+ cask.artifacts[:artifact].each do |artifact|
+ unless artifact.target.absolute?
+ add_error "target must be absolute path for #{artifact.class.english_name} #{artifact.source}"
end
- add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute?
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb
index 6d89a997c..72a23066f 100644
--- a/Library/Homebrew/cask/lib/hbc/cask.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask.rb
@@ -17,7 +17,7 @@ module Hbc
@token = token
@sourcefile_path = sourcefile_path
@tap = tap
- @dsl = DSL.new(@token)
+ @dsl = DSL.new(self)
return unless block_given?
@dsl.instance_eval(&block)
@dsl.language_eval
@@ -41,6 +41,14 @@ module Hbc
.reverse
end
+ def full_name
+ if @tap.nil? || @tap == Hbc.default_tap
+ token
+ else
+ "#{@tap}/#{token}"
+ end
+ end
+
def installed?
!versions.empty?
end
diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb
index dd9c61089..8fce9636a 100644
--- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb
@@ -56,7 +56,7 @@ module Hbc
class FromURILoader < FromPathLoader
def self.can_load?(ref)
- ref.to_s.match?(::URI.regexp)
+ ref.to_s.match?(::URI::DEFAULT_PARSER.make_regexp)
end
attr_reader :url
@@ -116,6 +116,22 @@ module Hbc
end
end
+ class FromInstanceLoader
+ attr_reader :cask
+
+ def self.can_load?(ref)
+ ref.is_a?(Cask)
+ end
+
+ def initialize(cask)
+ @cask = cask
+ end
+
+ def load
+ cask
+ end
+ end
+
class NullLoader < FromPathLoader
def self.can_load?(*)
true
@@ -149,6 +165,7 @@ module Hbc
def self.for(ref)
[
+ FromInstanceLoader,
FromURILoader,
FromTapLoader,
FromTapPathLoader,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
index 77f85301e..001a9623b 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
@@ -42,41 +42,32 @@ module Hbc
@args = process_arguments(*args)
end
- def self.warn_unavailable_with_suggestion(cask_token, e)
- exact_match, partial_matches = Search.search(cask_token)
- error_message = e.message
- if exact_match
- error_message.concat(" Did you mean:\n#{exact_match}")
- elsif !partial_matches.empty?
- error_message.concat(" Did you mean one of:\n")
- .concat(Formatter.columns(partial_matches.take(20)))
- end
- onoe error_message
- end
-
private
def casks(alternative: -> { [] })
- return to_enum(:casks, alternative: alternative) unless block_given?
-
- count = 0
-
+ return @casks if defined?(@casks)
casks = args.empty? ? alternative.call : args
+ @casks = casks.map { |cask| CaskLoader.load(cask) }
+ rescue CaskUnavailableError => e
+ reason = [e.reason, suggestion_message(e.token)].join(" ")
+ raise e.class.new(e.token, reason)
+ end
+
+ def suggestion_message(cask_token)
+ exact_match, partial_matches = Search.search(cask_token)
- casks.each do |cask_or_token|
- begin
- yield cask_or_token.respond_to?(:token) ? cask_or_token : CaskLoader.load(cask_or_token)
- count += 1
- rescue CaskUnavailableError => e
- cask_token = cask_or_token
- self.class.warn_unavailable_with_suggestion cask_token, e
- rescue CaskError => e
- onoe e.message
- end
+ if exact_match.nil? && partial_matches.count == 1
+ exact_match = partial_matches.first
end
- return :empty if casks.length.zero?
- (count == casks.length) ? :complete : :incomplete
+ if exact_match
+ "Did you mean “#{exact_match}”?"
+ elsif !partial_matches.empty?
+ "Did you mean one of these?\n"
+ .concat(Formatter.columns(partial_matches.take(20)))
+ else
+ ""
+ end
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/cat.rb b/Library/Homebrew/cask/lib/hbc/cli/cat.rb
index d08c87bea..043080556 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/cat.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/cat.rb
@@ -7,10 +7,6 @@ module Hbc
end
def run
- raise CaskError, "Cat incomplete." if cat_casks == :incomplete
- end
-
- def cat_casks
casks.each do |cask|
puts File.open(cask.sourcefile_path, &:read)
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb
index b9485886c..8bce81c52 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb
@@ -4,21 +4,18 @@ module Hbc
def initialize(*)
super
raise CaskUnspecifiedError if args.empty?
- raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1
+ raise ArgumentError, "Only one Cask can be edited at a time." if args.count > 1
end
def run
- cask_token = args.first
- cask_path = begin
- CaskLoader.load(cask_token).sourcefile_path
- rescue CaskUnavailableError => e
- reason = e.reason.empty? ? "" : "#{e.reason} "
- reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
- raise e.class.new(e.token, reason)
- end
-
- odebug "Opening editor for Cask #{cask_token}"
+ cask = casks.first
+ cask_path = cask.sourcefile_path
+ odebug "Opening editor for Cask #{cask.token}"
exec_editor cask_path
+ rescue CaskUnavailableError => e
+ reason = e.reason.empty? ? "" : "#{e.reason} "
+ reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
+ raise e.class.new(e.token, reason)
end
def self.help
diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
index e31b1a17c..12c794f5f 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Fetch incomplete." if fetch_casks == :incomplete
- end
-
- def fetch_casks
casks.each do |cask|
ohai "Downloading external files for Cask #{cask}"
downloaded_path = Download.new(cask, force: force?).perform
diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb
index d26747e17..9cdada62e 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/info.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb
@@ -69,13 +69,11 @@ module Hbc
def self.artifact_info(cask)
ohai "Artifacts"
- DSL::ORDINARY_ARTIFACT_TYPES.each do |type|
- next if cask.artifacts[type].empty?
- cask.artifacts[type].each do |artifact|
- activatable_item = (type == :stage_only) ? "<none>" : artifact.first
- puts "#{activatable_item} (#{type})"
- end
- end
+ DSL::ORDINARY_ARTIFACT_CLASSES.flat_map { |klass| klass.for_cask(cask) }
+ .select { |artifact| artifact.respond_to?(:install_phase) }
+ .each do |artifact|
+ puts artifact.to_s
+ end
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/install.rb b/Library/Homebrew/cask/lib/hbc/cli/install.rb
index 0f1a5dd34..9a2116e6a 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/install.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb
@@ -10,10 +10,6 @@ module Hbc
end
def run
- raise CaskError, "Install incomplete." if install_casks == :incomplete
- end
-
- def install_casks
casks.each do |cask|
begin
Installer.new(cask, binaries: binaries?,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
index cd2679782..a538ffd8c 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
@@ -12,7 +12,7 @@ module Hbc
if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
self.class.appcask_checkpoint_for_url(args)
else
- self.class.appcask_checkpoint(args, calculate?)
+ self.class.appcask_checkpoint(casks, calculate?)
end
end
@@ -23,33 +23,27 @@ module Hbc
end
end
- def self.appcask_checkpoint(cask_tokens, calculate)
- count = 0
-
- cask_tokens.each do |cask_token|
- cask = CaskLoader.load(cask_token)
-
+ def self.appcask_checkpoint(casks, calculate)
+ casks.each do |cask|
if cask.appcast.nil?
opoo "Cask '#{cask}' is missing an `appcast` stanza."
else
- if calculate
+ checkpoint = if calculate
result = cask.appcast.calculate_checkpoint
-
- checkpoint = result[:checkpoint]
+ result[:checkpoint]
else
- checkpoint = cask.appcast.checkpoint
+ cask.appcast.checkpoint
end
- if checkpoint.nil?
+ if calculate && checkpoint.nil?
onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}"
+ elsif casks.count > 1
+ puts "#{checkpoint} #{cask}"
else
- puts((cask_tokens.count > 1) ? "#{checkpoint} #{cask}" : checkpoint)
- count += 1
+ puts checkpoint
end
end
end
-
- count == cask_tokens.count
end
def self.help
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
index e21ce86b6..8a38ce1be 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
@@ -7,10 +7,6 @@ module Hbc
end
def run
- raise CaskError, "Dump incomplete." if dump_casks == :incomplet
- end
-
- def dump_casks
casks.each(&:dumpcask)
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
index 4515fe931..c04619798 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
@@ -3,7 +3,7 @@ module Hbc
class InternalStanza < AbstractInternalCommand
# Syntax
#
- # brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ]
+ # brew cask _stanza <stanza_name> [ --quiet ] [ --table | --yaml ] [ <cask_token> ... ]
#
# If no tokens are given, then data for all Casks is returned.
#
@@ -14,41 +14,16 @@ module Hbc
# Examples
#
# brew cask _stanza appcast --table
- # brew cask _stanza app --table alfred google-chrome adium voicemac logisim vagrant
- # brew cask _stanza url --table alfred google-chrome adium voicemac logisim vagrant
- # brew cask _stanza version --table alfred google-chrome adium voicemac logisim vagrant
- # brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant
- # brew cask _stanza artifacts --table --yaml alfred google-chrome adium voicemac logisim vagrant
+ # brew cask _stanza app --table alfred google-chrome adium vagrant
+ # brew cask _stanza url --table alfred google-chrome adium vagrant
+ # brew cask _stanza version --table alfred google-chrome adium vagrant
+ # brew cask _stanza artifacts --table alfred google-chrome adium vagrant
+ # brew cask _stanza artifacts --table --yaml alfred google-chrome adium vagrant
#
- # TODO: this should be retrievable from Hbc::DSL
- ARTIFACTS = Set.new [
- :app,
- :suite,
- :artifact,
- :prefpane,
- :qlplugin,
- :dictionary,
- :font,
- :service,
- :colorpicker,
- :binary,
- :input_method,
- :internet_plugin,
- :audio_unit_plugin,
- :vst_plugin,
- :vst3_plugin,
- :screen_saver,
- :pkg,
- :installer,
- :stage_only,
- :nested_container,
- :uninstall,
- :preflight,
- :postflight,
- :uninstall_preflight,
- :uninstall_postflight,
- ]
+ ARTIFACTS =
+ DSL::ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) +
+ DSL::ARTIFACT_BLOCK_CLASSES.map(&:dsl_key)
option "--table", :table, false
option "--quiet", :quiet, false
@@ -68,16 +43,9 @@ module Hbc
@stanza = args.shift.to_sym
@format = :to_yaml if yaml?
- @format = :inspect if inspect?
end
def run
- return unless print_stanzas == :incomplete
- exit 1 if quiet?
- raise CaskError, "Print incomplete."
- end
-
- def print_stanzas
if ARTIFACTS.include?(stanza)
artifact_name = stanza
@stanza = :artifacts
@@ -93,7 +61,7 @@ module Hbc
end
begin
- value = cask.send(@stanza)
+ value = cask.send(stanza)
rescue StandardError
opoo "failure calling '#{stanza}' on Cask '#{cask}'" unless quiet?
puts ""
@@ -106,11 +74,25 @@ module Hbc
next
end
- value = value.fetch(artifact_name).to_a.flatten if artifact_name
+ if stanza == :artifacts
+ value = Hash[
+ value.map do |k, v|
+ v = v.map do |a|
+ next a.to_a if a.respond_to?(:to_a)
+ next a.to_h if a.respond_to?(:to_h)
+ a
+ end
+
+ [k, v]
+ end
+ ]
+
+ value = value.fetch(artifact_name) if artifact_name
+ end
- if @format
- puts value.send(@format)
- elsif artifact_name || value.is_a?(Symbol)
+ if format
+ puts value.send(format)
+ elsif value.is_a?(Symbol)
puts value.inspect
else
puts value.to_s
diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb
index 9d978360e..32415af8a 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/list.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb
@@ -3,6 +3,7 @@ module Hbc
class List < AbstractCommand
option "-1", :one, false
option "--versions", :versions, false
+ option "--full-name", :full_name, false
option "-l", (lambda do |*|
one = true # rubocop:disable Lint/UselessAssignment
@@ -10,8 +11,7 @@ module Hbc
end)
def run
- retval = args.any? ? list : list_installed
- raise CaskError, "Listing incomplete." if retval == :incomplete
+ args.any? ? list : list_installed
end
def list
@@ -30,9 +30,9 @@ module Hbc
end
def self.list_artifacts(cask)
- Artifact.for_cask(cask).each do |artifact|
- summary = artifact.summary
- ohai summary[:english_description], summary[:contents] unless summary.empty?
+ Artifact.for_cask(cask).group_by(&:class).each do |klass, artifacts|
+ next unless klass.respond_to?(:english_description)
+ ohai klass.english_description, artifacts.map(&:summarize_installed)
end
end
@@ -43,11 +43,11 @@ module Hbc
puts installed_casks.map(&:to_s)
elsif versions?
puts installed_casks.map(&self.class.method(:format_versioned))
+ elsif full_name?
+ puts installed_casks.map(&:full_name).sort &tap_and_name_comparison
elsif !installed_casks.empty?
puts Formatter.columns(installed_casks.map(&:to_s))
end
-
- installed_casks.empty? ? :empty : :complete
end
def self.format_versioned(cask)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
index 337a2eb9d..408be134d 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
@@ -1,7 +1,7 @@
module Hbc
class CLI
class Reinstall < Install
- def install_casks
+ def run
casks.each do |cask|
Installer.new(cask, binaries: binaries?,
verbose: verbose?,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb
index e89dced92..d56d0c81f 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/search.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb
@@ -2,8 +2,12 @@ module Hbc
class CLI
class Search < AbstractCommand
def run
- results = self.class.search(*args)
- self.class.render_results(*results)
+ if args.empty?
+ puts Formatter.columns(CLI.nice_listing(Hbc.all_tokens))
+ else
+ results = self.class.search(*args)
+ self.class.render_results(*results)
+ end
end
def self.extract_regexp(string)
@@ -15,8 +19,17 @@ module Hbc
end
def self.search_remote(query)
- matches = GitHub.search_code(user: "caskroom", path: "Casks",
- filename: query, extension: "rb")
+ matches = begin
+ GitHub.search_code(
+ user: "caskroom",
+ path: "Casks",
+ filename: query,
+ extension: "rb",
+ )
+ rescue GitHub::Error => error
+ opoo "Error searching on GitHub: #{error}\n"
+ []
+ end
matches.map do |match|
tap = Tap.fetch(match["repository"]["full_name"])
next if tap.installed?
diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
index c0697c808..7e55db5f1 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Uninstall incomplete." if uninstall_casks == :incomplete
- end
-
- def uninstall_casks
casks.each do |cask|
odebug "Uninstalling Cask #{cask}"
diff --git a/Library/Homebrew/cask/lib/hbc/cli/zap.rb b/Library/Homebrew/cask/lib/hbc/cli/zap.rb
index e709f4191..7f5e6785d 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/zap.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/zap.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Zap incomplete." if zap_casks == :incomplete
- end
-
- def zap_casks
casks.each do |cask|
odebug "Zapping Cask #{cask}"
Installer.new(cask, verbose: verbose?, force: force?).zap
diff --git a/Library/Homebrew/cask/lib/hbc/container/naked.rb b/Library/Homebrew/cask/lib/hbc/container/naked.rb
index 375d62f7a..dc265c402 100644
--- a/Library/Homebrew/cask/lib/hbc/container/naked.rb
+++ b/Library/Homebrew/cask/lib/hbc/container/naked.rb
@@ -16,7 +16,7 @@ module Hbc
def target_file
return @path.basename if @nested
- URI.decode(File.basename(@cask.url.path))
+ CGI.unescape(File.basename(@cask.url.path))
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 8ad206c2f..3824b9761 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl.rb
@@ -1,6 +1,8 @@
require "set"
require "locale"
+require "hbc/artifact"
+
require "hbc/dsl/appcast"
require "hbc/dsl/base"
require "hbc/dsl/caveats"
@@ -8,7 +10,6 @@ require "hbc/dsl/conflicts_with"
require "hbc/dsl/container"
require "hbc/dsl/depends_on"
require "hbc/dsl/gpg"
-require "hbc/dsl/installer"
require "hbc/dsl/postflight"
require "hbc/dsl/preflight"
require "hbc/dsl/stanza_proxy"
@@ -18,39 +19,35 @@ require "hbc/dsl/version"
module Hbc
class DSL
- ORDINARY_ARTIFACT_TYPES = [
- :app,
- :artifact,
- :audio_unit_plugin,
- :binary,
- :colorpicker,
- :dictionary,
- :font,
- :input_method,
- :internet_plugin,
- :pkg,
- :prefpane,
- :qlplugin,
- :screen_saver,
- :service,
- :stage_only,
- :suite,
- :vst_plugin,
- :vst3_plugin,
+ ORDINARY_ARTIFACT_CLASSES = [
+ Artifact::Installer,
+ Artifact::App,
+ Artifact::Artifact,
+ Artifact::AudioUnitPlugin,
+ Artifact::Binary,
+ Artifact::Colorpicker,
+ Artifact::Dictionary,
+ Artifact::Font,
+ Artifact::InputMethod,
+ Artifact::InternetPlugin,
+ Artifact::Pkg,
+ Artifact::Prefpane,
+ Artifact::Qlplugin,
+ Artifact::ScreenSaver,
+ Artifact::Service,
+ Artifact::StageOnly,
+ Artifact::Suite,
+ Artifact::VstPlugin,
+ Artifact::Vst3Plugin,
+ Artifact::Uninstall,
+ Artifact::Zap,
].freeze
- ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze
-
- SPECIAL_ARTIFACT_TYPES = [
- :uninstall,
- :zap,
- ].freeze
+ ACTIVATABLE_ARTIFACT_TYPES = (ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) - [:stage_only]).freeze
- ARTIFACT_BLOCK_TYPES = [
- :preflight,
- :postflight,
- :uninstall_preflight,
- :uninstall_postflight,
+ ARTIFACT_BLOCK_CLASSES = [
+ Artifact::PreflightBlock,
+ Artifact::PostflightBlock,
].freeze
DSL_METHODS = Set.new [
@@ -72,15 +69,15 @@ module Hbc
:url,
:version,
:appdir,
- *ORDINARY_ARTIFACT_TYPES,
+ *ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
*ACTIVATABLE_ARTIFACT_TYPES,
- *SPECIAL_ARTIFACT_TYPES,
- *ARTIFACT_BLOCK_TYPES,
+ *ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] },
].freeze
- attr_reader :token
- def initialize(token)
- @token = token
+ attr_reader :token, :cask
+ def initialize(cask)
+ @cask = cask
+ @token = cask.token
end
def name(*args)
@@ -93,12 +90,14 @@ module Hbc
return instance_variable_get("@#{stanza}") if should_return
if instance_variable_defined?("@#{stanza}")
- raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once")
+ raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
end
instance_variable_set("@#{stanza}", yield)
+ rescue CaskInvalidError
+ raise
rescue StandardError => e
- raise CaskInvalidError.new(token, "'#{stanza}' stanza failed with: #{e}")
+ raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
end
def homepage(homepage = nil)
@@ -113,7 +112,7 @@ module Hbc
return unless default
unless @language_blocks.default.nil?
- raise CaskInvalidError.new(token, "Only one default language may be defined")
+ raise CaskInvalidError.new(cask, "Only one default language may be defined.")
end
@language_blocks.default = block
@@ -162,8 +161,8 @@ module Hbc
begin
DSL::Container.new(*args).tap do |container|
# TODO: remove this backward-compatibility section after removing nested_container
- if container && container.nested
- artifacts[:nested_container] << container.nested
+ if container&.nested
+ artifacts[:nested_container] << Artifact::NestedContainer.new(cask, container.nested)
end
end
end
@@ -173,7 +172,7 @@ module Hbc
def version(arg = nil)
set_unique_stanza(:version, arg.nil?) do
if !arg.is_a?(String) && arg != :latest
- raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'")
+ raise CaskInvalidError.new(cask, "invalid 'version' value: '#{arg.inspect}'")
end
DSL::Version.new(arg)
end
@@ -182,7 +181,7 @@ module Hbc
def sha256(arg = nil)
set_unique_stanza(:sha256, arg.nil?) do
if !arg.is_a?(String) && arg != :no_check
- raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'")
+ raise CaskInvalidError.new(cask, "invalid 'sha256' value: '#{arg.inspect}'")
end
arg
end
@@ -195,7 +194,7 @@ module Hbc
begin
@depends_on.load(*args)
rescue RuntimeError => e
- raise CaskInvalidError.new(token, e)
+ raise CaskInvalidError.new(cask, e)
end
@depends_on
end
@@ -237,39 +236,29 @@ module Hbc
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
end
- ORDINARY_ARTIFACT_TYPES.each do |type|
+ ORDINARY_ARTIFACT_CLASSES.each do |klass|
+ type = klass.dsl_key
+
define_method(type) do |*args|
- if type == :stage_only
- if args != [true]
- raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
+ begin
+ if [*artifacts.keys, type].include?(:stage_only) && (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).any?
+ raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.")
end
- unless (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty?
- raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact")
- end
+ artifacts[type].add(klass.from_args(cask, *args))
+ rescue CaskInvalidError
+ raise
+ rescue StandardError => e
+ raise CaskInvalidError.new(cask, "invalid '#{klass.dsl_key}' stanza: #{e}")
end
-
- artifacts[type].add(args)
end
end
- def installer(*args)
- return artifacts[:installer] if args.empty?
- artifacts[:installer] << DSL::Installer.new(*args)
- raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only)
- rescue StandardError => e
- raise CaskInvalidError.new(token, e)
- end
-
- SPECIAL_ARTIFACT_TYPES.each do |type|
- define_method(type) do |*args|
- artifacts[type].merge(args)
- end
- end
-
- ARTIFACT_BLOCK_TYPES.each do |type|
- define_method(type) do |&block|
- artifacts[type] << block
+ ARTIFACT_BLOCK_CLASSES.each do |klass|
+ [klass.dsl_key, klass.uninstall_dsl_key].each do |dsl_key|
+ define_method(dsl_key) do |&block|
+ artifacts[dsl_key] << block
+ end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb
deleted file mode 100644
index b01b28d76..000000000
--- a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-module Hbc
- class DSL
- class Installer
- VALID_KEYS = Set.new [
- :manual,
- :script,
- ]
-
- attr_accessor(*VALID_KEYS)
-
- def initialize(*parameters)
- raise CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty?
- parameters = {}.merge(*parameters)
- if parameters.key?(:script) && !parameters[:script].respond_to?(:key?)
- if parameters.key?(:executable)
- raise CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable")
- end
- parameters[:executable] = parameters[:script]
- parameters.delete(:script)
- parameters = { script: parameters }
- end
- unless parameters.keys.length == 1
- raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted"
- end
- key = parameters.keys.first
- raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key)
- writer_method = "#{key}=".to_sym
- send(writer_method, parameters[key])
- end
- end
- end
-end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/version.rb b/Library/Homebrew/cask/lib/hbc/dsl/version.rb
index d73205f52..9605feb57 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/version.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/version.rb
@@ -49,7 +49,7 @@ module Hbc
end
end
- DIVIDERS.keys.each do |divider|
+ DIVIDERS.each_key do |divider|
define_divider_methods(divider)
end
diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index 37cc4e561..01aae935d 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -159,7 +159,7 @@ module Hbc
odebug "Extracting primary container"
FileUtils.mkdir_p @cask.staged_path
- container = if @cask.container && @cask.container.type
+ container = if @cask.container&.type
Container.from_type(@cask.container.type)
else
Container.for_path(@downloaded_path, @command)
@@ -177,7 +177,7 @@ module Hbc
already_installed_artifacts = []
odebug "Installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = Artifact.for_cask(@cask)
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
@@ -188,7 +188,7 @@ module Hbc
next unless binaries?
end
- artifact.install_phase
+ artifact.install_phase(command: @command, verbose: verbose?, force: force?)
already_installed_artifacts.unshift(artifact)
end
rescue StandardError => e
@@ -196,7 +196,7 @@ module Hbc
already_installed_artifacts.each do |artifact|
next unless artifact.respond_to?(:uninstall_phase)
odebug "Reverting installation of artifact of class #{artifact.class}"
- artifact.uninstall_phase
+ artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
end
ensure
purge_versioned_files
@@ -361,7 +361,7 @@ module Hbc
savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
FileUtils.copy @cask.sourcefile_path, savedir
- old_savedir.rmtree unless old_savedir.nil?
+ old_savedir&.rmtree
end
def uninstall
@@ -374,25 +374,27 @@ module Hbc
def uninstall_artifacts
odebug "Un-installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = Artifact.for_cask(@cask)
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
next unless artifact.respond_to?(:uninstall_phase)
odebug "Un-installing artifact of class #{artifact.class}"
- artifact.uninstall_phase
+ artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
end
end
def zap
ohai %Q(Implied "brew cask uninstall #{@cask}")
uninstall_artifacts
- if Artifact::Zap.me?(@cask)
- ohai "Dispatching zap stanza"
- Artifact::Zap.new(@cask, command: @command).zap_phase
- else
+ if (zap_stanzas = Artifact::Zap.for_cask(@cask)).empty?
opoo "No zap stanza present for Cask '#{@cask}'"
+ else
+ ohai "Dispatching zap stanza"
+ zap_stanzas.each do |stanza|
+ stanza.zap_phase(command: @command, verbose: verbose?, force: force?)
+ end
end
ohai "Removing all staged versions of Cask '#{@cask}'"
purge_caskroom_path
diff --git a/Library/Homebrew/cask/lib/hbc/staged.rb b/Library/Homebrew/cask/lib/hbc/staged.rb
index c1aa01b29..dc21279de 100644
--- a/Library/Homebrew/cask/lib/hbc/staged.rb
+++ b/Library/Homebrew/cask/lib/hbc/staged.rb
@@ -4,7 +4,7 @@ module Hbc
index = 0 if index == :first
index = 1 if index == :second
index = -1 if index == :last
- Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist")
+ @cask.artifacts[:app].to_a.at(index).target.join("Contents", "Info.plist")
end
def plist_exec(cmd)
diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb
index b735ae4f9..be083c29e 100644
--- a/Library/Homebrew/cask/lib/hbc/system_command.rb
+++ b/Library/Homebrew/cask/lib/hbc/system_command.rb
@@ -61,7 +61,7 @@ module Hbc
end
def assert_success
- return if processed_status && processed_status.success?
+ return if processed_status&.success?
raise CaskCommandFailedError.new(command, processed_output[:stdout], processed_output[:stderr], processed_status)
end