mirror of
https://github.com/donl/homebrew-cask-versions.git
synced 2026-07-16 22:06:43 -06:00
prefpane support; artifact refactor
= New Concept: Cask::Artifact An Artifact is a file in an extacted container for which homebrew-cask should take some sort of action on install/uninstall. == Current artifacts: - App: link/unlink to ~/Applications - Pkg: install/uninstall (with sudo) - Prefpane: link/unlink to ~/Library/PreferencePanes = New Feature: Preference Pane Handling Specifying `prefpane 'MyApp.prefPane'` in a Cask causes it to be linked on install to the correct location for it to show up in System Preferences. refs #69 = Removed Commands: linkapps/unlinkapps These were old and mostly unused and don't really make much sense when linking/unlinking happens automatically in the install process. = Changed Behavior: stricter relative pathname requirement With this refactor, we remove the fuzzy searching for a file in an extracted container when that file was referenced from `link` or `install`. There may be some casks that need to be updated due to this change.
This commit is contained in:
parent
ed7358cf32
commit
c244385eb2
29 changed files with 409 additions and 372 deletions
7
Casks/hazel.rb
Normal file
7
Casks/hazel.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class Hazel < Cask
|
||||
url 'https://s3.amazonaws.com/Noodlesoft/Hazel-3.1.5.dmg'
|
||||
homepage 'http://www.noodlesoft.com/hazel.php'
|
||||
version '3.1.5'
|
||||
sha1 'a020aa443ed2b4812d72d7da802177c6e077c048'
|
||||
prefpane 'Hazel.prefPane'
|
||||
end
|
||||
7
Casks/tv-shows.rb
Normal file
7
Casks/tv-shows.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class TvShows < Cask
|
||||
url 'http://tvshowsapp.com/TVShows.zip'
|
||||
homepage 'http://tvshowsapp.com/'
|
||||
version 'latest'
|
||||
no_checksum
|
||||
prefpane 'TvShows.prefpane'
|
||||
end
|
||||
59
lib/cask.rb
59
lib/cask.rb
|
|
@ -4,7 +4,7 @@ HOMEBREW_CACHE_CASKS = HOMEBREW_CACHE.join('Casks')
|
|||
|
||||
class Cask; end
|
||||
|
||||
require 'cask/app_linker'
|
||||
require 'cask/artifact'
|
||||
require 'cask/audit'
|
||||
require 'cask/auditor'
|
||||
require 'cask/checkable'
|
||||
|
|
@ -16,8 +16,8 @@ require 'cask/exceptions'
|
|||
require 'cask/fetcher'
|
||||
require 'cask/installer'
|
||||
require 'cask/link_checker'
|
||||
require 'cask/locations'
|
||||
require 'cask/pkg'
|
||||
require 'cask/pkg_installer'
|
||||
require 'cask/scopes'
|
||||
require 'cask/system_command'
|
||||
|
||||
|
|
@ -25,36 +25,9 @@ require 'plist/parser'
|
|||
|
||||
class Cask
|
||||
include Cask::DSL
|
||||
include Cask::Locations
|
||||
include Cask::Scopes
|
||||
|
||||
def self.tapspath
|
||||
HOMEBREW_PREFIX.join "Library", "Taps"
|
||||
end
|
||||
|
||||
def self.caskroom
|
||||
@@caskroom ||= Pathname('/opt/homebrew-cask/Caskroom')
|
||||
end
|
||||
|
||||
def self.caskroom=(caskroom)
|
||||
@@caskroom = caskroom
|
||||
end
|
||||
|
||||
def self.appdir
|
||||
@appdir ||= Pathname.new(File.expand_path("~/Applications"))
|
||||
end
|
||||
|
||||
def self.appdir=(_appdir)
|
||||
@appdir = _appdir
|
||||
end
|
||||
|
||||
def self.default_tap
|
||||
@default_tap ||= 'phinze-cask'
|
||||
end
|
||||
|
||||
def self.default_tap=(_tap)
|
||||
@default_tap = _tap
|
||||
end
|
||||
|
||||
def self._file_source?(requested_cask)
|
||||
File.file?(requested_cask)
|
||||
end
|
||||
|
|
@ -76,24 +49,6 @@ class Cask
|
|||
appdir.mkpath unless appdir.exist?
|
||||
end
|
||||
|
||||
def self.path(cask_title)
|
||||
if cask_title.include?('/')
|
||||
cask_with_tap = cask_title
|
||||
else
|
||||
cask_with_tap = all_titles.detect { |tap_and_title|
|
||||
_, title = tap_and_title.split('/')
|
||||
title == cask_title
|
||||
}
|
||||
end
|
||||
|
||||
if cask_with_tap
|
||||
tap, cask = cask_with_tap.split('/')
|
||||
tapspath.join(tap, 'Casks', "#{cask}.rb")
|
||||
else
|
||||
tapspath.join(default_tap, 'Casks', "#{cask_title}.rb")
|
||||
end
|
||||
end
|
||||
|
||||
def self._load_from_tap(cask_title)
|
||||
if cask_title.include?('/')
|
||||
cask_with_tap = cask_title
|
||||
|
|
@ -161,14 +116,6 @@ class Cask
|
|||
destination_path.exist?
|
||||
end
|
||||
|
||||
def linkable_apps
|
||||
linkables.map { |app| Pathname.glob("#{destination_path}/**/#{app}").first }
|
||||
end
|
||||
|
||||
def installers
|
||||
installables.map { |pkg| Pathname.glob("#{destination_path}/**/#{pkg}").first }
|
||||
end
|
||||
|
||||
def to_s
|
||||
@title
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
class Cask
|
||||
class AppLinker
|
||||
def initialize(cask)
|
||||
@cask = cask
|
||||
end
|
||||
|
||||
def link
|
||||
@cask.linkable_apps.each { |app| link_app(app) }
|
||||
end
|
||||
|
||||
def unlink
|
||||
@cask.linkable_apps.each { |app| unlink_app(app) }
|
||||
end
|
||||
|
||||
def unlink_app(app)
|
||||
app_path = Cask.appdir.join(app.basename)
|
||||
if app_path.exist? && app_path.symlink?
|
||||
ohai "Removing link: #{app_path}"
|
||||
app_path.delete
|
||||
end
|
||||
end
|
||||
|
||||
def link_app(app)
|
||||
app_path = Cask.appdir.join(app.basename)
|
||||
if app_path.directory? && !app_path.symlink?
|
||||
ohai "It seems there is already an app at #{app_path}; not linking."
|
||||
return
|
||||
end
|
||||
ohai "Linking #{app.basename} to #{app_path}"
|
||||
system %Q(/bin/ln -hfs "#{app}" "#{app_path}")
|
||||
end
|
||||
end
|
||||
end
|
||||
21
lib/cask/artifact.rb
Normal file
21
lib/cask/artifact.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
module Cask::Artifact; end
|
||||
|
||||
require 'cask/artifact/base'
|
||||
|
||||
require 'cask/artifact/app'
|
||||
require 'cask/artifact/pkg'
|
||||
require 'cask/artifact/prefpane'
|
||||
|
||||
module Cask::Artifact
|
||||
def self.artifacts
|
||||
[
|
||||
Cask::Artifact::App,
|
||||
Cask::Artifact::Pkg,
|
||||
Cask::Artifact::Prefpane,
|
||||
]
|
||||
end
|
||||
|
||||
def self.for_cask(cask)
|
||||
artifacts.select { |artifact| artifact.me?(cask) }
|
||||
end
|
||||
end
|
||||
41
lib/cask/artifact/app.rb
Normal file
41
lib/cask/artifact/app.rb
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
class Cask::Artifact::App < Cask::Artifact::Base
|
||||
def self.me?(cask)
|
||||
cask.artifacts[:link].any?
|
||||
end
|
||||
|
||||
def install
|
||||
@cask.artifacts[:link].each { |app| link(app) }
|
||||
end
|
||||
|
||||
def uninstall
|
||||
@cask.artifacts[:link].each { |app| unlink(app) }
|
||||
end
|
||||
|
||||
def link(app_relative_path)
|
||||
source = @cask.destination_path.join(app_relative_path)
|
||||
target = Cask.appdir.join(source.basename)
|
||||
|
||||
return unless preflight_checks(source, target)
|
||||
ohai "Linking #{source.basename} to #{target}"
|
||||
@command.run('ln', :args => ['-hfs', source, target])
|
||||
end
|
||||
|
||||
def preflight_checks(source, target)
|
||||
if target.directory? && !target.symlink?
|
||||
ohai "It seems there is already an app at #{target}; not linking."
|
||||
return false
|
||||
end
|
||||
unless source.exist?
|
||||
raise "it seems the symlink source is not there: #{source}"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def unlink(app_relative_path)
|
||||
linked_path = Cask.appdir.join(Pathname(app_relative_path).basename)
|
||||
if linked_path.exist? && linked_path.symlink?
|
||||
ohai "Removing link: #{linked_path}"
|
||||
linked_path.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
6
lib/cask/artifact/base.rb
Normal file
6
lib/cask/artifact/base.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class Cask::Artifact::Base
|
||||
def initialize(cask, command=Cask::SystemCommand)
|
||||
@cask = cask
|
||||
@command = command
|
||||
end
|
||||
end
|
||||
59
lib/cask/artifact/pkg.rb
Normal file
59
lib/cask/artifact/pkg.rb
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
class Cask::Artifact::Pkg < Cask::Artifact::Base
|
||||
def self.me?(cask)
|
||||
cask.artifacts[:install].any?
|
||||
end
|
||||
|
||||
def install
|
||||
@cask.artifacts[:install].each { |pkg| run_installer(pkg) }
|
||||
end
|
||||
|
||||
def uninstall
|
||||
@cask.artifacts[:uninstall].each { |opts| manually_uninstall(opts) }
|
||||
end
|
||||
|
||||
def run_installer(pkg_relative_path)
|
||||
ohai "Running installer for #{@cask}; your password may be necessary."
|
||||
@command.run("installer", {
|
||||
:sudo => true,
|
||||
:args => %W[-pkg #{@cask.destination_path.join(pkg_relative_path)} -target /],
|
||||
:print => true
|
||||
})
|
||||
end
|
||||
|
||||
def manually_uninstall(uninstall_options)
|
||||
ohai "Running uninstall process for #{@cask}; your password may be necessary."
|
||||
if uninstall_options.key? :script
|
||||
@command.run(
|
||||
@cask.destination_path.join(uninstall_options[:script]),
|
||||
uninstall_options.merge(:sudo => true, :print => true)
|
||||
)
|
||||
end
|
||||
|
||||
if uninstall_options.key? :kext
|
||||
[*uninstall_options[:kext]].each do |kext|
|
||||
ohai "Unloading kernel extension #{kext}"
|
||||
@command.run('kextunload', :args => ['-b', kext], :sudo => true)
|
||||
end
|
||||
end
|
||||
|
||||
if uninstall_options.key? :pkgutil
|
||||
pkgs = Cask::Pkg.all_matching(uninstall_options[:pkgutil], @command)
|
||||
pkgs.each(&:uninstall)
|
||||
end
|
||||
|
||||
if uninstall_options.key? :launchctl
|
||||
[*uninstall_options[:launchctl]].each do |service|
|
||||
ohai "Removing launchctl service #{service}"
|
||||
@command.run('launchctl', :args => ['remove', service], :sudo => true)
|
||||
end
|
||||
end
|
||||
|
||||
if uninstall_options.key? :files
|
||||
uninstall_options[:files].each do |file|
|
||||
ohai "Removing file #{file}"
|
||||
@command.run('rm', :args => ['-rf', file], :sudo => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
41
lib/cask/artifact/prefpane.rb
Normal file
41
lib/cask/artifact/prefpane.rb
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
class Cask::Artifact::Prefpane < Cask::Artifact::Base
|
||||
def self.me?(cask)
|
||||
cask.artifacts[:prefpane].any?
|
||||
end
|
||||
|
||||
def install
|
||||
@cask.artifacts[:prefpane].each { |prefpane| link(prefpane) }
|
||||
end
|
||||
|
||||
def uninstall
|
||||
@cask.artifacts[:prefpane].each { |prefpane| unlink(prefpane) }
|
||||
end
|
||||
|
||||
def link(prefpane_relative_path)
|
||||
source = @cask.destination_path.join(prefpane_relative_path)
|
||||
target = Cask.prefpanedir.join(source.basename)
|
||||
|
||||
return unless preflight_checks(source, target)
|
||||
ohai "Linking prefPane #{source.basename} to #{target}"
|
||||
@command.run('ln', :args => ['-hfs', source, target])
|
||||
end
|
||||
|
||||
def preflight_checks(source, target)
|
||||
if target.directory? && !target.symlink?
|
||||
ohai "It seems there is already an prefpane at #{target}; not linking."
|
||||
false
|
||||
end
|
||||
unless source.exist?
|
||||
raise "it seems the symlink source is not there: #{source}"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def unlink(prefpane_relative_path)
|
||||
linked_path = Cask.prefpanedir.join(Pathname(prefpane_relative_path).basename)
|
||||
if linked_path.exist? && linked_path.symlink?
|
||||
ohai "Removing prefPane link: #{linked_path}"
|
||||
linked_path.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -11,11 +11,9 @@ require 'cask/cli/edit'
|
|||
require 'cask/cli/home'
|
||||
require 'cask/cli/info'
|
||||
require 'cask/cli/install'
|
||||
require 'cask/cli/linkapps'
|
||||
require 'cask/cli/list'
|
||||
require 'cask/cli/search'
|
||||
require 'cask/cli/uninstall'
|
||||
require 'cask/cli/unlinkapps'
|
||||
|
||||
class Cask::CLI
|
||||
def self.commands
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ class Cask::CLI::Install
|
|||
begin
|
||||
cask = Cask.load(cask_name)
|
||||
Cask::Installer.new(cask).install(force)
|
||||
Cask::AppLinker.new(cask).link
|
||||
Cask::PkgInstaller.new(cask).install
|
||||
rescue CaskError => e
|
||||
onoe e
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
class Cask::CLI::Linkapps
|
||||
def self.run(*args)
|
||||
casks_to_link = args.empty? ? Cask.installed : args
|
||||
casks_to_link.each do |cask_name|
|
||||
Cask::AppLinker.new(Cask.load(cask_name)).link
|
||||
end
|
||||
end
|
||||
|
||||
def self.help
|
||||
"makes a symlink from all cask-installed .app files into ~/Applications"
|
||||
end
|
||||
end
|
||||
|
|
@ -4,8 +4,6 @@ class Cask::CLI::Uninstall
|
|||
casks = cask_names.map { |cn| Cask.load(cn) }
|
||||
casks.each do |cask|
|
||||
raise CaskNotInstalledError.new(cask) unless cask.installed?
|
||||
Cask::PkgInstaller.new(cask).uninstall
|
||||
Cask::AppLinker.new(cask).unlink
|
||||
Cask::Installer.new(cask).uninstall
|
||||
end
|
||||
rescue CaskError => e
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
class Cask::CLI::Unlinkapps
|
||||
def self.run(*args)
|
||||
casks_to_link = args.empty? ? Cask.installed : args
|
||||
casks_to_link.each do |cask_name|
|
||||
Cask::AppLinker.new(Cask.load(cask_name)).unlink
|
||||
end
|
||||
end
|
||||
|
||||
def self.help
|
||||
"removes symlinks from cask-installed .app files from ~/Applications"
|
||||
end
|
||||
end
|
||||
|
|
@ -14,7 +14,8 @@ class Cask::Container::Criteria
|
|||
@imageinfo ||= @command.run(
|
||||
'hdiutil',
|
||||
:args => ['imageinfo', path],
|
||||
:stderr => :silence
|
||||
:stderr => :silence,
|
||||
:print => false
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,11 +14,7 @@ module Cask::DSL
|
|||
|
||||
def sums; self.class.sums || []; end
|
||||
|
||||
def linkables; self.class.linkables || {}; end
|
||||
|
||||
def installables; self.class.installables || []; end
|
||||
|
||||
def uninstallables; self.class.uninstallables || []; end
|
||||
def artifacts; self.class.artifacts; end
|
||||
|
||||
def caveats; ''; end
|
||||
|
||||
|
|
@ -35,31 +31,21 @@ module Cask::DSL
|
|||
@version ||= version
|
||||
end
|
||||
|
||||
def linkables
|
||||
@linkables ||= Set.new
|
||||
def artifacts
|
||||
@artifacts ||= Hash.new { |hash, key| hash[key] = Set.new }
|
||||
end
|
||||
|
||||
def link(*args)
|
||||
# handle old-style casks using link :app, 'Foo.app'
|
||||
args.shift if args.first.is_a? Symbol
|
||||
ARTIFACT_TYPES = [
|
||||
:link,
|
||||
:prefpane,
|
||||
:install,
|
||||
:uninstall
|
||||
]
|
||||
|
||||
linkables.merge args
|
||||
end
|
||||
|
||||
def installables
|
||||
@installables ||= Set.new
|
||||
end
|
||||
|
||||
def install(*files)
|
||||
installables.merge files
|
||||
end
|
||||
|
||||
def uninstallables
|
||||
@uninstallables ||= Set.new
|
||||
end
|
||||
|
||||
def uninstall(options)
|
||||
uninstallables.merge [options]
|
||||
ARTIFACT_TYPES.each do |type|
|
||||
define_method(type) do |*args|
|
||||
artifacts[type].merge(args)
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :sums
|
||||
|
|
|
|||
|
|
@ -11,25 +11,56 @@ class Cask::Installer
|
|||
raise CaskAlreadyInstalledError.new(@cask)
|
||||
end
|
||||
|
||||
download = Cask::Download.new(@cask)
|
||||
downloaded_path = download.perform
|
||||
|
||||
FileUtils.mkdir_p @cask.destination_path
|
||||
|
||||
container = Cask::Container.for_path(downloaded_path, @command)
|
||||
unless container
|
||||
raise "uh oh, could not identify container for #{downloaded_path}"
|
||||
end
|
||||
container.new(@cask, downloaded_path, @command).extract
|
||||
download
|
||||
extract_container
|
||||
install_artifacts
|
||||
|
||||
ohai "Success! #{@cask} installed to #{@cask.destination_path}"
|
||||
|
||||
print_caveats
|
||||
end
|
||||
|
||||
|
||||
def download
|
||||
download = Cask::Download.new(@cask)
|
||||
@downloaded_path = download.perform
|
||||
end
|
||||
|
||||
def extract_container
|
||||
FileUtils.mkdir_p @cask.destination_path
|
||||
container = Cask::Container.for_path(@downloaded_path, @command)
|
||||
unless container
|
||||
raise "uh oh, could not identify container for #{@downloaded_path}"
|
||||
end
|
||||
container.new(@cask, @downloaded_path, @command).extract
|
||||
end
|
||||
|
||||
def install_artifacts
|
||||
artifacts = Cask::Artifact.for_cask(@cask)
|
||||
artifacts.each do |artifact|
|
||||
artifact.new(@cask, @command).install
|
||||
end
|
||||
end
|
||||
|
||||
def print_caveats
|
||||
unless @cask.caveats.empty?
|
||||
ohai 'Caveats', @cask.caveats
|
||||
end
|
||||
end
|
||||
|
||||
def uninstall
|
||||
uninstall_artifacts
|
||||
purge_files
|
||||
end
|
||||
|
||||
def uninstall_artifacts
|
||||
artifacts = Cask::Artifact.for_cask(@cask)
|
||||
artifacts.each do |artifact|
|
||||
artifact.new(@cask, @command).uninstall
|
||||
end
|
||||
end
|
||||
|
||||
def purge_files
|
||||
@cask.destination_path.rmtree
|
||||
end
|
||||
end
|
||||
|
|
|
|||
61
lib/cask/locations.rb
Normal file
61
lib/cask/locations.rb
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
module Cask::Locations
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def tapspath
|
||||
HOMEBREW_PREFIX.join "Library", "Taps"
|
||||
end
|
||||
|
||||
def caskroom
|
||||
@@caskroom ||= Pathname('/opt/homebrew-cask/Caskroom')
|
||||
end
|
||||
|
||||
def caskroom=(caskroom)
|
||||
@@caskroom = caskroom
|
||||
end
|
||||
|
||||
def appdir
|
||||
@appdir ||= Pathname.new('~/Applications').expand_path
|
||||
end
|
||||
|
||||
def appdir=(_appdir)
|
||||
@appdir = _appdir
|
||||
end
|
||||
|
||||
def prefpanedir
|
||||
@prefpanedir ||= Pathname.new('~/Library/PreferencePanes').expand_path
|
||||
end
|
||||
|
||||
def prefpanedir=(_prefpanedir)
|
||||
@prefpanedir = _prefpanedir
|
||||
end
|
||||
|
||||
def default_tap
|
||||
@default_tap ||= 'phinze-cask'
|
||||
end
|
||||
|
||||
def default_tap=(_tap)
|
||||
@default_tap = _tap
|
||||
end
|
||||
|
||||
def path(cask_title)
|
||||
if cask_title.include?('/')
|
||||
cask_with_tap = cask_title
|
||||
else
|
||||
cask_with_tap = all_titles.detect { |tap_and_title|
|
||||
_, title = tap_and_title.split('/')
|
||||
title == cask_title
|
||||
}
|
||||
end
|
||||
|
||||
if cask_with_tap
|
||||
tap, cask = cask_with_tap.split('/')
|
||||
tapspath.join(tap, 'Casks', "#{cask}.rb")
|
||||
else
|
||||
tapspath.join(default_tap, 'Casks', "#{cask_title}.rb")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
class Cask::PkgInstaller
|
||||
def initialize(cask, command=Cask::SystemCommand)
|
||||
@cask = cask
|
||||
@command = command
|
||||
end
|
||||
|
||||
def install
|
||||
@cask.installers.each do |installer|
|
||||
ohai "Running installer for #{@cask}; your password may be necessary."
|
||||
@command.run("installer", {
|
||||
:sudo => true,
|
||||
:args => %W[-pkg #{installer} -target /],
|
||||
:print => true
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def uninstall
|
||||
@cask.uninstallables.each do |uninstall_options|
|
||||
ohai "Running uninstall process for #{@cask}; your password may be necessary."
|
||||
if uninstall_options.key? :script
|
||||
@command.run(
|
||||
@cask.destination_path.join(uninstall_options[:script]),
|
||||
uninstall_options.merge(:sudo => true, :print => true)
|
||||
)
|
||||
end
|
||||
|
||||
if uninstall_options.key? :kext
|
||||
[*uninstall_options[:kext]].each do |kext|
|
||||
ohai "Unloading kernel extension #{kext}"
|
||||
@command.run('kextunload', :args => ['-b', kext], :sudo => true)
|
||||
end
|
||||
end
|
||||
|
||||
if uninstall_options.key? :pkgutil
|
||||
pkgs = Cask::Pkg.all_matching(uninstall_options[:pkgutil], @command)
|
||||
pkgs.each(&:uninstall)
|
||||
end
|
||||
|
||||
if uninstall_options.key? :launchctl
|
||||
[*uninstall_options[:launchctl]].each do |service|
|
||||
ohai "Removing launchctl service #{service}"
|
||||
@command.run('launchctl', :args => ['remove', service], :sudo => true)
|
||||
end
|
||||
end
|
||||
|
||||
if uninstall_options.key? :files
|
||||
uninstall_options[:files].each do |file|
|
||||
ohai "Removing file #{file}"
|
||||
@command.run('rm', :args => ['-rf', file], :sudo => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
require 'test_helper'
|
||||
|
||||
describe Cask::AppLinker do
|
||||
describe 'linkapps' do
|
||||
before do
|
||||
@caffeine = Cask.load('local-caffeine')
|
||||
shutup { Cask::Installer.new(@caffeine).install }
|
||||
@app = @caffeine.destination_path/'Caffeine.app'
|
||||
end
|
||||
|
||||
it "works with an application in the root directory" do
|
||||
shutup do
|
||||
Cask::AppLinker.new(@caffeine).link
|
||||
end
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
end
|
||||
|
||||
it "works with an application in a subdir" do
|
||||
appsubdir = @caffeine.destination_path/'subdir'
|
||||
appsubdir.mkpath
|
||||
FileUtils.mv @app, appsubdir
|
||||
appinsubdir = appsubdir/'Caffeine.app'
|
||||
|
||||
shutup do
|
||||
Cask::AppLinker.new(@caffeine).link
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
end
|
||||
|
||||
it "only uses linkables when they are specified" do
|
||||
FileUtils.cp_r @app, @app.sub('Caffeine.app', 'CaffeineAgain.app')
|
||||
|
||||
shutup do
|
||||
Cask::AppLinker.new(@caffeine).link
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
TestHelper.valid_alias?(Cask.appdir/'CaffeineAgain.app').must_equal false
|
||||
end
|
||||
|
||||
it "avoids clobbering an existing app by linking over it" do
|
||||
(Cask.appdir/'Caffeine.app').mkpath
|
||||
|
||||
TestHelper.must_output(self, lambda {
|
||||
Cask::AppLinker.new(@caffeine).link
|
||||
}, "==> It seems there is already an app at #{Cask.appdir.join('Caffeine.app')}; not linking.")
|
||||
|
||||
(Cask.appdir/'Caffeine.app').wont_be :symlink?
|
||||
end
|
||||
|
||||
it "happily clobbers an existing symlink" do
|
||||
(Cask.appdir/'Caffeine.app').make_symlink('/tmp')
|
||||
|
||||
TestHelper.must_output(self, lambda {
|
||||
Cask::AppLinker.new(@caffeine).link
|
||||
}, "==> Linking Caffeine.app to #{Cask.appdir.join('Caffeine.app')}")
|
||||
|
||||
File.readlink(Cask.appdir/'Caffeine.app').wont_equal '/tmp'
|
||||
end
|
||||
end
|
||||
end
|
||||
83
test/cask/artifact/app_test.rb
Normal file
83
test/cask/artifact/app_test.rb
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
require 'test_helper'
|
||||
|
||||
describe Cask::Artifact::App do
|
||||
let(:local_caffeine) {
|
||||
Cask.load('local-caffeine').tap do |cask|
|
||||
TestHelper.install_without_artifacts(cask)
|
||||
end
|
||||
}
|
||||
|
||||
describe 'install' do
|
||||
it "links the noted applications to the proper directory" do
|
||||
cask = local_caffeine
|
||||
|
||||
shutup do
|
||||
Cask::Artifact::App.new(cask).install
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
end
|
||||
|
||||
it "works with an application in a subdir" do
|
||||
SubDirCask = Class.new(Cask)
|
||||
SubDirCask.class_eval do
|
||||
url TestHelper.local_binary('caffeine.zip')
|
||||
homepage 'http://example.com/local-caffeine'
|
||||
version '1.2.3'
|
||||
sha1 'd2fbdad1619934313026fc831e6c6e3dd97ac030'
|
||||
link 'subdir/Caffeine.app'
|
||||
end
|
||||
|
||||
subdir_cask = SubDirCask.new.tap do |cask|
|
||||
TestHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
appsubdir = (subdir_cask.destination_path/'subdir').tap(&:mkpath)
|
||||
FileUtils.mv((subdir_cask.destination_path/'Caffeine.app'), appsubdir)
|
||||
|
||||
shutup do
|
||||
Cask::Artifact::App.new(subdir_cask).install
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
end
|
||||
|
||||
it "only uses linkables when they are specified" do
|
||||
cask = local_caffeine
|
||||
|
||||
app_path = cask.destination_path.join('Caffeine.app')
|
||||
FileUtils.cp_r app_path, app_path.sub('Caffeine.app', 'CaffeineAgain.app')
|
||||
|
||||
shutup do
|
||||
Cask::Artifact::App.new(cask).install
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/'Caffeine.app').must_equal true
|
||||
TestHelper.valid_alias?(Cask.appdir/'CaffeineAgain.app').must_equal false
|
||||
end
|
||||
|
||||
it "avoids clobbering an existing app by linking over it" do
|
||||
cask = local_caffeine
|
||||
|
||||
(Cask.appdir/'Caffeine.app').mkpath
|
||||
|
||||
TestHelper.must_output(self, lambda {
|
||||
Cask::Artifact::App.new(cask).install
|
||||
}, "==> It seems there is already an app at #{Cask.appdir.join('Caffeine.app')}; not linking.")
|
||||
|
||||
(Cask.appdir/'Caffeine.app').wont_be :symlink?
|
||||
end
|
||||
|
||||
it "happily clobbers an existing symlink" do
|
||||
cask = local_caffeine
|
||||
|
||||
(Cask.appdir/'Caffeine.app').make_symlink('/tmp')
|
||||
|
||||
TestHelper.must_output(self, lambda {
|
||||
Cask::Artifact::App.new(cask).install
|
||||
}, "==> Linking Caffeine.app to #{Cask.appdir.join('Caffeine.app')}")
|
||||
|
||||
File.readlink(Cask.appdir/'Caffeine.app').wont_equal '/tmp'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
require 'test_helper'
|
||||
|
||||
describe Cask::PkgInstaller do
|
||||
describe Cask::Artifact::Pkg do
|
||||
before {
|
||||
@cask = Cask.load('with-installable')
|
||||
shutup do
|
||||
Cask::Installer.new(@cask).install
|
||||
TestHelper.install_without_artifacts(@cask)
|
||||
end
|
||||
}
|
||||
|
||||
describe 'install' do
|
||||
it 'runs the system installer on the specified pkgs' do
|
||||
pkg_installer = Cask::PkgInstaller.new(@cask, Cask::FakeSystemCommand)
|
||||
pkg = Cask::Artifact::Pkg.new(@cask, Cask::FakeSystemCommand)
|
||||
|
||||
expected_command = "sudo 'installer' '-pkg' '#{@cask.destination_path/'MyFancyPkg'/'Fancy.pkg'}' '-target' '/' 2>&1"
|
||||
Cask::FakeSystemCommand.fake_response_for(expected_command)
|
||||
|
||||
shutup do
|
||||
pkg_installer.install
|
||||
pkg.install
|
||||
end
|
||||
|
||||
Cask::FakeSystemCommand.system_calls[expected_command].must_equal 1
|
||||
|
|
@ -25,13 +25,13 @@ describe Cask::PkgInstaller do
|
|||
|
||||
describe 'uninstall' do
|
||||
it 'runs the specified uninstaller for the cask' do
|
||||
pkg_installer = Cask::PkgInstaller.new(@cask, Cask::FakeSystemCommand)
|
||||
pkg = Cask::Artifact::Pkg.new(@cask, Cask::FakeSystemCommand)
|
||||
|
||||
expected_command = "sudo '#{@cask.destination_path/'MyFancyPkg'/'FancyUninstaller.tool'}' '--please' 2>&1"
|
||||
Cask::FakeSystemCommand.fake_response_for(expected_command)
|
||||
|
||||
shutup do
|
||||
pkg_installer.uninstall
|
||||
pkg.uninstall
|
||||
end
|
||||
|
||||
Cask::FakeSystemCommand.system_calls[expected_command].must_equal 1
|
||||
|
|
@ -39,7 +39,7 @@ describe Cask::PkgInstaller do
|
|||
|
||||
it 'can uninstall using pkgutil, launchctl, and file lists' do
|
||||
cask = Cask.load('with-pkgutil-uninstall')
|
||||
pkg_installer = Cask::PkgInstaller.new(cask, Cask::FakeSystemCommand)
|
||||
pkg = Cask::Artifact::Pkg.new(cask, Cask::FakeSystemCommand)
|
||||
|
||||
Cask::FakeSystemCommand.fake_response_for(
|
||||
%Q(pkgutil --pkgs="my.fancy.package.*" 2>&1),
|
||||
|
|
@ -127,7 +127,7 @@ describe Cask::PkgInstaller do
|
|||
# No assertions after call since all assertions are implicit from the interactions setup above.
|
||||
# TODO: verify rmdir / rm commands (requires setting up actual file tree or faking out .exists?
|
||||
shutup do
|
||||
pkg_installer.uninstall
|
||||
pkg.uninstall
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -23,19 +23,6 @@ describe Cask::DSL do
|
|||
]
|
||||
end
|
||||
|
||||
it "still lets you set content_length even though it is deprecated" do
|
||||
OldContentLengthCask = Class.new(Cask)
|
||||
begin
|
||||
shutup do
|
||||
OldContentLengthCask.class_eval do
|
||||
content_length '12345'
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
flunk("expected content_length to work, but got exception #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
it "prevents the entire world from crashing when a cask includes an unknown method" do
|
||||
UnexpectedMethodCask = Class.new(Cask)
|
||||
begin
|
||||
|
|
@ -49,17 +36,6 @@ describe Cask::DSL do
|
|||
end
|
||||
end
|
||||
|
||||
it "allows you to specify linkables in the old way, for backcompat" do
|
||||
CaskWithOldSchoolLinkables = Class.new(Cask)
|
||||
CaskWithOldSchoolLinkables.class_eval do
|
||||
link :app, 'Foo.app'
|
||||
link :app, 'Bar.app'
|
||||
end
|
||||
|
||||
instance = CaskWithOldSchoolLinkables.new
|
||||
Array(instance.linkables).sort.must_equal %w[Bar.app Foo.app]
|
||||
end
|
||||
|
||||
it "allows you to specify linkables" do
|
||||
CaskWithLinkables = Class.new(Cask)
|
||||
CaskWithLinkables.class_eval do
|
||||
|
|
@ -68,14 +44,14 @@ describe Cask::DSL do
|
|||
end
|
||||
|
||||
instance = CaskWithLinkables.new
|
||||
Array(instance.linkables).sort.must_equal %w[Bar.app Foo.app]
|
||||
Array(instance.artifacts[:link]).sort.must_equal %w[Bar.app Foo.app]
|
||||
end
|
||||
|
||||
it "allow linkables to be set to empty" do
|
||||
CaskWithNoLinkables = Class.new(Cask)
|
||||
|
||||
instance = CaskWithNoLinkables.new
|
||||
Array(instance.linkable_apps).must_equal %w[]
|
||||
Array(instance.artifacts[:link]).must_equal %w[]
|
||||
end
|
||||
|
||||
it "allows caveats to be specified via a method define" do
|
||||
|
|
@ -106,6 +82,6 @@ describe Cask::DSL do
|
|||
end
|
||||
|
||||
instance = CaskWithInstallables.new
|
||||
Array(instance.installables).sort.must_equal %w[Bar.pkg Foo.pkg]
|
||||
Array(instance.artifacts[:install]).sort.must_equal %w[Bar.pkg Foo.pkg]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
require 'test_helper'
|
||||
|
||||
describe Cask::CLI::Linkapps do
|
||||
before do
|
||||
shutup do
|
||||
caffeine = Cask.load('local-caffeine')
|
||||
transmission = Cask.load('local-transmission')
|
||||
|
||||
Cask::Installer.new(caffeine).install
|
||||
Cask::Installer.new(transmission).install
|
||||
end
|
||||
end
|
||||
|
||||
it "only links casks mentioned when arguments are provided" do
|
||||
shutup do
|
||||
Cask::CLI::Linkapps.run('local-transmission')
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/"Transmission.app").must_equal true
|
||||
TestHelper.valid_alias?(Cask.appdir/"Caffeine.app").wont_equal true
|
||||
end
|
||||
|
||||
it "links all installed casks when no arguments supplied" do
|
||||
shutup do
|
||||
Cask::CLI::Linkapps.run
|
||||
end
|
||||
|
||||
TestHelper.valid_alias?(Cask.appdir/"Transmission.app").must_equal true
|
||||
TestHelper.valid_alias?(Cask.appdir/"Caffeine.app").must_equal true
|
||||
end
|
||||
end
|
||||
|
|
@ -19,9 +19,7 @@ describe Cask::CLI::Uninstall do
|
|||
|
||||
shutup do
|
||||
Cask::Installer.new(caffeine).install
|
||||
Cask::AppLinker.new(caffeine).link
|
||||
Cask::Installer.new(transmission).install
|
||||
Cask::AppLinker.new(transmission).link
|
||||
end
|
||||
|
||||
caffeine.must_be :installed?
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
require 'test_helper'
|
||||
|
||||
describe Cask::CLI::Unlinkapps do
|
||||
before do
|
||||
shutup do
|
||||
# use CLI so both casks start installed and linked
|
||||
Cask::CLI::Install.run('local-caffeine', 'local-transmission')
|
||||
end
|
||||
end
|
||||
|
||||
it "only unlinks casks mentioned when arguments are provided" do
|
||||
shutup do
|
||||
Cask::CLI::Unlinkapps.run('local-transmission')
|
||||
end
|
||||
|
||||
(Cask.appdir/"Transmission.app").wont_be :symlink?
|
||||
(Cask.appdir/"Caffeine.app").must_be :symlink?
|
||||
end
|
||||
|
||||
it "unlinks all installed casks when no arguments supplied" do
|
||||
shutup do
|
||||
Cask::CLI::Unlinkapps.run
|
||||
end
|
||||
|
||||
(Cask.appdir/"Transmission.app").wont_be :symlink?
|
||||
(Cask.appdir/"Caffeine.app").wont_be :symlink?
|
||||
end
|
||||
end
|
||||
|
|
@ -3,6 +3,6 @@ class WithInstallable < TestCask
|
|||
homepage 'http://example.com/fancy-pkg'
|
||||
version '1.2.3'
|
||||
sha1 '8588bd8175a54b8e0a1310cc18e6567d520ab7c4'
|
||||
install 'Fancy.pkg'
|
||||
install 'MyFancyPkg/Fancy.pkg'
|
||||
uninstall :script => 'MyFancyPkg/FancyUninstaller.tool', :args => %w[--please]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
module Cask::CleanupHooks
|
||||
def after_teardown
|
||||
super
|
||||
Cask.all.select(&:installed?).each { |c| Cask::Installer.new(c).uninstall }
|
||||
Cask.all.select(&:installed?).each do |cask|
|
||||
Cask::Installer.new(cask).tap do |installer|
|
||||
installer.purge_files
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,13 @@ class TestHelper
|
|||
return false unless candidate.symlink?
|
||||
candidate.readlink.exist?
|
||||
end
|
||||
|
||||
def self.install_without_artifacts(cask)
|
||||
Cask::Installer.new(cask).tap do |i|
|
||||
shutup { i.download }
|
||||
i.extract_container
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'support/fake_fetcher'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue