xcocoapods 1.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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6303 -0
  3. data/LICENSE +28 -0
  4. data/README.md +80 -0
  5. data/bin/pod +56 -0
  6. data/bin/sandbox-pod +168 -0
  7. data/lib/cocoapods.rb +73 -0
  8. data/lib/cocoapods/command.rb +175 -0
  9. data/lib/cocoapods/command/cache.rb +28 -0
  10. data/lib/cocoapods/command/cache/clean.rb +90 -0
  11. data/lib/cocoapods/command/cache/list.rb +69 -0
  12. data/lib/cocoapods/command/env.rb +66 -0
  13. data/lib/cocoapods/command/init.rb +128 -0
  14. data/lib/cocoapods/command/install.rb +45 -0
  15. data/lib/cocoapods/command/ipc.rb +19 -0
  16. data/lib/cocoapods/command/ipc/list.rb +40 -0
  17. data/lib/cocoapods/command/ipc/podfile.rb +31 -0
  18. data/lib/cocoapods/command/ipc/podfile_json.rb +30 -0
  19. data/lib/cocoapods/command/ipc/repl.rb +51 -0
  20. data/lib/cocoapods/command/ipc/spec.rb +29 -0
  21. data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
  22. data/lib/cocoapods/command/lib.rb +11 -0
  23. data/lib/cocoapods/command/lib/create.rb +105 -0
  24. data/lib/cocoapods/command/lib/lint.rb +121 -0
  25. data/lib/cocoapods/command/list.rb +39 -0
  26. data/lib/cocoapods/command/options/project_directory.rb +36 -0
  27. data/lib/cocoapods/command/options/repo_update.rb +34 -0
  28. data/lib/cocoapods/command/outdated.rb +140 -0
  29. data/lib/cocoapods/command/repo.rb +29 -0
  30. data/lib/cocoapods/command/repo/add.rb +103 -0
  31. data/lib/cocoapods/command/repo/lint.rb +82 -0
  32. data/lib/cocoapods/command/repo/list.rb +93 -0
  33. data/lib/cocoapods/command/repo/push.rb +281 -0
  34. data/lib/cocoapods/command/repo/remove.rb +36 -0
  35. data/lib/cocoapods/command/repo/update.rb +28 -0
  36. data/lib/cocoapods/command/setup.rb +103 -0
  37. data/lib/cocoapods/command/spec.rb +112 -0
  38. data/lib/cocoapods/command/spec/cat.rb +51 -0
  39. data/lib/cocoapods/command/spec/create.rb +283 -0
  40. data/lib/cocoapods/command/spec/edit.rb +87 -0
  41. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  42. data/lib/cocoapods/command/spec/lint.rb +137 -0
  43. data/lib/cocoapods/command/spec/which.rb +43 -0
  44. data/lib/cocoapods/command/update.rb +101 -0
  45. data/lib/cocoapods/config.rb +347 -0
  46. data/lib/cocoapods/core_overrides.rb +1 -0
  47. data/lib/cocoapods/downloader.rb +190 -0
  48. data/lib/cocoapods/downloader/cache.rb +233 -0
  49. data/lib/cocoapods/downloader/request.rb +86 -0
  50. data/lib/cocoapods/downloader/response.rb +16 -0
  51. data/lib/cocoapods/executable.rb +222 -0
  52. data/lib/cocoapods/external_sources.rb +57 -0
  53. data/lib/cocoapods/external_sources/abstract_external_source.rb +205 -0
  54. data/lib/cocoapods/external_sources/downloader_source.rb +30 -0
  55. data/lib/cocoapods/external_sources/path_source.rb +55 -0
  56. data/lib/cocoapods/external_sources/podspec_source.rb +54 -0
  57. data/lib/cocoapods/gem_version.rb +5 -0
  58. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  59. data/lib/cocoapods/generator/acknowledgements/markdown.rb +44 -0
  60. data/lib/cocoapods/generator/acknowledgements/plist.rb +94 -0
  61. data/lib/cocoapods/generator/app_target_helper.rb +244 -0
  62. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  63. data/lib/cocoapods/generator/constant.rb +19 -0
  64. data/lib/cocoapods/generator/copy_resources_script.rb +230 -0
  65. data/lib/cocoapods/generator/dummy_source.rb +31 -0
  66. data/lib/cocoapods/generator/embed_frameworks_script.rb +215 -0
  67. data/lib/cocoapods/generator/header.rb +103 -0
  68. data/lib/cocoapods/generator/info_plist_file.rb +116 -0
  69. data/lib/cocoapods/generator/module_map.rb +99 -0
  70. data/lib/cocoapods/generator/prefix_header.rb +60 -0
  71. data/lib/cocoapods/generator/umbrella_header.rb +46 -0
  72. data/lib/cocoapods/hooks_manager.rb +132 -0
  73. data/lib/cocoapods/installer.rb +703 -0
  74. data/lib/cocoapods/installer/analyzer.rb +972 -0
  75. data/lib/cocoapods/installer/analyzer/analysis_result.rb +87 -0
  76. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +98 -0
  77. data/lib/cocoapods/installer/analyzer/pod_variant.rb +67 -0
  78. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +157 -0
  79. data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
  80. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +240 -0
  81. data/lib/cocoapods/installer/analyzer/specs_state.rb +84 -0
  82. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +53 -0
  83. data/lib/cocoapods/installer/analyzer/target_inspector.rb +260 -0
  84. data/lib/cocoapods/installer/installation_options.rb +158 -0
  85. data/lib/cocoapods/installer/pod_source_installer.rb +202 -0
  86. data/lib/cocoapods/installer/pod_source_preparer.rb +77 -0
  87. data/lib/cocoapods/installer/podfile_validator.rb +139 -0
  88. data/lib/cocoapods/installer/post_install_hooks_context.rb +132 -0
  89. data/lib/cocoapods/installer/pre_install_hooks_context.rb +51 -0
  90. data/lib/cocoapods/installer/source_provider_hooks_context.rb +34 -0
  91. data/lib/cocoapods/installer/user_project_integrator.rb +250 -0
  92. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +463 -0
  93. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  94. data/lib/cocoapods/installer/xcode.rb +8 -0
  95. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +416 -0
  96. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +181 -0
  97. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +84 -0
  98. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +334 -0
  99. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +777 -0
  100. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +116 -0
  101. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +86 -0
  102. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +256 -0
  103. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +68 -0
  104. data/lib/cocoapods/installer/xcode/target_validator.rb +147 -0
  105. data/lib/cocoapods/open-uri.rb +33 -0
  106. data/lib/cocoapods/project.rb +414 -0
  107. data/lib/cocoapods/resolver.rb +585 -0
  108. data/lib/cocoapods/resolver/lazy_specification.rb +79 -0
  109. data/lib/cocoapods/sandbox.rb +404 -0
  110. data/lib/cocoapods/sandbox/file_accessor.rb +444 -0
  111. data/lib/cocoapods/sandbox/headers_store.rb +146 -0
  112. data/lib/cocoapods/sandbox/path_list.rb +220 -0
  113. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
  114. data/lib/cocoapods/sandbox/podspec_finder.rb +23 -0
  115. data/lib/cocoapods/sources_manager.rb +157 -0
  116. data/lib/cocoapods/target.rb +261 -0
  117. data/lib/cocoapods/target/aggregate_target.rb +338 -0
  118. data/lib/cocoapods/target/build_settings.rb +1075 -0
  119. data/lib/cocoapods/target/pod_target.rb +559 -0
  120. data/lib/cocoapods/user_interface.rb +459 -0
  121. data/lib/cocoapods/user_interface/error_report.rb +187 -0
  122. data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
  123. data/lib/cocoapods/validator.rb +981 -0
  124. metadata +533 -0
