2023-03-12 17:06:29 -07:00
|
|
|
# typed: true
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-09-17 14:01:37 +08:00
|
|
|
require "cask/cache"
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/cask"
|
2018-03-07 16:14:55 +00:00
|
|
|
require "uri"
|
2023-09-04 22:17:57 -04:00
|
|
|
require "utils/curl"
|
2024-01-12 09:38:49 -08:00
|
|
|
require "extend/hash/keys"
|
2018-03-07 16:14:55 +00:00
|
|
|
|
2018-09-06 08:29:14 +02:00
|
|
|
module Cask
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from various sources.
|
|
|
|
#
|
|
|
|
# @api private
|
2017-03-12 19:18:41 +01:00
|
|
|
module CaskLoader
|
2023-02-05 13:06:56 -08:00
|
|
|
extend Context
|
|
|
|
|
2023-03-12 17:06:29 -07:00
|
|
|
module ILoader
|
|
|
|
extend T::Helpers
|
|
|
|
interface!
|
|
|
|
|
|
|
|
sig { abstract.params(config: Config).returns(Cask) }
|
|
|
|
def load(config:); end
|
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from a string.
|
2023-04-18 00:22:13 +01:00
|
|
|
class AbstractContentLoader
|
2023-03-12 17:06:29 -07:00
|
|
|
include ILoader
|
2023-04-18 00:22:13 +01:00
|
|
|
extend T::Helpers
|
|
|
|
abstract!
|
|
|
|
|
|
|
|
sig { returns(String) }
|
|
|
|
attr_reader :content
|
|
|
|
|
|
|
|
sig { returns(T.nilable(Tap)) }
|
|
|
|
attr_reader :tap
|
2017-06-28 09:25:14 +02:00
|
|
|
|
2023-04-18 00:22:13 +01:00
|
|
|
private
|
|
|
|
|
|
|
|
sig {
|
|
|
|
overridable.params(
|
|
|
|
header_token: String,
|
|
|
|
options: T.untyped,
|
|
|
|
block: T.nilable(T.proc.bind(DSL).void),
|
|
|
|
).returns(Cask)
|
|
|
|
}
|
|
|
|
def cask(header_token, **options, &block)
|
|
|
|
Cask.new(header_token, source: content, tap: tap, **options, config: @config, &block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Loads a cask from a string.
|
|
|
|
class FromContentLoader < AbstractContentLoader
|
2017-10-08 15:20:58 +02:00
|
|
|
def self.can_load?(ref)
|
|
|
|
return false unless ref.respond_to?(:to_str)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
content = ref.to_str
|
2017-10-08 15:20:58 +02:00
|
|
|
|
2022-10-27 01:28:08 -04:00
|
|
|
# Cache compiled regex
|
|
|
|
@regex ||= begin
|
|
|
|
token = /(?:"[^"]*"|'[^']*')/
|
|
|
|
curly = /\(\s*#{token.source}\s*\)\s*\{.*\}/
|
|
|
|
do_end = /\s+#{token.source}\s+do(?:\s*;\s*|\s+).*end/
|
|
|
|
/\A\s*cask(?:#{curly.source}|#{do_end.source})\s*\Z/m
|
|
|
|
end
|
2017-10-08 15:20:58 +02:00
|
|
|
|
2022-10-27 01:28:08 -04:00
|
|
|
content.match?(@regex)
|
2017-10-08 15:20:58 +02:00
|
|
|
end
|
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
def initialize(content, tap: nil)
|
2023-04-18 00:22:13 +01:00
|
|
|
super()
|
|
|
|
|
2018-02-13 17:23:49 +01:00
|
|
|
@content = content.force_encoding("UTF-8")
|
2023-02-25 16:24:58 -05:00
|
|
|
@tap = tap
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
|
|
|
@config = config
|
|
|
|
|
2018-02-13 17:23:49 +01:00
|
|
|
instance_eval(content, __FILE__, __LINE__)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
2016-10-08 13:25:38 +02:00
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from a path.
|
2023-04-18 00:22:13 +01:00
|
|
|
class FromPathLoader < AbstractContentLoader
|
2017-03-12 19:18:41 +01:00
|
|
|
def self.can_load?(ref)
|
2024-02-06 20:16:03 +00:00
|
|
|
path = Pathname(ref)
|
2023-02-05 12:22:08 +01:00
|
|
|
%w[.rb .json].include?(path.extname) && path.expand_path.exist?
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :token, :path
|
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
def initialize(path, token: nil)
|
2023-04-18 00:22:13 +01:00
|
|
|
super()
|
|
|
|
|
2017-06-28 09:25:14 +02:00
|
|
|
path = Pathname(path).expand_path
|
2017-03-12 19:18:41 +01:00
|
|
|
|
2023-02-05 12:22:08 +01:00
|
|
|
@token = path.basename(path.extname).to_s
|
2023-04-18 00:22:13 +01:00
|
|
|
|
2017-03-12 19:18:41 +01:00
|
|
|
@path = path
|
2023-04-18 00:22:13 +01:00
|
|
|
@tap = Homebrew::API.tap_from_source_download(path)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
2017-06-28 09:25:14 +02:00
|
|
|
raise CaskUnavailableError.new(token, "'#{path}' does not exist.") unless path.exist?
|
|
|
|
raise CaskUnavailableError.new(token, "'#{path}' is not readable.") unless path.readable?
|
|
|
|
raise CaskUnavailableError.new(token, "'#{path}' is not a file.") unless path.file?
|
2017-03-12 19:18:41 +01:00
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
@content = path.read(encoding: "UTF-8")
|
|
|
|
@config = config
|
2017-03-12 19:18:41 +01:00
|
|
|
|
2023-02-05 12:22:08 +01:00
|
|
|
if path.extname == ".json"
|
|
|
|
return FromAPILoader.new(token, from_json: JSON.parse(@content)).load(config: config)
|
|
|
|
end
|
|
|
|
|
2018-07-29 11:05:23 +02:00
|
|
|
begin
|
|
|
|
instance_eval(content, path).tap do |cask|
|
2019-02-19 13:11:32 +00:00
|
|
|
raise CaskUnreadableError.new(token, "'#{path}' does not contain a cask.") unless cask.is_a?(Cask)
|
2018-07-29 11:05:23 +02:00
|
|
|
end
|
|
|
|
rescue NameError, ArgumentError, ScriptError => e
|
2020-09-29 23:46:30 +02:00
|
|
|
error = CaskUnreadableError.new(token, e.message)
|
|
|
|
error.set_backtrace e.backtrace
|
|
|
|
raise error
|
2018-07-29 11:05:23 +02:00
|
|
|
end
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2017-07-29 16:27:54 +02:00
|
|
|
def cask(header_token, **options, &block)
|
2019-02-19 13:11:32 +00:00
|
|
|
raise CaskTokenMismatchError.new(token, header_token) if token != header_token
|
2017-03-12 19:18:41 +01:00
|
|
|
|
2017-07-29 16:27:54 +02:00
|
|
|
super(header_token, **options, sourcefile_path: path, &block)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
2016-10-08 13:25:38 +02:00
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from a URI.
|
2017-03-12 19:18:41 +01:00
|
|
|
class FromURILoader < FromPathLoader
|
|
|
|
def self.can_load?(ref)
|
2022-10-27 01:28:08 -04:00
|
|
|
# Cache compiled regex
|
|
|
|
@uri_regex ||= begin
|
|
|
|
uri_regex = ::URI::DEFAULT_PARSER.make_regexp
|
|
|
|
Regexp.new("\\A#{uri_regex.source}\\Z", uri_regex.options)
|
|
|
|
end
|
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
return false unless ref.to_s.match?(@uri_regex)
|
2019-11-14 07:38:24 -08:00
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
uri = URI(ref)
|
2019-11-14 07:38:24 -08:00
|
|
|
return false unless uri.path
|
|
|
|
|
|
|
|
true
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2017-06-11 02:00:59 +02:00
|
|
|
attr_reader :url
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { params(url: T.any(URI::Generic, String)).void }
|
2017-03-12 19:18:41 +01:00
|
|
|
def initialize(url)
|
2017-06-11 02:00:59 +02:00
|
|
|
@url = URI(url)
|
2023-03-12 17:06:29 -07:00
|
|
|
super Cache.path/File.basename(T.must(@url.path))
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
2017-06-28 09:25:14 +02:00
|
|
|
path.dirname.mkpath
|
2017-03-12 19:18:41 +01:00
|
|
|
|
|
|
|
begin
|
2021-01-26 15:21:24 -05:00
|
|
|
ohai "Downloading #{url}"
|
2023-09-04 22:17:57 -04:00
|
|
|
::Utils::Curl.curl_download url, to: path
|
2017-03-12 19:18:41 +01:00
|
|
|
rescue ErrorDuringExecution
|
2017-06-28 09:25:14 +02:00
|
|
|
raise CaskUnavailableError.new(token, "Failed to download #{Formatter.url(url)}.")
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
super
|
|
|
|
end
|
2016-10-08 13:25:38 +02:00
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from a tap path.
|
2017-07-29 16:27:54 +02:00
|
|
|
class FromTapPathLoader < FromPathLoader
|
2017-03-12 19:18:41 +01:00
|
|
|
def self.can_load?(ref)
|
2018-03-29 22:05:02 +02:00
|
|
|
super && !Tap.from_path(ref).nil?
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2018-03-29 22:05:02 +02:00
|
|
|
def initialize(path)
|
|
|
|
super(path)
|
2023-04-18 00:22:13 +01:00
|
|
|
@tap = Tap.from_path(path)
|
2017-07-29 16:27:54 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from a specific tap.
|
2017-07-29 16:27:54 +02:00
|
|
|
class FromTapLoader < FromTapPathLoader
|
|
|
|
def self.can_load?(ref)
|
|
|
|
ref.to_s.match?(HOMEBREW_TAP_CASK_REGEX)
|
|
|
|
end
|
|
|
|
|
2017-03-12 19:18:41 +01:00
|
|
|
def initialize(tapped_name)
|
2017-06-28 09:25:14 +02:00
|
|
|
user, repo, token = tapped_name.split("/", 3)
|
2023-02-24 10:57:41 +00:00
|
|
|
tap = Tap.fetch(user, repo)
|
|
|
|
cask = CaskLoader.find_cask_in_tap(token, tap)
|
|
|
|
super cask
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
2016-10-08 13:25:38 +02:00
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
2023-04-18 00:22:13 +01:00
|
|
|
raise TapCaskUnavailableError.new(tap, token) unless T.must(tap).installed?
|
2017-03-12 19:18:41 +01:00
|
|
|
|
|
|
|
super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-05 13:06:56 -08:00
|
|
|
# Loads a cask from the default tap path.
|
|
|
|
class FromDefaultTapPathLoader < FromTapPathLoader
|
|
|
|
def self.can_load?(ref)
|
|
|
|
super CaskLoader.default_path(ref)
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(ref)
|
|
|
|
super CaskLoader.default_path(ref)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Loads a cask from an existing {Cask} instance.
|
2017-09-11 08:37:15 +02:00
|
|
|
class FromInstanceLoader
|
2023-03-12 17:06:29 -07:00
|
|
|
include ILoader
|
2017-09-11 08:37:15 +02:00
|
|
|
def self.can_load?(ref)
|
|
|
|
ref.is_a?(Cask)
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(cask)
|
|
|
|
@cask = cask
|
|
|
|
end
|
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
|
|
|
@cask
|
2017-09-11 08:37:15 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-12-29 02:48:31 -05:00
|
|
|
# Loads a cask from the JSON API.
|
|
|
|
class FromAPILoader
|
2023-03-12 17:06:29 -07:00
|
|
|
include ILoader
|
2022-12-29 02:48:31 -05:00
|
|
|
attr_reader :token, :path
|
|
|
|
|
|
|
|
def self.can_load?(ref)
|
2023-02-24 13:25:18 +00:00
|
|
|
return false if Homebrew::EnvConfig.no_install_from_api?
|
2023-01-31 00:09:57 -08:00
|
|
|
return false unless ref.is_a?(String)
|
2024-02-06 20:16:03 +00:00
|
|
|
return false unless ref.match?(HOMEBREW_MAIN_TAP_CASK_REGEX)
|
2023-01-31 00:09:57 -08:00
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
token = ref.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "")
|
2023-01-31 00:09:57 -08:00
|
|
|
Homebrew::API::Cask.all_casks.key?(token)
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
|
|
|
|
2024-02-06 20:16:03 +00:00
|
|
|
def initialize(token, from_json: nil)
|
2023-04-18 00:22:13 +01:00
|
|
|
@token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "")
|
2023-07-31 20:26:29 -04:00
|
|
|
@path = CaskLoader.default_path(@token)
|
2023-02-05 12:22:08 +01:00
|
|
|
@from_json = from_json
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def load(config:)
|
2024-02-06 20:16:03 +00:00
|
|
|
json_cask = @from_json || Homebrew::API::Cask.all_casks[token]
|
2023-02-18 12:08:54 -08:00
|
|
|
|
|
|
|
cask_options = {
|
|
|
|
loaded_from_api: true,
|
|
|
|
source: JSON.pretty_generate(json_cask),
|
|
|
|
config: config,
|
|
|
|
loader: self,
|
|
|
|
}
|
2022-12-29 02:48:31 -05:00
|
|
|
|
2023-02-25 02:08:39 -08:00
|
|
|
json_cask = Homebrew::API.merge_variations(json_cask).deep_symbolize_keys.freeze
|
2023-01-06 02:41:35 -05:00
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
cask_options[:tap] = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
|
2023-01-26 17:36:40 +00:00
|
|
|
|
2023-02-24 13:56:46 +00:00
|
|
|
user_agent = json_cask.dig(:url_specs, :user_agent)
|
|
|
|
json_cask[:url_specs][:user_agent] = user_agent[1..].to_sym if user_agent && user_agent[0] == ":"
|
|
|
|
if (using = json_cask.dig(:url_specs, :using))
|
|
|
|
json_cask[:url_specs][:using] = using.to_sym
|
|
|
|
end
|
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
api_cask = Cask.new(token, **cask_options) do
|
2022-12-29 02:48:31 -05:00
|
|
|
version json_cask[:version]
|
|
|
|
|
|
|
|
if json_cask[:sha256] == "no_check"
|
|
|
|
sha256 :no_check
|
|
|
|
else
|
|
|
|
sha256 json_cask[:sha256]
|
|
|
|
end
|
|
|
|
|
2023-08-20 12:20:39 -07:00
|
|
|
url json_cask[:url], **json_cask.fetch(:url_specs, {}) if json_cask[:url].present?
|
2022-12-29 02:48:31 -05:00
|
|
|
appcast json_cask[:appcast] if json_cask[:appcast].present?
|
2024-01-01 19:10:48 -08:00
|
|
|
json_cask[:name]&.each do |cask_name|
|
2022-12-29 02:48:31 -05:00
|
|
|
name cask_name
|
|
|
|
end
|
|
|
|
desc json_cask[:desc]
|
|
|
|
homepage json_cask[:homepage]
|
|
|
|
|
2023-12-04 00:30:49 -05:00
|
|
|
if (deprecation_date = json_cask[:deprecation_date].presence)
|
|
|
|
reason = DeprecateDisable.to_reason_string_or_symbol json_cask[:deprecation_reason], type: :cask
|
|
|
|
deprecate! date: deprecation_date, because: reason
|
|
|
|
end
|
|
|
|
|
|
|
|
if (disable_date = json_cask[:disable_date].presence)
|
|
|
|
reason = DeprecateDisable.to_reason_string_or_symbol json_cask[:disable_reason], type: :cask
|
2023-12-16 20:08:26 -05:00
|
|
|
disable! date: disable_date, because: reason
|
2023-12-04 00:30:49 -05:00
|
|
|
end
|
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
auto_updates json_cask[:auto_updates] unless json_cask[:auto_updates].nil?
|
2022-12-29 02:48:31 -05:00
|
|
|
conflicts_with(**json_cask[:conflicts_with]) if json_cask[:conflicts_with].present?
|
|
|
|
|
|
|
|
if json_cask[:depends_on].present?
|
|
|
|
dep_hash = json_cask[:depends_on].to_h do |dep_key, dep_value|
|
2023-01-11 13:16:34 -05:00
|
|
|
# Arch dependencies are encoded like `{ type: :intel, bits: 64 }`
|
|
|
|
# but `depends_on arch:` only accepts `:intel` or `:arm64`
|
2023-01-10 12:35:39 -05:00
|
|
|
if dep_key == :arch
|
|
|
|
next [:arch, :intel] if dep_value.first[:type] == "intel"
|
|
|
|
|
|
|
|
next [:arch, :arm64]
|
|
|
|
end
|
|
|
|
|
2023-04-18 15:06:50 -07:00
|
|
|
next [dep_key, dep_value] if dep_key != :macos
|
2022-12-29 02:48:31 -05:00
|
|
|
|
|
|
|
dep_type = dep_value.keys.first
|
|
|
|
if dep_type == :==
|
|
|
|
version_symbols = dep_value[dep_type].map do |version|
|
2023-05-09 02:15:28 +02:00
|
|
|
MacOSVersion::SYMBOLS.key(version) || version
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
|
|
|
next [dep_key, version_symbols]
|
|
|
|
end
|
|
|
|
|
|
|
|
version_symbol = dep_value[dep_type].first
|
2023-05-09 02:15:28 +02:00
|
|
|
version_symbol = MacOSVersion::SYMBOLS.key(version_symbol) || version_symbol
|
2022-12-29 02:48:31 -05:00
|
|
|
[dep_key, "#{dep_type} :#{version_symbol}"]
|
|
|
|
end.compact
|
|
|
|
depends_on(**dep_hash)
|
|
|
|
end
|
|
|
|
|
|
|
|
if json_cask[:container].present?
|
|
|
|
container_hash = json_cask[:container].to_h do |container_key, container_value|
|
2023-04-18 15:06:50 -07:00
|
|
|
next [container_key, container_value] if container_key != :type
|
2022-12-29 02:48:31 -05:00
|
|
|
|
|
|
|
[container_key, container_value.to_sym]
|
|
|
|
end
|
|
|
|
container(**container_hash)
|
|
|
|
end
|
|
|
|
|
|
|
|
json_cask[:artifacts].each do |artifact|
|
2023-02-14 14:19:40 +00:00
|
|
|
# convert generic string replacements into actual ones
|
2023-02-18 12:08:54 -08:00
|
|
|
artifact = cask.loader.from_h_gsubs(artifact, appdir)
|
2022-12-29 02:48:31 -05:00
|
|
|
key = artifact.keys.first
|
2023-02-25 02:08:39 -08:00
|
|
|
if artifact[key].nil?
|
|
|
|
# for artifacts with blocks that can't be loaded from the API
|
|
|
|
send(key) {} # empty on purpose
|
|
|
|
else
|
2023-09-29 04:47:44 +01:00
|
|
|
args = artifact[key]
|
|
|
|
kwargs = if args.last.is_a?(Hash)
|
|
|
|
args.pop
|
|
|
|
else
|
|
|
|
{}
|
|
|
|
end
|
|
|
|
send(key, *args, **kwargs)
|
2023-02-25 02:08:39 -08:00
|
|
|
end
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
|
|
|
|
2023-02-14 14:19:40 +00:00
|
|
|
if json_cask[:caveats].present?
|
|
|
|
# convert generic string replacements into actual ones
|
2023-02-25 02:08:39 -08:00
|
|
|
caveats cask.loader.from_h_string_gsubs(json_cask[:caveats], appdir)
|
2023-02-14 14:19:40 +00:00
|
|
|
end
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
2023-02-25 02:08:39 -08:00
|
|
|
api_cask.populate_from_api!(json_cask)
|
|
|
|
api_cask
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
2023-01-25 15:07:44 +00:00
|
|
|
|
2023-02-14 14:19:40 +00:00
|
|
|
def from_h_string_gsubs(string, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
string.to_s
|
2023-03-21 19:05:41 -07:00
|
|
|
.gsub(HOMEBREW_HOME_PLACEHOLDER, Dir.home)
|
|
|
|
.gsub(HOMEBREW_PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
|
2023-07-18 10:59:27 +01:00
|
|
|
.gsub(HOMEBREW_CELLAR_PLACEHOLDER, HOMEBREW_CELLAR)
|
2023-03-22 19:43:49 -07:00
|
|
|
.gsub(HOMEBREW_CASK_APPDIR_PLACEHOLDER, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
end
|
|
|
|
|
2023-02-14 14:19:40 +00:00
|
|
|
def from_h_array_gsubs(array, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
array.to_a.map do |value|
|
2023-02-14 14:19:40 +00:00
|
|
|
from_h_gsubs(value, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-14 14:19:40 +00:00
|
|
|
def from_h_hash_gsubs(hash, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
hash.to_h.transform_values do |value|
|
2023-02-14 14:19:40 +00:00
|
|
|
from_h_gsubs(value, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-14 14:19:40 +00:00
|
|
|
def from_h_gsubs(value, appdir)
|
2023-02-05 02:49:41 +01:00
|
|
|
return value if value.blank?
|
|
|
|
|
2023-02-18 12:08:54 -08:00
|
|
|
case value
|
|
|
|
when Hash
|
2023-02-14 14:19:40 +00:00
|
|
|
from_h_hash_gsubs(value, appdir)
|
2023-02-18 12:08:54 -08:00
|
|
|
when Array
|
2023-02-14 14:19:40 +00:00
|
|
|
from_h_array_gsubs(value, appdir)
|
2023-02-18 12:08:54 -08:00
|
|
|
when String
|
2023-02-14 14:19:40 +00:00
|
|
|
from_h_string_gsubs(value, appdir)
|
2023-01-25 15:07:44 +00:00
|
|
|
else
|
2023-02-06 15:07:28 +01:00
|
|
|
value
|
2023-01-25 15:07:44 +00:00
|
|
|
end
|
|
|
|
end
|
2022-12-29 02:48:31 -05:00
|
|
|
end
|
|
|
|
|
2020-08-24 22:50:29 +02:00
|
|
|
# Pseudo-loader which raises an error when trying to load the corresponding cask.
|
2017-03-12 19:18:41 +01:00
|
|
|
class NullLoader < FromPathLoader
|
2024-02-06 20:16:03 +00:00
|
|
|
def self.can_load?(*)
|
2017-03-12 19:18:41 +01:00
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { params(ref: T.any(String, Pathname)).void }
|
2017-03-12 19:18:41 +01:00
|
|
|
def initialize(ref)
|
2017-06-28 09:25:14 +02:00
|
|
|
token = File.basename(ref, ".rb")
|
|
|
|
super CaskLoader.default_path(token)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2020-09-29 23:46:30 +02:00
|
|
|
def load(config:)
|
2017-06-28 09:25:14 +02:00
|
|
|
raise CaskUnavailableError.new(token, "No Cask with this name exists.")
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.path(ref)
|
2023-01-04 13:51:21 +00:00
|
|
|
self.for(ref, need_path: true).path
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
def self.load(ref, config: nil, warn: true)
|
|
|
|
self.for(ref, warn: warn).load(config: config)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
def self.for(ref, need_path: false, warn: true)
|
2017-03-12 19:18:41 +01:00
|
|
|
[
|
2017-09-11 08:37:15 +02:00
|
|
|
FromInstanceLoader,
|
2017-10-08 15:20:58 +02:00
|
|
|
FromContentLoader,
|
2017-03-12 19:18:41 +01:00
|
|
|
FromURILoader,
|
2023-01-31 00:09:57 -08:00
|
|
|
FromAPILoader,
|
2017-03-12 19:18:41 +01:00
|
|
|
FromTapLoader,
|
2017-07-29 16:27:54 +02:00
|
|
|
FromTapPathLoader,
|
2017-03-12 19:18:41 +01:00
|
|
|
FromPathLoader,
|
2023-02-05 13:06:56 -08:00
|
|
|
FromDefaultTapPathLoader,
|
2017-03-12 19:18:41 +01:00
|
|
|
].each do |loader_class|
|
2024-02-06 20:16:03 +00:00
|
|
|
if loader_class.can_load?(ref)
|
|
|
|
$stderr.puts "#{$PROGRAM_NAME} (#{loader_class}): loading #{ref}" if debug?
|
|
|
|
return loader_class.new(ref)
|
2023-02-05 13:06:56 -08:00
|
|
|
end
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
case (possible_tap_casks = tap_paths(ref, warn: warn)).count
|
2017-07-29 16:27:54 +02:00
|
|
|
when 1
|
|
|
|
return FromTapPathLoader.new(possible_tap_casks.first)
|
|
|
|
when 2..Float::INFINITY
|
|
|
|
loaders = possible_tap_casks.map(&FromTapPathLoader.method(:new))
|
2024-02-06 20:16:03 +00:00
|
|
|
|
2022-06-17 15:22:41 -04:00
|
|
|
raise TapCaskAmbiguityError.new(ref, loaders)
|
2016-10-08 13:25:38 +02:00
|
|
|
end
|
2017-03-12 19:18:41 +01:00
|
|
|
|
|
|
|
possible_installed_cask = Cask.new(ref)
|
2024-02-06 20:16:03 +00:00
|
|
|
return FromPathLoader.new(possible_installed_cask.installed_caskfile) if possible_installed_cask.installed?
|
2017-03-12 19:18:41 +01:00
|
|
|
|
|
|
|
NullLoader.new(ref)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.default_path(token)
|
2023-08-04 16:21:31 +01:00
|
|
|
find_cask_in_tap(token.to_s.downcase, CoreCaskTap.instance)
|
2017-03-12 19:18:41 +01:00
|
|
|
end
|
|
|
|
|
2023-04-08 14:10:58 +02:00
|
|
|
def self.tap_paths(token, warn: true)
|
|
|
|
token = token.to_s.downcase
|
|
|
|
|
2023-02-24 10:57:41 +00:00
|
|
|
Tap.map do |tap|
|
2023-04-08 14:10:58 +02:00
|
|
|
new_token = tap.cask_renames[token]
|
|
|
|
opoo "Cask #{token} was renamed to #{new_token}." if new_token && warn
|
|
|
|
find_cask_in_tap(new_token || token, tap)
|
2023-02-24 10:57:41 +00:00
|
|
|
end.select(&:exist?)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.find_cask_in_tap(token, tap)
|
|
|
|
filename = "#{token}.rb"
|
|
|
|
|
2023-08-04 16:21:31 +01:00
|
|
|
Tap.cask_files_by_name(tap)
|
|
|
|
.fetch(token, tap.cask_dir/filename)
|
2016-10-08 13:25:38 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|