297 lines
7.7 KiB
Ruby
Raw Normal View History

require "locale"
2018-07-30 21:07:36 +02:00
require "lazy_object"
2016-08-18 22:11:42 +03:00
require "cask/artifact"
require "cask/caskroom"
require "cask/exceptions"
require "cask/dsl/appcast"
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
require "cask/url"
2018-09-06 08:29:14 +02:00
module Cask
2016-09-24 13:52:43 +02:00
class DSL
ORDINARY_ARTIFACT_CLASSES = [
Artifact::Installer,
Artifact::App,
Artifact::Artifact,
Artifact::AudioUnitPlugin,
Artifact::Binary,
Artifact::Colorpicker,
Artifact::Dictionary,
Artifact::Font,
Artifact::InputMethod,
Artifact::InternetPlugin,
Artifact::Pkg,
Artifact::Prefpane,
Artifact::Qlplugin,
Artifact::ScreenSaver,
Artifact::Service,
Artifact::StageOnly,
Artifact::Suite,
Artifact::VstPlugin,
Artifact::Vst3Plugin,
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
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([
:appcast,
:artifacts,
:auto_updates,
:caveats,
:conflicts_with,
:container,
:depends_on,
:homepage,
:language,
:languages,
:name,
:sha256,
:staged_path,
:url,
:version,
:appdir,
*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
2017-10-04 15:47:53 +02:00
attr_reader :cask, :token
def initialize(cask)
@cask = cask
@token = cask.token
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 name(*args)
@name ||= []
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
def set_unique_stanza(stanza, should_return)
return instance_variable_get("@#{stanza}") if should_return
if instance_variable_defined?("@#{stanza}")
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
end
instance_variable_set("@#{stanza}", yield)
rescue CaskInvalidError
raise
rescue => e
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
2016-09-24 13:52:43 +02:00
def homepage(homepage = nil)
set_unique_stanza(:homepage, homepage.nil?) { homepage }
2016-08-18 22:11:42 +03:00
end
def language(*args, default: false, &block)
if args.empty?
language_eval
elsif block_given?
@language_blocks ||= {}
@language_blocks[args] = block
return unless default
unless @language_blocks.default.nil?
raise CaskInvalidError.new(cask, "Only one default language may be defined.")
end
@language_blocks.default = block
2016-09-14 23:11:21 +02:00
else
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
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?
raise CaskInvalidError.new(cask, "No default language specified.") if @language_blocks.default.nil?
2018-08-19 22:10:20 +02:00
locales = MacOS.languages
.map do |language|
begin
Locale.parse(language)
rescue Locale::ParserError
nil
end
end
.compact
locales.each do |locale|
key = locale.detect(@language_blocks.keys)
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
def languages
return [] if @language_blocks.nil?
@language_blocks.keys.flatten
end
2018-07-30 21:07:36 +02:00
def url(*args)
set_unique_stanza(:url, args.empty? && !block_given?) do
2018-07-30 21:07:36 +02:00
if block_given?
LazyObject.new { URL.new(*yield) }
else
URL.new(*args)
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 appcast(*args)
set_unique_stanza(:appcast, args.empty?) { DSL::Appcast.new(*args) }
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def container(*args)
set_unique_stanza(:container, args.empty?) do
DSL::Container.new(*args)
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 version(arg = nil)
set_unique_stanza(:version, arg.nil?) do
if !arg.is_a?(String) && arg != :latest
raise CaskInvalidError.new(cask, "invalid 'version' value: '#{arg.inspect}'")
end
2018-09-17 02:45:00 +02:00
DSL::Version.new(arg)
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 sha256(arg = nil)
set_unique_stanza(:sha256, arg.nil?) do
if !arg.is_a?(String) && arg != :no_check
raise CaskInvalidError.new(cask, "invalid 'sha256' value: '#{arg.inspect}'")
end
2018-09-17 02:45:00 +02:00
arg
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
# depends_on uses a load method so that multiple stanzas can be merged
def depends_on(*args)
@depends_on ||= DSL::DependsOn.new
2017-06-28 17:53:59 +02:00
return @depends_on if args.empty?
2018-09-17 02:45:00 +02:00
2016-09-24 13:52:43 +02:00
begin
2017-06-28 17:53:59 +02:00
@depends_on.load(*args)
2016-09-24 13:52:43 +02:00
rescue RuntimeError => e
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
2016-09-24 13:52:43 +02:00
def conflicts_with(*args)
# TODO: remove this constraint, and instead merge multiple conflicts_with stanzas
set_unique_stanza(:conflicts_with, args.empty?) { DSL::ConflictsWith.new(*args) }
2016-08-18 22:11:42 +03:00
end
2016-09-24 13:52:43 +02:00
def artifacts
2017-10-04 17:08:35 +02:00
@artifacts ||= SortedSet.new
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 caskroom_path
@cask.caskroom_path
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 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
def caveats(*strings, &block)
@caveats ||= DSL::Caveats.new(cask)
2016-09-24 13:52:43 +02:00
if block_given?
@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
2016-09-24 13:52:43 +02:00
def auto_updates(auto_updates = nil)
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
ORDINARY_ARTIFACT_CLASSES.each do |klass|
2017-10-04 15:47:53 +02:00
define_method(klass.dsl_key) do |*args|
begin
if [*artifacts.map(&:class), klass].include?(Artifact::StageOnly) &&
(artifacts.map(&:class) & ACTIVATABLE_ARTIFACT_CLASSES).any?
raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.")
2017-02-05 22:40:14 +01:00
end
2017-10-04 17:08:35 +02:00
artifacts.add(klass.from_args(cask, *args))
rescue CaskInvalidError
raise
rescue => e
raise CaskInvalidError.new(cask, "invalid '#{klass.dsl_key}' stanza: #{e}")
2016-09-24 13:52:43 +02:00
end
2016-08-18 22:11:42 +03:00
end
end
ARTIFACT_BLOCK_CLASSES.each do |klass|
[klass.dsl_key, klass.uninstall_dsl_key].each do |dsl_key|
define_method(dsl_key) do |&block|
2017-10-04 17:08:35 +02:00
artifacts.add(klass.new(cask, dsl_key => block))
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
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
cask.config.appdir
2016-09-24 13:52:43 +02:00
end
2016-08-18 22:11:42 +03:00
end
end