@@ -0,0 +1,585 @@
1
+ require 'molinillo'
2
+ require 'cocoapods/resolver/lazy_specification'
3
+
4
+ module Pod
5
+ class NoSpecFoundError < Informative
6
+ def exit_status
7
+ @exit_status ||= 31
8
+ end
9
+ end
10
+
11
+ # The resolver is responsible of generating a list of specifications grouped
12
+ # by target for a given Podfile.
13
+ #
14
+ class Resolver
15
+ # A small container that wraps a resolved specification for a given target definition. Additional metadata
16
+ # is included here such as if the specification is only used by tests.
17
+ #
18
+ class ResolverSpecification
19
+ # @return [Specification] the specification that was resolved
20
+ #
21
+ attr_reader :spec
22
+
23
+ # @return [Source] the spec repo source the specification came from
24
+ #
25
+ attr_reader :source
26
+
27
+ # @return [Bool] whether this resolved specification is only used by tests.
28
+ #
29
+ attr_reader :used_by_tests_only
30
+ alias used_by_tests_only? used_by_tests_only
31
+
32
+ def initialize(spec, used_by_tests_only, source)
33
+ @spec = spec
34
+ @used_by_tests_only = used_by_tests_only
35
+ @source = source
36
+ end
37
+
38
+ def name
39
+ spec.name
40
+ end
41
+
42
+ def root
43
+ spec.root
44
+ end
45
+
46
+ def ==(other)
47
+ self.class == other &&
48
+ spec == other.spec &&
49
+ used_by_tests_only == other.test_only
50
+ end
51
+ end
52
+
53
+ include Pod::Installer::InstallationOptions::Mixin
54
+
55
+ delegate_installation_options { podfile }
56
+
57
+ # @return [Sandbox] the Sandbox used by the resolver to find external
58
+ # dependencies.
59
+ #
60
+ attr_reader :sandbox
61
+
62
+ # @return [Podfile] the Podfile used by the resolver.
63
+ #
64
+ attr_reader :podfile
65
+
66
+ # @return [Array<Dependency>] the list of dependencies locked to a specific
67
+ # version.
68
+ #
69
+ attr_reader :locked_dependencies
70
+
71
+ # @return [Array<Source>] The list of the sources which will be used for
72
+ # the resolution.
73
+ #
74
+ attr_reader :sources
75
+
76
+ # @return [Bool] Whether the resolver has sources repositories up-to-date.
77
+ #
78
+ attr_reader :specs_updated
79
+ alias specs_updated? specs_updated
80
+
81
+ # Init a new Resolver
82
+ #
83
+ # @param [Sandbox] sandbox @see sandbox
84
+ # @param [Podfile] podfile @see podfile
85
+ # @param [Array<Dependency>] locked_dependencies @see locked_dependencies
86
+ # @param [Array<Source>, Source] sources @see sources
87
+ # @param [Boolean] specs_updated @see specs_updated
88
+ # @param [PodfileDependencyCache] podfile_dependency_cache the podfile dependency cache to use
89
+ # within this Resolver.
90
+ #
91
+ def initialize(sandbox, podfile, locked_dependencies, sources, specs_updated,
92
+ podfile_dependency_cache: Installer::Analyzer::PodfileDependencyCache.from_podfile(podfile))
93
+ @sandbox = sandbox
94
+ @podfile = podfile
95
+ @locked_dependencies = locked_dependencies
96
+ @sources = Array(sources)
97
+ @specs_updated = specs_updated
98
+ @podfile_dependency_cache = podfile_dependency_cache
99
+ @platforms_by_dependency = Hash.new { |h, k| h[k] = [] }
100
+ @cached_sets = {}
101
+ end
102
+
103
+ #-------------------------------------------------------------------------#
104
+
105
+ public
106
+
107
+ # @!group Resolution
108
+
109
+ # Identifies the specifications that should be installed.
110
+ #
111
+ # @return [Hash{TargetDefinition => Array<ResolverSpecification>}] resolver_specs_by_target
112
+ # the resolved specifications that need to be installed grouped by target
113
+ # definition.
114
+ #
115
+ def resolve
116
+ dependencies = @podfile_dependency_cache.target_definition_list.flat_map do |target|
117
+ @podfile_dependency_cache.target_definition_dependencies(target).each do |dep|
118
+ next unless target.platform
119
+ @platforms_by_dependency[dep].push(target.platform)
120
+ end
121
+ end
122
+ @platforms_by_dependency.each_value(&:uniq!)
123
+ @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
124
+ resolver_specs_by_target
125
+ rescue Molinillo::ResolverError => e
126
+ handle_resolver_error(e)
127
+ end
128
+
129
+ # @return [Hash{Podfile::TargetDefinition => Array<ResolverSpecification>}]
130
+ # returns the resolved specifications grouped by target.
131
+ #
132
+ # @note The returned specifications can be subspecs.
133
+ #
134
+ def resolver_specs_by_target
135
+ @resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
136
+ @podfile_dependency_cache.target_definition_list.each do |target|
137
+ # can't use vertex.root? since that considers _all_ targets
138
+ explicit_dependencies = @podfile_dependency_cache.target_definition_dependencies(target).map(&:name).to_set
139
+ vertices = valid_dependencies_for_target(target)
140
+
141
+ resolver_specs_by_target[target] = vertices.
142
+ map do |vertex|
143
+ payload = vertex.payload
144
+ test_only = (!explicit_dependencies.include?(vertex.name) || payload.test_specification?) &&
145
+ (vertex.recursive_predecessors & vertices).all? { |v| !explicit_dependencies.include?(v.name) || v.payload.test_specification? }
146
+ spec_source = payload.respond_to?(:spec_source) && payload.spec_source
147
+ ResolverSpecification.new(payload, test_only, spec_source)
148
+ end.
149
+ sort_by(&:name)
150
+ end
151
+ end
152
+ end
153
+
154
+ #-------------------------------------------------------------------------#
155
+
156
+ public
157
+
158
+ # @!group Specification Provider
159
+
160
+ include Molinillo::SpecificationProvider
161
+
162
+ # Returns (and caches) the specification that satisfy the given dependency.
163
+ #
164
+ # @return [Array<Specification>] the specifications that satisfy the given
165
+ # `dependency`.
166
+ #
167
+ # @param [Dependency] dependency the dependency that is being searched for.
168
+ #
169
+ def search_for(dependency)
170
+ @search ||= {}
171
+ @search[dependency] ||= begin
172
+ locked_requirement = requirement_for_locked_pod_named(dependency.name)
173
+ additional_requirements = Array(locked_requirement)
174
+ specifications_for_dependency(dependency, additional_requirements)
175
+ end
176
+ @search[dependency].dup
177
+ end
178
+
179
+ # Returns the dependencies of `specification`.
180
+ #
181
+ # @return [Array<Specification>] all dependencies of `specification`.
182
+ #
183
+ # @param [Specification] specification the specification whose own
184
+ # dependencies are being asked for.
185
+ #
186
+ def dependencies_for(specification)
187
+ specification.all_dependencies.map do |dependency|
188
+ if dependency.root_name == Specification.root_name(specification.name)
189
+ dependency.dup.tap { |d| d.specific_version = specification.version }
190
+ else
191
+ dependency
192
+ end
193
+ end
194
+ end
195
+
196
+ # Returns the name for the given `dependency`.
197
+ #
198
+ # @return [String] the name for the given `dependency`.
199
+ #
200
+ # @param [Dependency] dependency the dependency whose name is being
201
+ # queried.
202
+ #
203
+ def name_for(dependency)
204
+ dependency.name
205
+ end
206
+
207
+ # @return [String] the user-facing name for a {Podfile}.
208
+ #
209
+ def name_for_explicit_dependency_source
210
+ 'Podfile'
211
+ end
212
+
213
+ # @return [String] the user-facing name for a {Lockfile}.
214
+ #
215
+ def name_for_locking_dependency_source
216
+ 'Podfile.lock'
217
+ end
218
+
219
+ # Determines whether the given `requirement` is satisfied by the given
220
+ # `spec`, in the context of the current `activated` dependency graph.
221
+ #
222
+ # @return [Boolean] whether `requirement` is satisfied by `spec` in the
223
+ # context of the current `activated` dependency graph.
224
+ #
225
+ # @param [Dependency] requirement the dependency in question.
226
+ #
227
+ # @param [Molinillo::DependencyGraph] activated the current dependency
228
+ # graph in the resolution process.
229
+ #
230
+ # @param [Specification] spec the specification in question.
231
+ #
232
+ def requirement_satisfied_by?(requirement, activated, spec)
233
+ version = spec.version
234
+ return false unless requirement.requirement.satisfied_by?(version)
235
+ return false unless valid_possibility_version_for_root_name?(requirement, activated, spec)
236
+ return false unless spec_is_platform_compatible?(activated, requirement, spec)
237
+ true
238
+ end
239
+
240
+ def valid_possibility_version_for_root_name?(requirement, activated, spec)
241
+ prerelease_requirement = requirement.prerelease? || requirement.external_source || !spec.version.prerelease?
242
+
243
+ activated.each do |vertex|
244
+ next unless vertex.payload
245
+ next unless Specification.root_name(vertex.name) == requirement.root_name
246
+
247
+ prerelease_requirement ||= vertex.requirements.any? { |r| r.prerelease? || r.external_source }
248
+
249
+ if vertex.payload.respond_to?(:version)
250
+ return true if vertex.payload.version == spec.version
251
+ break
252
+ end
253
+ end
254
+
255
+ prerelease_requirement
256
+ end
257
+ private :valid_possibility_version_for_root_name?
258
+
259
+ # Sort dependencies so that the ones that are easiest to resolve are first.
260
+ # Easiest to resolve is (usually) defined by:
261
+ # 1) Is this dependency already activated?
262
+ # 2) How relaxed are the requirements?
263
+ # 3) Are there any conflicts for this dependency?
264
+ # 4) How many possibilities are there to satisfy this dependency?
265
+ #
266
+ # @return [Array<Dependency>] the sorted dependencies.
267
+ #
268
+ # @param [Array<Dependency>] dependencies the unsorted dependencies.
269
+ #
270
+ # @param [Molinillo::DependencyGraph] activated the dependency graph of
271
+ # currently activated specs.
272
+ #
273
+ # @param [{String => Array<Conflict>}] conflicts the current conflicts.
274
+ #
275
+ def sort_dependencies(dependencies, activated, conflicts)
276
+ dependencies.sort_by do |dependency|
277
+ name = name_for(dependency)
278
+ [
279
+ activated.vertex_named(name).payload ? 0 : 1,
280
+ dependency.external_source ? 0 : 1,
281
+ dependency.prerelease? ? 0 : 1,
282
+ conflicts[name] ? 0 : 1,
283
+ search_for(dependency).count,
284
+ ]
285
+ end
286
+ end
287
+
288
+ #-------------------------------------------------------------------------#
289
+
290
+ public
291
+
292
+ # @!group Resolver UI
293
+
294
+ include Molinillo::UI
295
+
296
+ # The UI object the resolver should use for displaying user-facing output.
297
+ #
298
+ # @return [UserInterface] the normal CocoaPods UI object.
299
+ #
300
+ def output
301
+ UI
302
+ end
303
+
304
+ # Called before resolution starts.
305
+ #
306
+ # Completely silence this, as we show nothing.
307
+ #
308
+ # @return [Void]
309
+ #
310
+ def before_resolution
311
+ end
312
+
313
+ # Called after resolution ends.
314
+ #
315
+ # Completely silence this, as we show nothing.
316
+ #
317
+ # @return [Void]
318
+ #
319
+ def after_resolution
320
+ end
321
+
322
+ # Called during resolution to indicate progress.
323
+ #
324
+ # Completely silence this, as we show nothing.
325
+ #
326
+ # @return [Void]
327
+ #
328
+ def indicate_progress
329
+ end
330
+
331
+ #-------------------------------------------------------------------------#
332
+
333
+ private
334
+
335
+ # !@ Resolution context
336
+
337
+ # @return [Hash<String => Set>] A cache that keeps tracks of the sets
338
+ # loaded by the resolution process.
339
+ #
340
+ # @note Sets store the resolved dependencies and return the highest
341
+ # available specification found in the sources. This is done
342
+ # globally and not per target definition because there can be just
343
+ # one Pod installation, so different version of the same Pods for
344
+ # target definitions are not allowed.
345
+ #
346
+ attr_reader :cached_sets
347
+
348
+ #-------------------------------------------------------------------------#
349
+
350
+ private
351
+
352
+ # @!group Private helpers
353
+
354
+ # Returns available specifications which satisfy requirements of given dependency
355
+ # and additional requirements.
356
+ #
357
+ # @param [Dependency] dependency
358
+ # The dependency whose requirements will be satisfied.
359
+ #
360
+ # @param [Array<Requirement>] additional_requirements
361
+ # List of additional requirements which should also be satisfied.
362
+ #
363
+ # @return [Array<Specification>] List of specifications satisfying given requirements.
364
+ #
365
+ def specifications_for_dependency(dependency, additional_requirements = [])
366
+ requirement = Requirement.new(dependency.requirement.as_list + additional_requirements.flat_map(&:as_list))
367
+ find_cached_set(dependency).
368
+ all_specifications(installation_options.warn_for_multiple_pod_sources).
369
+ select { |s| requirement.satisfied_by? s.version }.
370
+ map { |s| s.subspec_by_name(dependency.name, false, true) }.
371
+ compact
372
+ end
373
+
374
+ # @return [Set] Loads or returns a previously initialized set for the Pod
375
+ # of the given dependency.
376
+ #
377
+ # @param [Dependency] dependency
378
+ # The dependency for which the set is needed.
379
+ #
380
+ # @return [Set] the cached set for a given dependency.
381
+ #
382
+ def find_cached_set(dependency)
383
+ name = dependency.root_name
384
+ unless cached_sets[name]
385
+ if dependency.external_source
386
+ spec = sandbox.specification(name)
387
+ unless spec
388
+ raise StandardError, '[Bug] Unable to find the specification ' \
389
+ "for `#{dependency}`."
390
+ end
391
+ set = Specification::Set::External.new(spec)
392
+ else
393
+ set = create_set_from_sources(dependency)
394
+ end
395
+ cached_sets[name] = set
396
+ unless set
397
+ raise Molinillo::NoSuchDependencyError.new(dependency) # rubocop:disable Style/RaiseArgs
398
+ end
399
+ end
400
+ cached_sets[name]
401
+ end
402
+
403
+ # @return [Requirement, Nil]
404
+ # The {Requirement} that locks the dependency with name `name` in
405
+ # {#locked_dependencies}.
406
+ #
407
+ def requirement_for_locked_pod_named(name)
408
+ if vertex = locked_dependencies.vertex_named(name)
409
+ if dependency = vertex.payload
410
+ dependency.requirement
411
+ end
412
+ end
413
+ end
414
+
415
+ # @return [Set] Creates a set for the Pod of the given dependency from the
416
+ # sources. The set will contain all versions from all sources that
417
+ # include the Pod.
418
+ #
419
+ # @param [Dependency] dependency
420
+ # The dependency for which the set is needed.
421
+ #
422
+ def create_set_from_sources(dependency)
423
+ aggregate_for_dependency(dependency).search(dependency)
424
+ end
425
+
426
+ # @return [Source::Aggregate] The aggregate of the {#sources}.
427
+ #
428
+ def aggregate_for_dependency(dependency)
429
+ if dependency && dependency.podspec_repo
430
+ return Config.instance.sources_manager.aggregate_for_dependency(dependency)
431
+ else
432
+ @aggregate ||= Source::Aggregate.new(sources)
433
+ end
434
+ end
435
+
436
+ # Ensures that a specification is compatible with the platform of a target.
437
+ #
438
+ # @raise If the specification is not supported by the target.
439
+ #
440
+ # @return [void]
441
+ #
442
+ def validate_platform(spec, target)
443
+ return unless target_platform = target.platform
444
+ unless spec.available_platforms.any? { |p| target_platform.to_sym == p.to_sym }
445
+ raise Informative, "The platform of the target `#{target.name}` " \
446
+ "(#{target.platform}) is not compatible with `#{spec}`, which does " \
447
+ "not support `#{target.platform.name}`."
448
+ end
449
+ end
450
+
451
+ # Handles errors that come out of a {Molinillo::Resolver}.
452
+ #
453
+ # @return [void]
454
+ #
455
+ # @param [Molinillo::ResolverError] error
456
+ #
457
+ def handle_resolver_error(error)
458
+ message = error.message
459
+ type = Informative
460
+ case error
461
+ when Molinillo::VersionConflict
462
+ message = error.message_with_trees(
463
+ :solver_name => 'CocoaPods',
464
+ :possibility_type => 'pod',
465
+ :version_for_spec => lambda(&:version),
466
+ :additional_message_for_conflict => lambda do |o, name, conflict|
467
+ local_pod_parent = conflict.requirement_trees.flatten.reverse.find(&:local?)
468
+ if local_pod_parent && !specifications_for_dependency(conflict.requirement).empty? && !conflict.possibility && conflict.locked_requirement
469
+ # Conflict was caused by a requirement from a local dependency.
470
+ # Tell user to use `pod update`.
471
+ o << "\nIt seems like you've changed the constraints of dependency `#{name}` " \
472
+ "inside your development pod `#{local_pod_parent.name}`.\nYou should run `pod update #{name}` to apply " \
473
+ "changes you've made."
474
+ elsif (conflict.possibility && conflict.possibility.version.prerelease?) &&
475
+ (conflict.requirement && !(
476
+ conflict.requirement.prerelease? ||
477
+ conflict.requirement.external_source)
478
+ )
479
+ # Conflict was caused by not specifying an explicit version for the requirement #[name],
480
+ # and there is no available stable version satisfying constraints for the requirement.
481
+ o << "\nThere are only pre-release versions available satisfying the following requirements:\n"
482
+ conflict.requirements.values.flatten.uniq.each do |r|
483
+ unless search_for(r).empty?
484
+ o << "\n\t'#{name}', '#{r.requirement}'\n"
485
+ end
486
+ end
487
+ o << "\nYou should explicitly specify the version in order to install a pre-release version"
488
+ elsif !conflict.existing
489
+ conflicts = conflict.requirements.values.flatten.uniq
490
+ found_conflicted_specs = conflicts.reject { |c| search_for(c).empty? }
491
+ if found_conflicted_specs.empty?
492
+ # There are no existing specification inside any of the spec repos with given requirements.
493
+ type = NoSpecFoundError
494
+ dependencies = conflicts.count == 1 ? 'dependency' : 'dependencies'
495
+ o << "\nNone of your spec sources contain a spec satisfying "\
496
+ "the #{dependencies}: `#{conflicts.join(', ')}`." \
497
+ "\n\nYou have either:"
498
+ unless specs_updated?
499
+ o << "\n * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`."
500
+ end
501
+ o << "\n * mistyped the name or version." \
502
+ "\n * not added the source repo that hosts the Podspec to your Podfile." \
503
+ "\n\nNote: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default."
504
+
505
+ else
506
+ o << "\nSpecs satisfying the `#{conflicts.join(', ')}` dependency were found, " \
507
+ 'but they required a higher minimum deployment target.'
508
+ end
509
+ end
510
+ end,
511
+ )
512
+ end
513
+ raise type.new(message).tap { |e| e.set_backtrace(error.backtrace) }
514
+ end
515
+
516
+ # Returns whether the given spec is platform-compatible with the dependency
517
+ # graph, taking into account the dependency that has required the spec.
518
+ #
519
+ # @param [Molinillo::DependencyGraph] dependency_graph
520
+ #
521
+ # @param [Dependency] dependency
522
+ #
523
+ # @param [Specification] specification
524
+ #
525
+ # @return [Bool]
526
+ def spec_is_platform_compatible?(dependency_graph, dependency, spec)
527
+ # This is safe since a pod will only be in locked dependencies if we're
528
+ # using the same exact version
529
+ return true if locked_dependencies.vertex_named(spec.name)
530
+
531
+ vertex = dependency_graph.vertex_named(dependency.name)
532
+ predecessors = vertex.recursive_predecessors.select(&:root?)
533
+ predecessors << vertex if vertex.root?
534
+ platforms_to_satisfy = predecessors.flat_map(&:explicit_requirements).flat_map { |r| @platforms_by_dependency[r] }.uniq
535
+
536
+ available_platforms = spec.available_platforms
537
+
538
+ platforms_to_satisfy.all? do |platform_to_satisfy|
539
+ available_platforms.all? do |spec_platform|
540
+ next true unless spec_platform.name == platform_to_satisfy.name
541
+ platform_to_satisfy.supports?(spec_platform)
542
+ end
543
+ end
544
+ end
545
+
546
+ # Returns the target-appropriate nodes that are `successors` of `node`,
547
+ # rejecting those that are scoped by target platform and have incompatible
548
+ # targets.
549
+ #
550
+ # @return [Array<Molinillo::DependencyGraph::Vertex>]
551
+ # An array of target-appropriate nodes whose `payload`s are
552
+ # dependencies for `target`.
553
+ #
554
+ def valid_dependencies_for_target(target)
555
+ dependencies = Set.new
556
+ @podfile_dependency_cache.target_definition_dependencies(target).each do |dep|
557
+ node = @activated.vertex_named(dep.name)
558
+ add_valid_dependencies_from_node(node, target, dependencies)
559
+ end
560
+ dependencies
561
+ end
562
+
563
+ def add_valid_dependencies_from_node(node, target, dependencies)
564
+ return unless dependencies.add?(node)
565
+ validate_platform(node.payload, target)
566
+ node.outgoing_edges.each do |edge|
567
+ next unless edge_is_valid_for_target_platform?(edge, target.platform)
568
+ add_valid_dependencies_from_node(edge.destination, target, dependencies)
569
+ end
570
+ end
571
+
572
+ # Whether the given `edge` should be followed to find dependencies for the
573
+ # given `target_platform`.
574
+ #
575
+ # @return [Bool]
576
+ #
577
+ def edge_is_valid_for_target_platform?(edge, target_platform)
578
+ requirement_name = edge.requirement.name
579
+
580
+ edge.origin.payload.all_dependencies(target_platform).any? do |dep|
581
+ dep.name == requirement_name
582
+ end
583
+ end
584
+ end
585
+ end