327 lines
8.4 KiB
Ruby
Raw Normal View History

2016-08-18 22:11:42 +03:00
require "set"
require "locale"
2016-08-18 22:11:42 +03:00
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/postflight"
require "hbc/dsl/preflight"
require "hbc/dsl/stanza_proxy"
require "hbc/dsl/uninstall_postflight"
require "hbc/dsl/uninstall_preflight"
require "hbc/dsl/version"
2016-09-24 13:52:43 +02:00
module Hbc
class DSL
ORDINARY_ARTIFACT_TYPES = [
2016-10-14 20:33:16 +02:00
:app,
:artifact,
:audio_unit_plugin,
:binary,
:colorpicker,
2016-10-23 17:32:19 +02:00
:dictionary,
2016-10-14 20:33:16 +02:00
:font,
:input_method,
:internet_plugin,
:pkg,
:prefpane,
:qlplugin,
:screen_saver,
:service,
:stage_only,
:suite,
:vst_plugin,
:vst3_plugin,
].freeze
2016-09-24 13:52:43 +02:00
ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze
SPECIAL_ARTIFACT_TYPES = [
2016-10-14 20:33:16 +02:00
:uninstall,
:zap,
].freeze
2016-09-24 13:52:43 +02:00
ARTIFACT_BLOCK_TYPES = [
2016-10-14 20:33:16 +02:00
:preflight,
:postflight,
:uninstall_preflight,
:uninstall_postflight,
].freeze
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
DSL_METHODS = Set.new [
2016-10-14 20:33:16 +02:00
:accessibility_access,
:appcast,
:artifacts,
:auto_updates,
:caskroom_path,
:caveats,
:conflicts_with,
:container,
:depends_on,
:gpg,
:homepage,
:language,
:name,
:sha256,
:staged_path,
:url,
:version,
:appdir,
*ORDINARY_ARTIFACT_TYPES,
*ACTIVATABLE_ARTIFACT_TYPES,
*SPECIAL_ARTIFACT_TYPES,
*ARTIFACT_BLOCK_TYPES,
].freeze
2016-09-24 13:52:43 +02:00
attr_reader :token
def initialize(token)
@token = token
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def name(*args)
@name ||= []
return @name if args.empty?
@name.concat(args.flatten)
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def assert_only_one_stanza_allowed(stanza, arg_given)
return unless instance_variable_defined?("@#{stanza}") && arg_given
raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once")
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def homepage(homepage = nil)
assert_only_one_stanza_allowed :homepage, !homepage.nil?
@homepage ||= homepage
2016-08-18 22:11:42 +03:00
end
def language(*args, default: false, &block)
2016-09-14 23:11:21 +02:00
if !args.empty? && block_given?
@language_blocks ||= {}
@language_blocks[args] = block
return unless default
unless @language_blocks.default.nil?
raise CaskInvalidError.new(token, "Only one default language may be defined")
end
@language_blocks.default = block
2016-09-14 23:11:21 +02:00
else
2016-09-18 04:15:28 +02:00
language_eval
2016-09-14 23:11:21 +02:00
end
end
2016-09-18 04:15:28 +02:00
def language_eval
2016-10-03 02:34:32 +02:00
return @language if instance_variable_defined?(:@language)
2017-05-29 18:24:52 +01:00
return @language = nil if @language_blocks.nil? || @language_blocks.empty?
2016-10-03 02:34:32 +02:00
MacOS.languages.map(&Locale.method(:parse)).each do |locale|
2016-10-23 14:44:14 +02:00
key = @language_blocks.keys.detect do |strings|
strings.any? { |string| locale.include?(string) }
2016-10-23 14:44:14 +02:00
end
2016-10-03 02:34:32 +02:00
next if key.nil?
return @language = @language_blocks[key].call
end
@language = @language_blocks.default.call
2016-09-18 04:15:28 +02:00
end
2016-09-24 13:52:43 +02:00
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
URL.from(*args, &block)
rescue StandardError => e
raise CaskInvalidError.new(token, "'url' stanza failed with: #{e}")
end
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def appcast(*args)
return @appcast if args.empty?
assert_only_one_stanza_allowed :appcast, !args.empty?
@appcast ||= begin
DSL::Appcast.new(*args) unless args.empty?
rescue StandardError => e
raise CaskInvalidError.new(token, e)
end
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def gpg(*args)
return @gpg if args.empty?
assert_only_one_stanza_allowed :gpg, !args.empty?
@gpg ||= begin
DSL::Gpg.new(*args) unless args.empty?
rescue StandardError => e
raise CaskInvalidError.new(token, e)
end
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
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
DSL::Container.new(*args) unless args.empty?
rescue StandardError => e
raise 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
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
SYMBOLIC_VERSIONS = Set.new [
2016-10-14 20:33:16 +02:00
:latest,
]
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def version(arg = nil)
return @version if arg.nil?
assert_only_one_stanza_allowed :version, !arg.nil?
raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg)
@version ||= DSL::Version.new(arg)
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
SYMBOLIC_SHA256S = Set.new [
2016-10-14 20:33:16 +02:00
:no_check,
]
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def sha256(arg = nil)
return @sha256 if arg.nil?
assert_only_one_stanza_allowed :sha256, !arg.nil?
raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg)
@sha256 ||= arg
end
2016-08-18 22:11:42 +03:00
2016-10-07 22:49:01 +08:00
def license(*)
# TODO: Uncomment after `license` has been
# removed from all official taps.
# odeprecated "Hbc::DSL#license"
end
2016-09-24 13:52:43 +02:00
# 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 ||= DSL::DependsOn.new
begin
@depends_on.load(*args) unless args.empty?
rescue RuntimeError => e
raise CaskInvalidError.new(token, e)
end
@depends_on
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
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
DSL::ConflictsWith.new(*args) unless args.empty?
rescue StandardError => e
raise CaskInvalidError.new(token, e)
end
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def artifacts
@artifacts ||= Hash.new { |hash, key| hash[key] = Set.new }
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def caskroom_path
@caskroom_path ||= Hbc.caskroom.join(token)
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def staged_path
return @staged_path if @staged_path
cask_version = version || :unknown
@staged_path = caskroom_path.join(cask_version.to_s)
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
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\n \t]*\Z/, "\n\n") }
2016-09-24 13:52:43 +02:00
end
@caveats
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def accessibility_access(accessibility_access = nil)
assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil?
@accessibility_access ||= accessibility_access
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def auto_updates(auto_updates = nil)
assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil?
@auto_updates ||= auto_updates
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
ORDINARY_ARTIFACT_TYPES.each do |type|
define_method(type) do |*args|
2017-02-05 22:40:14 +01:00
if type == :stage_only
if args != [true]
raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
end
unless (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty?
raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact")
end
2016-09-24 13:52:43 +02:00
end
2017-02-05 22:40:14 +01:00
artifacts[type].add(args)
2016-08-18 22:11:42 +03:00
end
end
2016-09-24 13:52:43 +02:00
def installer(*args)
return artifacts[:installer] if args.empty?
artifacts[:installer] << DSL::Installer.new(*args)
raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only)
rescue StandardError => e
raise CaskInvalidError.new(token, e)
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
SPECIAL_ARTIFACT_TYPES.each do |type|
define_method(type) do |*args|
artifacts[type].merge(args)
end
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
ARTIFACT_BLOCK_TYPES.each do |type|
define_method(type) do |&block|
artifacts[type] << block
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
2016-09-24 13:52:43 +02:00
def respond_to_missing?(*)
true
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def appdir
self.class.appdir
end
2016-08-18 22:11:42 +03:00
2016-09-24 13:52:43 +02:00
def self.appdir
Hbc.appdir.sub(%r{\/$}, "")
end
2016-08-18 22:11:42 +03:00
end
end