mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
284 lines
8.5 KiB
Ruby
284 lines
8.5 KiB
Ruby
![]() |
require "set"
|
||
|
|
||
|
class Hbc::DSL; end
|
||
|
|
||
|
require "hbc/dsl/appcast"
|
||
|
require "hbc/dsl/base"
|
||
|
require "hbc/dsl/caveats"
|
||
|
require "hbc/dsl/conflicts_with"
|
||
|
require "hbc/dsl/container"
|
||
|
require "hbc/dsl/depends_on"
|
||
|
require "hbc/dsl/gpg"
|
||
|
require "hbc/dsl/installer"
|
||
|
require "hbc/dsl/license"
|
||
|
require "hbc/dsl/postflight"
|
||
|
require "hbc/dsl/preflight"
|
||
|
require "hbc/dsl/stanza_proxy"
|
||
|
require "hbc/dsl/uninstall_postflight"
|
||
|
require "hbc/dsl/uninstall_preflight"
|
||
|
require "hbc/dsl/version"
|
||
|
|
||
|
class Hbc::DSL
|
||
|
ORDINARY_ARTIFACT_TYPES = [
|
||
|
:app,
|
||
|
:artifact,
|
||
|
:audio_unit_plugin,
|
||
|
:binary,
|
||
|
:colorpicker,
|
||
|
:font,
|
||
|
:input_method,
|
||
|
:internet_plugin,
|
||
|
:pkg,
|
||
|
:prefpane,
|
||
|
:qlplugin,
|
||
|
:screen_saver,
|
||
|
:service,
|
||
|
:stage_only,
|
||
|
:suite,
|
||
|
:vst_plugin,
|
||
|
:vst3_plugin,
|
||
|
].freeze
|
||
|
|
||
|
ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze
|
||
|
|
||
|
SPECIAL_ARTIFACT_TYPES = [
|
||
|
:uninstall,
|
||
|
:zap,
|
||
|
].freeze
|
||
|
|
||
|
ARTIFACT_BLOCK_TYPES = [
|
||
|
:preflight,
|
||
|
:postflight,
|
||
|
:uninstall_preflight,
|
||
|
:uninstall_postflight,
|
||
|
].freeze
|
||
|
|
||
|
DSL_METHODS = Set.new [
|
||
|
:accessibility_access,
|
||
|
:appcast,
|
||
|
:artifacts,
|
||
|
:auto_updates,
|
||
|
:caskroom_path,
|
||
|
:caveats,
|
||
|
:conflicts_with,
|
||
|
:container,
|
||
|
:depends_on,
|
||
|
:gpg,
|
||
|
:homepage,
|
||
|
:license,
|
||
|
:name,
|
||
|
:sha256,
|
||
|
:staged_path,
|
||
|
:url,
|
||
|
:version,
|
||
|
:appdir,
|
||
|
*ORDINARY_ARTIFACT_TYPES,
|
||
|
*ACTIVATABLE_ARTIFACT_TYPES,
|
||
|
*SPECIAL_ARTIFACT_TYPES,
|
||
|
*ARTIFACT_BLOCK_TYPES,
|
||
|
].freeze
|
||
|
|
||
|
attr_reader :token
|
||
|
def initialize(token)
|
||
|
@token = token
|
||
|
end
|
||
|
|
||
|
def name(*args)
|
||
|
@name ||= []
|
||
|
return @name if args.empty?
|
||
|
@name.concat(args.flatten)
|
||
|
end
|
||
|
|
||
|
def assert_only_one_stanza_allowed(stanza, arg_given)
|
||
|
return unless instance_variable_defined?("@#{stanza}") && arg_given
|
||
|
raise Hbc::CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once")
|
||
|
end
|
||
|
|
||
|
def homepage(homepage = nil)
|
||
|
assert_only_one_stanza_allowed :homepage, !homepage.nil?
|
||
|
@homepage ||= homepage
|
||
|
end
|
||
|
|
||
|
def url(*args, &block)
|
||
|
url_given = !args.empty? || block_given?
|
||
|
return @url unless url_given
|
||
|
assert_only_one_stanza_allowed :url, url_given
|
||
|
@url ||= begin
|
||
|
Hbc::URL.from(*args, &block)
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, "'url' stanza failed with: #{e}")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def appcast(*args)
|
||
|
return @appcast if args.empty?
|
||
|
assert_only_one_stanza_allowed :appcast, !args.empty?
|
||
|
@appcast ||= begin
|
||
|
Hbc::DSL::Appcast.new(*args) unless args.empty?
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def gpg(*args)
|
||
|
return @gpg if args.empty?
|
||
|
assert_only_one_stanza_allowed :gpg, !args.empty?
|
||
|
@gpg ||= begin
|
||
|
Hbc::DSL::Gpg.new(*args) unless args.empty?
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def container(*args)
|
||
|
return @container if args.empty?
|
||
|
# TODO: remove this constraint, and instead merge multiple container stanzas
|
||
|
assert_only_one_stanza_allowed :container, !args.empty?
|
||
|
@container ||= begin
|
||
|
Hbc::DSL::Container.new(*args) unless args.empty?
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
# TODO: remove this backward-compatibility section after removing nested_container
|
||
|
if @container && @container.nested
|
||
|
artifacts[:nested_container] << @container.nested
|
||
|
end
|
||
|
@container
|
||
|
end
|
||
|
|
||
|
SYMBOLIC_VERSIONS = Set.new [
|
||
|
:latest,
|
||
|
]
|
||
|
|
||
|
def version(arg = nil)
|
||
|
return @version if arg.nil?
|
||
|
assert_only_one_stanza_allowed :version, !arg.nil?
|
||
|
raise Hbc::CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg)
|
||
|
@version ||= Hbc::DSL::Version.new(arg)
|
||
|
end
|
||
|
|
||
|
SYMBOLIC_SHA256S = Set.new [
|
||
|
:no_check,
|
||
|
]
|
||
|
|
||
|
def sha256(arg = nil)
|
||
|
return @sha256 if arg.nil?
|
||
|
assert_only_one_stanza_allowed :sha256, !arg.nil?
|
||
|
raise Hbc::CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg)
|
||
|
@sha256 ||= arg
|
||
|
end
|
||
|
|
||
|
def license(arg = nil)
|
||
|
return @license if arg.nil?
|
||
|
assert_only_one_stanza_allowed :license, !arg.nil?
|
||
|
@license ||= begin
|
||
|
Hbc::DSL::License.new(arg) unless arg.nil?
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# depends_on uses a load method so that multiple stanzas can be merged
|
||
|
def depends_on(*args)
|
||
|
return @depends_on if args.empty?
|
||
|
@depends_on ||= Hbc::DSL::DependsOn.new
|
||
|
begin
|
||
|
@depends_on.load(*args) unless args.empty?
|
||
|
rescue RuntimeError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
@depends_on
|
||
|
end
|
||
|
|
||
|
def conflicts_with(*args)
|
||
|
return @conflicts_with if args.empty?
|
||
|
# TODO: remove this constraint, and instead merge multiple conflicts_with stanzas
|
||
|
assert_only_one_stanza_allowed :conflicts_with, !args.empty?
|
||
|
@conflicts_with ||= begin
|
||
|
Hbc::DSL::ConflictsWith.new(*args) unless args.empty?
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def artifacts
|
||
|
@artifacts ||= Hash.new { |hash, key| hash[key] = Set.new }
|
||
|
end
|
||
|
|
||
|
def caskroom_path
|
||
|
@caskroom_path ||= Hbc.caskroom.join(token)
|
||
|
end
|
||
|
|
||
|
def staged_path
|
||
|
return @staged_path if @staged_path
|
||
|
cask_version = version || :unknown
|
||
|
@staged_path = caskroom_path.join(cask_version.to_s)
|
||
|
end
|
||
|
|
||
|
def caveats(*string, &block)
|
||
|
@caveats ||= []
|
||
|
if block_given?
|
||
|
@caveats << Hbc::Caveats.new(block)
|
||
|
elsif string.any?
|
||
|
@caveats << string.map { |s| s.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") }
|
||
|
end
|
||
|
@caveats
|
||
|
end
|
||
|
|
||
|
def accessibility_access(accessibility_access = nil)
|
||
|
assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil?
|
||
|
@accessibility_access ||= accessibility_access
|
||
|
end
|
||
|
|
||
|
def auto_updates(auto_updates = nil)
|
||
|
assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil?
|
||
|
@auto_updates ||= auto_updates
|
||
|
end
|
||
|
|
||
|
ORDINARY_ARTIFACT_TYPES.each do |type|
|
||
|
define_method(type) do |*args|
|
||
|
if type == :stage_only && args != [true]
|
||
|
raise Hbc::CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
|
||
|
end
|
||
|
artifacts[type] << args
|
||
|
if artifacts.key?(:stage_only) && artifacts.keys.count > 1 &&
|
||
|
!(artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty?
|
||
|
raise Hbc::CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def installer(*args)
|
||
|
return artifacts[:installer] if args.empty?
|
||
|
artifacts[:installer] << Hbc::DSL::Installer.new(*args)
|
||
|
raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only)
|
||
|
rescue StandardError => e
|
||
|
raise Hbc::CaskInvalidError.new(token, e)
|
||
|
end
|
||
|
|
||
|
SPECIAL_ARTIFACT_TYPES.each do |type|
|
||
|
define_method(type) do |*args|
|
||
|
artifacts[type].merge(args)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
ARTIFACT_BLOCK_TYPES.each do |type|
|
||
|
define_method(type) do |&block|
|
||
|
artifacts[type] << block
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def method_missing(method, *)
|
||
|
Hbc::Utils.method_missing_message(method, token)
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
def appdir
|
||
|
self.class.appdir
|
||
|
end
|
||
|
|
||
|
def self.appdir
|
||
|
Hbc.appdir.sub(%r{\/$}, "")
|
||
|
end
|
||
|
end
|