2024-08-12 10:30:59 +01:00
|
|
|
# typed: true # rubocop:todo Sorbet/StrictSigil
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-09-28 00:48:19 +02:00
|
|
|
require "locale"
|
2018-07-30 21:07:36 +02:00
|
|
|
require "lazy_object"
|
2020-09-02 12:24:21 -07:00
|
|
|
require "livecheck"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/artifact"
|
2022-10-08 01:08:15 +01:00
|
|
|
require "cask/artifact_set"
|
2017-04-06 00:33:31 +02:00
|
|
|
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/caskroom"
|
|
|
|
require "cask/exceptions"
|
2018-06-09 12:20:58 +02:00
|
|
|
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/dsl/base"
|
|
|
|
require "cask/dsl/caveats"
|
|
|
|
require "cask/dsl/conflicts_with"
|
|
|
|
require "cask/dsl/container"
|
|
|
|
require "cask/dsl/depends_on"
|
|
|
|
require "cask/dsl/postflight"
|
|
|
|
require "cask/dsl/preflight"
|
|
|
|
require "cask/dsl/uninstall_postflight"
|
|
|
|
require "cask/dsl/uninstall_preflight"
|
|
|
|
require "cask/dsl/version"
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2018-09-03 19:39:07 +01:00
|
|
|
require "cask/url"
|
2020-08-01 02:30:46 +02:00
|
|
|
require "cask/utils"
|
2018-06-09 12:20:58 +02:00
|
|
|
|
2022-06-23 17:18:58 -04:00
|
|
|
require "extend/on_system"
|
|
|
|
|
2018-09-06 08:29:14 +02:00
|
|
|
module Cask
|
2020-08-24 23:09:43 +02:00
|
|
|
# Class representing the domain-specific language used for casks.
|
2016-09-24 13:52:43 +02:00
|
|
|
class DSL
|
2017-04-06 00:33:31 +02:00
|
|
|
ORDINARY_ARTIFACT_CLASSES = [
|
|
|
|
Artifact::Installer,
|
|
|
|
Artifact::App,
|
|
|
|
Artifact::Artifact,
|
|
|
|
Artifact::AudioUnitPlugin,
|
|
|
|
Artifact::Binary,
|
|
|
|
Artifact::Colorpicker,
|
|
|
|
Artifact::Dictionary,
|
|
|
|
Artifact::Font,
|
|
|
|
Artifact::InputMethod,
|
|
|
|
Artifact::InternetPlugin,
|
2023-03-26 08:10:40 +02:00
|
|
|
Artifact::KeyboardLayout,
|
2019-10-23 16:28:00 +03:00
|
|
|
Artifact::Manpage,
|
2017-04-06 00:33:31 +02:00
|
|
|
Artifact::Pkg,
|
|
|
|
Artifact::Prefpane,
|
|
|
|
Artifact::Qlplugin,
|
2020-04-05 15:30:37 +02:00
|
|
|
Artifact::Mdimporter,
|
2017-04-06 00:33:31 +02:00
|
|
|
Artifact::ScreenSaver,
|
|
|
|
Artifact::Service,
|
|
|
|
Artifact::StageOnly,
|
|
|
|
Artifact::Suite,
|
|
|
|
Artifact::VstPlugin,
|
|
|
|
Artifact::Vst3Plugin,
|
2025-03-03 17:54:54 +01:00
|
|
|
Artifact::ZshCompletion,
|
|
|
|
Artifact::FishCompletion,
|
|
|
|
Artifact::BashCompletion,
|
2017-04-06 00:33:31 +02:00
|
|
|
Artifact::Uninstall,
|
|
|
|
Artifact::Zap,
|
2016-10-14 20:33:16 +02:00
|
|
|
].freeze
|
2016-09-24 13:52:43 +02:00
|
|
|
|
2019-04-19 21:46:20 +09:00
|
|
|
ACTIVATABLE_ARTIFACT_CLASSES = (ORDINARY_ARTIFACT_CLASSES - [Artifact::StageOnly]).freeze
|
2016-09-24 13:52:43 +02:00
|
|
|
|
2017-04-06 00:33:31 +02:00
|
|
|
ARTIFACT_BLOCK_CLASSES = [
|
|
|
|
Artifact::PreflightBlock,
|
|
|
|
Artifact::PostflightBlock,
|
2016-10-14 20:33:16 +02:00
|
|
|
].freeze
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2019-04-19 21:46:20 +09:00
|
|
|
DSL_METHODS = Set.new([
|
2021-02-11 13:24:19 +00:00
|
|
|
:appcast,
|
2023-03-27 11:28:59 +11:00
|
|
|
:arch,
|
2021-02-11 13:24:19 +00:00
|
|
|
:artifacts,
|
|
|
|
:auto_updates,
|
|
|
|
:caveats,
|
|
|
|
:conflicts_with,
|
|
|
|
:container,
|
|
|
|
:desc,
|
|
|
|
:depends_on,
|
|
|
|
:homepage,
|
|
|
|
:language,
|
|
|
|
:name,
|
2025-04-03 19:28:02 -04:00
|
|
|
:os,
|
2021-02-11 13:24:19 +00:00
|
|
|
:sha256,
|
|
|
|
:staged_path,
|
|
|
|
:url,
|
|
|
|
:version,
|
|
|
|
:appdir,
|
2023-12-03 21:59:03 -05:00
|
|
|
:deprecate!,
|
|
|
|
:deprecated?,
|
|
|
|
:deprecation_date,
|
|
|
|
:deprecation_reason,
|
2025-04-02 13:19:49 +02:00
|
|
|
:deprecation_replacement_cask,
|
2025-04-22 17:53:19 -04:00
|
|
|
:deprecation_replacement_formula,
|
2023-12-03 21:59:03 -05:00
|
|
|
:disable!,
|
|
|
|
:disabled?,
|
|
|
|
:disable_date,
|
|
|
|
:disable_reason,
|
2025-04-02 13:19:49 +02:00
|
|
|
:disable_replacement_cask,
|
2025-04-22 17:53:19 -04:00
|
|
|
:disable_replacement_formula,
|
2023-12-17 18:07:51 -05:00
|
|
|
:discontinued?, # TODO: remove once discontinued? is removed (4.5.0)
|
2021-02-11 13:24:19 +00:00
|
|
|
:livecheck,
|
livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
2024-11-27 18:20:56 -05:00
|
|
|
:livecheck_defined?,
|
|
|
|
:livecheckable?, # TODO: remove once `#livecheckable?` is removed
|
2022-10-12 18:20:53 -04:00
|
|
|
:on_system_blocks_exist?,
|
2024-06-21 16:04:04 -04:00
|
|
|
:on_system_block_min_os,
|
2024-06-20 23:19:09 -04:00
|
|
|
:depends_on_set_in_block?,
|
2021-02-11 13:24:19 +00:00
|
|
|
*ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
|
|
|
|
*ACTIVATABLE_ARTIFACT_CLASSES.map(&:dsl_key),
|
|
|
|
*ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] },
|
|
|
|
]).freeze
|
2016-09-24 13:52:43 +02:00
|
|
|
|
2025-01-19 16:36:37 +01:00
|
|
|
include OnSystem::MacOSAndLinux
|
2022-06-23 17:18:58 -04:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
attr_reader :cask, :token, :artifacts, :deprecation_date, :deprecation_reason,
|
|
|
|
:deprecation_replacement_cask, :deprecation_replacement_formula,
|
|
|
|
:disable_date, :disable_reason, :disable_replacement_cask,
|
|
|
|
:disable_replacement_formula, :on_system_block_min_os
|
2017-10-04 15:47:53 +02:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
sig { params(cask: Cask).void }
|
2017-04-06 00:33:31 +02:00
|
|
|
def initialize(cask)
|
2025-04-22 23:18:23 -04:00
|
|
|
# NOTE: Variables set by `set_unique_stanza` must be initialized to `nil`.
|
|
|
|
@auto_updates = T.let(nil, T.nilable(T::Boolean))
|
|
|
|
@arch = T.let(nil, T.nilable(String))
|
2025-04-22 17:53:19 -04:00
|
|
|
@artifacts = T.let(ArtifactSet.new, ArtifactSet)
|
|
|
|
@called_in_on_system_block = T.let(false, T::Boolean)
|
|
|
|
@cask = T.let(cask, Cask)
|
|
|
|
@caveats = T.let(DSL::Caveats.new(cask), DSL::Caveats)
|
2025-04-22 23:18:23 -04:00
|
|
|
@conflicts_with = T.let(nil, T.nilable(DSL::ConflictsWith))
|
|
|
|
@container = T.let(nil, T.nilable(DSL::Container))
|
2025-04-22 17:53:19 -04:00
|
|
|
@depends_on = T.let(DSL::DependsOn.new, DSL::DependsOn)
|
2025-02-24 14:49:33 -08:00
|
|
|
@depends_on_set_in_block = T.let(false, T::Boolean)
|
|
|
|
@deprecated = T.let(false, T::Boolean)
|
2025-04-22 17:53:19 -04:00
|
|
|
@deprecation_date = T.let(nil, T.nilable(Date))
|
|
|
|
@deprecation_reason = T.let(nil, T.nilable(T.any(String, Symbol)))
|
|
|
|
@deprecation_replacement_cask = T.let(nil, T.nilable(String))
|
|
|
|
@deprecation_replacement_formula = T.let(nil, T.nilable(String))
|
2025-04-22 23:18:23 -04:00
|
|
|
@desc = T.let(nil, T.nilable(String))
|
2025-04-22 17:53:19 -04:00
|
|
|
@disable_date = T.let(nil, T.nilable(Date))
|
|
|
|
@disable_reason = T.let(nil, T.nilable(T.any(String, Symbol)))
|
|
|
|
@disable_replacement_cask = T.let(nil, T.nilable(String))
|
|
|
|
@disable_replacement_formula = T.let(nil, T.nilable(String))
|
2025-02-24 14:49:33 -08:00
|
|
|
@disabled = T.let(false, T::Boolean)
|
2025-04-22 23:18:23 -04:00
|
|
|
@homepage = T.let(nil, T.nilable(String))
|
2025-04-22 17:53:19 -04:00
|
|
|
@language_blocks = T.let({}, T::Hash[T::Array[String], Proc])
|
|
|
|
@language_eval = T.let(nil, T.nilable(String))
|
|
|
|
@livecheck = T.let(Livecheck.new(cask), Livecheck)
|
2025-02-24 14:49:33 -08:00
|
|
|
@livecheck_defined = T.let(false, T::Boolean)
|
2025-04-22 17:53:19 -04:00
|
|
|
@name = T.let([], T::Array[String])
|
2025-02-24 14:49:33 -08:00
|
|
|
@on_system_blocks_exist = T.let(false, T::Boolean)
|
2025-04-22 23:18:23 -04:00
|
|
|
@os = T.let(nil, T.nilable(String))
|
2025-04-22 17:53:19 -04:00
|
|
|
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
|
2025-04-22 23:18:23 -04:00
|
|
|
@sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol)))
|
2025-04-22 17:53:19 -04:00
|
|
|
@staged_path = T.let(nil, T.nilable(Pathname))
|
|
|
|
@token = T.let(cask.token, String)
|
2025-04-22 23:18:23 -04:00
|
|
|
@url = T.let(nil, T.nilable(URL))
|
|
|
|
@version = T.let(nil, T.nilable(DSL::Version))
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2025-02-24 14:49:33 -08:00
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def depends_on_set_in_block? = @depends_on_set_in_block
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def deprecated? = @deprecated
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def disabled? = @disabled
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def livecheck_defined? = @livecheck_defined
|
|
|
|
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def on_system_blocks_exist? = @on_system_blocks_exist
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Specifies the cask's name.
|
|
|
|
#
|
|
|
|
# NOTE: Multiple names can be specified.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# name "Visual Studio Code"
|
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2016-09-24 13:52:43 +02:00
|
|
|
def name(*args)
|
|
|
|
return @name if args.empty?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
@name.concat(args.flatten)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Describes the cask.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# desc "Open-source code editor"
|
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2020-07-29 15:40:31 +01:00
|
|
|
def desc(description = nil)
|
|
|
|
set_unique_stanza(:desc, description.nil?) { description }
|
|
|
|
end
|
|
|
|
|
2017-07-30 16:26:44 +02:00
|
|
|
def set_unique_stanza(stanza, should_return)
|
2023-12-18 09:34:01 -08:00
|
|
|
return instance_variable_get(:"@#{stanza}") if should_return
|
2017-07-30 16:26:44 +02:00
|
|
|
|
2022-06-23 17:18:58 -04:00
|
|
|
unless @cask.allow_reassignment
|
2025-04-22 23:18:23 -04:00
|
|
|
if !instance_variable_get(:"@#{stanza}").nil? && !@called_in_on_system_block
|
2022-06-23 17:18:58 -04:00
|
|
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
|
|
|
|
end
|
|
|
|
|
2023-12-18 09:34:01 -08:00
|
|
|
if instance_variable_defined?(:"@#{stanza}_set_in_block") && @called_in_on_system_block
|
2022-06-23 17:18:58 -04:00
|
|
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only be overridden once.")
|
|
|
|
end
|
2017-07-30 16:26:44 +02:00
|
|
|
end
|
|
|
|
|
2023-12-18 09:34:01 -08:00
|
|
|
instance_variable_set(:"@#{stanza}_set_in_block", true) if @called_in_on_system_block
|
|
|
|
instance_variable_set(:"@#{stanza}", yield)
|
2017-04-06 00:33:31 +02:00
|
|
|
rescue CaskInvalidError
|
|
|
|
raise
|
2018-09-02 20:14:54 +01:00
|
|
|
rescue => e
|
2017-04-06 00:33:31 +02:00
|
|
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's homepage.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# homepage "https://code.visualstudio.com/"
|
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2016-09-24 13:52:43 +02:00
|
|
|
def homepage(homepage = nil)
|
2017-07-30 16:26:44 +02:00
|
|
|
set_unique_stanza(:homepage, homepage.nil?) { homepage }
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-28 00:48:19 +02:00
|
|
|
def language(*args, default: false, &block)
|
2017-09-23 01:40:14 +02:00
|
|
|
if args.empty?
|
|
|
|
language_eval
|
2020-11-16 22:18:56 +01:00
|
|
|
elsif block
|
2016-09-25 22:13:44 +02:00
|
|
|
@language_blocks[args] = block
|
2016-09-28 00:57:19 +02:00
|
|
|
|
|
|
|
return unless default
|
|
|
|
|
2022-06-12 15:27:31 -04:00
|
|
|
if !@cask.allow_reassignment && @language_blocks.default.present?
|
2017-04-06 00:33:31 +02:00
|
|
|
raise CaskInvalidError.new(cask, "Only one default language may be defined.")
|
2016-09-28 00:57:19 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
@language_blocks.default = block
|
2016-09-14 23:11:21 +02:00
|
|
|
else
|
2017-09-23 01:40:14 +02:00
|
|
|
raise CaskInvalidError.new(cask, "No block given to language stanza.")
|
2016-09-14 23:11:21 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-18 04:15:28 +02:00
|
|
|
def language_eval
|
2025-04-22 17:53:19 -04:00
|
|
|
return @language_eval unless @language_eval.nil?
|
2016-09-25 22:13:44 +02:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
return @language_eval = nil if @language_blocks.empty?
|
2016-09-25 22:13:44 +02:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
if (language_blocks_default = @language_blocks.default).nil?
|
|
|
|
raise CaskInvalidError.new(cask, "No default language specified.")
|
|
|
|
end
|
2017-09-23 01:40:14 +02:00
|
|
|
|
2020-07-21 21:28:58 +02:00
|
|
|
locales = cask.config.languages
|
2024-02-22 23:29:55 +00:00
|
|
|
.filter_map do |language|
|
2020-07-22 00:50:27 +02:00
|
|
|
Locale.parse(language)
|
|
|
|
rescue Locale::ParserError
|
|
|
|
nil
|
|
|
|
end
|
2018-08-19 22:10:20 +02:00
|
|
|
|
|
|
|
locales.each do |locale|
|
2018-05-28 15:01:58 +01:00
|
|
|
key = locale.detect(@language_blocks.keys)
|
2025-04-22 17:53:19 -04:00
|
|
|
next if key.nil? || (language_block = @language_blocks[key]).nil?
|
2016-09-28 00:48:19 +02:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
return @language_eval = language_block.call
|
2016-10-03 02:34:32 +02:00
|
|
|
end
|
2016-09-25 22:13:44 +02:00
|
|
|
|
2025-04-22 17:53:19 -04:00
|
|
|
@language_eval = language_blocks_default.call
|
2016-09-18 04:15:28 +02:00
|
|
|
end
|
|
|
|
|
2017-09-27 00:17:47 -07:00
|
|
|
def languages
|
|
|
|
@language_blocks.keys.flatten
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's download URL.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# url "https://update.code.visualstudio.com/#{version}/#{arch}/stable"
|
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
|
|
|
def url(*args, **options, &block)
|
2023-03-12 17:06:29 -07:00
|
|
|
caller_location = T.must(caller_locations).fetch(0)
|
2020-12-07 18:46:35 +01:00
|
|
|
|
2021-03-31 06:14:41 +02:00
|
|
|
set_unique_stanza(:url, args.empty? && options.empty? && !block) do
|
|
|
|
if block
|
2024-03-07 16:20:20 +00:00
|
|
|
URL.new(*args, **options, caller_location:, dsl: self, &block)
|
2018-07-30 21:07:36 +02:00
|
|
|
else
|
2024-03-07 16:20:20 +00:00
|
|
|
URL.new(*args, **options, caller_location:)
|
2017-07-30 16:26:44 +02:00
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's container type or nested container path.
|
|
|
|
#
|
|
|
|
# ### Examples
|
|
|
|
#
|
|
|
|
# The container is a nested disk image:
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# container nested: "orca-#{version}.dmg"
|
|
|
|
# ```
|
|
|
|
#
|
|
|
|
# The container should not be unarchived:
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# container type: :naked
|
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2022-10-08 01:08:15 +01:00
|
|
|
def container(**kwargs)
|
|
|
|
set_unique_stanza(:container, kwargs.empty?) do
|
|
|
|
DSL::Container.new(**kwargs)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's version.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# version "1.88.1"
|
|
|
|
# ```
|
|
|
|
#
|
|
|
|
# @see DSL::Version
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2025-02-19 14:51:36 -05:00
|
|
|
sig { params(arg: T.nilable(T.any(String, Symbol))).returns(T.nilable(DSL::Version)) }
|
2016-09-24 13:52:43 +02:00
|
|
|
def version(arg = nil)
|
2017-07-30 16:26:44 +02:00
|
|
|
set_unique_stanza(:version, arg.nil?) do
|
|
|
|
if !arg.is_a?(String) && arg != :latest
|
2021-01-26 15:21:24 -05:00
|
|
|
raise CaskInvalidError.new(cask, "invalid 'version' value: #{arg.inspect}")
|
2017-07-30 16:26:44 +02:00
|
|
|
end
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-07-30 16:26:44 +02:00
|
|
|
DSL::Version.new(arg)
|
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's download checksum.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# For universal or single-architecture downloads:
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# sha256 "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca"
|
|
|
|
# ```
|
|
|
|
#
|
|
|
|
# For architecture-dependent downloads:
|
|
|
|
#
|
|
|
|
# ```ruby
|
2025-02-09 12:18:48 +01:00
|
|
|
# sha256 arm: "7bdb497080ffafdfd8cc94d8c62b004af1be9599e865e5555e456e2681e150ca",
|
|
|
|
# x86_64: "b3c1c2442480a0219b9e05cf91d03385858c20f04b764ec08a3fa83d1b27e7b2"
|
|
|
|
# x86_64_linux: "1a2aee7f1ddc999993d4d7d42a150c5e602bc17281678050b8ed79a0500cc90f"
|
|
|
|
# arm64_linux: "bd766af7e692afceb727a6f88e24e6e68d9882aeb3e8348412f6c03d96537c75"
|
2024-04-26 20:55:51 +02:00
|
|
|
# ```
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2025-02-09 12:18:48 +01:00
|
|
|
sig {
|
|
|
|
params(
|
|
|
|
arg: T.nilable(T.any(String, Symbol)),
|
|
|
|
arm: T.nilable(String),
|
|
|
|
intel: T.nilable(String),
|
|
|
|
x86_64: T.nilable(String),
|
|
|
|
x86_64_linux: T.nilable(String),
|
|
|
|
arm64_linux: T.nilable(String),
|
|
|
|
).returns(T.nilable(T.any(Symbol, Checksum)))
|
|
|
|
}
|
|
|
|
def sha256(arg = nil, arm: nil, intel: nil, x86_64: nil, x86_64_linux: nil, arm64_linux: nil)
|
|
|
|
should_return = arg.nil? && arm.nil? && (intel.nil? || x86_64.nil?) && x86_64_linux.nil? && arm64_linux.nil?
|
|
|
|
|
|
|
|
x86_64 ||= intel if intel.present? && x86_64.nil?
|
2022-08-16 00:48:24 -04:00
|
|
|
set_unique_stanza(:sha256, should_return) do
|
2025-02-09 12:18:48 +01:00
|
|
|
if arm.present? || x86_64.present? || x86_64_linux.present? || arm64_linux.present?
|
|
|
|
@on_system_blocks_exist = true
|
|
|
|
end
|
2022-08-16 00:48:24 -04:00
|
|
|
|
2025-02-09 12:18:48 +01:00
|
|
|
val = arg || on_system_conditional(
|
|
|
|
macos: on_arch_conditional(arm:, intel: x86_64),
|
|
|
|
linux: on_arch_conditional(arm: arm64_linux, intel: x86_64_linux),
|
|
|
|
)
|
2023-03-12 17:06:29 -07:00
|
|
|
case val
|
2020-11-19 18:12:16 +01:00
|
|
|
when :no_check
|
2023-03-12 17:06:29 -07:00
|
|
|
val
|
2020-11-19 18:12:16 +01:00
|
|
|
when String
|
2023-03-12 17:06:29 -07:00
|
|
|
Checksum.new(val)
|
2020-11-19 18:12:16 +01:00
|
|
|
else
|
2023-03-12 17:06:29 -07:00
|
|
|
raise CaskInvalidError.new(cask, "invalid 'sha256' value: #{val.inspect}")
|
2017-07-30 16:26:44 +02:00
|
|
|
end
|
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Sets the cask's architecture strings.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# arch arm: "darwin-arm64", intel: "darwin"
|
|
|
|
# ```
|
|
|
|
#
|
2022-08-05 15:51:02 -04:00
|
|
|
# @api public
|
|
|
|
def arch(arm: nil, intel: nil)
|
2022-08-16 11:04:59 -04:00
|
|
|
should_return = arm.nil? && intel.nil?
|
2022-08-05 15:51:02 -04:00
|
|
|
|
|
|
|
set_unique_stanza(:arch, should_return) do
|
|
|
|
@on_system_blocks_exist = true
|
|
|
|
|
2024-03-07 16:20:20 +00:00
|
|
|
on_arch_conditional(arm:, intel:)
|
2022-08-05 15:51:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-01-19 16:15:19 +00:00
|
|
|
# Sets the cask's os strings.
|
|
|
|
#
|
|
|
|
# ### Example
|
|
|
|
#
|
|
|
|
# ```ruby
|
|
|
|
# os macos: "darwin", linux: "tux"
|
|
|
|
# ```
|
|
|
|
#
|
|
|
|
# @api public
|
2025-02-09 12:18:48 +01:00
|
|
|
sig {
|
|
|
|
params(
|
|
|
|
macos: T.nilable(String),
|
|
|
|
linux: T.nilable(String),
|
|
|
|
).returns(T.nilable(String))
|
|
|
|
}
|
2025-01-19 16:15:19 +00:00
|
|
|
def os(macos: nil, linux: nil)
|
|
|
|
should_return = macos.nil? && linux.nil?
|
|
|
|
|
|
|
|
set_unique_stanza(:os, should_return) do
|
|
|
|
@on_system_blocks_exist = true
|
|
|
|
|
|
|
|
on_system_conditional(macos:, linux:)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Declare dependencies and requirements for a cask.
|
|
|
|
#
|
|
|
|
# NOTE: Multiple dependencies can be specified.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2022-10-08 01:08:15 +01:00
|
|
|
def depends_on(**kwargs)
|
2024-06-20 23:19:09 -04:00
|
|
|
@depends_on_set_in_block = true if @called_in_on_system_block
|
2022-10-08 01:08:15 +01:00
|
|
|
return @depends_on if kwargs.empty?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
begin
|
2022-10-08 01:08:15 +01:00
|
|
|
@depends_on.load(**kwargs)
|
2016-09-24 13:52:43 +02:00
|
|
|
rescue RuntimeError => e
|
2017-04-06 00:33:31 +02:00
|
|
|
raise CaskInvalidError.new(cask, e)
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
@depends_on
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2025-02-05 10:26:50 -05:00
|
|
|
# @api private
|
|
|
|
def add_implicit_macos_dependency
|
2025-04-22 17:53:19 -04:00
|
|
|
return if (cask_depends_on = @depends_on).present? && cask_depends_on.macos.present?
|
2025-02-05 10:26:50 -05:00
|
|
|
|
|
|
|
depends_on macos: ">= :#{MacOSVersion::SYMBOLS.key MacOSVersion::SYMBOLS.values.min}"
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Declare conflicts that keep a cask from installing or working correctly.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2022-10-08 01:08:15 +01:00
|
|
|
def conflicts_with(**kwargs)
|
2024-04-26 20:55:51 +02:00
|
|
|
# TODO: Remove this constraint and instead merge multiple `conflicts_with` stanzas
|
2022-10-08 01:08:15 +01:00
|
|
|
set_unique_stanza(:conflicts_with, kwargs.empty?) { DSL::ConflictsWith.new(**kwargs) }
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2025-03-03 17:55:10 +01:00
|
|
|
sig { returns(Pathname) }
|
2016-09-24 13:52:43 +02:00
|
|
|
def caskroom_path
|
2020-07-21 21:28:58 +02:00
|
|
|
cask.caskroom_path
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# The staged location for this cask, including version number.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2025-03-03 17:55:10 +01:00
|
|
|
sig { returns(Pathname) }
|
2016-09-24 13:52:43 +02:00
|
|
|
def staged_path
|
|
|
|
return @staged_path if @staged_path
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
cask_version = version || :unknown
|
|
|
|
@staged_path = caskroom_path.join(cask_version.to_s)
|
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Provide the user with cask-specific information at install time.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2017-11-24 17:44:01 +01:00
|
|
|
def caveats(*strings, &block)
|
2020-11-16 22:18:56 +01:00
|
|
|
if block
|
2017-11-24 17:44:01 +01:00
|
|
|
@caveats.eval_caveats(&block)
|
|
|
|
elsif strings.any?
|
|
|
|
strings.each do |string|
|
|
|
|
@caveats.eval_caveats { string }
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return @caveats.to_s
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
|
|
|
@caveats
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Asserts that the cask artifacts auto-update.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2016-09-24 13:52:43 +02:00
|
|
|
def auto_updates(auto_updates = nil)
|
2017-07-30 16:26:44 +02:00
|
|
|
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Automatically fetch the latest version of a cask from changelogs.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2020-09-02 12:24:21 -07:00
|
|
|
def livecheck(&block)
|
2020-12-11 16:24:49 +01:00
|
|
|
return @livecheck unless block
|
2020-09-02 12:24:21 -07:00
|
|
|
|
livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
2024-11-27 18:20:56 -05:00
|
|
|
if !@cask.allow_reassignment && @livecheck_defined
|
2022-06-12 15:27:31 -04:00
|
|
|
raise CaskInvalidError.new(cask, "'livecheck' stanza may only appear once.")
|
|
|
|
end
|
2020-09-02 12:24:21 -07:00
|
|
|
|
livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
2024-11-27 18:20:56 -05:00
|
|
|
@livecheck_defined = true
|
2020-09-02 12:24:21 -07:00
|
|
|
@livecheck.instance_eval(&block)
|
|
|
|
end
|
|
|
|
|
livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
2024-11-27 18:20:56 -05:00
|
|
|
# Whether the cask contains a `livecheck` block. This is a legacy alias
|
|
|
|
# for `#livecheck_defined?`.
|
|
|
|
sig { returns(T::Boolean) }
|
|
|
|
def livecheckable?
|
2025-04-22 17:15:23 +01:00
|
|
|
odeprecated "`livecheckable?`", "`livecheck_defined?`"
|
livecheck: clarify livecheckable language
Formulae, casks, and resources have a `#livecheckable?` method that
indicates whether they contain a `livecheck` block. This is intended
to be read as "has a livecheckable?", not "is livecheckable?" (as
livecheck can find versions for some packages/resources without a
`livecheck` block). Unfortunately, correct understanding of this
method's behavior [outside of documentation] relies on historical
knowledge that few people possess, so this is often confusing to
anyone who hasn't been working on livecheck since 2020.
In the olden days, a "livecheckable" was a Ruby file containing a
`livecheck` block (originally a hash) with a filename that
corresponded to a related formula. The `livecheck` blocks in
livecheckable files were integrated into their respective formulae in
August 2020, so [first-party] livecheckables ceased to exist at that
time. From that point forward, we simply referred to these as
`livecheck` blocks.
With that in mind, this clarifies the situation by replacing
"livecheckable" language. This includes renaming `#livecheckable?` to
`#livecheck_defined?`, replacing usage of "livecheckable" as a noun
with "`livecheck` block", replacing "livecheckable" as a boolean with
"livecheck_defined", and replacing incorrect usage of "livecheckable"
as an adjective with "checkable".
2024-11-27 18:20:56 -05:00
|
|
|
@livecheck_defined == true
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Declare that a cask is no longer functional or supported.
|
|
|
|
#
|
|
|
|
# NOTE: A warning will be shown when trying to install this cask.
|
|
|
|
#
|
2023-12-03 21:59:03 -05:00
|
|
|
# @api public
|
2025-04-02 13:19:49 +02:00
|
|
|
def deprecate!(date:, because:, replacement: nil, replacement_formula: nil, replacement_cask: nil)
|
2025-04-14 13:46:05 +02:00
|
|
|
if [replacement, replacement_formula, replacement_cask].filter_map(&:presence).length > 1
|
|
|
|
raise ArgumentError, "more than one of replacement, replacement_formula and/or replacement_cask specified!"
|
2025-04-02 13:19:49 +02:00
|
|
|
end
|
|
|
|
|
2025-04-22 17:15:23 +01:00
|
|
|
if replacement
|
|
|
|
odeprecated(
|
|
|
|
"deprecate!(:replacement)",
|
|
|
|
"deprecate!(:replacement_formula) or deprecate!(:replacement_cask)",
|
|
|
|
)
|
|
|
|
end
|
2025-03-24 16:23:57 +01:00
|
|
|
|
2023-12-03 21:59:03 -05:00
|
|
|
@deprecation_date = Date.parse(date)
|
|
|
|
return if @deprecation_date > Date.today
|
|
|
|
|
|
|
|
@deprecation_reason = because
|
2025-04-14 13:46:05 +02:00
|
|
|
@deprecation_replacement_formula = replacement_formula.presence || replacement
|
|
|
|
@deprecation_replacement_cask = replacement_cask.presence || replacement
|
2023-12-03 21:59:03 -05:00
|
|
|
@deprecated = true
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# Declare that a cask is no longer functional or supported.
|
|
|
|
#
|
|
|
|
# NOTE: An error will be thrown when trying to install this cask.
|
|
|
|
#
|
2023-12-03 21:59:03 -05:00
|
|
|
# @api public
|
2025-04-02 13:19:49 +02:00
|
|
|
def disable!(date:, because:, replacement: nil, replacement_formula: nil, replacement_cask: nil)
|
2025-04-14 13:46:05 +02:00
|
|
|
if [replacement, replacement_formula, replacement_cask].filter_map(&:presence).length > 1
|
|
|
|
raise ArgumentError, "more than one of replacement, replacement_formula and/or replacement_cask specified!"
|
2025-04-02 13:19:49 +02:00
|
|
|
end
|
|
|
|
|
2025-04-22 17:15:23 +01:00
|
|
|
if replacement
|
|
|
|
odeprecated(
|
|
|
|
"disable!(:replacement)",
|
|
|
|
"disable!(:replacement_formula) or disable!(:replacement_cask)",
|
|
|
|
)
|
|
|
|
end
|
2025-03-24 16:23:57 +01:00
|
|
|
|
2023-12-03 21:59:03 -05:00
|
|
|
@disable_date = Date.parse(date)
|
|
|
|
|
|
|
|
if @disable_date > Date.today
|
|
|
|
@deprecation_reason = because
|
2025-04-14 13:46:05 +02:00
|
|
|
@deprecation_replacement_formula = replacement_formula.presence || replacement
|
|
|
|
@deprecation_replacement_cask = replacement_cask.presence || replacement
|
2023-12-03 21:59:03 -05:00
|
|
|
@deprecated = true
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
@disable_reason = because
|
2025-04-14 13:46:05 +02:00
|
|
|
@disable_replacement_formula = replacement_formula.presence || replacement
|
|
|
|
@disable_replacement_cask = replacement_cask.presence || replacement
|
2023-12-03 21:59:03 -05:00
|
|
|
@disabled = true
|
2020-09-02 12:24:21 -07:00
|
|
|
end
|
|
|
|
|
2017-04-06 00:33:31 +02:00
|
|
|
ORDINARY_ARTIFACT_CLASSES.each do |klass|
|
2022-10-08 01:08:15 +01:00
|
|
|
define_method(klass.dsl_key) do |*args, **kwargs|
|
2023-03-19 19:37:28 -07:00
|
|
|
T.bind(self, DSL)
|
2019-10-13 10:03:26 +01:00
|
|
|
if [*artifacts.map(&:class), klass].include?(Artifact::StageOnly) &&
|
2024-01-18 14:11:43 +00:00
|
|
|
artifacts.map(&:class).intersect?(ACTIVATABLE_ARTIFACT_CLASSES)
|
2019-10-13 10:03:26 +01:00
|
|
|
raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.")
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2019-10-13 10:03:26 +01:00
|
|
|
|
2022-10-08 01:08:15 +01:00
|
|
|
artifacts.add(klass.from_args(cask, *args, **kwargs))
|
2019-10-13 10:03:26 +01:00
|
|
|
rescue CaskInvalidError
|
|
|
|
raise
|
|
|
|
rescue => e
|
|
|
|
raise CaskInvalidError.new(cask, "invalid '#{klass.dsl_key}' stanza: #{e}")
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-06 00:33:31 +02:00
|
|
|
ARTIFACT_BLOCK_CLASSES.each do |klass|
|
|
|
|
[klass.dsl_key, klass.uninstall_dsl_key].each do |dsl_key|
|
|
|
|
define_method(dsl_key) do |&block|
|
2023-03-19 19:37:28 -07:00
|
|
|
T.bind(self, DSL)
|
2017-10-04 17:08:35 +02:00
|
|
|
artifacts.add(klass.new(cask, dsl_key => block))
|
2017-04-06 00:33:31 +02:00
|
|
|
end
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
|
2016-09-24 13:52:43 +02:00
|
|
|
def method_missing(method, *)
|
|
|
|
if method
|
|
|
|
Utils.method_missing_message(method, token)
|
|
|
|
nil
|
|
|
|
else
|
|
|
|
super
|
|
|
|
end
|
2016-09-20 15:11:33 +02:00
|
|
|
end
|
|
|
|
|
2021-03-31 06:14:41 +02:00
|
|
|
def respond_to_missing?(*)
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2025-03-03 17:55:10 +01:00
|
|
|
sig { returns(T.nilable(MacOSVersion)) }
|
|
|
|
def os_version
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
2024-04-26 20:55:51 +02:00
|
|
|
# The directory `app`s are installed into.
|
|
|
|
#
|
2021-03-31 06:14:41 +02:00
|
|
|
# @api public
|
2025-03-03 17:55:10 +01:00
|
|
|
sig { returns(T.any(Pathname, String)) }
|
2016-09-24 13:52:43 +02:00
|
|
|
def appdir
|
2023-03-22 19:43:49 -07:00
|
|
|
return HOMEBREW_CASK_APPDIR_PLACEHOLDER if Cask.generating_hash?
|
2023-02-14 14:19:40 +00:00
|
|
|
|
2017-12-03 21:21:31 +01:00
|
|
|
cask.config.appdir
|
2016-09-24 13:52:43 +02:00
|
|
|
end
|
2016-08-18 22:11:42 +03:00
|
|
|
end
|
|
|
|
end
|