xcocoapods 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
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