aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.rb42
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb)130
-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.rb91
-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.rb74
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb16
-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.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/info.rb12
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb37
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/list.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl.rb129
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/installer.rb32
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/staged.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/alt_target_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/app_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/artifact/binary_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb12
-rw-r--r--Library/Homebrew/test/cask/artifact/nested_container_spec.rb3
-rw-r--r--Library/Homebrew/test/cask/artifact/pkg_spec.rb8
-rw-r--r--Library/Homebrew/test/cask/artifact/postflight_block_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/artifact/preflight_block_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/artifact/suite_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb26
-rw-r--r--Library/Homebrew/test/cask/audit_spec.rb9
-rw-r--r--Library/Homebrew/test/cask/cli/info_spec.rb10
-rw-r--r--Library/Homebrew/test/cask/cli/list_spec.rb3
-rw-r--r--Library/Homebrew/test/cask/dsl_spec.rb24
43 files changed, 555 insertions, 535 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..6670d4249 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,47 @@
-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
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..9499d5c03 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,33 @@ 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 = directives
+ 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 +58,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 +77,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 +118,15 @@ module Hbc
end
# :signal should come after :quit so it can be used as a backup when :quit fails
- def uninstall_signal(*signals)
+ def uninstall_signal(*signals, **options)
signals.flatten.each_slice(2) 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, **options).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 +140,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 +151,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 +176,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 +223,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 +268,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 +276,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..64ce2d4bc 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
@@ -1,30 +1,77 @@
-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
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 0e8e42c9b..72a6f6bb5 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
@@ -1,33 +1,57 @@
-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 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?
@@ -35,31 +59,15 @@ module Hbc
altnames = "(#{altnames})"
# Some packages are shipped as u=rx (e.g. Bitcoin Core)
- @command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
+ 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..7aef66469 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
@@ -1,10 +1,18 @@
-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
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..27f8ae791 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
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/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
index 4515fe931..2727f95b7 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
@@ -21,34 +21,9 @@ module Hbc
# brew cask _stanza artifacts --table --yaml alfred google-chrome adium voicemac logisim 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
@@ -93,7 +68,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 ""
@@ -108,8 +83,8 @@ module Hbc
value = value.fetch(artifact_name).to_a.flatten if artifact_name
- if @format
- puts value.send(@format)
+ if format
+ puts value.send(format)
elsif artifact_name || value.is_a?(Symbol)
puts value.inspect
else
diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb
index 9d978360e..4b5fcd873 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/list.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb
@@ -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
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 8ad206c2f..2dda47627 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
@@ -163,7 +162,7 @@ module Hbc
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
+ 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/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index 37cc4e561..b9c34e3a1 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -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
@@ -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/test/cask/artifact/alt_target_spec.rb b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
index 9e8d83bb4..02be796ed 100644
--- a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
@@ -3,7 +3,7 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-alt-target.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path) { cask.staged_path.join("Caffeine.app") }
diff --git a/Library/Homebrew/test/cask/artifact/app_spec.rb b/Library/Homebrew/test/cask/artifact/app_spec.rb
index 0add472e2..f67ffd31b 100644
--- a/Library/Homebrew/test/cask/artifact/app_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/app_spec.rb
@@ -2,13 +2,13 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") }
let(:command) { Hbc::SystemCommand }
let(:force) { false }
- let(:app) { Hbc::Artifact::App.new(cask, command: command, force: force) }
+ let(:app) { described_class.for_cask(cask).first }
let(:source_path) { cask.staged_path.join("Caffeine.app") }
let(:target_path) { Hbc.appdir.join("Caffeine.app") }
- let(:install_phase) { app.install_phase }
- let(:uninstall_phase) { app.uninstall_phase }
+ let(:install_phase) { app.install_phase(command: command, force: force) }
+ let(:uninstall_phase) { app.uninstall_phase(command: command, force: force) }
before(:each) do
InstallHelper.install_without_artifacts(cask)
@@ -105,8 +105,8 @@ describe Hbc::Artifact::App, :cask do
describe "target is user-owned but contains read-only files" do
before(:each) do
- system "/usr/bin/touch", "--", "#{target_path}/foo"
- system "/bin/chmod", "--", "0555", target_path
+ FileUtils.touch "#{target_path}/foo"
+ FileUtils.chmod 0555, target_path
end
it "overwrites the existing app" do
@@ -138,7 +138,7 @@ describe Hbc::Artifact::App, :cask do
end
after(:each) do
- system "/bin/chmod", "--", "0755", target_path
+ FileUtils.chmod 0755, target_path
end
end
end
@@ -206,8 +206,8 @@ describe Hbc::Artifact::App, :cask do
end
describe "summary" do
- let(:description) { app.summary[:english_description] }
- let(:contents) { app.summary[:contents] }
+ let(:description) { app.class.english_description }
+ let(:contents) { app.summarize_installed }
it "returns the correct english_description" do
expect(description).to eq("Apps")
@@ -217,14 +217,13 @@ describe Hbc::Artifact::App, :cask do
it "returns the path to the app" do
install_phase
- expect(contents).to eq(["#{target_path} (#{target_path.abv})"])
+ expect(contents).to eq("#{target_path} (#{target_path.abv})")
end
end
describe "app is missing" do
it "returns a warning and the supposed path to the app" do
- expect(contents.size).to eq(1)
- expect(contents[0]).to match(/.*Missing App.*: #{target_path}/)
+ expect(contents).to match(/.*Missing App.*: #{target_path}/)
end
end
end
diff --git a/Library/Homebrew/test/cask/artifact/binary_spec.rb b/Library/Homebrew/test/cask/artifact/binary_spec.rb
index ce00e3935..5ffaca861 100644
--- a/Library/Homebrew/test/cask/artifact/binary_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb
@@ -26,7 +26,8 @@ describe Hbc::Artifact::Binary, :cask do
end
it "links the binary to the proper directory" do
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to exist
@@ -45,7 +46,8 @@ describe Hbc::Artifact::Binary, :cask do
expect(FileUtils).to receive(:chmod)
.with("+x", cask.staged_path.join("naked_non_executable")).and_call_original
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to be_executable
@@ -56,7 +58,8 @@ describe Hbc::Artifact::Binary, :cask do
FileUtils.touch expected_path
expect {
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
}.to raise_error(Hbc::CaskError)
expect(expected_path).not_to be :symlink?
@@ -65,7 +68,8 @@ describe Hbc::Artifact::Binary, :cask do
it "clobbers an existing symlink" do
expected_path.make_symlink("/tmp")
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(File.readlink(expected_path)).not_to eq("/tmp")
end
@@ -73,7 +77,8 @@ describe Hbc::Artifact::Binary, :cask do
it "creates parent directory if it doesn't exist" do
FileUtils.rmdir Hbc.binarydir
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path.exist?).to be true
end
@@ -86,8 +91,10 @@ describe Hbc::Artifact::Binary, :cask do
}
it "links the binary to the proper directory" do
- Hbc::Artifact::App.new(cask).install_phase
- Hbc::Artifact::Binary.new(cask).install_phase
+ Hbc::Artifact::App.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to exist
diff --git a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
index cb2ef9850..bec8c2742 100644
--- a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
@@ -2,7 +2,7 @@ describe Hbc::Artifact::Artifact, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::Artifact.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path) { cask.staged_path.join("Caffeine.app") }
@@ -12,11 +12,11 @@ describe Hbc::Artifact::Artifact, :cask do
InstallHelper.install_without_artifacts(cask)
end
- describe "with no target" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact-no-target.rb") }
-
- it "fails to install with no target" do
- expect(install_phase).to raise_error(Hbc::CaskInvalidError)
+ context "without target" do
+ it "fails to load" do
+ expect {
+ Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact-no-target.rb")
+ }.to raise_error(Hbc::CaskInvalidError, /target required for Generic Artifact/)
end
end
diff --git a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
index be7ba5ff8..41d143764 100644
--- a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
@@ -5,7 +5,8 @@ describe Hbc::Artifact::NestedContainer, :cask do
InstallHelper.install_without_artifacts(c)
end
- Hbc::Artifact::NestedContainer.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(cask.staged_path.join("MyNestedApp.app")).to be_a_directory
end
diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
index 3e62616ea..c6a45c49a 100644
--- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
@@ -8,7 +8,7 @@ describe Hbc::Artifact::Pkg, :cask do
describe "install_phase" do
it "runs the system installer on the specified pkgs" do
- pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command)
+ pkg = described_class.for_cask(cask).first
expect(fake_system_command).to receive(:run!).with(
"/usr/sbin/installer",
@@ -17,7 +17,7 @@ describe Hbc::Artifact::Pkg, :cask do
print_stdout: true,
)
- pkg.install_phase
+ pkg.install_phase(command: fake_system_command)
end
end
@@ -25,7 +25,7 @@ describe Hbc::Artifact::Pkg, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-choices.rb") }
it "passes the choice changes xml to the system installer" do
- pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command)
+ pkg = described_class.for_cask(cask).first
file = double(path: Pathname.new("/tmp/choices.xml"))
@@ -57,7 +57,7 @@ describe Hbc::Artifact::Pkg, :cask do
print_stdout: true,
)
- pkg.install_phase
+ pkg.install_phase(command: fake_system_command)
end
end
end
diff --git a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
index 51b1431f0..4a44bb59b 100644
--- a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
@@ -11,7 +11,8 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of(Hbc::DSL::Postflight)
@@ -30,7 +31,8 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of(Hbc::DSL::UninstallPostflight)
diff --git a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
index b13c4ab9d..d7d4e72d9 100644
--- a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
@@ -11,7 +11,8 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of Hbc::DSL::Preflight
@@ -30,7 +31,8 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of Hbc::DSL::UninstallPreflight
diff --git a/Library/Homebrew/test/cask/artifact/suite_spec.rb b/Library/Homebrew/test/cask/artifact/suite_spec.rb
index 8c217a9e0..2f913fecc 100644
--- a/Library/Homebrew/test/cask/artifact/suite_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/suite_spec.rb
@@ -1,7 +1,9 @@
describe Hbc::Artifact::Suite, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-suite.rb") }
- let(:install_phase) { -> { Hbc::Artifact::Suite.new(cask).install_phase } }
+ let(:install_phase) {
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
+ }
let(:target_path) { Hbc.appdir.join("Caffeine") }
let(:source_path) { cask.staged_path.join("Caffeine") }
diff --git a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
index a1fdd3b74..f6e0d3c97 100644
--- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
@@ -3,7 +3,7 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-correct.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path_mini) { cask.staged_path.join("Caffeine Mini.app") }
diff --git a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
index 8cd0b1e41..d6a8393da 100644
--- a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
@@ -2,7 +2,7 @@ describe Hbc::Artifact::Zap, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") }
let(:zap_artifact) {
- Hbc::Artifact::Zap.new(cask)
+ described_class.for_cask(cask).first
}
before(:each) do
diff --git a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
index 0e522bc21..06eec4a01 100644
--- a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
+++ b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
@@ -1,12 +1,12 @@
shared_examples "#uninstall_phase or #zap_phase" do
- let(:artifact_name) { described_class.artifact_name }
- let(:artifact) { described_class.new(cask, command: fake_system_command) }
+ let(:artifact_dsl_key) { described_class.dsl_key }
+ let(:artifact) { described_class.for_cask(cask).first }
let(:fake_system_command) { Hbc::FakeSystemCommand }
- subject { artifact.public_send(:"#{artifact_name}_phase") }
+ subject { artifact.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) }
context "using :launchctl" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-launchctl.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-launchctl.rb") }
let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] }
let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service] }
let(:unknown_response) { "launchctl list returned unknown response\n" }
@@ -61,7 +61,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
context "using :pkgutil" do
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-pkgutil.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-pkgutil.rb") }
let(:main_pkg_id) { "my.fancy.package.main" }
let(:agent_pkg_id) { "my.fancy.package.agent" }
@@ -85,7 +85,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :kext" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-kext.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-kext.rb") }
let(:kext_id) { "my.fancy.package.kernelextension" }
it "is supported" do
@@ -110,7 +110,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :quit" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-quit.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-quit.rb") }
let(:bundle_id) { "my.fancy.package.app" }
let(:quit_application_script) do
%Q(tell application id "#{bundle_id}" to quit)
@@ -130,7 +130,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :signal" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-signal.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-signal.rb") }
let(:bundle_id) { "my.fancy.package.app" }
let(:signals) { %w[TERM KILL] }
let(:unix_pids) { [12_345, 67_890] }
@@ -170,10 +170,10 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-#{directive}.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-#{directive}.rb") }
before(:each) do
- allow_any_instance_of(Hbc::Artifact::UninstallBase).to receive(:trash_paths)
+ allow_any_instance_of(Hbc::Artifact::AbstractUninstall).to receive(:trash_paths)
.and_wrap_original do |method, *args|
result = method.call(*args)
FileUtils.rm_rf result.stdout.split("\0")
@@ -196,7 +196,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
context "using :rmdir" do
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-rmdir.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-rmdir.rb") }
let(:empty_directory) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") }
let(:ds_store) { empty_directory.join(".DS_Store") }
@@ -223,7 +223,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
[:script, :early_script].each do |script_type|
context "using #{script_type.inspect}" do
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:token) { "with-#{artifact_name}-#{script_type}".tr("_", "-") }
+ let(:token) { "with-#{artifact_dsl_key}-#{script_type}".tr("_", "-") }
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/#{token}.rb") }
let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") }
@@ -250,7 +250,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :login_item" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-login-item.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-login-item.rb") }
it "is supported" do
Hbc::FakeSystemCommand.expects_command(
diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb
index ddc773e3e..7e140acb2 100644
--- a/Library/Homebrew/test/cask/audit_spec.rb
+++ b/Library/Homebrew/test/cask/audit_spec.rb
@@ -265,19 +265,14 @@ describe Hbc::Audit, :cask do
end
describe "generic artifact checks" do
- context "with no target" do
- let(:cask_token) { "generic-artifact-no-target" }
- it { is_expected.to fail_with(/target required for generic artifact/) }
- end
-
context "with relative target" do
let(:cask_token) { "generic-artifact-relative-target" }
- it { is_expected.to fail_with(/target must be absolute path for generic artifact/) }
+ it { is_expected.to fail_with(/target must be absolute path for Generic Artifact/) }
end
context "with absolute target" do
let(:cask_token) { "generic-artifact-absolute-target" }
- it { should_not fail_with(/target required for generic artifact/) }
+ it { should_not fail_with(/target required for Generic Artifact/) }
end
end
diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb
index bffe900ec..aec7080de 100644
--- a/Library/Homebrew/test/cask/cli/info_spec.rb
+++ b/Library/Homebrew/test/cask/cli/info_spec.rb
@@ -10,7 +10,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
@@ -24,7 +24,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
local-transmission: 2.61
http://example.com/local-transmission
Not installed
@@ -32,7 +32,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Transmission.app (app)
+ Transmission.app (App)
EOS
}
@@ -60,7 +60,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
==> Caveats
Here are some things you might want to know.
@@ -86,7 +86,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb
index ecca3035f..fd6997f41 100644
--- a/Library/Homebrew/test/cask/cli/list_spec.rb
+++ b/Library/Homebrew/test/cask/cli/list_spec.rb
@@ -48,7 +48,8 @@ describe Hbc::CLI::List, :cask do
it "lists the installed files for those Casks" do
casks.each(&InstallHelper.method(:install_without_artifacts_with_caskfile))
- Hbc::Artifact::App.new(transmission).install_phase
+ Hbc::Artifact::App.for_cask(transmission)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect {
Hbc::CLI::List.run("local-transmission", "local-caffeine")
diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb
index 7f2207a87..aec1e917f 100644
--- a/Library/Homebrew/test/cask/dsl_spec.rb
+++ b/Library/Homebrew/test/cask/dsl_spec.rb
@@ -186,12 +186,12 @@ describe Hbc::DSL, :cask do
app "Bar.app"
end
- expect(Array(cask.artifacts[:app])).to eq([["Foo.app"], ["Bar.app"]])
+ expect(cask.artifacts[:app].map(&:to_s)).to eq(["Foo.app (App)", "Bar.app (App)"])
end
it "allow app stanzas to be empty" do
cask = Hbc::Cask.new("cask-with-no-apps")
- expect(Array(cask.artifacts[:app])).to eq([])
+ expect(cask.artifacts[:app]).to be_empty
end
end
@@ -219,7 +219,7 @@ describe Hbc::DSL, :cask do
pkg "Bar.pkg"
end
- expect(Array(cask.artifacts[:pkg])).to eq([["Foo.pkg"], ["Bar.pkg"]])
+ expect(cask.artifacts[:pkg].map(&:to_s)).to eq(["Foo.pkg (Pkg)", "Bar.pkg (Pkg)"])
end
end
@@ -471,10 +471,10 @@ describe Hbc::DSL, :cask do
let(:token) { "with-installer-script" }
it "allows installer script to be specified" do
- expect(cask.artifacts[:installer].first.script[:executable]).to eq("/usr/bin/true")
- expect(cask.artifacts[:installer].first.script[:args]).to eq(["--flag"])
- expect(cask.artifacts[:installer].to_a[1].script[:executable]).to eq("/usr/bin/false")
- expect(cask.artifacts[:installer].to_a[1].script[:args]).to eq(["--flag"])
+ expect(cask.artifacts[:installer].first.path).to eq(Pathname("/usr/bin/true"))
+ expect(cask.artifacts[:installer].first.args[:args]).to eq(["--flag"])
+ expect(cask.artifacts[:installer].to_a[1].path).to eq(Pathname("/usr/bin/false"))
+ expect(cask.artifacts[:installer].to_a[1].args[:args]).to eq(["--flag"])
end
end
@@ -482,7 +482,9 @@ describe Hbc::DSL, :cask do
let(:token) { "with-installer-manual" }
it "allows installer manual to be specified" do
- expect(cask.artifacts[:installer].first.manual).to eq("Caffeine.app")
+ installer = cask.artifacts[:installer].first
+ expect(installer).to be_a(Hbc::Artifact::Installer::ManualInstaller)
+ expect(installer.path).to eq(cask.staged_path.join("Caffeine.app"))
end
end
end
@@ -492,7 +494,7 @@ describe Hbc::DSL, :cask do
let(:token) { "stage-only" }
it "allows stage_only stanza to be specified" do
- expect(cask.artifacts[:stage_only].first).to eq([true])
+ expect(cask.artifacts[:stage_only]).not_to be_empty
end
end
@@ -518,7 +520,7 @@ describe Hbc::DSL, :cask do
let(:token) { "appdir-interpolation" }
it "is allowed" do
- expect(cask.artifacts[:binary].first).to eq(["#{Hbc.appdir}/some/path"])
+ expect(cask.artifacts[:binary].first.source).to eq(Hbc.appdir/"some/path")
end
end
@@ -531,7 +533,7 @@ describe Hbc::DSL, :cask do
binary "#{appdir}/some/path"
end
- expect(cask.artifacts[:binary].first).to eq(["#{original_appdir}/some/path"])
+ expect(cask.artifacts[:binary].first.source).to eq(original_appdir/"some/path")
ensure
Hbc.appdir = original_appdir
end