diff --git a/lib/cask/artifact.rb b/lib/cask/artifact.rb
index efcd9ba7c2b9..bfb16b005f21 100644
--- a/lib/cask/artifact.rb
+++ b/lib/cask/artifact.rb
@@ -1,6 +1,7 @@
module Cask::Artifact; end
require 'cask/artifact/base'
+require 'cask/artifact/uninstall_base'
require 'cask/artifact/symlinked'
require 'cask/artifact/hardlinked'
@@ -19,6 +20,7 @@ module Cask::Artifact; end
require 'cask/artifact/caskroom_only'
require 'cask/artifact/input_method'
require 'cask/artifact/screen_saver'
+require 'cask/artifact/uninstall'
module Cask::Artifact
@@ -42,6 +44,7 @@ def self.artifacts
Cask::Artifact::Binary,
Cask::Artifact::InputMethod,
Cask::Artifact::ScreenSaver,
+ Cask::Artifact::Uninstall,
Cask::Artifact::AfterBlock,
]
end
diff --git a/lib/cask/artifact/after_block.rb b/lib/cask/artifact/after_block.rb
index 8fc73213bf5e..f2fdd2a5a064 100644
--- a/lib/cask/artifact/after_block.rb
+++ b/lib/cask/artifact/after_block.rb
@@ -4,11 +4,11 @@ def self.me?(cask)
cask.artifacts[:after_uninstall].any?
end
- def install
+ def install_phase
@cask.artifacts[:after_install].each { |block| @cask.instance_eval &block }
end
- def uninstall
+ def uninstall_phase
@cask.artifacts[:after_uninstall].each { |block| @cask.instance_eval &block }
end
end
diff --git a/lib/cask/artifact/before_block.rb b/lib/cask/artifact/before_block.rb
index a9eaa8bc336f..4915b56ae74a 100644
--- a/lib/cask/artifact/before_block.rb
+++ b/lib/cask/artifact/before_block.rb
@@ -4,11 +4,11 @@ def self.me?(cask)
cask.artifacts[:before_uninstall].any?
end
- def install
+ def install_phase
@cask.artifacts[:before_install].each { |block| @cask.instance_eval &block }
end
- def uninstall
+ def uninstall_phase
@cask.artifacts[:before_uninstall].each { |block| @cask.instance_eval &block }
end
end
diff --git a/lib/cask/artifact/binary.rb b/lib/cask/artifact/binary.rb
index 6743ddf48d49..f09b2de7b586 100644
--- a/lib/cask/artifact/binary.rb
+++ b/lib/cask/artifact/binary.rb
@@ -1,5 +1,5 @@
class Cask::Artifact::Binary < Cask::Artifact::Symlinked
- def install
+ def install_phase
super unless Cask.no_binaries
end
end
diff --git a/lib/cask/artifact/nested_container.rb b/lib/cask/artifact/nested_container.rb
index 51f65f5632cf..338776e55261 100644
--- a/lib/cask/artifact/nested_container.rb
+++ b/lib/cask/artifact/nested_container.rb
@@ -1,9 +1,9 @@
class Cask::Artifact::NestedContainer < Cask::Artifact::Base
- def install
+ def install_phase
@cask.artifacts[:nested_container].each { |container| extract(container) }
end
- def uninstall
+ def uninstall_phase
# no need to take action; we will get removed by rmtree of parent
end
diff --git a/lib/cask/artifact/pkg.rb b/lib/cask/artifact/pkg.rb
index daaa3b025842..f6bd0c303a27 100644
--- a/lib/cask/artifact/pkg.rb
+++ b/lib/cask/artifact/pkg.rb
@@ -1,40 +1,8 @@
class Cask::Artifact::Pkg < Cask::Artifact::Base
- # this class actually covers two keys, :install and :uninstall
def self.artifact_dsl_key
:install
end
- def self.read_script_arguments(uninstall_options, key)
- script_arguments = uninstall_options[key]
-
- # backwards-compatible string value
- if script_arguments.kind_of?(String)
- script_arguments = { :executable => script_arguments }
- end
-
- # key sanity
- permitted_keys = [:args, :input, :executable, :must_succeed]
- unknown_keys = script_arguments.keys - permitted_keys
- unless unknown_keys.empty?
- opoo %Q{Unknown arguments to uninstall :#{key} -- :#{unknown_keys.join(", :")} (ignored). Running "brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup" will likely fix it.}
- end
- script_arguments.reject! {|k,v| ! permitted_keys.include?(k)}
-
- # extract executable
- if script_arguments.key?(:executable)
- executable = script_arguments.delete(:executable)
- else
- executable = nil
- end
-
- unless script_arguments.key?(:must_succeed)
- script_arguments[:must_succeed] = true
- end
-
- script_arguments.merge!(:sudo => true, :print => true)
- return executable, script_arguments
- end
-
def load_pkg_description(pkg_description)
@pkg_relative_path = pkg_description.shift
@pkg_install_opts = pkg_description.shift
@@ -58,12 +26,12 @@ def pkg_relative_path
@pkg_relative_path
end
- def install
+ def install_phase
@cask.artifacts[:install].each { |pkg_description| run_installer(pkg_description) }
end
- def uninstall
- manually_uninstall(@cask.artifacts[:uninstall])
+ def uninstall_phase
+ # Do nothing. Must be handled explicitly by a separate :uninstall stanza.
end
def run_installer(pkg_description)
@@ -81,113 +49,4 @@ def run_installer(pkg_description)
args << '-allowUntrusted' if pkg_install_opts :allow_untrusted
@command.run!('/usr/sbin/installer', {:sudo => true, :args => args, :print => true})
end
-
- def manually_uninstall(uninstall_set)
- ohai "Running uninstall process for #{@cask}; your password may be necessary"
-
- uninstall_set.each do |uninstall_options|
- unknown_keys = uninstall_options.keys - [:early_script, :launchctl, :quit, :signal, :kext, :script, :pkgutil, :files]
- unless unknown_keys.empty?
- opoo %Q{Unknown arguments to uninstall: #{unknown_keys.join(", ")}. Running "brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup" will likely fix it.}
- end
- end
-
- # 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.
- uninstall_set.select{ |h| h.key?(:early_script) }.each do |uninstall_options|
- executable, script_arguments = self.class.read_script_arguments(uninstall_options, :early_script)
- ohai "Running uninstall script #{executable}"
- raise CaskInvalidError.new(@cask, 'uninstall :early_script without :executable') if executable.nil?
- @command.run(@cask.destination_path.join(executable), script_arguments)
- sleep 1
- end
-
- # :launchctl must come before :quit/:signal for cases where app would instantly re-launch
- uninstall_set.select{ |h| h.key?(:launchctl) }.each do |uninstall_options|
- Array(uninstall_options[:launchctl]).each do |service|
- ohai "Removing launchctl service #{service}"
- [false, true].each do |with_sudo|
- xml_status = @command.run('/bin/launchctl', :args => ['list', '-x', service], :sudo => with_sudo)
- if %r{^<\?xml}.match(xml_status)
- @command.run('/bin/launchctl', :args => ['unload', '-w', '--', service], :sudo => with_sudo)
- sleep 1
- @command.run!('/bin/launchctl', :args => ['remove', service], :sudo => with_sudo)
- sleep 1
- end
- end
- end
- end
-
- # :quit/:signal must come before :kext so the kext will not be in use by a running process
- uninstall_set.select{ |h| h.key?(:quit) }.each do |uninstall_options|
- Array(uninstall_options[:quit]).each do |id|
- ohai "Quitting application ID #{id}"
- num_running = @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application "System Events" to count processes whose bundle identifier is "#{id}"}], :sudo => true).to_i
- if num_running > 0
- @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application id "#{id}" to quit}], :sudo => true)
- sleep 3
- end
- end
- end
-
- # :signal should come after :quit so it can be used as a backup when :quit fails
- uninstall_set.select{ |h| h.key?(:signal) }.each do |uninstall_options|
- Array(uninstall_options[:signal]).flatten.each_slice(2) do |pair|
- raise CaskInvalidError.new(@cask, 'Each uninstall :signal must have 2 elements.') unless pair.length == 2
- signal, id = pair
- ohai "Signalling '#{signal}' to application ID '#{id}'"
- pid_string = @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{id}"}], :sudo => true)
- if pid_string.match(%r{\A\d+(?:\s*,\s*\d+)*\Z}) # sanity check
- pids = pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i)
- if pids.length > 0
- # 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 there should be some
- # additional thought/safety checks about that, as a
- # misapplied "kill" by root could bring down the system.
- # The fact that we learned the pid from AppleScript is
- # already some degree of protection, though indirect.
- Process.kill(signal, *pids)
- sleep 3
- end
- end
- end
- end
-
- # :kext should be unloaded before attempting to delete the relevant file
- uninstall_set.select{ |h| h.key?(:kext) }.each do |uninstall_options|
- Array(uninstall_options[:kext]).each do |kext|
- ohai "Unloading kernel extension #{kext}"
- is_loaded = @command.run!('/usr/sbin/kextstat', :args => ['-l', '-b', kext], :sudo => true)
- if is_loaded.length > 1
- @command.run!('/sbin/kextunload', :args => ['-b', '--', kext], :sudo => true)
- sleep 1
- end
- end
- end
-
- # :script must come before :pkgutil or :files so that the script file is not already deleted
- uninstall_set.select{ |h| h.key?(:script) }.each do |uninstall_options|
- executable, script_arguments = self.class.read_script_arguments(uninstall_options, :script)
- raise CaskInvalidError.new(@cask, 'uninstall :script without :executable.') if executable.nil?
- @command.run(@cask.destination_path.join(executable), script_arguments)
- sleep 1
- end
-
- uninstall_set.select{ |h| h.key?(:pkgutil) }.each do |uninstall_options|
- ohai "Removing files from pkgutil Bill-of-Materials"
- Array(uninstall_options[:pkgutil]).each do |regexp|
- pkgs = Cask::Pkg.all_matching(regexp, @command)
- pkgs.each(&:uninstall)
- end
- end
-
- uninstall_set.select{ |h| h.key?(:files) }.each do |uninstall_options|
- Array(uninstall_options[:files]).flatten.each_slice(500) do |file_slice|
- ohai "Removing files: #{file_slice.utf8_inspect}"
- @command.run!('/bin/rm', :args => file_slice.unshift('-rf', '--'), :sudo => true)
- end
- end
- end
end
diff --git a/lib/cask/artifact/symlinked.rb b/lib/cask/artifact/symlinked.rb
index 8f7d7a3d4e6d..41142f2c5bae 100644
--- a/lib/cask/artifact/symlinked.rb
+++ b/lib/cask/artifact/symlinked.rb
@@ -82,12 +82,12 @@ def unlink(artifact_spec)
end
end
- def install
+ def install_phase
# the sort is for predictability between Ruby versions
@cask.artifacts[self.class.artifact_dsl_key].sort.each { |artifact| link(artifact) }
end
- def uninstall
+ def uninstall_phase
# the sort is for predictability between Ruby versions
@cask.artifacts[self.class.artifact_dsl_key].sort.each { |artifact| unlink(artifact) }
end
diff --git a/lib/cask/artifact/uninstall.rb b/lib/cask/artifact/uninstall.rb
new file mode 100644
index 000000000000..09fbf0176e2a
--- /dev/null
+++ b/lib/cask/artifact/uninstall.rb
@@ -0,0 +1,2 @@
+class Cask::Artifact::Uninstall < Cask::Artifact::UninstallBase
+end
diff --git a/lib/cask/artifact/uninstall_base.rb b/lib/cask/artifact/uninstall_base.rb
new file mode 100644
index 000000000000..4af12d23832c
--- /dev/null
+++ b/lib/cask/artifact/uninstall_base.rb
@@ -0,0 +1,154 @@
+class Cask::Artifact::UninstallBase < Cask::Artifact::Base
+
+ # todo: these methods were consolidated here from separate
+ # sources and, should be refactored for consistency
+
+ def install_phase
+ odebug "Nothing to do. The uninstall artifact has no install phase."
+ end
+
+ def uninstall_phase
+ dispatch_uninstall_directives(self.class.artifact_dsl_key)
+ end
+
+ def self.read_script_arguments(uninstall_options, key)
+ script_arguments = uninstall_options[key]
+
+ # backwards-compatible string value
+ if script_arguments.kind_of?(String)
+ script_arguments = { :executable => script_arguments }
+ end
+
+ # key sanity
+ permitted_keys = [:args, :input, :executable, :must_succeed]
+ unknown_keys = script_arguments.keys - permitted_keys
+ unless unknown_keys.empty?
+ opoo %Q{Unknown arguments to #{stanza} #{key.inspect} -- #{unknown_keys.inspect} (ignored). Running "brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup" will likely fix it.}
+ end
+ script_arguments.reject! {|k,v| ! permitted_keys.include?(k)}
+
+ # extract executable
+ if script_arguments.key?(:executable)
+ executable = script_arguments.delete(:executable)
+ else
+ executable = nil
+ end
+
+ unless script_arguments.key?(:must_succeed)
+ script_arguments[:must_succeed] = true
+ end
+
+ script_arguments.merge!(:sudo => true, :print => true)
+ return executable, script_arguments
+ end
+
+ def dispatch_uninstall_directives(stanza)
+ directives_set = @cask.artifacts[stanza]
+ ohai "Running #{stanza} process for #{@cask}; your password may be necessary"
+
+ directives_set.each do |directives|
+ unknown_keys = directives.keys - [:early_script, :launchctl, :quit, :signal, :kext, :script, :pkgutil, :files]
+ unless unknown_keys.empty?
+ opoo %Q{Unknown arguments to #{stanza} -- #{unknown_keys.inspect}. Running "brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup" will likely fix it.}
+ end
+ end
+
+ # 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.
+ directives_set.select{ |h| h.key?(:early_script) }.each do |directives|
+ executable, script_arguments = self.class.read_script_arguments(directives, :early_script)
+ ohai "Running uninstall script #{executable}"
+ raise CaskInvalidError.new(@cask, "#{stanza} :early_script without :executable") if executable.nil?
+ @command.run(@cask.destination_path.join(executable), script_arguments)
+ sleep 1
+ end
+
+ # :launchctl must come before :quit/:signal for cases where app would instantly re-launch
+ directives_set.select{ |h| h.key?(:launchctl) }.each do |directives|
+ Array(directives[:launchctl]).each do |service|
+ ohai "Removing launchctl service #{service}"
+ [false, true].each do |with_sudo|
+ xml_status = @command.run('/bin/launchctl', :args => ['list', '-x', service], :sudo => with_sudo)
+ if %r{^<\?xml}.match(xml_status)
+ @command.run('/bin/launchctl', :args => ['unload', '-w', '--', service], :sudo => with_sudo)
+ sleep 1
+ @command.run!('/bin/launchctl', :args => ['remove', service], :sudo => with_sudo)
+ sleep 1
+ end
+ end
+ end
+ end
+
+ # :quit/:signal must come before :kext so the kext will not be in use by a running process
+ directives_set.select{ |h| h.key?(:quit) }.each do |directives|
+ Array(directives[:quit]).each do |id|
+ ohai "Quitting application ID #{id}"
+ num_running = @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application "System Events" to count processes whose bundle identifier is "#{id}"}], :sudo => true).to_i
+ if num_running > 0
+ @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application id "#{id}" to quit}], :sudo => true)
+ sleep 3
+ end
+ end
+ end
+
+ # :signal should come after :quit so it can be used as a backup when :quit fails
+ directives_set.select{ |h| h.key?(:signal) }.each do |directives|
+ Array(directives[:signal]).flatten.each_slice(2) do |pair|
+ raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2
+ signal, id = pair
+ ohai "Signalling '#{signal}' to application ID '#{id}'"
+ pid_string = @command.run!('/usr/bin/osascript', :args => ['-e', %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{id}"}], :sudo => true)
+ if pid_string.match(%r{\A\d+(?:\s*,\s*\d+)*\Z}) # sanity check
+ pids = pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i)
+ if pids.length > 0
+ # 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 there should be some
+ # additional thought/safety checks about that, as a
+ # misapplied "kill" by root could bring down the system.
+ # The fact that we learned the pid from AppleScript is
+ # already some degree of protection, though indirect.
+ Process.kill(signal, *pids)
+ sleep 3
+ end
+ end
+ end
+ end
+
+ # :kext should be unloaded before attempting to delete the relevant file
+ directives_set.select{ |h| h.key?(:kext) }.each do |directives|
+ Array(directives[:kext]).each do |kext|
+ ohai "Unloading kernel extension #{kext}"
+ is_loaded = @command.run!('/usr/sbin/kextstat', :args => ['-l', '-b', kext], :sudo => true)
+ if is_loaded.length > 1
+ @command.run!('/sbin/kextunload', :args => ['-b', '--', kext], :sudo => true)
+ sleep 1
+ end
+ end
+ end
+
+ # :script must come before :pkgutil or :files so that the script file is not already deleted
+ directives_set.select{ |h| h.key?(:script) }.each do |directives|
+ executable, script_arguments = self.class.read_script_arguments(directives, :script)
+ raise CaskInvalidError.new(@cask, "#{stanza} :script without :executable.") if executable.nil?
+ @command.run(@cask.destination_path.join(executable), script_arguments)
+ sleep 1
+ end
+
+ directives_set.select{ |h| h.key?(:pkgutil) }.each do |directives|
+ ohai "Removing files from pkgutil Bill-of-Materials"
+ Array(directives[:pkgutil]).each do |regexp|
+ pkgs = Cask::Pkg.all_matching(regexp, @command)
+ pkgs.each(&:uninstall)
+ end
+ end
+
+ directives_set.select{ |h| h.key?(:files) }.each do |directives|
+ Array(directives[:files]).flatten.each_slice(500) do |file_slice|
+ ohai "Removing files: #{file_slice.utf8_inspect}"
+ @command.run!('/bin/rm', :args => file_slice.unshift('-rf', '--'), :sudo => true)
+ end
+ end
+ end
+end
diff --git a/lib/cask/installer.rb b/lib/cask/installer.rb
index 27469e4db295..cdc7e33bdb93 100644
--- a/lib/cask/installer.rb
+++ b/lib/cask/installer.rb
@@ -81,7 +81,7 @@ def install_artifacts
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
odebug "Installing artifact of class #{artifact}"
- artifact.new(@cask, @command).install
+ artifact.new(@cask, @command).install_phase
end
end
@@ -124,7 +124,7 @@ def uninstall_artifacts
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
odebug "Un-installing artifact of class #{artifact}"
- artifact.new(@cask, @command).uninstall
+ artifact.new(@cask, @command).uninstall_phase
end
end
diff --git a/test/cask/artifact/after_block_test.rb b/test/cask/artifact/after_block_test.rb
index f4523fc314c8..9fa796612aa6 100644
--- a/test/cask/artifact/after_block_test.rb
+++ b/test/cask/artifact/after_block_test.rb
@@ -1,7 +1,7 @@
require 'test_helper'
describe Cask::Artifact::AfterBlock do
- describe 'install' do
+ describe 'install_phase' do
it 'calls the specified block after installing, passing the cask' do
called = false
yielded_arg = nil
@@ -15,14 +15,14 @@
end
cask = CaskWithAfterInstall.new
- Cask::Artifact::AfterBlock.new(cask).install
+ Cask::Artifact::AfterBlock.new(cask).install_phase
called.must_equal true
yielded_arg.must_equal cask
end
end
- describe 'uninstall' do
+ describe 'uninstall_phase' do
it 'calls the specified block after uninstalling, passing the cask' do
called = false
yielded_arg = nil
@@ -36,7 +36,7 @@
end
cask = CaskWithAfterUninstall.new
- Cask::Artifact::AfterBlock.new(cask).uninstall
+ Cask::Artifact::AfterBlock.new(cask).uninstall_phase
called.must_equal true
yielded_arg.must_equal cask
diff --git a/test/cask/artifact/alt_target_test.rb b/test/cask/artifact/alt_target_test.rb
index af66fe379345..0a85c74f8b19 100644
--- a/test/cask/artifact/alt_target_test.rb
+++ b/test/cask/artifact/alt_target_test.rb
@@ -12,7 +12,7 @@
cask = local_alt_caffeine
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'AnotherName.app').must_equal true
@@ -22,7 +22,7 @@
cask = local_alt_caffeine
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
Cask::SystemCommand.run('/usr/bin/xattr',
@@ -51,7 +51,7 @@
FileUtils.mv((subdir_cask.destination_path/'Caffeine.app'), appsubdir)
shutup do
- Cask::Artifact::App.new(subdir_cask).install
+ Cask::Artifact::App.new(subdir_cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'AnotherName.app').must_equal true
@@ -71,7 +71,7 @@
FileUtils.cp_r app_path, app_path.sub('Caffeine.app', 'CaffeineAgain.app')
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'AnotherName.app').must_equal true
@@ -84,7 +84,7 @@
(Cask.appdir/'AnotherName.app').mkpath
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, "==> It seems there is already an App at '#{Cask.appdir.join('AnotherName.app')}'; not linking.")
(Cask.appdir/'AnotherName.app').wont_be :symlink?
@@ -96,7 +96,7 @@
(Cask.appdir/'AnotherName.app').make_symlink('/tmp')
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, "==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('AnotherName.app')}'")
File.readlink(Cask.appdir/'AnotherName.app').wont_equal '/tmp'
diff --git a/test/cask/artifact/app_test.rb b/test/cask/artifact/app_test.rb
index 07d20d3f5ddc..94ccbf092098 100644
--- a/test/cask/artifact/app_test.rb
+++ b/test/cask/artifact/app_test.rb
@@ -7,12 +7,12 @@
end
}
- describe 'install' do
+ describe 'install_phase' do
it "links the noted applications to the proper directory" do
cask = local_caffeine
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
@@ -37,7 +37,7 @@
FileUtils.mv((subdir_cask.destination_path/'Caffeine.app'), appsubdir)
shutup do
- Cask::Artifact::App.new(subdir_cask).install
+ Cask::Artifact::App.new(subdir_cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
@@ -57,7 +57,7 @@
FileUtils.cp_r app_path, app_path.sub('Caffeine.app', 'CaffeineAgain.app')
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
@@ -70,7 +70,7 @@
(Cask.appdir/'Caffeine.app').mkpath
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, "==> It seems there is already an App at '#{Cask.appdir.join('Caffeine.app')}'; not linking.")
(Cask.appdir/'Caffeine.app').wont_be :symlink?
@@ -82,7 +82,7 @@
(Cask.appdir/'Caffeine.app').make_symlink('/tmp')
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, "==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('Caffeine.app')}'")
File.readlink(Cask.appdir/'Caffeine.app').wont_equal '/tmp'
diff --git a/test/cask/artifact/before_block_test.rb b/test/cask/artifact/before_block_test.rb
index e80bec077141..a7c3aa7f2578 100644
--- a/test/cask/artifact/before_block_test.rb
+++ b/test/cask/artifact/before_block_test.rb
@@ -1,7 +1,7 @@
require 'test_helper'
describe Cask::Artifact::BeforeBlock do
- describe 'install' do
+ describe 'install_phase' do
it 'calls the specified block before installing' do
called = false
yielded_arg = nil
@@ -15,14 +15,14 @@
end
cask = CaskWithBeforeInstall.new
- Cask::Artifact::BeforeBlock.new(cask).install
+ Cask::Artifact::BeforeBlock.new(cask).install_phase
called.must_equal true
yielded_arg.must_equal cask
end
end
- describe 'uninstall' do
+ describe 'uninstall_phase' do
it 'calls the specified block before uninstalling, passing the cask' do
called = false
yielded_arg = nil
@@ -36,7 +36,7 @@
end
cask = CaskWithBeforeUninstall.new
- Cask::Artifact::BeforeBlock.new(cask).uninstall
+ Cask::Artifact::BeforeBlock.new(cask).uninstall_phase
called.must_equal true
yielded_arg.must_equal cask
diff --git a/test/cask/artifact/binary_test.rb b/test/cask/artifact/binary_test.rb
index b50467c09e26..9934b471966c 100644
--- a/test/cask/artifact/binary_test.rb
+++ b/test/cask/artifact/binary_test.rb
@@ -12,7 +12,7 @@
it "links the binary to the proper directory" do
shutup do
- Cask::Artifact::Binary.new(cask).install
+ Cask::Artifact::Binary.new(cask).install_phase
end
TestHelper.valid_alias?(expected_path).must_equal true
@@ -22,7 +22,7 @@
FileUtils.touch expected_path
shutup do
- Cask::Artifact::Binary.new(cask).install
+ Cask::Artifact::Binary.new(cask).install_phase
end
expected_path.wont_be :symlink?
@@ -32,7 +32,7 @@
expected_path.make_symlink('/tmp')
shutup do
- Cask::Artifact::Binary.new(cask).install
+ Cask::Artifact::Binary.new(cask).install_phase
end
File.readlink(expected_path).wont_equal '/tmp'
@@ -42,7 +42,7 @@
Cask.no_binaries = true
shutup do
- Cask::Artifact::Binary.new(cask).install
+ Cask::Artifact::Binary.new(cask).install_phase
end
expected_path.exist?.must_equal false
diff --git a/test/cask/artifact/nested_container_test.rb b/test/cask/artifact/nested_container_test.rb
index 5f0f14aafe3c..7c78aaa7d86f 100644
--- a/test/cask/artifact/nested_container_test.rb
+++ b/test/cask/artifact/nested_container_test.rb
@@ -8,7 +8,7 @@
end
shutup do
- Cask::Artifact::NestedContainer.new(cask).install
+ Cask::Artifact::NestedContainer.new(cask).install_phase
end
cask.destination_path.join('MyNestedApp.app').must_be :directory?
diff --git a/test/cask/artifact/pkg_test.rb b/test/cask/artifact/pkg_test.rb
index 31eefbfe46eb..74a264fcf36f 100644
--- a/test/cask/artifact/pkg_test.rb
+++ b/test/cask/artifact/pkg_test.rb
@@ -8,167 +8,23 @@
end
}
- describe 'install' do
+ describe 'install_phase' do
it 'runs the system installer on the specified pkgs' do
pkg = Cask::Artifact::Pkg.new(@cask, Cask::FakeSystemCommand)
Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/installer', '-pkg', @cask.destination_path/'MyFancyPkg'/'Fancy.pkg', '-target', '/'])
shutup do
- pkg.install
+ pkg.install_phase
end
end
end
- describe 'uninstall' do
- # todo: uninstall tests for :signal (implementation does not use SystemComment)
- it 'runs the specified uninstaller for the cask' do
+ describe 'uninstall_phase' do
+ it 'does nothing, because the uninstall_phase method is a no-op' do
pkg = Cask::Artifact::Pkg.new(@cask, Cask::FakeSystemCommand)
-
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1')
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit'])
-
- Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', @cask.destination_path/'MyFancyPkg'/'FancyUninstaller.tool', '--please'])
-
- shutup do
- pkg.uninstall
- end
- end
-
- it 'can uninstall using pkgutil, launchctl, and file lists' do
- cask = Cask.load('with-pkgutil-uninstall')
- pkg = Cask::Artifact::Pkg.new(cask, Cask::FakeSystemCommand)
-
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--pkgs=my.fancy.package.*'],
- [
- 'my.fancy.package.main',
- 'my.fancy.package.agent',
- ].join("\n")
- )
-
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.main'],
- [
- 'fancy/bin/fancy.exe',
- 'fancy/var/fancy.data',
- ].join("\n")
- )
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.main'],
- [
- 'fancy',
- 'fancy/bin',
- 'fancy/var',
- ].join("\n")
- )
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.main'],
- <<-PLIST
-
-
-
-
- install-location
- tmp
- volume
- /
-
-
- PLIST
- )
-
- Cask::FakeSystemCommand.stubs_command(
- ['/bin/launchctl', 'list', '-x', 'my.fancy.package.service'],
- "launchctl list returned unknown response\n"
- )
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'list', '-x', 'my.fancy.package.service'],
- <<-"PLIST"
-
-
-
-
-\tLabel
-\tmy.fancy.package.service
-\tLastExitStatus
-\t0
-\tLimitLoadToSessionType
-\tSystem
-\tOnDemand
-\t
-\tProgramArguments
-\t
-\t\targument
-\t
-\tTimeOut
-\t30
-
-
- PLIST
- )
-
- Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'remove', 'my.fancy.package.service'])
- Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'unload', '-w', '--', 'my.fancy.package.service'])
-
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/kextstat', '-l', '-b', 'my.fancy.package.kernelextension'], 'loaded')
- Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/sbin/kextunload', '-b', '--', 'my.fancy.package.kernelextension'])
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.main'])
-
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.agent'],
- [
- 'fancy/agent/fancy-agent.exe',
- 'fancy/agent/fancy-agent.pid',
- 'fancy/agent/fancy-agent.log',
- ].join("\n")
- )
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.agent'],
- [
- 'fancy',
- 'fancy/agent',
- ].join("\n")
- )
- Cask::FakeSystemCommand.stubs_command(
- ['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.agent'],
- <<-PLIST
-
-
-
-
- install-location
- tmp
- volume
- /
-
-
- PLIST
- )
-
- %w[
- /tmp/fancy
- /tmp/fancy/agent
- /tmp/fancy/bin
- /tmp/fancy/var
- ].each do |dir|
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/chmod', '--', '777', '#{dir}'])
- end
-
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.agent'])
-
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
- Pathname.new('/tmp/fancy/bin/fancy.exe'),
- Pathname.new('/tmp/fancy/var/fancy.data')])
- Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
- Pathname.new('/tmp/fancy/agent/fancy-agent.exe'),
- Pathname.new('/tmp/fancy/agent/fancy-agent.pid'),
- Pathname.new('/tmp/fancy/agent/fancy-agent.log')])
-
- # No assertions after call since all assertions are implicit from the interactions setup above.
- # TODO: verify rmdir commands (requires setting up actual file tree or faking out .exists?
shutup do
- pkg.uninstall
+ pkg.uninstall_phase
end
end
end
diff --git a/test/cask/artifact/two_links_correct_test.rb b/test/cask/artifact/two_links_correct_test.rb
index e637306402fd..cc22cce4a121 100644
--- a/test/cask/artifact/two_links_correct_test.rb
+++ b/test/cask/artifact/two_links_correct_test.rb
@@ -12,7 +12,7 @@
cask = local_two_links_caffeine
shutup do
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
@@ -39,7 +39,7 @@
FileUtils.mv((subdir_cask.destination_path/'Caffeine.app'), appsubdir)
shutup do
- Cask::Artifact::App.new(subdir_cask).install
+ Cask::Artifact::App.new(subdir_cask).install_phase
end
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
@@ -61,7 +61,7 @@
# FileUtils.cp_r app_path, app_path.sub('Caffeine.app', 'CaffeineAgain.app')
#
# shutup do
- # Cask::Artifact::App.new(cask).install
+ # Cask::Artifact::App.new(cask).install_phase
# end
#
# TestHelper.valid_alias?(Cask.appdir/'AnotherName.app').must_equal true
@@ -74,7 +74,7 @@
(Cask.appdir/'Caffeine.app').mkpath
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, <<-MESSAGE.undent.chomp)
==> It seems there is already an App at '#{Cask.appdir.join('Caffeine.app')}'; not linking.
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('AnotherName.app')}'
@@ -89,7 +89,7 @@
(Cask.appdir/'AnotherName.app').mkpath
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, <<-MESSAGE.undent.chomp)
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('Caffeine.app')}'
==> It seems there is already an App at '#{Cask.appdir.join('AnotherName.app')}'; not linking.
@@ -104,7 +104,7 @@
(Cask.appdir/'Caffeine.app').make_symlink('/tmp')
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, <<-MESSAGE.undent.chomp)
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('Caffeine.app')}'
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('AnotherName.app')}'
@@ -119,7 +119,7 @@
(Cask.appdir/'AnotherName.app').make_symlink('/tmp')
TestHelper.must_output(self, lambda {
- Cask::Artifact::App.new(cask).install
+ Cask::Artifact::App.new(cask).install_phase
}, <<-MESSAGE.undent.chomp)
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('Caffeine.app')}'
==> Symlinking App 'Caffeine.app' to '#{Cask.appdir.join('AnotherName.app')}'
diff --git a/test/cask/artifact/uninstall_test.rb b/test/cask/artifact/uninstall_test.rb
new file mode 100644
index 000000000000..ed07a4d5045d
--- /dev/null
+++ b/test/cask/artifact/uninstall_test.rb
@@ -0,0 +1,172 @@
+require 'test_helper'
+
+describe Cask::Artifact::Uninstall do
+ before {
+ @cask = Cask.load('with-installable')
+ shutup do
+ TestHelper.install_without_artifacts(@cask)
+ end
+ }
+
+ describe 'install_phase' do
+ it 'does nothing, because the install_phase method is a no-op' do
+ uninstall_artifact = Cask::Artifact::Uninstall.new(@cask, Cask::FakeSystemCommand)
+ shutup do
+ uninstall_artifact.install_phase
+ end
+ end
+ end
+
+ describe 'uninstall_phase' do
+ # todo: uninstall tests for :signal (implementation does not use SystemComment)
+ it 'runs the specified uninstaller for the cask' do
+ uninstall_artifact = Cask::Artifact::Uninstall.new(@cask, Cask::FakeSystemCommand)
+
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application "System Events" to count processes whose bundle identifier is "my.fancy.package.app"'], '1')
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/bin/osascript', '-e', 'tell application id "my.fancy.package.app" to quit'])
+
+ Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', @cask.destination_path/'MyFancyPkg'/'FancyUninstaller.tool', '--please'])
+
+ shutup do
+ uninstall_artifact.uninstall_phase
+ end
+ end
+
+ it 'can uninstall using pkgutil, launchctl, and file lists' do
+ cask = Cask.load('with-pkgutil-uninstall')
+ uninstall_artifact = Cask::Artifact::Uninstall.new(cask, Cask::FakeSystemCommand)
+
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--pkgs=my.fancy.package.*'],
+ [
+ 'my.fancy.package.main',
+ 'my.fancy.package.agent',
+ ].join("\n")
+ )
+
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.main'],
+ [
+ 'fancy/bin/fancy.exe',
+ 'fancy/var/fancy.data',
+ ].join("\n")
+ )
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.main'],
+ [
+ 'fancy',
+ 'fancy/bin',
+ 'fancy/var',
+ ].join("\n")
+ )
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.main'],
+ <<-PLIST
+
+
+
+
+ install-location
+ tmp
+ volume
+ /
+
+
+ PLIST
+ )
+
+ Cask::FakeSystemCommand.stubs_command(
+ ['/bin/launchctl', 'list', '-x', 'my.fancy.package.service'],
+ "launchctl list returned unknown response\n"
+ )
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'list', '-x', 'my.fancy.package.service'],
+ <<-"PLIST"
+
+
+
+
+\tLabel
+\tmy.fancy.package.service
+\tLastExitStatus
+\t0
+\tLimitLoadToSessionType
+\tSystem
+\tOnDemand
+\t
+\tProgramArguments
+\t
+\t\targument
+\t
+\tTimeOut
+\t30
+
+
+ PLIST
+ )
+
+ Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'remove', 'my.fancy.package.service'])
+ Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/bin/launchctl', 'unload', '-w', '--', 'my.fancy.package.service'])
+
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/kextstat', '-l', '-b', 'my.fancy.package.kernelextension'], 'loaded')
+ Cask::FakeSystemCommand.expects_command(['/usr/bin/sudo', '-E', '--', '/sbin/kextunload', '-b', '--', 'my.fancy.package.kernelextension'])
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.main'])
+
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--only-files', '--files', 'my.fancy.package.agent'],
+ [
+ 'fancy/agent/fancy-agent.exe',
+ 'fancy/agent/fancy-agent.pid',
+ 'fancy/agent/fancy-agent.log',
+ ].join("\n")
+ )
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--only-dirs', '--files', 'my.fancy.package.agent'],
+ [
+ 'fancy',
+ 'fancy/agent',
+ ].join("\n")
+ )
+ Cask::FakeSystemCommand.stubs_command(
+ ['/usr/sbin/pkgutil', '--pkg-info-plist', 'my.fancy.package.agent'],
+ <<-PLIST
+
+
+
+
+ install-location
+ tmp
+ volume
+ /
+
+
+ PLIST
+ )
+
+ %w[
+ /tmp/fancy
+ /tmp/fancy/agent
+ /tmp/fancy/bin
+ /tmp/fancy/var
+ ].each do |dir|
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/chmod', '--', '777', '#{dir}'])
+ end
+
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/usr/sbin/pkgutil', '--forget', 'my.fancy.package.agent'])
+
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
+ Pathname.new('/tmp/fancy/bin/fancy.exe'),
+ Pathname.new('/tmp/fancy/var/fancy.data')])
+ Cask::FakeSystemCommand.stubs_command(['/usr/bin/sudo', '-E', '--', '/bin/rm', '-f', '--',
+ Pathname.new('/tmp/fancy/agent/fancy-agent.exe'),
+ Pathname.new('/tmp/fancy/agent/fancy-agent.pid'),
+ Pathname.new('/tmp/fancy/agent/fancy-agent.log')])
+
+ # No assertions after call since all assertions are implicit from the interactions setup above.
+ # TODO: verify rmdir commands (requires setting up actual file tree or faking out .exists?
+ shutup do
+ uninstall_artifact.uninstall_phase
+ end
+ end
+ end
+end