blob: 16ce86d79cc2b8b83c378afd1ead681cd01bc9f2 [file] [log] [blame]
require 'active_support/hash_with_indifferent_access'
module Pod
class Installer
# Represents the installation options the user can customize via a
# `Podfile`.
#
class InstallationOptions
# Parses installation options from a podfile.
#
# @param [Podfile] podfile the podfile to parse installation options
# from.
#
# @raise [Informative] if `podfile` does not specify a `CocoaPods`
# install.
#
# @return [Self]
#
def self.from_podfile(podfile)
name, options = podfile.installation_method
unless name.downcase == 'cocoapods'
raise Informative, "Currently need to specify a `cocoapods` install, you chose `#{name}`."
end
new(options)
end
# Defines a new installation option.
#
# @param [#to_s] name the name of the option.
#
# @param default the default value for the option.
#
# @param [Boolean] boolean whether the option has a boolean value.
#
# @return [void]
#
# @!macro [attach] option
#
# @note this option defaults to $2.
#
# @return the $1 $0 for installation.
#
def self.option(name, default, boolean: true)
name = name.to_s
raise ArgumentError, "The `#{name}` option is already defined" if defaults.key?(name)
defaults[name] = default
attr_accessor name
alias_method "#{name}?", name if boolean
end
# @return [Hash<Symbol,Object>] all known installation options and their
# default values.
#
def self.defaults
@defaults ||= {}
end
# @return [Array<Symbol>] the names of all known installation options.
#
def self.all_options
defaults.keys
end
# Initializes the installation options with a hash of options from a
# Podfile.
#
# @param [Hash] options the options to parse.
#
# @raise [Informative] if `options` contains any unknown keys.
#
def initialize(options = {})
options = ActiveSupport::HashWithIndifferentAccess.new(options)
unknown_keys = options.keys - self.class.all_options.map(&:to_s)
raise Informative, "Unknown installation options: #{unknown_keys.to_sentence}." unless unknown_keys.empty?
self.class.defaults.each do |key, default|
value = options.fetch(key, default)
send("#{key}=", value)
end
end
# @param [Boolean] include_defaults whether values that match the default
# for their option should be included. Defaults to `true`.
#
# @return [Hash] the options, keyed by option name.
#
def to_h(include_defaults: true)
self.class.defaults.reduce(ActiveSupport::HashWithIndifferentAccess.new) do |hash, (option, default)|
value = send(option)
hash[option] = value if include_defaults || value != default
hash
end
end
def ==(other)
other.is_a?(self.class) && to_h == other.to_h
end
alias_method :eql, :==
def hash
to_h.hash
end
option :clean, true
option :deduplicate_targets, true
option :deterministic_uuids, true
option :integrate_targets, true
option :lock_pod_sources, true
option :warn_for_multiple_pod_sources, true
option :share_schemes_for_development_pods, false
module Mixin
module ClassMethods
# Delegates the creation of {#installation_options} to the `Podfile`
# returned by the given block.
#
# @param blk a block that returns the `Podfile` to create
# installation options from.
#
# @return [Void]
#
def delegate_installation_options(&blk)
define_method(:installation_options) do
@installation_options ||= InstallationOptions.from_podfile(instance_eval(&blk))
end
end
# Delegates the installation options attributes directly to
# {#installation_options}.
#
# @return [Void]
#
def delegate_installation_option_attributes!
define_method(:respond_to_missing?) do |name, *args|
installation_options.respond_to?(name, *args) || super
end
define_method(:method_missing) do |name, *args, &blk|
if installation_options.respond_to?(name)
installation_options.send(name, *args, &blk)
else
super
end
end
end
end
# @return [InstallationOptions] The installation options.
#
attr_accessor :installation_options
def self.included(mod)
mod.extend(ClassMethods)
end
end
end
end
end