cocoapods-dykit 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pod/command.rb +2 -0
- data/lib/pod/command/dyinstall.rb +51 -0
- data/lib/pod/command/dyupdate.rb +106 -0
- data/lib/pod/command/fmwk.rb +4 -0
- data/lib/pod/command/lib/dylint.rb +1 -0
- data/lib/pod/gem_version.rb +1 -1
- data/lib/pod/installer.rb +715 -0
- data/lib/pod/installer/analyzer.rb +934 -0
- data/lib/pod/installer/analyzer/analysis_result.rb +57 -0
- data/lib/pod/installer/analyzer/locking_dependency_analyzer.rb +95 -0
- data/lib/pod/installer/analyzer/pod_variant.rb +68 -0
- data/lib/pod/installer/analyzer/pod_variant_set.rb +157 -0
- data/lib/pod/installer/analyzer/podfile_dependency_cache.rb +54 -0
- data/lib/pod/installer/analyzer/sandbox_analyzer.rb +251 -0
- data/lib/pod/installer/analyzer/specs_state.rb +84 -0
- data/lib/pod/installer/analyzer/target_inspection_result.rb +45 -0
- data/lib/pod/installer/analyzer/target_inspector.rb +254 -0
- data/lib/pod/installer/installation_options.rb +158 -0
- data/lib/pod/installer/pod_source_installer.rb +214 -0
- data/lib/pod/installer/pod_source_preparer.rb +77 -0
- data/lib/pod/installer/podfile_validator.rb +139 -0
- data/lib/pod/installer/post_install_hooks_context.rb +107 -0
- data/lib/pod/installer/pre_install_hooks_context.rb +42 -0
- data/lib/pod/installer/source_provider_hooks_context.rb +32 -0
- data/lib/pod/installer/user_project_integrator.rb +253 -0
- data/lib/pod/installer/user_project_integrator/target_integrator.rb +462 -0
- data/lib/pod/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
- data/lib/pod/installer/xcode.rb +8 -0
- data/lib/pod/installer/xcode/pods_project_generator.rb +353 -0
- data/lib/pod/installer/xcode/pods_project_generator/aggregate_target_installer.rb +172 -0
- data/lib/pod/installer/xcode/pods_project_generator/file_references_installer.rb +367 -0
- data/lib/pod/installer/xcode/pods_project_generator/pod_target_installer.rb +718 -0
- data/lib/pod/installer/xcode/pods_project_generator/pod_target_integrator.rb +111 -0
- data/lib/pod/installer/xcode/pods_project_generator/target_installer.rb +265 -0
- data/lib/pod/installer/xcode/target_validator.rb +141 -0
- data/lib/pod/resolver.rb +632 -0
- metadata +34 -2
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class DyInstaller
|
5
|
+
class Analyzer
|
6
|
+
# This class represents the state of a collection of Pods.
|
7
|
+
#
|
8
|
+
# @note The names of the pods stored by this class are always the **root**
|
9
|
+
# name of the specification.
|
10
|
+
#
|
11
|
+
# @note The motivation for this class is to ensure that the names of the
|
12
|
+
# subspecs are added instead of the name of the Pods.
|
13
|
+
#
|
14
|
+
class SpecsState
|
15
|
+
# @return [Set<String>] the names of the pods that were added.
|
16
|
+
#
|
17
|
+
attr_reader :added
|
18
|
+
|
19
|
+
# @return [Set<String>] the names of the pods that were changed.
|
20
|
+
#
|
21
|
+
attr_reader :changed
|
22
|
+
|
23
|
+
# @return [Set<String>] the names of the pods that were deleted.
|
24
|
+
#
|
25
|
+
attr_reader :deleted
|
26
|
+
|
27
|
+
# @return [Set<String>] the names of the pods that were unchanged.
|
28
|
+
#
|
29
|
+
attr_reader :unchanged
|
30
|
+
|
31
|
+
# Initialize a new instance
|
32
|
+
#
|
33
|
+
# @param [Hash{Symbol=>String}] pods_by_state
|
34
|
+
# The name of the pods grouped by their state
|
35
|
+
# (`:added`, `:removed`, `:changed` or `:unchanged`).
|
36
|
+
#
|
37
|
+
def initialize(pods_by_state = nil)
|
38
|
+
@added = Set.new
|
39
|
+
@deleted = Set.new
|
40
|
+
@changed = Set.new
|
41
|
+
@unchanged = Set.new
|
42
|
+
|
43
|
+
if pods_by_state
|
44
|
+
{
|
45
|
+
:added => :added,
|
46
|
+
:changed => :changed,
|
47
|
+
:removed => :deleted,
|
48
|
+
:unchanged => :unchanged,
|
49
|
+
}.each do |state, spec_state|
|
50
|
+
Array(pods_by_state[state]).each do |name|
|
51
|
+
add_name(name, spec_state)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Displays the state of each pod.
|
58
|
+
#
|
59
|
+
# @return [void]
|
60
|
+
#
|
61
|
+
def print
|
62
|
+
added .sort.each { |pod| UI.message('A'.green + " #{pod}", '', 2) }
|
63
|
+
deleted .sort.each { |pod| UI.message('R'.red + " #{pod}", '', 2) }
|
64
|
+
changed .sort.each { |pod| UI.message('M'.yellow + " #{pod}", '', 2) }
|
65
|
+
unchanged.sort.each { |pod| UI.message('-' + " #{pod}", '', 2) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds the name of a Pod to the give state.
|
69
|
+
#
|
70
|
+
# @param [String] name
|
71
|
+
# the name of the Pod.
|
72
|
+
#
|
73
|
+
# @param [Symbol] state
|
74
|
+
# the state of the Pod.
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
#
|
78
|
+
def add_name(name, state)
|
79
|
+
send(state) << Specification.root_name(name)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Pod
|
2
|
+
class DyInstaller
|
3
|
+
class Analyzer
|
4
|
+
class TargetInspectionResult
|
5
|
+
# @return [TargetDefinition] the target definition, whose project was
|
6
|
+
# inspected
|
7
|
+
#
|
8
|
+
attr_accessor :target_definition
|
9
|
+
|
10
|
+
# @return [Pathname] the path of the user project that the
|
11
|
+
# #target_definition should integrate
|
12
|
+
#
|
13
|
+
attr_accessor :project_path
|
14
|
+
|
15
|
+
# @return [Array<String>] the uuid of the user's targets
|
16
|
+
#
|
17
|
+
attr_accessor :project_target_uuids
|
18
|
+
|
19
|
+
# @return [Hash{String=>Symbol}] A hash representing the user build
|
20
|
+
# configurations where each key corresponds to the name of a
|
21
|
+
# configuration and its value to its type (`:debug` or
|
22
|
+
# `:release`).
|
23
|
+
#
|
24
|
+
attr_accessor :build_configurations
|
25
|
+
|
26
|
+
# @return [Platform] the platform of the user targets
|
27
|
+
#
|
28
|
+
attr_accessor :platform
|
29
|
+
|
30
|
+
# @return [Array<String>] the architectures used by user's targets
|
31
|
+
#
|
32
|
+
attr_accessor :archs
|
33
|
+
|
34
|
+
# @return [Bool] whether frameworks are recommended for the integration
|
35
|
+
# due to the presence of Swift source in the user's targets
|
36
|
+
#
|
37
|
+
attr_accessor :recommends_frameworks
|
38
|
+
|
39
|
+
# @return [Xcodeproj::Project] the user's Xcode project
|
40
|
+
#
|
41
|
+
attr_accessor :project
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'active_support/core_ext/array/conversions'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class DyInstaller
|
5
|
+
class Analyzer
|
6
|
+
class TargetInspector
|
7
|
+
PLATFORM_INFO_URL = 'https://guides.cocoapods.org/syntax/podfile.html#platform'.freeze
|
8
|
+
|
9
|
+
# @return [TargetDefinition] the target definition to inspect
|
10
|
+
#
|
11
|
+
attr_reader :target_definition
|
12
|
+
|
13
|
+
# @return [Pathname] the root of the CocoaPods installation where the
|
14
|
+
# Podfile is located
|
15
|
+
#
|
16
|
+
attr_reader :installation_root
|
17
|
+
|
18
|
+
# Initialize a new instance
|
19
|
+
#
|
20
|
+
# @param [TargetDefinition] target_definition
|
21
|
+
# @see #target_definition
|
22
|
+
#
|
23
|
+
# @param [Pathname] installation_root
|
24
|
+
# @see #installation_root
|
25
|
+
#
|
26
|
+
def initialize(target_definition, installation_root)
|
27
|
+
@target_definition = target_definition
|
28
|
+
@installation_root = installation_root
|
29
|
+
end
|
30
|
+
|
31
|
+
# Inspect the #target_definition
|
32
|
+
#
|
33
|
+
# @raise If no `user_project` is set
|
34
|
+
#
|
35
|
+
# @return [TargetInspectionResult]
|
36
|
+
#
|
37
|
+
def compute_results(user_project)
|
38
|
+
raise ArgumentError, 'Cannot compute results without a user project set' unless user_project
|
39
|
+
|
40
|
+
targets = compute_targets(user_project)
|
41
|
+
|
42
|
+
result = TargetInspectionResult.new
|
43
|
+
result.target_definition = target_definition
|
44
|
+
result.project_path = user_project.path
|
45
|
+
result.project_target_uuids = targets.map(&:uuid)
|
46
|
+
result.build_configurations = compute_build_configurations(targets)
|
47
|
+
result.platform = compute_platform(targets)
|
48
|
+
result.archs = compute_archs(targets)
|
49
|
+
result.project = user_project
|
50
|
+
result.target_definition.swift_version = compute_swift_version_from_targets(targets)
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the path of the user project that the #target_definition
|
55
|
+
# should integrate.
|
56
|
+
#
|
57
|
+
# @raise If the project is implicit and there are multiple projects.
|
58
|
+
#
|
59
|
+
# @raise If the path doesn't exits.
|
60
|
+
#
|
61
|
+
# @return [Pathname] the path of the user project.
|
62
|
+
#
|
63
|
+
def compute_project_path
|
64
|
+
if target_definition.user_project_path
|
65
|
+
path = installation_root + target_definition.user_project_path
|
66
|
+
path = "#{path}.xcodeproj" unless File.extname(path) == '.xcodeproj'
|
67
|
+
path = Pathname.new(path)
|
68
|
+
unless path.exist?
|
69
|
+
raise Informative, 'Unable to find the Xcode project ' \
|
70
|
+
"`#{path}` for the target `#{target_definition.label}`."
|
71
|
+
end
|
72
|
+
else
|
73
|
+
xcodeprojs = installation_root.children.select { |e| e.fnmatch('*.xcodeproj') }
|
74
|
+
if xcodeprojs.size == 1
|
75
|
+
path = xcodeprojs.first
|
76
|
+
else
|
77
|
+
raise Informative, 'Could not automatically select an Xcode project. ' \
|
78
|
+
"Specify one in your Podfile like so:\n\n" \
|
79
|
+
" project 'path/to/Project.xcodeproj'\n"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
path
|
83
|
+
end
|
84
|
+
|
85
|
+
#-----------------------------------------------------------------------#
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Returns a list of the targets from the project of #target_definition
|
90
|
+
# that needs to be integrated.
|
91
|
+
#
|
92
|
+
# @note The method first looks if there is a target specified with
|
93
|
+
# the `link_with` option of the {TargetDefinition}. Otherwise
|
94
|
+
# it looks for the target that has the same name of the target
|
95
|
+
# definition. Finally if no target was found the first
|
96
|
+
# encountered target is returned (it is assumed to be the one
|
97
|
+
# to integrate in simple projects).
|
98
|
+
#
|
99
|
+
# @param [Xcodeproj::Project] user_project
|
100
|
+
# the user project
|
101
|
+
#
|
102
|
+
# @return [Array<PBXNativeTarget>]
|
103
|
+
#
|
104
|
+
def compute_targets(user_project)
|
105
|
+
native_targets = user_project.native_targets
|
106
|
+
target = native_targets.find { |t| t.name == target_definition.name.to_s }
|
107
|
+
unless target
|
108
|
+
found = native_targets.map { |t| "`#{t.name}`" }.to_sentence
|
109
|
+
raise Informative, "Unable to find a target named `#{target_definition.name}`, did find #{found}."
|
110
|
+
end
|
111
|
+
[target]
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param [Array<PBXNativeTarget] user_targets the user's targets of the project of
|
115
|
+
# #target_definition which needs to be integrated
|
116
|
+
#
|
117
|
+
# @return [Hash{String=>Symbol}] A hash representing the user build
|
118
|
+
# configurations where each key corresponds to the name of a
|
119
|
+
# configuration and its value to its type (`:debug` or `:release`).
|
120
|
+
#
|
121
|
+
def compute_build_configurations(user_targets)
|
122
|
+
if user_targets
|
123
|
+
user_targets.flat_map { |t| t.build_configurations.map(&:name) }.each_with_object({}) do |name, hash|
|
124
|
+
hash[name] = name == 'Debug' ? :debug : :release
|
125
|
+
end.merge(target_definition.build_configurations || {})
|
126
|
+
else
|
127
|
+
target_definition.build_configurations || {}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# @param [Array<PBXNativeTarget] user_targets the user's targets of the project of
|
132
|
+
# #target_definition which needs to be integrated
|
133
|
+
#
|
134
|
+
# @return [Platform] The platform of the user's targets
|
135
|
+
#
|
136
|
+
# @note This resolves to the lowest deployment target across the user
|
137
|
+
# targets.
|
138
|
+
#
|
139
|
+
# @todo Is assigning the platform to the target definition the best way
|
140
|
+
# to go?
|
141
|
+
#
|
142
|
+
def compute_platform(user_targets)
|
143
|
+
return target_definition.platform if target_definition.platform
|
144
|
+
name = nil
|
145
|
+
deployment_target = nil
|
146
|
+
|
147
|
+
user_targets.each do |target|
|
148
|
+
name ||= target.platform_name
|
149
|
+
raise Informative, 'Targets with different platforms' unless name == target.platform_name
|
150
|
+
if !deployment_target || deployment_target > Version.new(target.deployment_target)
|
151
|
+
deployment_target = Version.new(target.deployment_target)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
unless name
|
156
|
+
raise Informative,
|
157
|
+
"Unable to determine the platform for the `#{target_definition.name}` target."
|
158
|
+
end
|
159
|
+
|
160
|
+
UI.warn "Automatically assigning platform `#{name}` with version `#{deployment_target}` " \
|
161
|
+
"on target `#{target_definition.name}` because no platform was specified. " \
|
162
|
+
"Please specify a platform for this target in your Podfile. See `#{PLATFORM_INFO_URL}`."
|
163
|
+
|
164
|
+
target_definition.set_platform(name, deployment_target)
|
165
|
+
Platform.new(name, deployment_target)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Computes the architectures relevant for the user's targets.
|
169
|
+
#
|
170
|
+
# @param [Array<PBXNativeTarget] user_targets the user's targets of the project of
|
171
|
+
# #target_definition which needs to be integrated
|
172
|
+
#
|
173
|
+
# @return [Array<String>]
|
174
|
+
#
|
175
|
+
def compute_archs(user_targets)
|
176
|
+
user_targets.flat_map do |target|
|
177
|
+
Array(target.common_resolved_build_setting('ARCHS'))
|
178
|
+
end.compact.uniq.sort
|
179
|
+
end
|
180
|
+
|
181
|
+
# Checks if any of the targets for the {TargetDefinition} computed before
|
182
|
+
# by #compute_user_project_targets is recommended to be build as a framework
|
183
|
+
# due the presence of Swift source code in any of the source build phases.
|
184
|
+
#
|
185
|
+
# @param [TargetDefinition] target_definition
|
186
|
+
# the target definition
|
187
|
+
#
|
188
|
+
# @param [Array<PBXNativeTarget>] native_targets
|
189
|
+
# the targets which are checked for presence of Swift source code
|
190
|
+
#
|
191
|
+
# @return [Boolean] Whether the user project targets to integrate into
|
192
|
+
# uses Swift
|
193
|
+
#
|
194
|
+
def compute_recommends_frameworks(target_definition, native_targets)
|
195
|
+
file_predicate = nil
|
196
|
+
file_predicate = proc do |file_ref|
|
197
|
+
if file_ref.respond_to?(:last_known_file_type)
|
198
|
+
file_ref.last_known_file_type == 'sourcecode.swift'
|
199
|
+
elsif file_ref.respond_to?(:files)
|
200
|
+
file_ref.files.any?(&file_predicate)
|
201
|
+
else
|
202
|
+
false
|
203
|
+
end
|
204
|
+
end
|
205
|
+
target_definition.platform.supports_dynamic_frameworks? || native_targets.any? do |target|
|
206
|
+
target.source_build_phase.files.any? do |build_file|
|
207
|
+
file_predicate.call(build_file.file_ref)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Compute the Swift version for the target build configurations. If more
|
213
|
+
# than one Swift version is defined for a given target, then it will raise.
|
214
|
+
#
|
215
|
+
# @param [Array<PBXNativeTarget>] targets
|
216
|
+
# the targets that are checked for Swift versions.
|
217
|
+
#
|
218
|
+
# @return [String] the targets Swift version or nil
|
219
|
+
#
|
220
|
+
def compute_swift_version_from_targets(targets)
|
221
|
+
versions_to_targets = targets.inject({}) do |memo, target|
|
222
|
+
versions = target.resolved_build_setting('SWIFT_VERSION').values
|
223
|
+
versions.each do |version|
|
224
|
+
memo[version] = [] if memo[version].nil?
|
225
|
+
memo[version] << target.name unless memo[version].include? target.name
|
226
|
+
end
|
227
|
+
memo
|
228
|
+
end
|
229
|
+
|
230
|
+
case versions_to_targets.count
|
231
|
+
when 0
|
232
|
+
nil
|
233
|
+
when 1
|
234
|
+
versions_to_targets.keys.first
|
235
|
+
else
|
236
|
+
target_version_pairs = versions_to_targets.map do |version_names, target_names|
|
237
|
+
target_names.map { |target_name| [target_name, version_names] }
|
238
|
+
end
|
239
|
+
|
240
|
+
sorted_pairs = target_version_pairs.flat_map { |i| i }.sort_by do |target_name, version_name|
|
241
|
+
"#{target_name} #{version_name}"
|
242
|
+
end
|
243
|
+
|
244
|
+
formatted_output = sorted_pairs.map do |target, version_name|
|
245
|
+
"#{target}: Swift #{version_name}"
|
246
|
+
end.join("\n")
|
247
|
+
|
248
|
+
raise Informative, "There may only be up to 1 unique SWIFT_VERSION per target. Found target(s) with multiple Swift versions:\n#{formatted_output}"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class DyInstaller
|
5
|
+
# Represents the installation options the user can customize via a
|
6
|
+
# `Podfile`.
|
7
|
+
#
|
8
|
+
class InstallationOptions
|
9
|
+
# Parses installation options from a podfile.
|
10
|
+
#
|
11
|
+
# @param [Podfile] podfile the podfile to parse installation options
|
12
|
+
# from.
|
13
|
+
#
|
14
|
+
# @raise [Informative] if `podfile` does not specify a `CocoaPods`
|
15
|
+
# install.
|
16
|
+
#
|
17
|
+
# @return [Self]
|
18
|
+
#
|
19
|
+
def self.from_podfile(podfile)
|
20
|
+
name, options = podfile.installation_method
|
21
|
+
unless name.downcase == 'cocoapods'
|
22
|
+
raise Informative, "Currently need to specify a `cocoapods` install, you chose `#{name}`."
|
23
|
+
end
|
24
|
+
new(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Defines a new installation option.
|
28
|
+
#
|
29
|
+
# @param [#to_s] name the name of the option.
|
30
|
+
#
|
31
|
+
# @param default the default value for the option.
|
32
|
+
#
|
33
|
+
# @param [Boolean] boolean whether the option has a boolean value.
|
34
|
+
#
|
35
|
+
# @return [void]
|
36
|
+
#
|
37
|
+
# @!macro [attach] option
|
38
|
+
#
|
39
|
+
# @note this option defaults to $2.
|
40
|
+
#
|
41
|
+
# @return the $1 $0 for installation.
|
42
|
+
#
|
43
|
+
def self.option(name, default, boolean: true)
|
44
|
+
name = name.to_s
|
45
|
+
raise ArgumentError, "The `#{name}` option is already defined" if defaults.key?(name)
|
46
|
+
defaults[name] = default
|
47
|
+
attr_accessor name
|
48
|
+
alias_method "#{name}?", name if boolean
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Hash<Symbol,Object>] all known installation options and their
|
52
|
+
# default values.
|
53
|
+
#
|
54
|
+
def self.defaults
|
55
|
+
@defaults ||= {}
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<Symbol>] the names of all known installation options.
|
59
|
+
#
|
60
|
+
def self.all_options
|
61
|
+
defaults.keys
|
62
|
+
end
|
63
|
+
|
64
|
+
# Initializes the installation options with a hash of options from a
|
65
|
+
# Podfile.
|
66
|
+
#
|
67
|
+
# @param [Hash] options the options to parse.
|
68
|
+
#
|
69
|
+
# @raise [Informative] if `options` contains any unknown keys.
|
70
|
+
#
|
71
|
+
def initialize(options = {})
|
72
|
+
options = ActiveSupport::HashWithIndifferentAccess.new(options)
|
73
|
+
unknown_keys = options.keys - self.class.all_options.map(&:to_s)
|
74
|
+
raise Informative, "Unknown installation options: #{unknown_keys.to_sentence}." unless unknown_keys.empty?
|
75
|
+
self.class.defaults.each do |key, default|
|
76
|
+
value = options.fetch(key, default)
|
77
|
+
send("#{key}=", value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param [Boolean] include_defaults whether values that match the default
|
82
|
+
# for their option should be included. Defaults to `true`.
|
83
|
+
#
|
84
|
+
# @return [Hash] the options, keyed by option name.
|
85
|
+
#
|
86
|
+
def to_h(include_defaults: true)
|
87
|
+
self.class.defaults.reduce(ActiveSupport::HashWithIndifferentAccess.new) do |hash, (option, default)|
|
88
|
+
value = send(option)
|
89
|
+
hash[option] = value if include_defaults || value != default
|
90
|
+
hash
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==(other)
|
95
|
+
other.is_a?(self.class) && to_h == other.to_h
|
96
|
+
end
|
97
|
+
|
98
|
+
alias_method :eql, :==
|
99
|
+
|
100
|
+
def hash
|
101
|
+
to_h.hash
|
102
|
+
end
|
103
|
+
|
104
|
+
option :clean, true
|
105
|
+
option :deduplicate_targets, true
|
106
|
+
option :deterministic_uuids, true
|
107
|
+
option :integrate_targets, true
|
108
|
+
option :lock_pod_sources, true
|
109
|
+
option :warn_for_multiple_pod_sources, true
|
110
|
+
option :share_schemes_for_development_pods, false
|
111
|
+
|
112
|
+
module Mixin
|
113
|
+
module ClassMethods
|
114
|
+
# Delegates the creation of {#installation_options} to the `Podfile`
|
115
|
+
# returned by the given block.
|
116
|
+
#
|
117
|
+
# @param blk a block that returns the `Podfile` to create
|
118
|
+
# installation options from.
|
119
|
+
#
|
120
|
+
# @return [Void]
|
121
|
+
#
|
122
|
+
def delegate_installation_options(&blk)
|
123
|
+
define_method(:installation_options) do
|
124
|
+
@installation_options ||= InstallationOptions.from_podfile(instance_eval(&blk))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Delegates the installation options attributes directly to
|
129
|
+
# {#installation_options}.
|
130
|
+
#
|
131
|
+
# @return [Void]
|
132
|
+
#
|
133
|
+
def delegate_installation_option_attributes!
|
134
|
+
define_method(:respond_to_missing?) do |name, *args|
|
135
|
+
installation_options.respond_to?(name, *args) || super
|
136
|
+
end
|
137
|
+
|
138
|
+
define_method(:method_missing) do |name, *args, &blk|
|
139
|
+
if installation_options.respond_to?(name)
|
140
|
+
installation_options.send(name, *args, &blk)
|
141
|
+
else
|
142
|
+
super
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [InstallationOptions] The installation options.
|
149
|
+
#
|
150
|
+
attr_accessor :installation_options
|
151
|
+
|
152
|
+
def self.included(mod)
|
153
|
+
mod.extend(ClassMethods)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|