2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-08-18 22:11:42 +03:00
|
|
|
require "rubygems"
|
|
|
|
|
2017-06-28 17:53:59 +02:00
|
|
|
require "formula_installer"
|
2018-07-23 23:04:49 +02:00
|
|
|
require "unpack_strategy"
|
2017-06-28 17:53:59 +02:00
|
|
|
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/cask_dependencies"
|
2019-02-03 13:03:16 +01:00
|
|
|
require "cask/config"
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/download"
|
|
|
|
require "cask/staged"
|
|
|
|
require "cask/verify"
|
|
|
|
require "cask/quarantine"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-07-16 20:22:37 +02:00
|
|
|
require "cgi"
|
|
|
|
|
2018-09-06 08:29:14 +02:00
|
|
|
module Cask
|
2016-09-24 13:52:43 +02:00
|
|
|
class Installer
|
2017-06-26 07:30:28 +02:00
|
|
|
extend Predicable
|
2018-09-06 08:29:14 +02:00
|
|
|
# TODO: it is unwise for Cask::Staged to be a module, when we are
|
2016-09-24 13:52:43 +02:00
|
|
|
# dealing with both staged and unstaged Casks here. This should
|
|
|
|
# either be a class which is only sometimes instantiated, or there
|
|
|
|
# should be explicit checks on whether staged state is valid in
|
|
|
|
# every method.
|
|
|
|
include Staged
|
|
|
|
|
2018-08-31 13:16:11 +00:00
|
|
|
def initialize(cask, command: SystemCommand, force: false,
|
|
|
|
skip_cask_deps: false, binaries: true, verbose: false,
|
|
|
|
require_sha: false, upgrade: false,
|
|
|
|
installed_as_dependency: false, quarantine: true)
|
2016-09-24 13:52:43 +02:00
|
|
|
@cask = cask
|
|
|
|
@command = command
|
|
|
|
@force = force
|
|
|
|
@skip_cask_deps = skip_cask_deps
|
2017-05-19 19:13:23 +02:00
|
|
|
@binaries = binaries
|
2017-05-21 00:15:56 +02:00
|
|
|
@verbose = verbose
|
2016-09-24 13:52:43 +02:00
|
|
|
@require_sha = require_sha
|
2017-03-27 01:31:29 -05:00
|
|
|
@reinstall = false
|
2017-10-29 17:31:07 -03:00
|
|
|
@upgrade = upgrade
|
2018-07-14 03:25:42 +02:00
|
|
|
@installed_as_dependency = installed_as_dependency
|
2018-08-31 13:16:11 +00:00
|
|
|
@quarantine = quarantine
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-08-31 13:16:11 +00:00
|
|
|
attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?,
|
2019-02-02 17:11:37 +01:00
|
|
|
:reinstall?, :upgrade?, :verbose?, :installed_as_dependency?,
|
2018-08-31 13:16:11 +00:00
|
|
|
:quarantine?
|
2017-05-21 00:15:56 +02:00
|
|
|
|
2019-03-11 21:20:02 -04:00
|
|
|
def self.caveats(cask)
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "Printing caveats"
|
2016-10-24 17:07:57 +02:00
|
|
|
|
2017-11-24 17:44:01 +01:00
|
|
|
caveats = cask.caveats
|
|
|
|
return if caveats.empty?
|
2016-10-24 17:07:57 +02:00
|
|
|
|
2019-02-24 21:53:04 -05:00
|
|
|
<<~EOS
|
|
|
|
#{ohai_title "Caveats"}
|
|
|
|
#{caveats}
|
|
|
|
EOS
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-12-04 23:13:39 +01:00
|
|
|
def fetch
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#fetch"
|
2016-12-04 23:13:39 +01:00
|
|
|
|
|
|
|
satisfy_dependencies
|
2018-07-14 03:25:42 +02:00
|
|
|
|
2017-06-26 07:30:28 +02:00
|
|
|
verify_has_sha if require_sha? && !force?
|
2016-12-04 23:13:39 +01:00
|
|
|
download
|
|
|
|
verify
|
|
|
|
end
|
|
|
|
|
|
|
|
def stage
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#stage"
|
2016-12-04 23:13:39 +01:00
|
|
|
|
2018-06-09 11:18:40 +02:00
|
|
|
Caskroom.ensure_caskroom_exists
|
|
|
|
|
2018-07-14 03:25:42 +02:00
|
|
|
unpack_dependencies
|
|
|
|
|
2016-12-04 23:13:39 +01:00
|
|
|
extract_primary_container
|
|
|
|
save_caskfile
|
2018-09-02 20:14:54 +01:00
|
|
|
rescue => e
|
2016-12-04 23:13:39 +01:00
|
|
|
purge_versioned_files
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def install
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#install"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2019-02-03 13:03:16 +01:00
|
|
|
old_config = @cask.config
|
|
|
|
|
2019-02-19 13:11:32 +00:00
|
|
|
raise CaskAlreadyInstalledError, @cask if @cask.installed? && !force? && !reinstall? && !upgrade?
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2017-08-05 15:56:34 +02:00
|
|
|
check_conflicts
|
|
|
|
|
2019-03-11 21:20:02 -04:00
|
|
|
print caveats
|
2016-12-04 23:13:39 +01:00
|
|
|
fetch
|
2019-02-02 17:11:37 +01:00
|
|
|
uninstall_existing_cask if reinstall?
|
2017-03-18 18:57:04 -05:00
|
|
|
|
2018-02-09 11:31:51 +09:00
|
|
|
oh1 "Installing Cask #{Formatter.identifier(@cask)}"
|
2018-08-31 13:16:11 +00:00
|
|
|
opoo "macOS's Gatekeeper has been disabled for this Cask" unless quarantine?
|
2016-12-04 23:13:39 +01:00
|
|
|
stage
|
2019-02-03 13:03:16 +01:00
|
|
|
|
|
|
|
@cask.config = Config.global.merge(old_config)
|
|
|
|
|
2016-12-04 23:13:39 +01:00
|
|
|
install_artifacts
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2019-02-19 13:11:32 +00:00
|
|
|
::Utils::Analytics.report_event("cask_install", @cask.token) unless @cask.tap&.private?
|
2018-08-06 12:21:48 -07:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
puts summary
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2017-08-05 15:56:34 +02:00
|
|
|
def check_conflicts
|
|
|
|
return unless @cask.conflicts_with
|
|
|
|
|
2019-01-27 21:34:24 +01:00
|
|
|
@cask.conflicts_with[:cask].each do |conflicting_cask|
|
2017-08-05 15:56:34 +02:00
|
|
|
begin
|
|
|
|
conflicting_cask = CaskLoader.load(conflicting_cask)
|
2019-02-19 13:11:32 +00:00
|
|
|
raise CaskConflictError.new(@cask, conflicting_cask) if conflicting_cask.installed?
|
2017-08-05 15:56:34 +02:00
|
|
|
rescue CaskUnavailableError
|
|
|
|
next # Ignore conflicting Casks that do not exist.
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-27 01:31:29 -05:00
|
|
|
def reinstall
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#reinstall"
|
2017-03-27 01:31:29 -05:00
|
|
|
@reinstall = true
|
|
|
|
install
|
|
|
|
end
|
|
|
|
|
2017-04-17 17:21:02 -07:00
|
|
|
def uninstall_existing_cask
|
|
|
|
return unless @cask.installed?
|
2017-03-18 17:48:20 -05:00
|
|
|
|
|
|
|
# use the same cask file that was used for installation, if possible
|
2017-04-17 17:21:02 -07:00
|
|
|
installed_caskfile = @cask.installed_caskfile
|
2017-10-07 15:58:49 +02:00
|
|
|
installed_cask = installed_caskfile.exist? ? CaskLoader.load(installed_caskfile) : @cask
|
2017-03-18 17:48:20 -05:00
|
|
|
|
|
|
|
# Always force uninstallation, ignore method parameter
|
2017-11-06 18:33:29 -03:00
|
|
|
Installer.new(installed_cask, binaries: binaries?, verbose: verbose?, force: true, upgrade: upgrade?).uninstall
|
2017-03-18 17:48:20 -05:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def summary
|
2019-04-20 14:07:29 +09:00
|
|
|
s = +""
|
2016-12-04 21:52:30 +01:00
|
|
|
s << "#{Emoji.install_badge} " if Emoji.enabled?
|
2017-11-06 21:27:02 -03:00
|
|
|
s << "#{@cask} was successfully #{upgrade? ? "upgraded" : "installed"}!"
|
2019-04-20 14:07:29 +09:00
|
|
|
s.freeze
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def download
|
|
|
|
odebug "Downloading"
|
2018-08-31 13:16:11 +00:00
|
|
|
@downloaded_path = Download.new(@cask, force: false, quarantine: quarantine?).perform
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "Downloaded to -> #{@downloaded_path}"
|
|
|
|
@downloaded_path
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def verify_has_sha
|
|
|
|
odebug "Checking cask has checksum"
|
|
|
|
return unless @cask.sha256 == :no_check
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-06-11 02:00:59 +02:00
|
|
|
raise CaskNoShasumError, @cask.token
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def verify
|
|
|
|
Verify.all(@cask, @downloaded_path)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-07-14 03:25:42 +02:00
|
|
|
def primary_container
|
|
|
|
@primary_container ||= begin
|
2019-04-09 21:45:35 +00:00
|
|
|
UnpackStrategy.detect(@downloaded_path, type: @cask.container&.type, merge_xattrs: true)
|
2016-10-14 20:11:33 +02:00
|
|
|
end
|
2018-07-14 03:25:42 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def extract_primary_container
|
|
|
|
odebug "Extracting primary container"
|
2016-12-04 23:13:39 +01:00
|
|
|
|
2018-07-14 03:25:42 +02:00
|
|
|
odebug "Using container class #{primary_container.class} for #{@downloaded_path}"
|
2018-07-16 20:22:37 +02:00
|
|
|
|
|
|
|
basename = CGI.unescape(File.basename(@cask.url.path))
|
2018-07-23 23:04:49 +02:00
|
|
|
|
|
|
|
if nested_container = @cask.container&.nested
|
|
|
|
Dir.mktmpdir do |tmpdir|
|
|
|
|
tmpdir = Pathname(tmpdir)
|
|
|
|
primary_container.extract(to: tmpdir, basename: basename, verbose: verbose?)
|
|
|
|
|
2018-11-02 14:26:35 +01:00
|
|
|
FileUtils.chmod_R "+rw", tmpdir/nested_container, force: true, verbose: verbose?
|
|
|
|
|
2019-04-09 21:45:35 +00:00
|
|
|
UnpackStrategy.detect(tmpdir/nested_container, merge_xattrs: true)
|
2018-07-23 23:04:49 +02:00
|
|
|
.extract_nestedly(to: @cask.staged_path, verbose: verbose?)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
primary_container.extract_nestedly(to: @cask.staged_path, basename: basename, verbose: verbose?)
|
|
|
|
end
|
2018-08-31 13:16:11 +00:00
|
|
|
|
|
|
|
return unless quarantine?
|
|
|
|
return unless Quarantine.available?
|
|
|
|
|
2018-09-04 21:11:29 +00:00
|
|
|
Quarantine.propagate(from: @downloaded_path, to: @cask.staged_path)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def install_artifacts
|
2016-12-04 23:14:35 +01:00
|
|
|
already_installed_artifacts = []
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "Installing artifacts"
|
2017-10-04 17:08:35 +02:00
|
|
|
artifacts = @cask.artifacts
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "#{artifacts.length} artifact/s defined", artifacts
|
2016-12-04 23:14:35 +01:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
artifacts.each do |artifact|
|
2017-02-05 07:47:54 +01:00
|
|
|
next unless artifact.respond_to?(:install_phase)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-02-05 23:27:35 +01:00
|
|
|
odebug "Installing artifact of class #{artifact.class}"
|
2017-05-19 19:13:23 +02:00
|
|
|
|
|
|
|
if artifact.is_a?(Artifact::Binary)
|
|
|
|
next unless binaries?
|
|
|
|
end
|
|
|
|
|
2017-04-06 00:33:31 +02:00
|
|
|
artifact.install_phase(command: @command, verbose: verbose?, force: force?)
|
2017-01-23 14:19:14 +01:00
|
|
|
already_installed_artifacts.unshift(artifact)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2019-02-02 17:11:37 +01:00
|
|
|
|
|
|
|
save_config_file
|
2018-09-02 20:14:54 +01:00
|
|
|
rescue => e
|
2016-12-04 23:14:35 +01:00
|
|
|
begin
|
|
|
|
already_installed_artifacts.each do |artifact|
|
2017-02-05 07:47:54 +01:00
|
|
|
next unless artifact.respond_to?(:uninstall_phase)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-02-05 23:27:35 +01:00
|
|
|
odebug "Reverting installation of artifact of class #{artifact.class}"
|
2017-04-06 00:33:31 +02:00
|
|
|
artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
|
2016-12-04 23:14:35 +01:00
|
|
|
end
|
2019-02-06 19:04:29 +01:00
|
|
|
|
|
|
|
already_installed_artifacts.each do |artifact|
|
|
|
|
next unless artifact.respond_to?(:post_uninstall_phase)
|
|
|
|
|
|
|
|
odebug "Reverting installation of artifact of class #{artifact.class}"
|
|
|
|
artifact.post_uninstall_phase(command: @command, verbose: verbose?, force: force?)
|
|
|
|
end
|
2016-12-04 23:14:35 +01:00
|
|
|
ensure
|
|
|
|
purge_versioned_files
|
2016-12-16 18:22:04 +01:00
|
|
|
raise e
|
2016-12-04 23:14:35 +01:00
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-10-18 21:42:43 -04:00
|
|
|
# TODO: move dependencies to a separate class,
|
|
|
|
# dependencies should also apply for `brew cask stage`,
|
|
|
|
# override dependencies with `--force` or perhaps `--force-deps`
|
2016-09-24 13:52:43 +02:00
|
|
|
def satisfy_dependencies
|
|
|
|
return unless @cask.depends_on
|
|
|
|
|
|
|
|
ohai "Satisfying dependencies"
|
|
|
|
macos_dependencies
|
|
|
|
arch_dependencies
|
|
|
|
x11_dependencies
|
|
|
|
formula_dependencies
|
2018-07-14 03:25:42 +02:00
|
|
|
cask_dependencies unless skip_cask_deps? || installed_as_dependency?
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def macos_dependencies
|
|
|
|
return unless @cask.depends_on.macos
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
if @cask.depends_on.macos.first.is_a?(Array)
|
|
|
|
operator, release = @cask.depends_on.macos.first
|
|
|
|
unless MacOS.version.send(operator, release)
|
2018-09-02 16:15:09 +01:00
|
|
|
raise CaskError,
|
2019-04-30 08:44:35 +01:00
|
|
|
"Cask #{@cask} depends on macOS release #{operator} #{release}, " \
|
|
|
|
"but you are running release #{MacOS.version}."
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
elsif @cask.depends_on.macos.length > 1
|
|
|
|
unless @cask.depends_on.macos.include?(Gem::Version.new(MacOS.version.to_s))
|
2018-09-02 16:15:09 +01:00
|
|
|
raise CaskError,
|
2019-04-30 08:44:35 +01:00
|
|
|
"Cask #{@cask} depends on macOS release being one of " \
|
|
|
|
"[#{@cask.depends_on.macos.map(&:to_s).join(", ")}], " \
|
|
|
|
"but you are running release #{MacOS.version}."
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
unless MacOS.version == @cask.depends_on.macos.first
|
2018-09-02 16:15:09 +01:00
|
|
|
raise CaskError,
|
2019-04-30 08:44:35 +01:00
|
|
|
"Cask #{@cask} depends on macOS release " \
|
|
|
|
"#{@cask.depends_on.macos.first}, " \
|
|
|
|
"but you are running release #{MacOS.version}."
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def arch_dependencies
|
|
|
|
return if @cask.depends_on.arch.nil?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
@current_arch ||= { type: Hardware::CPU.type, bits: Hardware::CPU.bits }
|
2016-10-23 14:44:14 +02:00
|
|
|
return if @cask.depends_on.arch.any? do |arch|
|
2016-09-24 13:52:43 +02:00
|
|
|
arch[:type] == @current_arch[:type] &&
|
|
|
|
Array(arch[:bits]).include?(@current_arch[:bits])
|
2016-10-23 14:44:14 +02:00
|
|
|
end
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2018-09-02 16:15:09 +01:00
|
|
|
raise CaskError,
|
2019-04-30 08:44:35 +01:00
|
|
|
"Cask #{@cask} depends on hardware architecture being one of " \
|
|
|
|
"[#{@cask.depends_on.arch.map(&:to_s).join(", ")}], " \
|
|
|
|
"but you are running #{@current_arch}"
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def x11_dependencies
|
|
|
|
return unless @cask.depends_on.x11
|
2016-12-04 21:35:43 +01:00
|
|
|
raise CaskX11DependencyError, @cask.token unless MacOS::X11.installed?
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def formula_dependencies
|
2017-06-28 17:53:59 +02:00
|
|
|
formulae = @cask.depends_on.formula.map { |f| Formula[f] }
|
|
|
|
return if formulae.empty?
|
|
|
|
|
|
|
|
if formulae.all?(&:any_version_installed?)
|
|
|
|
puts "All Formula dependencies satisfied."
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
not_installed = formulae.reject(&:any_version_installed?)
|
|
|
|
|
|
|
|
ohai "Installing Formula dependencies: #{not_installed.map(&:to_s).join(", ")}"
|
|
|
|
not_installed.each do |formula|
|
2018-07-14 03:25:42 +02:00
|
|
|
FormulaInstaller.new(formula).tap do |fi|
|
|
|
|
fi.installed_as_dependency = true
|
|
|
|
fi.installed_on_request = false
|
|
|
|
fi.show_header = true
|
|
|
|
fi.verbose = verbose?
|
|
|
|
fi.prelude
|
|
|
|
fi.install
|
|
|
|
fi.finish
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def cask_dependencies
|
2017-06-28 17:53:59 +02:00
|
|
|
casks = CaskDependencies.new(@cask)
|
2018-07-14 03:25:42 +02:00
|
|
|
return if casks.empty?
|
2017-06-28 17:53:59 +02:00
|
|
|
|
|
|
|
if casks.all?(&:installed?)
|
|
|
|
puts "All Cask dependencies satisfied."
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
not_installed = casks.reject(&:installed?)
|
|
|
|
|
|
|
|
ohai "Installing Cask dependencies: #{not_installed.map(&:to_s).join(", ")}"
|
|
|
|
not_installed.each do |cask|
|
2018-09-02 16:15:09 +01:00
|
|
|
Installer.new(
|
|
|
|
cask,
|
2018-11-02 17:18:07 +00:00
|
|
|
binaries: binaries?,
|
|
|
|
verbose: verbose?,
|
2018-09-02 16:15:09 +01:00
|
|
|
installed_as_dependency: true,
|
2018-11-02 17:18:07 +00:00
|
|
|
force: false,
|
2018-09-02 16:15:09 +01:00
|
|
|
).install
|
2018-07-14 03:25:42 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def unpack_dependencies
|
|
|
|
formulae = primary_container.dependencies.select { |dep| dep.is_a?(Formula) }
|
|
|
|
casks = primary_container.dependencies.select { |dep| dep.is_a?(Cask) }
|
|
|
|
.flat_map { |cask| [*CaskDependencies.new(cask), cask] }
|
|
|
|
|
|
|
|
not_installed_formulae = formulae.reject(&:any_version_installed?)
|
|
|
|
not_installed_casks = casks.reject(&:installed?)
|
|
|
|
|
|
|
|
return if (not_installed_formulae + not_installed_casks).empty?
|
|
|
|
|
|
|
|
ohai "Satisfying unpack dependencies"
|
|
|
|
|
|
|
|
not_installed_formulae.each do |formula|
|
|
|
|
FormulaInstaller.new(formula).tap do |fi|
|
|
|
|
fi.installed_as_dependency = true
|
|
|
|
fi.installed_on_request = false
|
|
|
|
fi.show_header = true
|
|
|
|
fi.verbose = verbose?
|
|
|
|
fi.prelude
|
|
|
|
fi.install
|
|
|
|
fi.finish
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
not_installed_casks.each do |cask|
|
|
|
|
Installer.new(cask, verbose: verbose?, installed_as_dependency: true).install
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2019-03-11 21:20:02 -04:00
|
|
|
def caveats
|
|
|
|
self.class.caveats(@cask)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def save_caskfile
|
2017-04-20 10:48:32 +02:00
|
|
|
old_savedir = @cask.metadata_timestamped_path
|
2017-03-11 18:55:16 +01:00
|
|
|
|
|
|
|
return unless @cask.sourcefile_path
|
|
|
|
|
2017-04-20 10:48:32 +02:00
|
|
|
savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
|
2017-03-11 18:55:16 +01:00
|
|
|
FileUtils.copy @cask.sourcefile_path, savedir
|
2017-09-24 19:24:46 +01:00
|
|
|
old_savedir&.rmtree
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2019-02-02 17:11:37 +01:00
|
|
|
def save_config_file
|
2019-02-09 02:19:01 +01:00
|
|
|
@cask.config_path.atomic_write(@cask.config.to_json)
|
2019-02-02 17:11:37 +01:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def uninstall
|
2018-02-09 11:31:51 +09:00
|
|
|
oh1 "Uninstalling Cask #{Formatter.identifier(@cask)}"
|
2017-11-10 10:05:18 -03:00
|
|
|
uninstall_artifacts(clear: true)
|
2019-02-02 17:11:37 +01:00
|
|
|
remove_config_file unless reinstall? || upgrade?
|
2017-10-29 17:31:07 -03:00
|
|
|
purge_versioned_files
|
|
|
|
purge_caskroom_path if force?
|
|
|
|
end
|
|
|
|
|
2019-02-02 17:11:37 +01:00
|
|
|
def remove_config_file
|
|
|
|
FileUtils.rm_f @cask.config_path
|
|
|
|
@cask.config_path.parent.rmdir_if_possible
|
|
|
|
end
|
|
|
|
|
2017-10-30 23:29:00 -03:00
|
|
|
def start_upgrade
|
|
|
|
uninstall_artifacts
|
2017-11-28 17:37:36 +00:00
|
|
|
backup
|
2017-11-28 13:00:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def backup
|
2017-11-28 17:37:36 +00:00
|
|
|
@cask.staged_path.rename backup_path
|
2017-11-28 21:00:16 +00:00
|
|
|
@cask.metadata_versioned_path.rename backup_metadata_path
|
2017-11-28 13:00:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def restore_backup
|
2017-11-28 21:00:16 +00:00
|
|
|
return unless backup_path.directory? && backup_metadata_path.directory?
|
2017-11-28 13:00:08 +00:00
|
|
|
|
|
|
|
Pathname.new(@cask.staged_path).rmtree if @cask.staged_path.exist?
|
2017-11-28 21:00:16 +00:00
|
|
|
Pathname.new(@cask.metadata_versioned_path).rmtree if @cask.metadata_versioned_path.exist?
|
2017-11-28 13:00:08 +00:00
|
|
|
|
2017-11-28 17:37:36 +00:00
|
|
|
backup_path.rename @cask.staged_path
|
2017-11-28 21:00:16 +00:00
|
|
|
backup_metadata_path.rename @cask.metadata_versioned_path
|
2017-10-30 23:29:00 -03:00
|
|
|
end
|
|
|
|
|
|
|
|
def revert_upgrade
|
|
|
|
opoo "Reverting upgrade for Cask #{@cask}"
|
2017-11-28 17:37:36 +00:00
|
|
|
restore_backup
|
2017-11-06 21:27:02 -03:00
|
|
|
install_artifacts
|
2017-10-30 23:29:00 -03:00
|
|
|
end
|
|
|
|
|
|
|
|
def finalize_upgrade
|
2017-11-28 20:36:36 +00:00
|
|
|
purge_backed_up_versioned_files
|
2017-11-11 17:21:13 -03:00
|
|
|
|
|
|
|
puts summary
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2017-11-10 10:05:18 -03:00
|
|
|
def uninstall_artifacts(clear: false)
|
2019-04-08 12:47:15 -04:00
|
|
|
odebug "Uninstalling artifacts"
|
2017-10-04 17:08:35 +02:00
|
|
|
artifacts = @cask.artifacts
|
2017-02-16 17:10:40 +01:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "#{artifacts.length} artifact/s defined", artifacts
|
2017-02-16 17:10:40 +01:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
artifacts.each do |artifact|
|
2017-02-05 07:47:54 +01:00
|
|
|
next unless artifact.respond_to?(:uninstall_phase)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2019-02-06 19:04:29 +01:00
|
|
|
odebug "Uninstalling artifact of class #{artifact.class}"
|
2018-10-25 01:05:53 +02:00
|
|
|
artifact.uninstall_phase(command: @command, verbose: verbose?, skip: clear, force: force?, upgrade: upgrade?)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2019-02-06 19:04:29 +01:00
|
|
|
|
|
|
|
artifacts.each do |artifact|
|
|
|
|
next unless artifact.respond_to?(:post_uninstall_phase)
|
|
|
|
|
|
|
|
odebug "Post-uninstalling artifact of class #{artifact.class}"
|
|
|
|
artifact.post_uninstall_phase(
|
|
|
|
command: @command, verbose: verbose?, skip: clear, force: force?, upgrade: upgrade?,
|
|
|
|
)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def zap
|
2016-10-14 20:08:05 +02:00
|
|
|
ohai %Q(Implied "brew cask uninstall #{@cask}")
|
2016-09-24 13:52:43 +02:00
|
|
|
uninstall_artifacts
|
2017-10-04 17:08:35 +02:00
|
|
|
if (zap_stanzas = @cask.artifacts.select { |a| a.is_a?(Artifact::Zap) }).empty?
|
2016-09-24 13:52:43 +02:00
|
|
|
opoo "No zap stanza present for Cask '#{@cask}'"
|
2017-04-06 00:33:31 +02:00
|
|
|
else
|
|
|
|
ohai "Dispatching zap stanza"
|
|
|
|
zap_stanzas.each do |stanza|
|
|
|
|
stanza.zap_phase(command: @command, verbose: verbose?, force: force?)
|
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
ohai "Removing all staged versions of Cask '#{@cask}'"
|
|
|
|
purge_caskroom_path
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2017-11-28 17:37:36 +00:00
|
|
|
def backup_path
|
2018-09-02 20:14:54 +01:00
|
|
|
return if @cask.staged_path.nil?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2018-04-29 05:34:32 +02:00
|
|
|
Pathname("#{@cask.staged_path}.upgrading")
|
2017-11-28 13:00:08 +00:00
|
|
|
end
|
|
|
|
|
2017-11-28 21:00:16 +00:00
|
|
|
def backup_metadata_path
|
2018-09-02 20:14:54 +01:00
|
|
|
return if @cask.metadata_versioned_path.nil?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2018-04-29 05:34:32 +02:00
|
|
|
Pathname("#{@cask.metadata_versioned_path}.upgrading")
|
2017-11-28 21:00:16 +00:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def gain_permissions_remove(path)
|
|
|
|
Utils.gain_permissions_remove(path, command: @command)
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2017-11-28 20:36:36 +00:00
|
|
|
def purge_backed_up_versioned_files
|
2017-11-10 10:05:18 -03:00
|
|
|
ohai "Purging files for version #{@cask.version} of Cask #{@cask}"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
# versioned staged distribution
|
2018-04-29 05:34:32 +02:00
|
|
|
gain_permissions_remove(backup_path) if backup_path&.exist?
|
2017-11-28 13:00:08 +00:00
|
|
|
|
2018-09-03 20:12:29 +01:00
|
|
|
# Homebrew Cask metadata
|
2018-04-29 05:34:32 +02:00
|
|
|
return unless backup_metadata_path.directory?
|
|
|
|
|
|
|
|
backup_metadata_path.children.each do |subdir|
|
|
|
|
gain_permissions_remove(subdir)
|
2017-11-28 21:00:16 +00:00
|
|
|
end
|
|
|
|
backup_metadata_path.rmdir_if_possible
|
2017-11-28 18:03:57 +00:00
|
|
|
end
|
|
|
|
|
2017-11-10 10:05:18 -03:00
|
|
|
def purge_versioned_files
|
|
|
|
ohai "Purging files for version #{@cask.version} of Cask #{@cask}"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
# versioned staged distribution
|
2018-04-29 05:34:32 +02:00
|
|
|
gain_permissions_remove(@cask.staged_path) if @cask.staged_path&.exist?
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-09-03 20:12:29 +01:00
|
|
|
# Homebrew Cask metadata
|
2018-04-29 05:34:32 +02:00
|
|
|
if @cask.metadata_versioned_path.directory?
|
2017-04-20 10:48:32 +02:00
|
|
|
@cask.metadata_versioned_path.children.each do |subdir|
|
2018-04-29 05:34:32 +02:00
|
|
|
gain_permissions_remove(subdir)
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
2018-04-29 05:34:32 +02:00
|
|
|
|
|
|
|
@cask.metadata_versioned_path.rmdir_if_possible
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
2017-11-07 22:27:04 -03:00
|
|
|
@cask.metadata_master_container_path.rmdir_if_possible unless upgrade?
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
# toplevel staged distribution
|
2017-11-07 22:27:04 -03:00
|
|
|
@cask.caskroom_path.rmdir_if_possible unless upgrade?
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def purge_caskroom_path
|
|
|
|
odebug "Purging all staged versions of Cask #{@cask}"
|
|
|
|
gain_permissions_remove(@cask.caskroom_path)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
end
|