2023-03-18 16:03:10 -07:00
|
|
|
# typed: true
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2023-12-28 11:45:18 -08:00
|
|
|
require "attrable"
|
2017-06-28 17:53:59 +02:00
|
|
|
require "formula_installer"
|
2018-07-23 23:04:49 +02:00
|
|
|
require "unpack_strategy"
|
2021-09-09 13:30:55 -07:00
|
|
|
require "utils/topological_hash"
|
2017-06-28 17:53:59 +02:00
|
|
|
|
2019-02-03 13:03:16 +01:00
|
|
|
require "cask/config"
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/download"
|
2023-04-08 14:10:58 +02:00
|
|
|
require "cask/migrator"
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/quarantine"
|
2024-06-22 13:31:50 -04:00
|
|
|
require "cask/tab"
|
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
|
2020-08-24 23:33:12 +02:00
|
|
|
# Installer for a {Cask}.
|
2016-09-24 13:52:43 +02:00
|
|
|
class Installer
|
2023-12-28 11:45:18 -08:00
|
|
|
extend Attrable
|
2016-09-24 13:52:43 +02:00
|
|
|
|
2022-10-21 23:28:51 -04:00
|
|
|
def initialize(cask, command: SystemCommand, force: false, adopt: false,
|
2018-08-31 13:16:11 +00:00
|
|
|
skip_cask_deps: false, binaries: true, verbose: false,
|
2023-04-04 11:36:27 -05:00
|
|
|
zap: false, require_sha: false, upgrade: false, reinstall: false,
|
2024-06-22 13:31:50 -04:00
|
|
|
installed_as_dependency: false, installed_on_request: true,
|
|
|
|
quarantine: true, verify_download_integrity: true, quiet: false)
|
2016-09-24 13:52:43 +02:00
|
|
|
@cask = cask
|
|
|
|
@command = command
|
|
|
|
@force = force
|
2022-10-21 23:28:51 -04:00
|
|
|
@adopt = adopt
|
2016-09-24 13:52:43 +02:00
|
|
|
@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
|
2022-04-05 00:57:33 +01:00
|
|
|
@zap = zap
|
2016-09-24 13:52:43 +02:00
|
|
|
@require_sha = require_sha
|
2023-04-04 11:36:27 -05:00
|
|
|
@reinstall = reinstall
|
2017-10-29 17:31:07 -03:00
|
|
|
@upgrade = upgrade
|
2018-07-14 03:25:42 +02:00
|
|
|
@installed_as_dependency = installed_as_dependency
|
2024-06-22 13:31:50 -04:00
|
|
|
@installed_on_request = installed_on_request
|
2018-08-31 13:16:11 +00:00
|
|
|
@quarantine = quarantine
|
2020-12-04 00:07:02 +01:00
|
|
|
@verify_download_integrity = verify_download_integrity
|
2021-09-10 23:11:41 +09:00
|
|
|
@quiet = quiet
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2022-10-21 23:28:51 -04:00
|
|
|
attr_predicate :binaries?, :force?, :adopt?, :skip_cask_deps?, :require_sha?,
|
2024-06-22 13:31:50 -04:00
|
|
|
:reinstall?, :upgrade?, :verbose?, :zap?, :installed_as_dependency?, :installed_on_request?,
|
2021-09-10 23:11:41 +09:00
|
|
|
:quarantine?, :quiet?
|
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
|
|
|
|
2021-06-08 23:43:14 +01:00
|
|
|
Homebrew.messages.record_caveats(cask.token, caveats)
|
|
|
|
|
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
|
|
|
|
2021-03-24 10:55:33 +01:00
|
|
|
sig { params(quiet: T.nilable(T::Boolean), timeout: T.nilable(T.any(Integer, Float))).void }
|
|
|
|
def fetch(quiet: nil, timeout: nil)
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#fetch"
|
2016-12-04 23:13:39 +01:00
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
load_cask_from_source_api! if @cask.loaded_from_api? && @cask.caskfile_only?
|
2017-06-26 07:30:28 +02:00
|
|
|
verify_has_sha if require_sha? && !force?
|
2023-08-20 12:20:39 -07:00
|
|
|
check_requirements
|
2021-03-24 01:22:18 -04:00
|
|
|
|
2024-03-07 16:20:20 +00:00
|
|
|
download(quiet:, timeout:)
|
2021-03-24 10:55:33 +01:00
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
satisfy_cask_and_formula_dependencies
|
2024-04-08 16:38:32 +01:00
|
|
|
|
|
|
|
forbidden_tap_check
|
|
|
|
forbidden_cask_and_formula_check
|
2016-12-04 23:13:39 +01:00
|
|
|
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
|
|
|
|
|
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
|
2021-09-02 08:42:48 -07:00
|
|
|
start_time = Time.now
|
2018-09-06 08:29:14 +02:00
|
|
|
odebug "Cask::Installer#install"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
Migrator.migrate_if_needed(@cask)
|
|
|
|
|
2019-02-03 13:03:16 +01:00
|
|
|
old_config = @cask.config
|
2023-05-03 11:29:01 -05:00
|
|
|
predecessor = @cask if reinstall? && @cask.installed?
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2023-12-04 00:30:49 -05:00
|
|
|
check_deprecate_disable
|
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
|
|
|
|
2019-10-24 15:15:40 +02:00
|
|
|
backup if force? && @cask.staged_path.exist? && @cask.metadata_versioned_path.exist?
|
|
|
|
|
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
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
@cask.config = @cask.default_config.merge(old_config)
|
2019-02-03 13:03:16 +01:00
|
|
|
|
2024-03-07 16:20:20 +00:00
|
|
|
install_artifacts(predecessor:)
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-06-22 13:31:50 -04:00
|
|
|
tab = Tab.create(@cask)
|
|
|
|
tab.installed_as_dependency = installed_as_dependency?
|
|
|
|
tab.installed_on_request = installed_on_request?
|
|
|
|
tab.write
|
|
|
|
|
2023-03-20 15:26:47 +00:00
|
|
|
if (tap = @cask.tap) && tap.should_report_analytics?
|
2024-03-07 15:19:04 +00:00
|
|
|
::Utils::Analytics.report_package_event(:cask_install, package_name: @cask.token, tap_name: tap.name,
|
2023-03-20 15:26:47 +00:00
|
|
|
on_request: true)
|
2023-02-15 03:24:15 +00:00
|
|
|
end
|
2018-08-06 12:21:48 -07:00
|
|
|
|
2019-10-24 15:15:40 +02:00
|
|
|
purge_backed_up_versioned_files
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
puts summary
|
2021-09-02 08:42:48 -07:00
|
|
|
end_time = Time.now
|
|
|
|
Homebrew.messages.package_installed(@cask.token, end_time - start_time)
|
2019-10-24 15:15:40 +02:00
|
|
|
rescue
|
|
|
|
restore_backup
|
|
|
|
raise
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2023-12-04 00:30:49 -05:00
|
|
|
def check_deprecate_disable
|
|
|
|
deprecate_disable_type = DeprecateDisable.type(@cask)
|
2023-12-16 20:08:42 -05:00
|
|
|
return if deprecate_disable_type.nil?
|
2023-12-04 00:30:49 -05:00
|
|
|
|
2024-03-14 09:49:12 +00:00
|
|
|
message = DeprecateDisable.message(@cask)
|
|
|
|
message_full = "#{@cask.token} has been #{message}"
|
|
|
|
|
2023-12-16 20:08:42 -05:00
|
|
|
case deprecate_disable_type
|
|
|
|
when :deprecated
|
2024-03-14 09:49:12 +00:00
|
|
|
opoo message_full
|
2023-12-16 20:08:42 -05:00
|
|
|
when :disabled
|
2024-05-09 13:19:14 +01:00
|
|
|
GitHub::Actions.puts_annotation_if_env_set(:error, message)
|
2024-03-14 09:49:12 +00:00
|
|
|
raise CaskCannotBeInstalledError.new(@cask, message)
|
2023-12-04 00:30:49 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
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|
|
2024-03-01 03:13:56 +01:00
|
|
|
if (conflicting_cask_tap_with_token = Tap.with_cask_token(conflicting_cask))
|
|
|
|
conflicting_cask_tap, = conflicting_cask_tap_with_token
|
2020-12-22 15:32:05 -08:00
|
|
|
next unless conflicting_cask_tap.installed?
|
|
|
|
end
|
|
|
|
|
2019-10-13 10:03:26 +01:00
|
|
|
conflicting_cask = CaskLoader.load(conflicting_cask)
|
|
|
|
raise CaskConflictError.new(@cask, conflicting_cask) if conflicting_cask.installed?
|
|
|
|
rescue CaskUnavailableError
|
|
|
|
next # Ignore conflicting Casks that do not exist.
|
2017-08-05 15:56:34 +02:00
|
|
|
end
|
|
|
|
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
|
|
|
|
|
|
|
# Always force uninstallation, ignore method parameter
|
2023-04-04 11:36:27 -05:00
|
|
|
cask_installer = Installer.new(@cask, verbose: verbose?, force: true, upgrade: upgrade?, reinstall: true)
|
2023-04-27 10:40:45 -05:00
|
|
|
zap? ? cask_installer.zap : cask_installer.uninstall(successor: @cask)
|
2017-03-18 17:48:20 -05:00
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(String) }
|
2016-09-24 13:52:43 +02:00
|
|
|
def summary
|
2019-04-20 14:07:29 +09:00
|
|
|
s = +""
|
2020-04-05 15:44:50 +01:00
|
|
|
s << "#{Homebrew::EnvConfig.install_badge} " unless Homebrew::EnvConfig.no_emoji?
|
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
|
|
|
|
|
2020-12-21 15:43:25 +01:00
|
|
|
sig { returns(Download) }
|
|
|
|
def downloader
|
|
|
|
@downloader ||= Download.new(@cask, quarantine: quarantine?)
|
|
|
|
end
|
|
|
|
|
2021-03-24 10:55:33 +01:00
|
|
|
sig { params(quiet: T.nilable(T::Boolean), timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) }
|
|
|
|
def download(quiet: nil, timeout: nil)
|
2022-05-07 20:19:54 -07:00
|
|
|
# Store cask download path in cask to prevent multiple downloads in a row when checking if it's outdated
|
2024-03-07 16:20:20 +00:00
|
|
|
@cask.download ||= downloader.fetch(quiet:, verify_download_integrity: @verify_download_integrity,
|
|
|
|
timeout:)
|
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_has_sha
|
|
|
|
odebug "Checking cask has checksum"
|
2023-04-18 15:06:50 -07:00
|
|
|
return if @cask.sha256 != :no_check
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2020-11-19 19:44:23 +01:00
|
|
|
raise CaskError, <<~EOS
|
|
|
|
Cask '#{@cask}' does not have a sha256 checksum defined and was not installed.
|
|
|
|
This means you have the #{Formatter.identifier("--require-sha")} option set, perhaps in your HOMEBREW_CASK_OPTS.
|
|
|
|
EOS
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-07-14 03:25:42 +02:00
|
|
|
def primary_container
|
|
|
|
@primary_container ||= begin
|
2021-03-24 10:55:33 +01:00
|
|
|
downloaded_path = download(quiet: true)
|
2020-12-04 00:07:02 +01: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
|
|
|
|
|
2020-12-04 00:07:02 +01:00
|
|
|
def extract_primary_container(to: @cask.staged_path)
|
2018-07-14 03:25:42 +02:00
|
|
|
odebug "Extracting primary container"
|
2016-12-04 23:13:39 +01:00
|
|
|
|
2020-12-04 00:07:02 +01:00
|
|
|
odebug "Using container class #{primary_container.class} for #{primary_container.path}"
|
2018-07-16 20:22:37 +02:00
|
|
|
|
2020-12-21 15:43:25 +01:00
|
|
|
basename = downloader.basename
|
2018-07-23 23:04:49 +02:00
|
|
|
|
2021-02-12 18:33:37 +05:30
|
|
|
if (nested_container = @cask.container&.nested)
|
2024-02-26 16:58:39 +00:00
|
|
|
Dir.mktmpdir("cask-installer", HOMEBREW_TEMP) do |tmpdir|
|
2018-07-23 23:04:49 +02:00
|
|
|
tmpdir = Pathname(tmpdir)
|
2024-03-07 16:20:20 +00:00
|
|
|
primary_container.extract(to: tmpdir, basename:, verbose: verbose?)
|
2018-07-23 23:04:49 +02:00
|
|
|
|
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)
|
2024-03-07 16:20:20 +00:00
|
|
|
.extract_nestedly(to:, verbose: verbose?)
|
2018-07-23 23:04:49 +02:00
|
|
|
end
|
|
|
|
else
|
2024-03-07 16:20:20 +00:00
|
|
|
primary_container.extract_nestedly(to:, basename:, verbose: verbose?)
|
2018-07-23 23:04:49 +02:00
|
|
|
end
|
2018-08-31 13:16:11 +00:00
|
|
|
|
|
|
|
return unless quarantine?
|
|
|
|
return unless Quarantine.available?
|
|
|
|
|
2024-03-07 16:20:20 +00:00
|
|
|
Quarantine.propagate(from: primary_container.path, to:)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2023-05-12 14:47:56 -05:00
|
|
|
sig { params(predecessor: T.nilable(Cask)).void }
|
2023-04-08 16:13:12 -05:00
|
|
|
def install_artifacts(predecessor: nil)
|
2020-07-06 15:41:58 -04:00
|
|
|
artifacts = @cask.artifacts
|
2016-12-04 23:14:35 +01:00
|
|
|
already_installed_artifacts = []
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
odebug "Installing 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
|
|
|
|
2020-09-01 14:05:52 +01:00
|
|
|
next if artifact.is_a?(Artifact::Binary) && !binaries?
|
2017-05-19 19:13:23 +02:00
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
artifact.install_phase(
|
2024-03-07 16:20:20 +00:00
|
|
|
command: @command, verbose: verbose?, adopt: adopt?, force: force?, predecessor:,
|
2023-04-08 14:10:58 +02:00
|
|
|
)
|
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
|
2022-05-07 20:19:54 -07:00
|
|
|
save_download_sha if @cask.version.latest?
|
2018-09-02 20:14:54 +01:00
|
|
|
rescue => e
|
2016-12-04 23:14:35 +01:00
|
|
|
begin
|
2023-03-18 16:03:10 -07:00
|
|
|
already_installed_artifacts&.each do |artifact|
|
2020-09-01 14:05:52 +01:00
|
|
|
if artifact.respond_to?(:uninstall_phase)
|
|
|
|
odebug "Reverting installation of artifact of class #{artifact.class}"
|
|
|
|
artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
|
|
|
|
end
|
2019-02-06 19:04:29 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
def check_requirements
|
|
|
|
check_macos_requirements
|
|
|
|
check_arch_requirements
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
def check_macos_requirements
|
2016-09-24 13:52:43 +02:00
|
|
|
return unless @cask.depends_on.macos
|
2019-08-15 10:14:10 +02:00
|
|
|
return if @cask.depends_on.macos.satisfied?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2019-08-15 10:14:10 +02:00
|
|
|
raise CaskError, @cask.depends_on.macos.message(type: :cask)
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
def check_arch_requirements
|
2016-09-24 13:52:43 +02:00
|
|
|
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(", ")}], " \
|
2021-01-26 15:21:24 -05:00
|
|
|
"but you are running #{@current_arch}."
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
def cask_and_formula_dependencies
|
2019-11-01 20:28:24 +01:00
|
|
|
return @cask_and_formula_dependencies if @cask_and_formula_dependencies
|
2019-10-31 20:20:55 +01:00
|
|
|
|
2021-09-09 13:30:55 -07:00
|
|
|
graph = ::Utils::TopologicalHash.graph_package_dependencies(@cask)
|
2018-07-14 03:25:42 +02:00
|
|
|
|
2023-03-18 16:03:10 -07:00
|
|
|
raise CaskSelfReferencingDependencyError, @cask.token if graph[@cask].include?(@cask)
|
2018-07-14 03:25:42 +02:00
|
|
|
|
2021-09-09 13:30:55 -07:00
|
|
|
::Utils::TopologicalHash.graph_package_dependencies(primary_container.dependencies, graph)
|
2018-07-14 03:25:42 +02:00
|
|
|
|
2019-11-01 20:28:24 +01:00
|
|
|
begin
|
2019-11-02 00:33:08 +01:00
|
|
|
@cask_and_formula_dependencies = graph.tsort - [@cask]
|
2019-10-31 20:20:55 +01:00
|
|
|
rescue TSort::Cyclic
|
|
|
|
strongly_connected_components = graph.strongly_connected_components.sort_by(&:count)
|
|
|
|
cyclic_dependencies = strongly_connected_components.last - [@cask]
|
|
|
|
raise CaskCyclicDependencyError.new(@cask.token, cyclic_dependencies.to_sentence)
|
|
|
|
end
|
2019-11-01 20:28:24 +01:00
|
|
|
end
|
2018-07-14 03:25:42 +02:00
|
|
|
|
2019-11-01 20:28:24 +01:00
|
|
|
def missing_cask_and_formula_dependencies
|
2023-08-20 12:20:39 -07:00
|
|
|
cask_and_formula_dependencies.reject do |cask_or_formula|
|
2023-10-08 09:36:08 -07:00
|
|
|
case cask_or_formula
|
|
|
|
when Formula
|
|
|
|
cask_or_formula.any_version_installed? && cask_or_formula.optlinked?
|
|
|
|
when Cask
|
|
|
|
cask_or_formula.installed?
|
2020-07-12 17:13:04 -07:00
|
|
|
end
|
2019-10-31 20:20:55 +01:00
|
|
|
end
|
2019-11-01 20:28:24 +01:00
|
|
|
end
|
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
def satisfy_cask_and_formula_dependencies
|
2019-11-01 20:28:24 +01:00
|
|
|
return if installed_as_dependency?
|
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
formulae_and_casks = cask_and_formula_dependencies
|
2019-11-01 20:28:24 +01:00
|
|
|
|
|
|
|
return if formulae_and_casks.empty?
|
|
|
|
|
|
|
|
missing_formulae_and_casks = missing_cask_and_formula_dependencies
|
2019-10-31 20:20:55 +01:00
|
|
|
|
2019-11-01 20:28:24 +01:00
|
|
|
if missing_formulae_and_casks.empty?
|
2024-04-09 00:22:16 -04:00
|
|
|
puts "All dependencies satisfied."
|
2019-10-31 20:20:55 +01:00
|
|
|
return
|
2018-07-14 03:25:42 +02:00
|
|
|
end
|
|
|
|
|
2019-11-01 20:28:24 +01:00
|
|
|
ohai "Installing dependencies: #{missing_formulae_and_casks.map(&:to_s).join(", ")}"
|
|
|
|
missing_formulae_and_casks.each do |cask_or_formula|
|
2019-10-31 20:20:55 +01:00
|
|
|
if cask_or_formula.is_a?(Cask)
|
|
|
|
if skip_cask_deps?
|
2021-09-27 18:25:39 -07:00
|
|
|
opoo "`--skip-cask-deps` is set; skipping installation of #{cask_or_formula}."
|
2019-10-31 20:20:55 +01:00
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
Installer.new(
|
|
|
|
cask_or_formula,
|
2022-10-21 23:28:51 -04:00
|
|
|
adopt: adopt?,
|
2019-10-31 20:20:55 +01:00
|
|
|
binaries: binaries?,
|
|
|
|
verbose: verbose?,
|
|
|
|
installed_as_dependency: true,
|
2024-06-22 13:31:50 -04:00
|
|
|
installed_on_request: false,
|
2019-10-31 20:20:55 +01:00
|
|
|
force: false,
|
|
|
|
).install
|
|
|
|
else
|
2020-11-18 05:37:12 +01:00
|
|
|
fi = FormulaInstaller.new(
|
|
|
|
cask_or_formula,
|
|
|
|
**{
|
|
|
|
show_header: true,
|
|
|
|
installed_as_dependency: true,
|
|
|
|
installed_on_request: false,
|
|
|
|
verbose: verbose?,
|
|
|
|
}.compact,
|
|
|
|
)
|
|
|
|
fi.prelude
|
|
|
|
fi.fetch
|
|
|
|
fi.install
|
|
|
|
fi.finish
|
2019-10-31 20:20:55 +01:00
|
|
|
end
|
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
|
|
|
|
2023-01-08 02:45:56 -05:00
|
|
|
def metadata_subdir
|
|
|
|
@metadata_subdir ||= @cask.metadata_subdir("Casks", timestamp: :now, create: true)
|
|
|
|
end
|
|
|
|
|
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
|
|
|
|
2021-08-14 16:18:13 -04:00
|
|
|
return if @cask.source.blank?
|
2017-03-11 18:55:16 +01:00
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
extension = @cask.loaded_from_api? ? "json" : "rb"
|
2023-02-05 12:22:08 +01:00
|
|
|
(metadata_subdir/"#{@cask.token}.#{extension}").write @cask.source
|
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
|
|
|
|
|
2022-05-07 20:19:54 -07:00
|
|
|
def save_download_sha
|
2022-05-31 10:44:34 -07:00
|
|
|
@cask.download_sha_path.atomic_write(@cask.new_download_sha) if @cask.checksumable?
|
2022-05-07 20:19:54 -07:00
|
|
|
end
|
|
|
|
|
2023-05-12 14:47:56 -05:00
|
|
|
sig { params(successor: T.nilable(Cask)).void }
|
2023-04-08 16:13:12 -05:00
|
|
|
def uninstall(successor: nil)
|
2023-02-25 02:08:39 -08:00
|
|
|
load_installed_caskfile!
|
2018-02-09 11:31:51 +09:00
|
|
|
oh1 "Uninstalling Cask #{Formatter.identifier(@cask)}"
|
2024-03-07 16:20:20 +00:00
|
|
|
uninstall_artifacts(clear: true, successor:)
|
2022-06-05 13:00:20 -07:00
|
|
|
if !reinstall? && !upgrade?
|
2024-06-22 13:31:50 -04:00
|
|
|
remove_tabfile
|
2022-06-05 13:00:20 -07:00
|
|
|
remove_download_sha
|
|
|
|
remove_config_file
|
|
|
|
end
|
2017-10-29 17:31:07 -03:00
|
|
|
purge_versioned_files
|
|
|
|
purge_caskroom_path if force?
|
|
|
|
end
|
|
|
|
|
2024-06-22 13:31:50 -04:00
|
|
|
def remove_tabfile
|
|
|
|
tabfile = @cask.tab.tabfile
|
|
|
|
FileUtils.rm_f tabfile if tabfile.present? && tabfile.exist?
|
|
|
|
@cask.config_path.parent.rmdir_if_possible
|
|
|
|
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
|
|
|
|
|
2022-06-05 13:00:20 -07:00
|
|
|
def remove_download_sha
|
2023-04-08 14:10:58 +02:00
|
|
|
FileUtils.rm_f @cask.download_sha_path
|
|
|
|
@cask.download_sha_path.parent.rmdir_if_possible
|
2022-06-05 13:00:20 -07:00
|
|
|
end
|
|
|
|
|
2023-05-12 14:47:56 -05:00
|
|
|
sig { params(successor: T.nilable(Cask)).void }
|
2023-04-08 16:13:12 -05:00
|
|
|
def start_upgrade(successor:)
|
2024-03-07 16:20:20 +00:00
|
|
|
uninstall_artifacts(successor:)
|
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
|
2021-01-07 13:49:05 -08:00
|
|
|
return if !backup_path.directory? || !backup_metadata_path.directory?
|
2017-11-28 13:00:08 +00:00
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
@cask.staged_path.rmtree if @cask.staged_path.exist?
|
|
|
|
@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
|
|
|
|
|
2023-05-12 14:47:56 -05:00
|
|
|
sig { params(predecessor: Cask).void }
|
|
|
|
def revert_upgrade(predecessor:)
|
2017-10-30 23:29:00 -03:00
|
|
|
opoo "Reverting upgrade for Cask #{@cask}"
|
2017-11-28 17:37:36 +00:00
|
|
|
restore_backup
|
2024-03-07 16:20:20 +00:00
|
|
|
install_artifacts(predecessor:)
|
2017-10-30 23:29:00 -03:00
|
|
|
end
|
|
|
|
|
|
|
|
def finalize_upgrade
|
2019-10-24 15:15:40 +02:00
|
|
|
ohai "Purging files for version #{@cask.version} of Cask #{@cask}"
|
|
|
|
|
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
|
|
|
|
|
2023-05-12 14:47:56 -05:00
|
|
|
sig { params(clear: T::Boolean, successor: T.nilable(Cask)).void }
|
2023-04-08 16:13:12 -05:00
|
|
|
def uninstall_artifacts(clear: false, successor: nil)
|
2017-10-04 17:08:35 +02:00
|
|
|
artifacts = @cask.artifacts
|
2017-02-16 17:10:40 +01:00
|
|
|
|
2020-07-06 15:41:58 -04:00
|
|
|
odebug "Uninstalling artifacts"
|
2023-03-20 07:23:17 -04:00
|
|
|
odebug "#{::Utils.pluralize("artifact", artifacts.length, include_count: true)} defined", artifacts
|
2017-02-16 17:10:40 +01:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
artifacts.each do |artifact|
|
2020-09-01 14:05:52 +01:00
|
|
|
if artifact.respond_to?(:uninstall_phase)
|
|
|
|
odebug "Uninstalling artifact of class #{artifact.class}"
|
|
|
|
artifact.uninstall_phase(
|
2023-04-08 16:13:12 -05:00
|
|
|
command: @command,
|
|
|
|
verbose: verbose?,
|
|
|
|
skip: clear,
|
|
|
|
force: force?,
|
2024-03-07 16:20:20 +00:00
|
|
|
successor:,
|
2024-01-19 23:08:26 +11:00
|
|
|
upgrade: upgrade?,
|
|
|
|
reinstall: reinstall?,
|
2020-09-01 14:05:52 +01:00
|
|
|
)
|
|
|
|
end
|
2019-02-06 19:04:29 +01:00
|
|
|
|
|
|
|
next unless artifact.respond_to?(:post_uninstall_phase)
|
|
|
|
|
|
|
|
odebug "Post-uninstalling artifact of class #{artifact.class}"
|
|
|
|
artifact.post_uninstall_phase(
|
2023-04-08 16:13:12 -05:00
|
|
|
command: @command,
|
|
|
|
verbose: verbose?,
|
|
|
|
skip: clear,
|
|
|
|
force: force?,
|
2024-03-07 16:20:20 +00:00
|
|
|
successor:,
|
2019-02-06 19:04:29 +01:00
|
|
|
)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def zap
|
2023-02-25 02:08:39 -08:00
|
|
|
load_installed_caskfile!
|
2021-01-24 21:40:41 -05:00
|
|
|
ohai "Implied `brew uninstall --cask #{@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
|
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
|
2021-07-06 23:48:26 +05:30
|
|
|
@cask.metadata_main_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?
|
2023-04-08 14:10:58 +02:00
|
|
|
|
|
|
|
# Remove symlinks for renamed casks if they are now broken.
|
|
|
|
@cask.old_tokens.each do |old_token|
|
|
|
|
old_caskroom_path = Caskroom.path/old_token
|
|
|
|
FileUtils.rm old_caskroom_path if old_caskroom_path.symlink? && !old_caskroom_path.exist?
|
|
|
|
end
|
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
|
2023-02-25 02:08:39 -08:00
|
|
|
|
2024-04-08 16:38:32 +01:00
|
|
|
sig { void }
|
|
|
|
def forbidden_tap_check
|
2024-05-03 16:08:42 +01:00
|
|
|
return if Tap.allowed_taps.blank? && Tap.forbidden_taps.blank?
|
2024-04-08 16:38:32 +01:00
|
|
|
|
|
|
|
owner = Homebrew::EnvConfig.forbidden_owner
|
|
|
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
|
|
|
"\n#{contact}"
|
|
|
|
end
|
|
|
|
|
|
|
|
unless skip_cask_deps?
|
|
|
|
cask_and_formula_dependencies.each do |cask_or_formula|
|
|
|
|
dep_tap = cask_or_formula.tap
|
2024-05-05 13:54:26 +01:00
|
|
|
next if dep_tap.blank? || (dep_tap.allowed_by_env? && !dep_tap.forbidden_by_env?)
|
2024-04-08 16:38:32 +01:00
|
|
|
|
|
|
|
dep_full_name = cask_or_formula.full_name
|
2024-05-03 16:08:42 +01:00
|
|
|
error_message = +"The installation of #{@cask} has a dependency #{dep_full_name}\n" \
|
|
|
|
"from the #{dep_tap} tap but #{owner} "
|
|
|
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless dep_tap.allowed_by_env?
|
|
|
|
error_message << " and\n" if !dep_tap.allowed_by_env? && dep_tap.forbidden_by_env?
|
|
|
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if dep_tap.forbidden_by_env?
|
|
|
|
error_message << ".#{owner_contact}"
|
|
|
|
|
|
|
|
raise CaskCannotBeInstalledError.new(@cask, error_message)
|
2024-04-08 16:38:32 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
cask_tap = @cask.tap
|
2024-05-05 13:54:26 +01:00
|
|
|
return if cask_tap.blank? || (cask_tap.allowed_by_env? && !cask_tap.forbidden_by_env?)
|
2024-04-08 16:38:32 +01:00
|
|
|
|
2024-05-03 16:08:42 +01:00
|
|
|
error_message = +"The installation of #{@cask.full_name} has the tap #{cask_tap}\n" \
|
|
|
|
"but #{owner} "
|
|
|
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless cask_tap.allowed_by_env?
|
|
|
|
error_message << " and\n" if !cask_tap.allowed_by_env? && cask_tap.forbidden_by_env?
|
|
|
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if cask_tap.forbidden_by_env?
|
|
|
|
error_message << ".#{owner_contact}"
|
|
|
|
|
|
|
|
raise CaskCannotBeInstalledError.new(@cask, error_message)
|
2024-04-08 16:38:32 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
sig { void }
|
|
|
|
def forbidden_cask_and_formula_check
|
|
|
|
forbidden_formulae = Set.new(Homebrew::EnvConfig.forbidden_formulae.to_s.split)
|
|
|
|
forbidden_casks = Set.new(Homebrew::EnvConfig.forbidden_casks.to_s.split)
|
|
|
|
return if forbidden_formulae.blank? && forbidden_casks.blank?
|
|
|
|
|
|
|
|
owner = Homebrew::EnvConfig.forbidden_owner
|
|
|
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
|
|
|
"\n#{contact}"
|
|
|
|
end
|
|
|
|
|
|
|
|
unless skip_cask_deps?
|
|
|
|
cask_and_formula_dependencies.each do |dep_cask_or_formula|
|
|
|
|
dep_name, dep_type, variable = if dep_cask_or_formula.is_a?(Cask) && forbidden_casks.present?
|
|
|
|
dep_cask = dep_cask_or_formula
|
|
|
|
dep_cask_name = if forbidden_casks.include?(dep_cask.token)
|
|
|
|
dep_cask.token
|
|
|
|
elsif dep_cask.tap.present? &&
|
|
|
|
forbidden_casks.include?(dep_cask.full_name)
|
|
|
|
dep_cask.full_name
|
|
|
|
end
|
|
|
|
[dep_cask_name, "cask", "HOMEBREW_FORBIDDEN_CASKS"]
|
|
|
|
elsif dep_cask_or_formula.is_a?(Formula) && forbidden_formulae.present?
|
|
|
|
dep_formula = dep_cask_or_formula
|
|
|
|
formula_name = if forbidden_formulae.include?(dep_formula.name)
|
|
|
|
dep_formula.name
|
|
|
|
elsif dep_formula.tap.present? &&
|
|
|
|
forbidden_formulae.include?(dep_formula.full_name)
|
|
|
|
dep_formula.full_name
|
|
|
|
end
|
|
|
|
[formula_name, "formula", "HOMEBREW_FORBIDDEN_FORMULAE"]
|
|
|
|
end
|
|
|
|
next if dep_name.blank?
|
|
|
|
|
|
|
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
|
|
|
The installation of #{@cask} has a dependency #{dep_name}
|
|
|
|
but the #{dep_name} #{dep_type} was forbidden by #{owner} in `#{variable}`.#{owner_contact}
|
|
|
|
EOS
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return if forbidden_casks.blank?
|
|
|
|
|
|
|
|
cask_name = if forbidden_casks.include?(@cask.token)
|
|
|
|
@cask.token
|
|
|
|
elsif forbidden_casks.include?(@cask.full_name)
|
|
|
|
@cask.full_name
|
|
|
|
else
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
|
|
|
The installation of #{cask_name} was forbidden by #{owner}
|
|
|
|
in `HOMEBREW_FORBIDDEN_CASKS`.#{owner_contact}
|
|
|
|
EOS
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2023-02-25 02:08:39 -08:00
|
|
|
private
|
|
|
|
|
|
|
|
# load the same cask file that was used for installation, if possible
|
|
|
|
def load_installed_caskfile!
|
2023-04-08 14:10:58 +02:00
|
|
|
Migrator.migrate_if_needed(@cask)
|
|
|
|
|
2023-02-25 02:08:39 -08:00
|
|
|
installed_caskfile = @cask.installed_caskfile
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
if installed_caskfile&.exist?
|
2023-02-25 02:08:39 -08:00
|
|
|
begin
|
|
|
|
@cask = CaskLoader.load(installed_caskfile)
|
|
|
|
return
|
|
|
|
rescue CaskInvalidError
|
|
|
|
# could be caused by trying to load outdated caskfile
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
load_cask_from_source_api! if @cask.loaded_from_api? && @cask.caskfile_only?
|
2023-02-25 02:08:39 -08:00
|
|
|
# otherwise we default to the current cask
|
|
|
|
end
|
|
|
|
|
|
|
|
def load_cask_from_source_api!
|
2023-04-18 00:22:13 +01:00
|
|
|
@cask = Homebrew::API::Cask.source_download(@cask)
|
2023-02-25 02:08:39 -08:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
end
|