cocoapods-square-stable 0.19.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 +7 -0
- data/CHANGELOG.md +1296 -0
- data/LICENSE +20 -0
- data/README.md +94 -0
- data/bin/pod +16 -0
- data/bin/sandbox-pod +120 -0
- data/lib/cocoapods.rb +77 -0
- data/lib/cocoapods/command.rb +116 -0
- data/lib/cocoapods/command/help.rb +23 -0
- data/lib/cocoapods/command/inter_process_communication.rb +178 -0
- data/lib/cocoapods/command/list.rb +77 -0
- data/lib/cocoapods/command/outdated.rb +56 -0
- data/lib/cocoapods/command/podfile_info.rb +91 -0
- data/lib/cocoapods/command/project.rb +88 -0
- data/lib/cocoapods/command/push.rb +172 -0
- data/lib/cocoapods/command/repo.rb +145 -0
- data/lib/cocoapods/command/search.rb +61 -0
- data/lib/cocoapods/command/setup.rb +134 -0
- data/lib/cocoapods/command/spec.rb +590 -0
- data/lib/cocoapods/config.rb +231 -0
- data/lib/cocoapods/downloader.rb +59 -0
- data/lib/cocoapods/executable.rb +118 -0
- data/lib/cocoapods/external_sources.rb +363 -0
- data/lib/cocoapods/file_list.rb +36 -0
- data/lib/cocoapods/gem_version.rb +7 -0
- data/lib/cocoapods/generator/acknowledgements.rb +107 -0
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
- data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
- data/lib/cocoapods/generator/bridge_support.rb +22 -0
- data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
- data/lib/cocoapods/generator/dummy_source.rb +22 -0
- data/lib/cocoapods/generator/prefix_header.rb +82 -0
- data/lib/cocoapods/generator/target_environment_header.rb +86 -0
- data/lib/cocoapods/generator/xcconfig.rb +185 -0
- data/lib/cocoapods/hooks/installer_representation.rb +134 -0
- data/lib/cocoapods/hooks/library_representation.rb +94 -0
- data/lib/cocoapods/hooks/pod_representation.rb +74 -0
- data/lib/cocoapods/installer.rb +571 -0
- data/lib/cocoapods/installer/analyzer.rb +559 -0
- data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
- data/lib/cocoapods/installer/file_references_installer.rb +179 -0
- data/lib/cocoapods/installer/pod_source_installer.rb +248 -0
- data/lib/cocoapods/installer/target_installer.rb +379 -0
- data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
- data/lib/cocoapods/library.rb +202 -0
- data/lib/cocoapods/open_uri.rb +24 -0
- data/lib/cocoapods/project.rb +209 -0
- data/lib/cocoapods/resolver.rb +212 -0
- data/lib/cocoapods/sandbox.rb +343 -0
- data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
- data/lib/cocoapods/sandbox/headers_store.rb +96 -0
- data/lib/cocoapods/sandbox/path_list.rb +208 -0
- data/lib/cocoapods/sources_manager.rb +276 -0
- data/lib/cocoapods/user_interface.rb +304 -0
- data/lib/cocoapods/user_interface/error_report.rb +101 -0
- data/lib/cocoapods/validator.rb +350 -0
- metadata +238 -0
@@ -0,0 +1,559 @@
|
|
1
|
+
module Pod
|
2
|
+
class Installer
|
3
|
+
|
4
|
+
# Analyzes the Podfile, the Lockfile, and the sandbox manifest to generate
|
5
|
+
# the information relative to a CocoaPods installation.
|
6
|
+
#
|
7
|
+
class Analyzer
|
8
|
+
|
9
|
+
include Config::Mixin
|
10
|
+
|
11
|
+
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
|
12
|
+
|
13
|
+
# @return [Sandbox] The sandbox where the Pods should be installed.
|
14
|
+
#
|
15
|
+
attr_reader :sandbox
|
16
|
+
|
17
|
+
# @return [Podfile] The Podfile specification that contains the
|
18
|
+
# information of the Pods that should be installed.
|
19
|
+
#
|
20
|
+
attr_reader :podfile
|
21
|
+
|
22
|
+
# @return [Lockfile] The Lockfile that stores the information about the
|
23
|
+
# Pods previously installed on any machine.
|
24
|
+
#
|
25
|
+
attr_reader :lockfile
|
26
|
+
|
27
|
+
# @param [Sandbox] sandbox @see sandbox
|
28
|
+
# @param [Podfile] podfile @see podfile
|
29
|
+
# @param [Lockfile] lockfile @see lockfile
|
30
|
+
#
|
31
|
+
def initialize(sandbox, podfile, lockfile = nil)
|
32
|
+
@sandbox = sandbox
|
33
|
+
@podfile = podfile
|
34
|
+
@lockfile = lockfile
|
35
|
+
|
36
|
+
@update_mode = false
|
37
|
+
@allow_pre_downloads = true
|
38
|
+
end
|
39
|
+
|
40
|
+
# Performs the analysis.
|
41
|
+
#
|
42
|
+
# The Podfile and the Lockfile provide the information necessary to
|
43
|
+
# compute which specification should be installed. The manifest of the
|
44
|
+
# sandbox returns which specifications are installed.
|
45
|
+
#
|
46
|
+
# @return [AnalysisResult]
|
47
|
+
#
|
48
|
+
def analyze(allow_fetches = true)
|
49
|
+
update_repositories_if_needed if allow_fetches
|
50
|
+
@result = AnalysisResult.new
|
51
|
+
@result.podfile_state = generate_podfile_state
|
52
|
+
@locked_dependencies = generate_version_locking_dependencies
|
53
|
+
|
54
|
+
@result.libraries = generated_libraries
|
55
|
+
fetch_external_sources if allow_fetches
|
56
|
+
@result.specs_by_target = resolve_dependencies
|
57
|
+
@result.specifications = generate_specifications
|
58
|
+
@result.sandbox_state = generate_sandbox_state
|
59
|
+
@result
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_accessor :result
|
63
|
+
|
64
|
+
# @return [Bool] Whether an installation should be performed or this
|
65
|
+
# CocoaPods project is already up to date.
|
66
|
+
#
|
67
|
+
def needs_install?
|
68
|
+
analysis_result = analyze(false)
|
69
|
+
podfile_needs_install?(analysis_result) || sandbox_needs_install?(analysis_result)
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Bool] Whether the podfile has changes respect to the lockfile.
|
73
|
+
#
|
74
|
+
def podfile_needs_install?(analysis_result)
|
75
|
+
state = analysis_result.podfile_state
|
76
|
+
needing_install = state.added + state.changed + state.deleted
|
77
|
+
!needing_install.empty?
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Bool] Whether the sandbox is in synch with the lockfile.
|
81
|
+
#
|
82
|
+
def sandbox_needs_install?(analysis_result)
|
83
|
+
state = analysis_result.sandbox_state
|
84
|
+
needing_install = state.added + state.changed + state.deleted
|
85
|
+
!needing_install.empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
#-----------------------------------------------------------------------#
|
89
|
+
|
90
|
+
# @!group Configuration
|
91
|
+
|
92
|
+
# @return [Bool] Whether the version of the dependencies which did non
|
93
|
+
# change in the Podfile should be locked.
|
94
|
+
#
|
95
|
+
attr_accessor :update_mode
|
96
|
+
alias_method :update_mode?, :update_mode
|
97
|
+
|
98
|
+
# @return [Bool] Whether the analysis allows pre-downloads and thus
|
99
|
+
# modifications to the sandbox.
|
100
|
+
#
|
101
|
+
# @note This flag should not be used in installations.
|
102
|
+
#
|
103
|
+
# @note This is used by the `pod outdated` command to prevent
|
104
|
+
# modification of the sandbox in the resolution process.
|
105
|
+
#
|
106
|
+
attr_accessor :allow_pre_downloads
|
107
|
+
alias_method :allow_pre_downloads?, :allow_pre_downloads
|
108
|
+
|
109
|
+
#-----------------------------------------------------------------------#
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
# @!group Analysis steps
|
114
|
+
|
115
|
+
# Compares the {Podfile} with the {Lockfile} in order to detect which
|
116
|
+
# dependencies should be locked.
|
117
|
+
#
|
118
|
+
# @return [SpecsState] the states of the Podfile specs.
|
119
|
+
#
|
120
|
+
# @note As the target definitions share the same sandbox they should have
|
121
|
+
# the same version of a Pod. For this reason this method returns
|
122
|
+
# the name of the Pod (root name of the dependencies) and doesn't
|
123
|
+
# group them by target definition.
|
124
|
+
#
|
125
|
+
# @todo [CocoaPods > 0.18] If there isn't a Lockfile all the Pods should
|
126
|
+
# be marked as added.
|
127
|
+
#
|
128
|
+
def generate_podfile_state
|
129
|
+
if lockfile
|
130
|
+
pods_state = nil
|
131
|
+
UI.section "Finding Podfile changes" do
|
132
|
+
pods_by_state = lockfile.detect_changes_with_podfile(podfile)
|
133
|
+
pods_by_state.dup.each do |state, full_names|
|
134
|
+
pods_by_state[state] = full_names.map { |fn| Specification.root_name(fn) }
|
135
|
+
end
|
136
|
+
pods_state = SpecsState.new(pods_by_state)
|
137
|
+
pods_state.print
|
138
|
+
end
|
139
|
+
pods_state
|
140
|
+
else
|
141
|
+
state = SpecsState.new
|
142
|
+
state.added.concat(podfile.dependencies.map(&:root_name).uniq)
|
143
|
+
state
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Updates the source repositories unless the config indicates to skip it.
|
148
|
+
#
|
149
|
+
# @return [void]
|
150
|
+
#
|
151
|
+
def update_repositories_if_needed
|
152
|
+
unless config.skip_repo_update?
|
153
|
+
UI.section 'Updating spec repositories' do
|
154
|
+
SourcesManager.update
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Creates the models that represent the libraries generated by CocoaPods.
|
160
|
+
#
|
161
|
+
# @note The libraries are generated before the resolution process
|
162
|
+
# because it might be necessary to infer the platform from the
|
163
|
+
# user targets, which in turns requires to identify the user
|
164
|
+
# project.
|
165
|
+
#
|
166
|
+
# @note The specification of the libraries are added in the
|
167
|
+
# {#resolve_dependencies} step.
|
168
|
+
#
|
169
|
+
# @return [Array<Libraries>] the generated libraries.
|
170
|
+
#
|
171
|
+
def generated_libraries
|
172
|
+
libraries = []
|
173
|
+
podfile.target_definition_list.each do |target_definition|
|
174
|
+
lib = Library.new(target_definition)
|
175
|
+
lib.support_files_root = sandbox.library_support_files_dir(lib.name)
|
176
|
+
|
177
|
+
if config.integrate_targets?
|
178
|
+
project_path = compute_user_project_path(target_definition)
|
179
|
+
user_project = Xcodeproj::Project.new(project_path)
|
180
|
+
targets = compute_user_project_targets(target_definition, user_project)
|
181
|
+
|
182
|
+
lib.user_project_path = project_path
|
183
|
+
lib.client_root = project_path.dirname
|
184
|
+
lib.user_target_uuids = targets.map(&:uuid)
|
185
|
+
lib.user_build_configurations = compute_user_build_configurations(target_definition, targets)
|
186
|
+
lib.platform = compute_platform_for_target_definition(target_definition, targets)
|
187
|
+
else
|
188
|
+
unless target_definition.platform
|
189
|
+
raise Informative, "It is necessary to specify the platform in the Podfile if not integrating."
|
190
|
+
end
|
191
|
+
lib.client_root = config.installation_root
|
192
|
+
lib.user_target_uuids = []
|
193
|
+
lib.user_build_configurations = {}
|
194
|
+
lib.platform = target_definition.platform
|
195
|
+
end
|
196
|
+
libraries << lib
|
197
|
+
end
|
198
|
+
libraries
|
199
|
+
end
|
200
|
+
|
201
|
+
# Generates dependencies that require the specific version of the Pods
|
202
|
+
# that haven't changed in the {Lockfile}.
|
203
|
+
#
|
204
|
+
# These dependencies are passed to the {Resolver}, unless the installer
|
205
|
+
# is in update mode, to prevent it from upgrading the Pods that weren't
|
206
|
+
# changed in the {Podfile}.
|
207
|
+
#
|
208
|
+
# @return [Array<Dependency>] the dependencies generate by the lockfile
|
209
|
+
# that prevent the resolver to update a Pod.
|
210
|
+
#
|
211
|
+
def generate_version_locking_dependencies
|
212
|
+
if update_mode?
|
213
|
+
[]
|
214
|
+
else
|
215
|
+
result.podfile_state.unchanged.map do |pod|
|
216
|
+
lockfile.dependency_to_lock_pod_named(pod)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Fetches the podspecs of external sources if modifications to the
|
222
|
+
# sandbox are allowed.
|
223
|
+
#
|
224
|
+
# @note In update mode all the external sources are refreshed while in
|
225
|
+
# normal mode they are refreshed only if added or changed in the
|
226
|
+
# Podfile. Moreover, in normal specifications for unchanged Pods
|
227
|
+
# which are missing or are generated from an local source are
|
228
|
+
# fetched as well.
|
229
|
+
#
|
230
|
+
# @note It is possible to perform this step before the resolution
|
231
|
+
# process because external sources identify a single specific
|
232
|
+
# version (checkout). If the other dependencies are not
|
233
|
+
# compatible with the version reported by the podspec of the
|
234
|
+
# external source the resolver will raise.
|
235
|
+
#
|
236
|
+
# @return [void]
|
237
|
+
#
|
238
|
+
# TODO Specs
|
239
|
+
#
|
240
|
+
def fetch_external_sources
|
241
|
+
return unless allow_pre_downloads?
|
242
|
+
deps_to_fetch = []
|
243
|
+
deps_to_fetch_if_needed = []
|
244
|
+
deps_with_external_source = podfile.dependencies.select { |dep| dep.external_source }
|
245
|
+
if update_mode?
|
246
|
+
deps_to_fetch = deps_with_external_source
|
247
|
+
else
|
248
|
+
pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
|
249
|
+
deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) }
|
250
|
+
deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) }
|
251
|
+
deps_to_fetch += deps_to_fetch_if_needed.select { |dep| sandbox.specification(dep.root_name).nil? || !dep.external_source[:local].nil? || !dep.external_source[:path].nil? }
|
252
|
+
end
|
253
|
+
|
254
|
+
unless deps_to_fetch.empty?
|
255
|
+
UI.section "Fetching external sources" do
|
256
|
+
deps_to_fetch.uniq.sort.each do |dependency|
|
257
|
+
source = ExternalSources.from_dependency(dependency, podfile.defined_in_file)
|
258
|
+
source.fetch(sandbox)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Converts the Podfile in a list of specifications grouped by target.
|
265
|
+
#
|
266
|
+
# @note In this step the specs are added to the libraries.
|
267
|
+
#
|
268
|
+
# @note As some dependencies might have external sources the resolver
|
269
|
+
# is aware of the {Sandbox} and interacts with it to download the
|
270
|
+
# podspecs of the external sources. This is necessary because the
|
271
|
+
# resolver needs their specifications to analyze their
|
272
|
+
# dependencies.
|
273
|
+
#
|
274
|
+
# @note The specifications of the external sources which are added,
|
275
|
+
# modified or removed need to deleted from the sandbox before the
|
276
|
+
# resolution process. Otherwise the resolver might use an
|
277
|
+
# incorrect specification instead of pre-downloading it.
|
278
|
+
#
|
279
|
+
# @note In update mode the resolver is set to always update the specs
|
280
|
+
# from external sources.
|
281
|
+
#
|
282
|
+
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
|
283
|
+
# grouped by target.
|
284
|
+
#
|
285
|
+
def resolve_dependencies
|
286
|
+
specs_by_target = nil
|
287
|
+
|
288
|
+
UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do
|
289
|
+
resolver = Resolver.new(sandbox, podfile, locked_dependencies)
|
290
|
+
specs_by_target = resolver.resolve
|
291
|
+
end
|
292
|
+
|
293
|
+
specs_by_target.each do |target_definition, specs|
|
294
|
+
lib = result.libraries.find { |l| l.target_definition == target_definition}
|
295
|
+
lib.specs = specs
|
296
|
+
end
|
297
|
+
|
298
|
+
specs_by_target
|
299
|
+
end
|
300
|
+
|
301
|
+
# Returns the list of all the resolved the resolved specifications.
|
302
|
+
#
|
303
|
+
# @return [Array<Specification>] the list of the specifications.
|
304
|
+
#
|
305
|
+
def generate_specifications
|
306
|
+
result.specs_by_target.values.flatten.uniq
|
307
|
+
end
|
308
|
+
|
309
|
+
# Computes the state of the sandbox respect to the resolved
|
310
|
+
# specifications.
|
311
|
+
#
|
312
|
+
# @return [SpecsState] the representation of the state of the manifest
|
313
|
+
# specifications.
|
314
|
+
#
|
315
|
+
def generate_sandbox_state
|
316
|
+
sandbox_state = nil
|
317
|
+
UI.section "Comparing resolved specification to the sandbox manifest" do
|
318
|
+
sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode, lockfile)
|
319
|
+
sandbox_state = sandbox_analyzer.analyze
|
320
|
+
sandbox_state.print
|
321
|
+
end
|
322
|
+
sandbox_state
|
323
|
+
end
|
324
|
+
|
325
|
+
#-----------------------------------------------------------------------#
|
326
|
+
|
327
|
+
# @!group Analysis internal products
|
328
|
+
|
329
|
+
# @return [Array<Dependency>] the dependencies generate by the lockfile
|
330
|
+
# that prevent the resolver to update a Pod.
|
331
|
+
#
|
332
|
+
attr_reader :locked_dependencies
|
333
|
+
|
334
|
+
#-----------------------------------------------------------------------#
|
335
|
+
|
336
|
+
private
|
337
|
+
|
338
|
+
# @!group Analysis sub-steps
|
339
|
+
|
340
|
+
# Returns the path of the user project that the {TargetDefinition}
|
341
|
+
# should integrate.
|
342
|
+
#
|
343
|
+
# @raise If the project is implicit and there are multiple projects.
|
344
|
+
#
|
345
|
+
# @raise If the path doesn't exits.
|
346
|
+
#
|
347
|
+
# @return [Pathname] the path of the user project.
|
348
|
+
#
|
349
|
+
def compute_user_project_path(target_definition)
|
350
|
+
if target_definition.user_project_path
|
351
|
+
path = config.installation_root + target_definition.user_project_path
|
352
|
+
path = "#{path}.xcodeproj" unless File.extname(path) == '.xcodeproj'
|
353
|
+
path = Pathname.new(path)
|
354
|
+
unless path.exist?
|
355
|
+
raise Informative, "Unable to find the Xcode project " \
|
356
|
+
"`#{path}` for the target `#{target_definition.label}`."
|
357
|
+
end
|
358
|
+
|
359
|
+
else
|
360
|
+
xcodeprojs = Pathname.glob(config.installation_root + '*.xcodeproj')
|
361
|
+
if xcodeprojs.size == 1
|
362
|
+
path = xcodeprojs.first
|
363
|
+
else
|
364
|
+
raise Informative, "Could not automatically select an Xcode project. " \
|
365
|
+
"Specify one in your Podfile like so:\n\n" \
|
366
|
+
" xcodeproj 'path/to/Project.xcodeproj'\n"
|
367
|
+
end
|
368
|
+
end
|
369
|
+
path
|
370
|
+
end
|
371
|
+
|
372
|
+
# Returns a list of the targets from the project of {TargetDefinition}
|
373
|
+
# that needs to be integrated.
|
374
|
+
#
|
375
|
+
# @note The method first looks if there is a target specified with
|
376
|
+
# the `link_with` option of the {TargetDefinition}. Otherwise
|
377
|
+
# it looks for the target that has the same name of the target
|
378
|
+
# definition. Finally if no target was found the first
|
379
|
+
# encountered target is returned (it is assumed to be the one
|
380
|
+
# to integrate in simple projects).
|
381
|
+
#
|
382
|
+
# @note This will only return targets that do **not** already have
|
383
|
+
# the Pods library in their frameworks build phase.
|
384
|
+
#
|
385
|
+
#
|
386
|
+
def compute_user_project_targets(target_definition, user_project)
|
387
|
+
if link_with = target_definition.link_with
|
388
|
+
targets = native_targets(user_project).select { |t| link_with.include?(t.name) }
|
389
|
+
raise Informative, "Unable to find the targets named `#{link_with.to_sentence}` to link with target definition `#{target_definition.name}`" if targets.empty?
|
390
|
+
elsif target_definition.link_with_first_target?
|
391
|
+
targets = [ native_targets(user_project).first ].compact
|
392
|
+
raise Informative, "Unable to find a target" if targets.empty?
|
393
|
+
else
|
394
|
+
target = native_targets(user_project).find { |t| t.name == target_definition.name.to_s }
|
395
|
+
targets = [ target ].compact
|
396
|
+
raise Informative, "Unable to find a target named `#{target_definition.name.to_s}`" if targets.empty?
|
397
|
+
end
|
398
|
+
targets
|
399
|
+
end
|
400
|
+
|
401
|
+
# @return [Array<PBXNativeTarget>] Returns the user’s targets, excluding
|
402
|
+
# aggregate targets.
|
403
|
+
#
|
404
|
+
def native_targets(user_project)
|
405
|
+
user_project.targets.reject do |target|
|
406
|
+
target.is_a? Xcodeproj::Project::Object::PBXAggregateTarget
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
# @return [Hash{String=>Symbol}] A hash representing the user build
|
411
|
+
# configurations where each key corresponds to the name of a
|
412
|
+
# configuration and its value to its type (`:debug` or `:release`).
|
413
|
+
#
|
414
|
+
def compute_user_build_configurations(target_definition, user_targets)
|
415
|
+
if user_targets
|
416
|
+
user_targets.map { |t| t.build_configurations.map(&:name) }.flatten.inject({}) do |hash, name|
|
417
|
+
unless name == 'Debug' || name == 'Release'
|
418
|
+
hash[name] = :release
|
419
|
+
end
|
420
|
+
hash
|
421
|
+
end.merge(target_definition.build_configurations || {})
|
422
|
+
else
|
423
|
+
target_definition.build_configurations || {}
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
# @return [Platform] The platform for the library.
|
428
|
+
#
|
429
|
+
# @note This resolves to the lowest deployment target across the user
|
430
|
+
# targets.
|
431
|
+
#
|
432
|
+
# @todo Is assigning the platform to the target definition the best way
|
433
|
+
# to go?
|
434
|
+
#
|
435
|
+
def compute_platform_for_target_definition(target_definition, user_targets)
|
436
|
+
return target_definition.platform if target_definition.platform
|
437
|
+
name = nil
|
438
|
+
deployment_target = nil
|
439
|
+
|
440
|
+
user_targets.each do |target|
|
441
|
+
name ||= target.platform_name
|
442
|
+
raise Informative, "Targets with different platforms" unless name == target.platform_name
|
443
|
+
if !deployment_target || deployment_target > Version.new(target.deployment_target)
|
444
|
+
deployment_target = Version.new(target.deployment_target)
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
target_definition.set_platform(name, deployment_target)
|
449
|
+
Platform.new(name, deployment_target)
|
450
|
+
end
|
451
|
+
|
452
|
+
#-----------------------------------------------------------------------#
|
453
|
+
|
454
|
+
class AnalysisResult
|
455
|
+
|
456
|
+
# @return [SpecsState] the states of the Podfile specs.
|
457
|
+
#
|
458
|
+
attr_accessor :podfile_state
|
459
|
+
|
460
|
+
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
|
461
|
+
# grouped by target.
|
462
|
+
#
|
463
|
+
attr_accessor :specs_by_target
|
464
|
+
|
465
|
+
# @return [Array<Specification>] the specifications of the resolved
|
466
|
+
# version of Pods that should be installed.
|
467
|
+
#
|
468
|
+
attr_accessor :specifications
|
469
|
+
|
470
|
+
# @return [SpecsState] the states of the {Sandbox} respect the resolved
|
471
|
+
# specifications.
|
472
|
+
#
|
473
|
+
attr_accessor :sandbox_state
|
474
|
+
|
475
|
+
# @return [Array<Library>] the libraries generated by the target
|
476
|
+
# definitions.
|
477
|
+
#
|
478
|
+
attr_accessor :libraries
|
479
|
+
|
480
|
+
end
|
481
|
+
|
482
|
+
#-----------------------------------------------------------------------#
|
483
|
+
|
484
|
+
# This class represents the state of a collection of Pods.
|
485
|
+
#
|
486
|
+
# @note The names of the pods stored by this class are always the **root**
|
487
|
+
# name of the specification.
|
488
|
+
#
|
489
|
+
# @note The motivation for this class is to ensure that the names of the
|
490
|
+
# subspecs are added instead of the name of the Pods.
|
491
|
+
#
|
492
|
+
class SpecsState
|
493
|
+
|
494
|
+
# @param [Hash{Symbol=>String}] pods_by_state
|
495
|
+
# The **root** name of the pods grouped by their state
|
496
|
+
# (`:added`, `:removed`, `:changed` or `:unchanged`).
|
497
|
+
#
|
498
|
+
def initialize(pods_by_state = nil)
|
499
|
+
@added = []
|
500
|
+
@deleted = []
|
501
|
+
@changed = []
|
502
|
+
@unchanged = []
|
503
|
+
|
504
|
+
if pods_by_state
|
505
|
+
@added = pods_by_state[:added] || []
|
506
|
+
@deleted = pods_by_state[:removed] || []
|
507
|
+
@changed = pods_by_state[:changed] || []
|
508
|
+
@unchanged = pods_by_state[:unchanged] || []
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
# @return [Array<String>] the names of the pods that were added.
|
513
|
+
#
|
514
|
+
attr_accessor :added
|
515
|
+
|
516
|
+
# @return [Array<String>] the names of the pods that were changed.
|
517
|
+
#
|
518
|
+
attr_accessor :changed
|
519
|
+
|
520
|
+
# @return [Array<String>] the names of the pods that were deleted.
|
521
|
+
#
|
522
|
+
attr_accessor :deleted
|
523
|
+
|
524
|
+
# @return [Array<String>] the names of the pods that were unchanged.
|
525
|
+
#
|
526
|
+
attr_accessor :unchanged
|
527
|
+
|
528
|
+
# Displays the state of each pod.
|
529
|
+
#
|
530
|
+
# @return [void]
|
531
|
+
#
|
532
|
+
def print
|
533
|
+
added .sort.each { |pod| UI.message("A".green + " #{pod}", '', 2) }
|
534
|
+
deleted .sort.each { |pod| UI.message("R".red + " #{pod}", '', 2) }
|
535
|
+
changed .sort.each { |pod| UI.message("M".yellow + " #{pod}", '', 2) }
|
536
|
+
unchanged.sort.each { |pod| UI.message("-" + " #{pod}", '', 2) }
|
537
|
+
end
|
538
|
+
|
539
|
+
# Adds the name of a Pod to the give state.
|
540
|
+
#
|
541
|
+
# @param [String]
|
542
|
+
# the name of the Pod.
|
543
|
+
#
|
544
|
+
# @param [Symbol]
|
545
|
+
# the state of the Pod.
|
546
|
+
#
|
547
|
+
# @raise If there is an attempt to add the name of a subspec.
|
548
|
+
#
|
549
|
+
# @return [void]
|
550
|
+
#
|
551
|
+
def add_name(name, state)
|
552
|
+
raise "[Bug] Attempt to add subspec to the pods state" if name.include?('/')
|
553
|
+
self.send(state) << name
|
554
|
+
end
|
555
|
+
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|