cocoapods 1.5.2 → 1.6.1

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 (81) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +365 -1
  3. data/bin/pod +1 -1
  4. data/lib/cocoapods/command/cache/clean.rb +1 -1
  5. data/lib/cocoapods/command/init.rb +4 -2
  6. data/lib/cocoapods/command/install.rb +7 -0
  7. data/lib/cocoapods/command/lib/lint.rb +8 -1
  8. data/lib/cocoapods/command/outdated.rb +4 -9
  9. data/lib/cocoapods/command/repo/add.rb +1 -1
  10. data/lib/cocoapods/command/repo/list.rb +1 -1
  11. data/lib/cocoapods/command/repo/push.rb +17 -12
  12. data/lib/cocoapods/command/repo/remove.rb +1 -1
  13. data/lib/cocoapods/command/repo/update.rb +1 -1
  14. data/lib/cocoapods/command/setup.rb +1 -1
  15. data/lib/cocoapods/command/spec/create.rb +39 -39
  16. data/lib/cocoapods/command/spec/lint.rb +8 -1
  17. data/lib/cocoapods/command.rb +3 -1
  18. data/lib/cocoapods/config.rb +13 -2
  19. data/lib/cocoapods/downloader/cache.rb +1 -1
  20. data/lib/cocoapods/executable.rb +3 -3
  21. data/lib/cocoapods/external_sources/abstract_external_source.rb +23 -13
  22. data/lib/cocoapods/external_sources.rb +7 -4
  23. data/lib/cocoapods/gem_version.rb +1 -1
  24. data/lib/cocoapods/generator/acknowledgements/markdown.rb +6 -0
  25. data/lib/cocoapods/generator/acknowledgements/plist.rb +13 -2
  26. data/lib/cocoapods/generator/app_target_helper.rb +141 -17
  27. data/lib/cocoapods/generator/copy_resources_script.rb +14 -3
  28. data/lib/cocoapods/generator/dummy_source.rb +14 -5
  29. data/lib/cocoapods/generator/embed_frameworks_script.rb +37 -20
  30. data/lib/cocoapods/generator/header.rb +1 -1
  31. data/lib/cocoapods/generator/info_plist_file.rb +12 -4
  32. data/lib/cocoapods/generator/prefix_header.rb +2 -2
  33. data/lib/cocoapods/hooks_manager.rb +28 -17
  34. data/lib/cocoapods/installer/analyzer/analysis_result.rb +52 -22
  35. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +14 -6
  36. data/lib/cocoapods/installer/analyzer/pod_variant.rb +4 -5
  37. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +3 -14
  38. data/lib/cocoapods/installer/analyzer/specs_state.rb +28 -4
  39. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +27 -14
  40. data/lib/cocoapods/installer/analyzer/target_inspector.rb +17 -11
  41. data/lib/cocoapods/installer/analyzer.rb +391 -284
  42. data/lib/cocoapods/installer/installation_options.rb +2 -0
  43. data/lib/cocoapods/installer/pod_source_installer.rb +31 -43
  44. data/lib/cocoapods/installer/post_install_hooks_context.rb +72 -47
  45. data/lib/cocoapods/installer/pre_install_hooks_context.rb +22 -13
  46. data/lib/cocoapods/installer/source_provider_hooks_context.rb +3 -1
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +44 -11
  48. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +69 -29
  49. data/lib/cocoapods/installer/user_project_integrator.rb +6 -4
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +25 -16
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +104 -0
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +23 -50
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +296 -177
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +51 -33
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +93 -0
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +62 -69
  57. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +72 -0
  58. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +130 -122
  59. data/lib/cocoapods/installer/xcode/target_validator.rb +15 -9
  60. data/lib/cocoapods/installer.rb +140 -63
  61. data/lib/cocoapods/project.rb +16 -14
  62. data/lib/cocoapods/resolver/resolver_specification.rb +41 -0
  63. data/lib/cocoapods/resolver.rb +79 -98
  64. data/lib/cocoapods/sandbox/file_accessor.rb +11 -6
  65. data/lib/cocoapods/sandbox/headers_store.rb +9 -8
  66. data/lib/cocoapods/sandbox/path_list.rb +5 -8
  67. data/lib/cocoapods/sandbox.rb +31 -43
  68. data/lib/cocoapods/sources_manager.rb +1 -1
  69. data/lib/cocoapods/target/aggregate_target.rb +143 -85
  70. data/lib/cocoapods/target/build_settings.rb +1124 -0
  71. data/lib/cocoapods/target/framework_paths.rb +36 -0
  72. data/lib/cocoapods/target/pod_target.rb +198 -295
  73. data/lib/cocoapods/target.rb +92 -37
  74. data/lib/cocoapods/user_interface.rb +5 -0
  75. data/lib/cocoapods/validator.rb +149 -44
  76. data/lib/cocoapods.rb +0 -1
  77. metadata +31 -23
  78. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +0 -260
  79. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +0 -87
  80. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +0 -558
  81. data/lib/cocoapods/generator/xcconfig.rb +0 -13
@@ -19,43 +19,62 @@ module Pod
19
19
  autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result'
20
20
  autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector'
21
21
 
22
- # @return [Sandbox] The sandbox where the Pods should be installed.
22
+ # @return [String] The version of iOS which requires binaries with only 64-bit architectures
23
+ #
24
+ IOS_64_BIT_ONLY_VERSION = Version.new('11.0')
25
+
26
+ # @return [Integer] The Xcode object version until which 64-bit architectures should be manually specified
27
+ #
28
+ # Xcode 10 will automatically select the correct architectures based on deployment target
29
+ IOS_64_BIT_ONLY_PROJECT_VERSION = 50
30
+
31
+ # @return [Sandbox] The sandbox to use for this analysis.
23
32
  #
24
33
  attr_reader :sandbox
25
34
 
26
- # @return [Podfile] The Podfile specification that contains the
27
- # information of the Pods that should be installed.
35
+ # @return [Podfile] The Podfile specification that contains the information of the Pods that should be installed.
28
36
  #
29
37
  attr_reader :podfile
30
38
 
31
- # @return [Lockfile] The Lockfile that stores the information about the
32
- # Pods previously installed on any machine.
39
+ # @return [Lockfile] The Lockfile, if available, that stores the information about the Pods previously installed.
33
40
  #
34
41
  attr_reader :lockfile
35
42
 
36
- # @return [Array<Source>] Sources provided by plugins
43
+ # @return [Array<Source>] Sources provided by plugins or `nil`.
37
44
  #
38
45
  attr_reader :plugin_sources
39
46
 
47
+ # @return [Bool] Whether the analysis has dependencies and thus sources must be configured.
48
+ #
49
+ # @note This is used by the `pod lib lint` command to prevent update of specs when not needed.
50
+ #
51
+ attr_reader :has_dependencies
52
+ alias_method :has_dependencies?, :has_dependencies
53
+
54
+ # @return [Hash, Boolean, nil] Pods that have been requested to be updated or true if all Pods should be updated.
55
+ # This can be false if no pods should be updated.
56
+ #
57
+ attr_reader :pods_to_update
58
+
40
59
  # Initialize a new instance
41
60
  #
42
- # @param [Sandbox] sandbox @see sandbox
43
- # @param [Podfile] podfile @see podfile
44
- # @param [Lockfile] lockfile @see lockfile
45
- # @param [Array<Source>] plugin_sources @see plugin_sources
61
+ # @param [Sandbox] sandbox @see #sandbox
62
+ # @param [Podfile] podfile @see #podfile
63
+ # @param [Lockfile] lockfile @see #lockfile
64
+ # @param [Array<Source>] plugin_sources @see #plugin_sources
65
+ # @param [Boolean] has_dependencies @see #has_dependencies
66
+ # @param [Hash, Boolean, nil] pods_to_update @see #pods_to_update
46
67
  #
47
- def initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil)
68
+ def initialize(sandbox, podfile, lockfile = nil, plugin_sources = nil, has_dependencies = true,
69
+ pods_to_update = false)
48
70
  @sandbox = sandbox
49
71
  @podfile = podfile
50
72
  @lockfile = lockfile
51
73
  @plugin_sources = plugin_sources
52
-
53
- @update = false
54
- @allow_pre_downloads = true
55
- @has_dependencies = true
56
- @test_pod_target_analyzer_cache = {}
57
- @test_pod_target_key = Struct.new(:name, :pod_targets)
74
+ @has_dependencies = has_dependencies
75
+ @pods_to_update = pods_to_update
58
76
  @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
77
+ @result = nil
59
78
  end
60
79
 
61
80
  # Performs the analysis.
@@ -70,124 +89,124 @@ module Pod
70
89
  # @return [AnalysisResult]
71
90
  #
72
91
  def analyze(allow_fetches = true)
92
+ return @result if @result
73
93
  validate_podfile!
74
94
  validate_lockfile_version!
75
- @result = AnalysisResult.new
76
- @result.podfile_dependency_cache = @podfile_dependency_cache
77
95
  if installation_options.integrate_targets?
78
- @result.target_inspections = inspect_targets_to_integrate
96
+ target_inspections = inspect_targets_to_integrate
79
97
  else
80
98
  verify_platforms_specified!
99
+ target_inspections = {}
81
100
  end
82
- @result.podfile_state = generate_podfile_state
101
+ podfile_state = generate_podfile_state
83
102
 
84
103
  store_existing_checkout_options
85
- fetch_external_sources if allow_fetches
104
+ if allow_fetches == :outdated
105
+ # special-cased -- we're only really resolving for outdated, rather than doing a full analysis
106
+ elsif allow_fetches == true
107
+ fetch_external_sources(podfile_state)
108
+ elsif !dependencies_to_fetch(podfile_state).all?(&:local?)
109
+ raise Informative, 'Cannot analyze without fetching dependencies since the sandbox is not up-to-date. Run `pod install` to ensure all dependencies have been fetched.' \
110
+ "\n The missing dependencies are:\n \t#{dependencies_to_fetch(podfile_state).reject(&:local?).join("\n \t")}"
111
+ end
86
112
 
87
- @locked_dependencies = generate_version_locking_dependencies
88
- resolver_specs_by_target = resolve_dependencies
113
+ locked_dependencies = generate_version_locking_dependencies(podfile_state)
114
+ resolver_specs_by_target = resolve_dependencies(locked_dependencies)
89
115
  validate_platforms(resolver_specs_by_target)
90
- @result.specifications = generate_specifications(resolver_specs_by_target)
91
- @result.targets = generate_targets(resolver_specs_by_target)
92
- @result.sandbox_state = generate_sandbox_state
93
- @result.specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
116
+ specifications = generate_specifications(resolver_specs_by_target)
117
+ targets = generate_targets(resolver_specs_by_target, target_inspections)
118
+ pod_targets = calculate_pod_targets(targets)
119
+ sandbox_state = generate_sandbox_state(specifications)
120
+ specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
94
121
  hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
95
122
  end
96
- @result.specs_by_source = Hash[resolver_specs_by_target.values.flatten(1).group_by(&:source).map { |source, specs| [source, specs.map(&:spec).uniq] }]
97
- sources.each { |s| @result.specs_by_source[s] ||= [] }
98
- @result
123
+ specs_by_source = Hash[resolver_specs_by_target.values.flatten(1).group_by(&:source).map do |source, specs|
124
+ [source, specs.map(&:spec).uniq]
125
+ end]
126
+ sources.each { |s| specs_by_source[s] ||= [] }
127
+ @result = AnalysisResult.new(podfile_state, specs_by_target, specs_by_source, specifications, sandbox_state,
128
+ targets, pod_targets, @podfile_dependency_cache)
99
129
  end
100
130
 
101
- attr_accessor :result
102
-
103
- # @return [Bool] Whether an installation should be performed or this
104
- # CocoaPods project is already up to date.
131
+ # Updates the git source repositories.
105
132
  #
106
- def needs_install?
107
- analysis_result = analyze(false)
108
- podfile_needs_install?(analysis_result) || sandbox_needs_install?(analysis_result)
133
+ def update_repositories
134
+ sources.each do |source|
135
+ if source.git?
136
+ config.sources_manager.update(source.name, true)
137
+ else
138
+ UI.message "Skipping `#{source.name}` update because the repository is not a git source repository."
139
+ end
140
+ end
141
+ @specs_updated = true
109
142
  end
110
143
 
111
- # @param [AnalysisResult] analysis_result
112
- # the analysis result to check for changes
144
+ # Returns the sources used to query for specifications.
113
145
  #
114
- # @return [Bool] Whether the podfile has changes respect to the lockfile.
146
+ # When no explicit Podfile sources or plugin sources are defined, this defaults to the master spec repository.
115
147
  #
116
- def podfile_needs_install?(analysis_result)
117
- state = analysis_result.podfile_state
118
- needing_install = state.added + state.changed + state.deleted
119
- !needing_install.empty?
120
- end
121
-
122
- # @param [AnalysisResult] analysis_result
123
- # the analysis result to check for changes
124
- #
125
- # @return [Bool] Whether the sandbox is in synch with the lockfile.
148
+ # @return [Array<Source>] the sources to be used in finding specifications, as specified by the podfile or all
149
+ # sources.
126
150
  #
127
- def sandbox_needs_install?(analysis_result)
128
- state = analysis_result.sandbox_state
129
- needing_install = state.added + state.changed + state.deleted
130
- !needing_install.empty?
151
+ def sources
152
+ @sources ||= begin
153
+ sources = podfile.sources
154
+ plugin_sources = @plugin_sources || []
155
+
156
+ # Add any sources specified using the :source flag on individual dependencies.
157
+ dependency_sources = podfile_dependencies.map(&:podspec_repo).compact
158
+ all_dependencies_have_sources = dependency_sources.count == podfile_dependencies.count
159
+
160
+ if all_dependencies_have_sources
161
+ sources = dependency_sources
162
+ elsif has_dependencies? && sources.empty? && plugin_sources.empty?
163
+ sources = ['https://github.com/CocoaPods/Specs.git']
164
+ else
165
+ sources += dependency_sources
166
+ end
167
+
168
+ result = sources.uniq.map do |source_url|
169
+ config.sources_manager.find_or_create_source_with_url(source_url)
170
+ end
171
+ unless plugin_sources.empty?
172
+ result.insert(0, *plugin_sources)
173
+ end
174
+ result
175
+ end
131
176
  end
132
177
 
133
178
  #-----------------------------------------------------------------------#
134
179
 
135
- # @!group Configuration
180
+ private
136
181
 
137
- # @return [Hash, Boolean, nil] Pods that have been requested to be
138
- # updated or true if all Pods should be updated
139
- #
140
- attr_accessor :update
182
+ # @!group Configuration
141
183
 
142
184
  # @return [Bool] Whether the version of the dependencies which did not
143
185
  # change in the Podfile should be locked.
144
186
  #
145
187
  def update_mode?
146
- update != nil
188
+ pods_to_update != nil
147
189
  end
148
190
 
149
191
  # @return [Symbol] Whether and how the dependencies in the Podfile
150
192
  # should be updated.
151
193
  #
152
194
  def update_mode
153
- if !update
195
+ if !pods_to_update
154
196
  :none
155
- elsif update == true
197
+ elsif pods_to_update == true
156
198
  :all
157
- elsif !update[:pods].nil?
199
+ elsif !pods_to_update[:pods].nil?
158
200
  :selected
159
201
  end
160
202
  end
161
203
 
162
- # @return [Bool] Whether the analysis allows pre-downloads and thus
163
- # modifications to the sandbox.
164
- #
165
- # @note This flag should not be used in installations.
166
- #
167
- # @note This is used by the `pod outdated` command to prevent
168
- # modification of the sandbox in the resolution process.
169
- #
170
- attr_accessor :allow_pre_downloads
171
- alias_method :allow_pre_downloads?, :allow_pre_downloads
172
-
173
- # @return [Bool] Whether the analysis has dependencies and thus
174
- # sources must be configured.
175
- #
176
- # @note This is used by the `pod lib lint` command to prevent
177
- # update of specs when not needed.
178
- #
179
- attr_accessor :has_dependencies
180
- alias_method :has_dependencies?, :has_dependencies
204
+ def podfile_dependencies
205
+ @podfile_dependency_cache.podfile_dependencies
206
+ end
181
207
 
182
208
  #-----------------------------------------------------------------------#
183
209
 
184
- private
185
-
186
- # @return [Bool] Whether the analysis has updated sources repositories.
187
- #
188
- attr_accessor :specs_updated
189
- alias_method :specs_updated?, :specs_updated
190
-
191
210
  def validate_podfile!
192
211
  validator = Installer::PodfileValidator.new(podfile, @podfile_dependency_cache)
193
212
  validator.validate
@@ -223,8 +242,7 @@ module Pod
223
242
  # the name of the Pod (root name of the dependencies) and doesn't
224
243
  # group them by target definition.
225
244
  #
226
- # @todo [CocoaPods > 0.18] If there isn't a Lockfile all the Pods should
227
- # be marked as added.
245
+ # @return [SpecState]
228
246
  #
229
247
  def generate_podfile_state
230
248
  if lockfile
@@ -232,34 +250,17 @@ module Pod
232
250
  UI.section 'Finding Podfile changes' do
233
251
  pods_by_state = lockfile.detect_changes_with_podfile(podfile)
234
252
  pods_state = SpecsState.new(pods_by_state)
235
- pods_state.print
253
+ pods_state.print if config.verbose?
236
254
  end
237
255
  pods_state
238
256
  else
239
257
  state = SpecsState.new
240
- state.added.merge(@podfile_dependency_cache.podfile_dependencies.map(&:root_name))
258
+ state.added.merge(podfile_dependencies.map(&:root_name))
241
259
  state
242
260
  end
243
261
  end
244
262
 
245
- public
246
-
247
- # Updates the git source repositories.
248
- #
249
- def update_repositories
250
- sources.each do |source|
251
- if source.git?
252
- config.sources_manager.update(source.name, true)
253
- else
254
- UI.message "Skipping `#{source.name}` update because the repository is not a git source repository."
255
- end
256
- end
257
- @specs_updated = true
258
- end
259
-
260
- private
261
-
262
- # Copies the pod_targets of any of the app embedded aggregate targets into
263
+ # Copies the pod targets of any of the app embedded aggregate targets into
263
264
  # their potential host aggregate target, if that potential host aggregate target's
264
265
  # user_target hosts any of the app embedded aggregate targets' user_targets
265
266
  #
@@ -273,13 +274,17 @@ module Pod
273
274
  # targets are considered, otherwise, all other types are have
274
275
  # their pods copied to their host targets as well (extensions, etc.)
275
276
  #
276
- def copy_embedded_target_pod_targets_to_host(aggregate_target, embedded_aggregate_targets, libraries_only)
277
- return if aggregate_target.requires_host_target?
278
- pod_target_names = Set.new(aggregate_target.pod_targets.map(&:name))
277
+ # @return [Hash{String=>Array<PodTarget>}] the additional pod targets to include to the host
278
+ # keyed by their configuration.
279
+ #
280
+ def embedded_target_pod_targets_by_host(aggregate_target, embedded_aggregate_targets, libraries_only)
281
+ return {} if aggregate_target.requires_host_target?
279
282
  aggregate_user_target_uuids = Set.new(aggregate_target.user_targets.map(&:uuid))
283
+ embedded_pod_targets_by_build_config = Hash.new([].freeze)
280
284
  embedded_aggregate_targets.each do |embedded_aggregate_target|
281
285
  # Skip non libraries in library-only mode
282
286
  next if libraries_only && !embedded_aggregate_target.library?
287
+ next if aggregate_target.search_paths_aggregate_targets.include?(embedded_aggregate_target)
283
288
  next unless embedded_aggregate_target.user_targets.any? do |embedded_user_target|
284
289
  # You have to ask the host target's project for the host targets of
285
290
  # the embedded target, as opposed to asking user_project for the
@@ -290,11 +295,18 @@ module Pod
290
295
  host_target_uuids = Set.new(aggregate_target.user_project.host_targets_for_embedded_target(embedded_user_target).map(&:uuid))
291
296
  !aggregate_user_target_uuids.intersection(host_target_uuids).empty?
292
297
  end
293
- # This embedded target is hosted by the aggregate target's user_target; copy over the non-duplicate pod_targets
294
- aggregate_target.pod_targets = aggregate_target.pod_targets + embedded_aggregate_target.pod_targets.select do |pod_target|
295
- !pod_target_names.include? pod_target.name
298
+ embedded_aggregate_target.user_build_configurations.keys.each do |configuration_name|
299
+ pod_target_names = Set.new(aggregate_target.pod_targets_for_build_configuration(configuration_name).map(&:name))
300
+ embedded_pod_targets = embedded_aggregate_target.pod_targets_for_build_configuration(configuration_name).select do |pod_target|
301
+ if !pod_target_names.include?(pod_target.name) &&
302
+ aggregate_target.pod_targets.none? { |aggregate_pod_target| (pod_target.specs - aggregate_pod_target.specs).empty? }
303
+ pod_target.name
304
+ end
305
+ end
306
+ embedded_pod_targets_by_build_config[configuration_name] = embedded_pod_targets
296
307
  end
297
308
  end
309
+ embedded_pod_targets_by_build_config
298
310
  end
299
311
 
300
312
  # Raises an error if there are embedded targets in the Podfile, but
@@ -384,13 +396,22 @@ module Pod
384
396
  # mapping of targets to resolved specs (containing information about test usage)
385
397
  # aggregate targets
386
398
  #
399
+ # @param [Array<TargetInspection>] target_inspections
400
+ # the user target inspections used to construct the aggregate and pod targets.
401
+ #
387
402
  # @return [Array<AggregateTarget>] the list of aggregate targets generated.
388
403
  #
389
- def generate_targets(resolver_specs_by_target)
404
+ def generate_targets(resolver_specs_by_target, target_inspections)
390
405
  resolver_specs_by_target = resolver_specs_by_target.reject { |td, _| td.abstract? }
391
- pod_targets = generate_pod_targets(resolver_specs_by_target)
406
+ pod_targets = generate_pod_targets(resolver_specs_by_target, target_inspections)
392
407
  aggregate_targets = resolver_specs_by_target.keys.map do |target_definition|
393
- generate_target(target_definition, pod_targets, resolver_specs_by_target)
408
+ generate_target(target_definition, target_inspections, pod_targets, resolver_specs_by_target)
409
+ end
410
+ aggregate_targets.each do |target|
411
+ search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
412
+ target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
413
+ end
414
+ target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze
394
415
  end
395
416
  if installation_options.integrate_targets?
396
417
  # Copy embedded target pods that cannot have their pods embedded as frameworks to
@@ -399,21 +420,20 @@ module Pod
399
420
  analyze_host_targets_in_podfile(aggregate_targets, embedded_targets)
400
421
 
401
422
  use_frameworks_embedded_targets, non_use_frameworks_embedded_targets = embedded_targets.partition(&:requires_frameworks?)
402
- aggregate_targets.each do |target|
423
+ aggregate_targets = aggregate_targets.map do |aggregate_target|
403
424
  # For targets that require frameworks, we always have to copy their pods to their
404
425
  # host targets because those frameworks will all be loaded from the host target's bundle
405
- copy_embedded_target_pod_targets_to_host(target, use_frameworks_embedded_targets, false)
426
+ embedded_pod_targets = embedded_target_pod_targets_by_host(aggregate_target, use_frameworks_embedded_targets, false)
406
427
 
407
428
  # For targets that don't require frameworks, we only have to consider library-type
408
429
  # targets because their host targets will still need to link their pods
409
- copy_embedded_target_pod_targets_to_host(target, non_use_frameworks_embedded_targets, true)
430
+ embedded_pod_targets.merge!(embedded_target_pod_targets_by_host(aggregate_target, non_use_frameworks_embedded_targets, true))
431
+
432
+ next aggregate_target if embedded_pod_targets.empty?
433
+ aggregate_target.merge_embedded_pod_targets(embedded_pod_targets)
410
434
  end
411
435
  end
412
- aggregate_targets.each do |target|
413
- target.search_paths_aggregate_targets.concat(aggregate_targets.select do |aggregate_target|
414
- target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
415
- end).freeze
416
- end
436
+ aggregate_targets
417
437
  end
418
438
 
419
439
  # Setup the aggregate target for a single user target
@@ -421,6 +441,9 @@ module Pod
421
441
  # @param [TargetDefinition] target_definition
422
442
  # the target definition for the user target.
423
443
  #
444
+ # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections
445
+ # the user target inspections used to construct the aggregate and pod targets.
446
+ #
424
447
  # @param [Array<PodTarget>] pod_targets
425
448
  # the pod targets, which were generated.
426
449
  #
@@ -429,30 +452,44 @@ module Pod
429
452
  #
430
453
  # @return [AggregateTarget]
431
454
  #
432
- def generate_target(target_definition, pod_targets, resolver_specs_by_target)
433
- target = AggregateTarget.new(target_definition, sandbox)
434
- target.host_requires_frameworks |= target_definition.uses_frameworks?
435
-
455
+ def generate_target(target_definition, target_inspections, pod_targets, resolver_specs_by_target)
436
456
  if installation_options.integrate_targets?
437
- target_inspection = result.target_inspections[target_definition]
457
+ target_inspection = target_inspections[target_definition]
438
458
  raise "missing inspection: #{target_definition.name}" unless target_inspection
439
- target.user_project = target_inspection.project
440
- target.client_root = target.user_project_path.dirname.realpath
441
- target.user_target_uuids = target_inspection.project_target_uuids
442
- target.user_build_configurations = target_inspection.build_configurations
443
- target.archs = target_inspection.archs
459
+ target_requires_64_bit = Analyzer.requires_64_bit_archs?(target_definition.platform, target_inspection.project.object_version)
460
+ user_project = target_inspection.project
461
+ client_root = target_inspection.client_root
462
+ user_target_uuids = target_inspection.project_target_uuids
463
+ user_build_configurations = target_inspection.build_configurations
464
+ archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : target_inspection.archs
444
465
  else
445
- target.client_root = config.installation_root.realpath
446
- target.user_target_uuids = []
447
- target.user_build_configurations = target_definition.build_configurations || { 'Release' => :release, 'Debug' => :debug }
448
- if target_definition.platform && target_definition.platform.name == :osx
449
- target.archs = '$(ARCHS_STANDARD_64_BIT)'
450
- end
466
+ target_requires_64_bit = Analyzer.requires_64_bit_archs?(target_definition.platform, nil)
467
+ user_project = nil
468
+ client_root = config.installation_root.realpath
469
+ user_target_uuids = []
470
+ user_build_configurations = target_definition.build_configurations || Target::DEFAULT_BUILD_CONFIGURATIONS
471
+ archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : []
451
472
  end
473
+ platform = target_definition.platform
474
+ build_configurations = user_build_configurations.keys.concat(target_definition.all_whitelisted_configurations).uniq
475
+ pod_targets_for_build_configuration = filter_pod_targets_for_target_definition(target_definition, pod_targets,
476
+ resolver_specs_by_target,
477
+ build_configurations)
478
+ AggregateTarget.new(sandbox, target_definition.uses_frameworks?, user_build_configurations, archs, platform,
479
+ target_definition, client_root, user_project, user_target_uuids,
480
+ pod_targets_for_build_configuration)
481
+ end
452
482
 
453
- target.pod_targets = filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target)
454
-
455
- target
483
+ # @return [Array<PodTarget>] The model representations of pod targets.
484
+ #
485
+ def calculate_pod_targets(aggregate_targets)
486
+ aggregate_target_pod_targets = aggregate_targets.flat_map(&:pod_targets).uniq
487
+ test_dependent_targets = aggregate_target_pod_targets.flat_map do |pod_target|
488
+ pod_target.test_specs.flat_map do |test_spec|
489
+ pod_target.recursive_test_dependent_targets(test_spec)
490
+ end
491
+ end
492
+ (aggregate_target_pod_targets + test_dependent_targets).uniq
456
493
  end
457
494
 
458
495
  # Returns a filtered list of pod targets that should or should not be part of the target definition. Pod targets
@@ -467,14 +504,48 @@ module Pod
467
504
  # @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
468
505
  # the resolved specifications grouped by target.
469
506
  #
470
- # @return [Array<PodTarget>] the filtered list of pod targets.
507
+ # @param [Array<String>] build_configurations
508
+ # The list of all build configurations the targets will be built for.
471
509
  #
472
- def filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target)
473
- pod_targets.select do |pod_target|
474
- included_in_target_definition = pod_target.target_definitions.include?(target_definition)
475
- used_by_tests_only = resolver_specs_by_target[target_definition].select { |resolver_spec| pod_target.specs.include?(resolver_spec.spec) }.all?(&:used_by_tests_only?)
476
- included_in_target_definition && !used_by_tests_only
510
+ # @return [Hash<String => Array<PodTarget>>]
511
+ # the filtered list of pod targets, grouped by build configuration.
512
+ #
513
+ def filter_pod_targets_for_target_definition(target_definition, pod_targets, resolver_specs_by_target, build_configurations)
514
+ pod_targets_by_build_config = Hash.new([].freeze)
515
+ build_configurations.each { |config| pod_targets_by_build_config[config] = [] }
516
+
517
+ pod_targets.each do |pod_target|
518
+ next unless pod_target.target_definitions.include?(target_definition)
519
+ next unless resolver_specs_by_target[target_definition].any? do |resolver_spec|
520
+ !resolver_spec.used_by_tests_only? && pod_target.specs.include?(resolver_spec.spec)
521
+ end
522
+
523
+ pod_name = pod_target.pod_name
524
+
525
+ dependencies = @podfile_dependency_cache.target_definition_dependencies(target_definition).select do |dependency|
526
+ Specification.root_name(dependency.name) == pod_name
527
+ end
528
+
529
+ build_configurations.each do |configuration_name|
530
+ whitelists = dependencies.map do |dependency|
531
+ target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name)
532
+ end.uniq
533
+
534
+ case whitelists
535
+ when [], [true] then nil
536
+ when [false] then next
537
+ else
538
+ raise Informative, "The subspecs of `#{pod_name}` are linked to " \
539
+ "different build configurations for the `#{target_definition}` " \
540
+ 'target. CocoaPods does not currently support subspecs across ' \
541
+ 'different build configurations.'
542
+ end
543
+
544
+ pod_targets_by_build_config[configuration_name] << pod_target
545
+ end
477
546
  end
547
+
548
+ pod_targets_by_build_config
478
549
  end
479
550
 
480
551
  # Setup the pod targets for an aggregate target. Deduplicates resulting
@@ -484,9 +555,12 @@ module Pod
484
555
  # @param [Hash{Podfile::TargetDefinition => Array<ResolvedSpecification>}] resolver_specs_by_target
485
556
  # the resolved specifications grouped by target.
486
557
  #
558
+ # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections
559
+ # the user target inspections used to construct the aggregate and pod targets.
560
+ #
487
561
  # @return [Array<PodTarget>]
488
562
  #
489
- def generate_pod_targets(resolver_specs_by_target)
563
+ def generate_pod_targets(resolver_specs_by_target, target_inspections)
490
564
  if installation_options.deduplicate_targets?
491
565
  distinct_targets = resolver_specs_by_target.each_with_object({}) do |dependency, hash|
492
566
  target_definition, dependent_specs = *dependency
@@ -503,7 +577,7 @@ module Pod
503
577
  pod_targets = distinct_targets.flat_map do |_root, target_definitions_by_variant|
504
578
  suffixes = PodVariantSet.new(target_definitions_by_variant.keys).scope_suffixes
505
579
  target_definitions_by_variant.flat_map do |variant, target_definitions|
506
- generate_pod_target(target_definitions, variant.specs + variant.test_specs, :scope_suffix => suffixes[variant])
580
+ generate_pod_target(target_definitions, target_inspections, variant.specs + variant.test_specs, :scope_suffix => suffixes[variant])
507
581
  end
508
582
  end
509
583
 
@@ -514,28 +588,32 @@ module Pod
514
588
  hash[name] = values.sort_by { |pt| pt.specs.count }
515
589
  end
516
590
  pod_targets.each do |target|
517
- all_specs = all_resolver_specs.to_set
518
- dependencies = transitive_dependencies_for_specs(target.non_test_specs.to_set, target.platform, all_specs).group_by(&:root)
519
- test_dependencies = transitive_dependencies_for_specs(target.test_specs.to_set, target.platform, all_specs).group_by(&:root)
520
- test_dependencies.delete_if { |k| dependencies.key? k }
591
+ all_specs = all_resolver_specs.group_by(&:name)
592
+ dependencies = dependencies_for_specs(target.non_test_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
521
593
  target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
522
- target.test_dependent_targets = filter_dependencies(test_dependencies, pod_targets_by_name, target)
594
+ target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
595
+ test_dependencies = dependencies_for_specs([test_spec], target.platform, all_specs).group_by(&:root)
596
+ test_dependencies.delete_if { |k| dependencies.key? k }
597
+ hash[test_spec.name] = filter_dependencies(test_dependencies, pod_targets_by_name, target)
598
+ end
523
599
  end
524
600
  else
525
601
  dedupe_cache = {}
526
602
  resolver_specs_by_target.flat_map do |target_definition, specs|
527
603
  grouped_specs = specs.group_by(&:root).values.uniq
528
604
  pod_targets = grouped_specs.flat_map do |pod_specs|
529
- generate_pod_target([target_definition], pod_specs.map(&:spec)).scoped(dedupe_cache)
605
+ generate_pod_target([target_definition], target_inspections, pod_specs.map(&:spec)).scoped(dedupe_cache)
530
606
  end
531
607
 
532
608
  pod_targets.each do |target|
533
- all_specs = specs.map(&:spec).to_set
534
- dependencies = transitive_dependencies_for_specs(target.non_test_specs.to_set, target.platform, all_specs).group_by(&:root)
535
- test_dependencies = transitive_dependencies_for_specs(target.test_specs.to_set, target.platform, all_specs).group_by(&:root)
536
- test_dependencies.delete_if { |k| dependencies.key? k }
609
+ all_specs = specs.map(&:spec).group_by(&:name)
610
+ dependencies = dependencies_for_specs(target.non_test_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
537
611
  target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
538
- target.test_dependent_targets = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
612
+ target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash|
613
+ test_dependencies = dependencies_for_specs(target.test_specs.to_set, target.platform, all_specs.dup).group_by(&:root)
614
+ test_dependencies.delete_if { |k| dependencies.key? k }
615
+ hash[test_spec.name] = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
616
+ end
539
617
  end
540
618
  end
541
619
  end
@@ -552,7 +630,7 @@ module Pod
552
630
  end
553
631
  end
554
632
 
555
- # Returns the specs upon which the given specs _transitively_ depend.
633
+ # Returns the specs upon which the given specs _directly_ depend.
556
634
  #
557
635
  # @note: This is implemented in the analyzer, because we don't have to
558
636
  # care about the requirements after dependency resolution.
@@ -563,37 +641,36 @@ module Pod
563
641
  # @param [Platform] platform
564
642
  # The platform for which the dependencies should be returned.
565
643
  #
566
- # @param [Array<Specification>] all_specs
644
+ # @param [Hash<String, Specification>] all_specs
567
645
  # All specifications which are installed alongside.
568
646
  #
569
647
  # @return [Array<Specification>]
570
648
  #
571
- def transitive_dependencies_for_specs(specs, platform, all_specs)
649
+ def dependencies_for_specs(specs, platform, all_specs)
572
650
  return [] if specs.empty? || all_specs.empty?
573
651
 
574
652
  dependent_specs = Set.new
575
- specs.each do |spec|
576
- spec.consumer(platform).dependencies.each do |dependency|
577
- match = all_specs.find do |s|
578
- next false unless s.name == dependency.name
579
- next false if specs.include?(s)
580
- true
653
+
654
+ specs.each do |s|
655
+ s.dependencies(platform).each do |dep|
656
+ all_specs[dep.name].each do |spec|
657
+ dependent_specs << spec
581
658
  end
582
- dependent_specs << match if match
583
659
  end
584
660
  end
585
661
 
586
- remaining_specs = all_specs - dependent_specs
587
-
588
- dependent_specs.union transitive_dependencies_for_specs(dependent_specs, platform, remaining_specs)
662
+ dependent_specs - specs
589
663
  end
590
664
 
591
665
  # Create a target for each spec group
592
666
  #
593
- # @param [TargetDefinitions] target_definitions
594
- # the aggregate target
667
+ # @param [Array<TargetDefinition>] target_definitions
668
+ # the target definitions of the aggregate target
595
669
  #
596
- # @param [Array<Specification>] pod_specs
670
+ # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections
671
+ # the user target inspections used to construct the aggregate and pod targets.
672
+ #
673
+ # @param [Array<Specification>] specs
597
674
  # the specifications of an equal root.
598
675
  #
599
676
  # @param [String] scope_suffix
@@ -601,22 +678,71 @@ module Pod
601
678
  #
602
679
  # @return [PodTarget]
603
680
  #
604
- def generate_pod_target(target_definitions, pod_specs, scope_suffix: nil)
605
- pod_target = PodTarget.new(pod_specs, target_definitions, sandbox, scope_suffix)
606
- pod_target.host_requires_frameworks = target_definitions.any?(&:uses_frameworks?)
607
-
681
+ def generate_pod_target(target_definitions, target_inspections, specs, scope_suffix: nil)
682
+ object_version = target_inspections.values.map { |ti| ti.project.object_version }.min
683
+ target_requires_64_bit = target_definitions.all? { |td| Analyzer.requires_64_bit_archs?(td.platform, object_version) }
608
684
  if installation_options.integrate_targets?
609
- target_inspections = result.target_inspections.select { |t, _| target_definitions.include?(t) }.values
610
- pod_target.user_build_configurations = target_inspections.map(&:build_configurations).reduce({}, &:merge)
611
- pod_target.archs = target_inspections.flat_map(&:archs).compact.uniq.sort
685
+ target_inspections = target_inspections.select { |t, _| target_definitions.include?(t) }.values
686
+ user_build_configurations = target_inspections.map(&:build_configurations).reduce({}, &:merge)
687
+ archs = if target_requires_64_bit
688
+ ['$(ARCHS_STANDARD_64_BIT)']
689
+ else
690
+ target_inspections.flat_map(&:archs).compact.uniq.sort
691
+ end
612
692
  else
613
- pod_target.user_build_configurations = {}
614
- if target_definitions.first.platform.name == :osx
615
- pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
616
- end
693
+ user_build_configurations = {}
694
+ archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : []
695
+ end
696
+ host_requires_frameworks = target_definitions.any?(&:uses_frameworks?)
697
+ platform = determine_platform(specs, target_definitions, host_requires_frameworks)
698
+ file_accessors = create_file_accessors(specs, platform)
699
+ PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs,
700
+ target_definitions, file_accessors, scope_suffix)
701
+ end
702
+
703
+ # Creates the file accessors for a given pod.
704
+ #
705
+ # @param [Array<Specification>] specs
706
+ # the specs to map each file accessor to.
707
+ #
708
+ # @param [Platform] platform
709
+ # the platform to use when generating each file accessor.
710
+ #
711
+ # @return [Array<FileAccessor>]
712
+ #
713
+ def create_file_accessors(specs, platform)
714
+ name = specs.first.name
715
+ pod_root = sandbox.pod_dir(name)
716
+ path_list = Sandbox::PathList.new(pod_root)
717
+ specs.map do |spec|
718
+ Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
617
719
  end
720
+ end
618
721
 
619
- pod_target
722
+ # Calculates and returns the platform to use for the given list of specs and target definitions.
723
+ #
724
+ # @param [Array<Specification>] specs
725
+ # the specs to inspect and calculate the platform for.
726
+ #
727
+ # @param [Array<TargetDefinition>] target_definitions
728
+ # the target definitions these specs are part of.
729
+ #
730
+ # @param [Boolean] host_requires_frameworks
731
+ # whether the platform is calculated for a target that needs to be packaged as a framework.
732
+ #
733
+ # @return [Platform]
734
+ #
735
+ def determine_platform(specs, target_definitions, host_requires_frameworks)
736
+ platform_name = target_definitions.first.platform.name
737
+ default = Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform_name]
738
+ deployment_target = specs.map do |spec|
739
+ Version.new(spec.deployment_target(platform_name) || default)
740
+ end.max
741
+ if platform_name == :ios && host_requires_frameworks
742
+ minimum = Version.new('8.0')
743
+ deployment_target = [deployment_target, minimum].max
744
+ end
745
+ Platform.new(platform_name, deployment_target)
620
746
  end
621
747
 
622
748
  # Generates dependencies that require the specific version of the Pods
@@ -626,21 +752,25 @@ module Pod
626
752
  # is in update mode, to prevent it from upgrading the Pods that weren't
627
753
  # changed in the {Podfile}.
628
754
  #
755
+ # @param [SpecState] podfile_state
756
+ # the state of the podfile for which dependencies have or have not changed, added, deleted or updated.
757
+ #
629
758
  # @return [Molinillo::DependencyGraph<Dependency>] the dependencies
630
759
  # generated by the lockfile that prevent the resolver to update
631
760
  # a Pod.
632
761
  #
633
- def generate_version_locking_dependencies
762
+ def generate_version_locking_dependencies(podfile_state)
634
763
  if update_mode == :all || !lockfile
635
764
  LockingDependencyAnalyzer.unlocked_dependency_graph
636
765
  else
637
- pods_to_update = result.podfile_state.changed + result.podfile_state.deleted
638
- pods_to_update += update[:pods] if update_mode == :selected
639
- local_pod_names = @podfile_dependency_cache.podfile_dependencies.select(&:local?).map(&:root_name)
640
- pods_to_unlock = local_pod_names.reject do |pod_name|
641
- sandbox.specification(pod_name).checksum == lockfile.checksum(pod_name)
766
+ deleted_and_changed = podfile_state.changed + podfile_state.deleted
767
+ deleted_and_changed += pods_to_update[:pods] if update_mode == :selected
768
+ local_pod_names = podfile_dependencies.select(&:local?).map(&:root_name)
769
+ pods_to_unlock = local_pod_names.to_set.delete_if do |pod_name|
770
+ next unless sandbox_specification = sandbox.specification(pod_name)
771
+ sandbox_specification.checksum == lockfile.checksum(pod_name)
642
772
  end
643
- LockingDependencyAnalyzer.generate_version_locking_dependencies(lockfile, pods_to_update, pods_to_unlock)
773
+ LockingDependencyAnalyzer.generate_version_locking_dependencies(lockfile, deleted_and_changed, pods_to_unlock)
644
774
  end
645
775
  end
646
776
 
@@ -659,25 +789,25 @@ module Pod
659
789
  # compatible with the version reported by the podspec of the
660
790
  # external source the resolver will raise.
661
791
  #
662
- # @return [void]
792
+ # @param [SpecState] podfile_state
793
+ # the state of the podfile for which dependencies have or have not changed, added, deleted or updated.
663
794
  #
664
- # TODO: Specs
795
+ # @return [void]
665
796
  #
666
- def fetch_external_sources
667
- return unless allow_pre_downloads?
668
-
797
+ def fetch_external_sources(podfile_state)
669
798
  verify_no_pods_with_different_sources!
670
- unless dependencies_to_fetch.empty?
671
- UI.section 'Fetching external sources' do
672
- dependencies_to_fetch.sort.each do |dependency|
673
- fetch_external_source(dependency, !pods_to_fetch.include?(dependency.root_name))
674
- end
799
+ deps = dependencies_to_fetch(podfile_state)
800
+ pods = pods_to_fetch(podfile_state)
801
+ return if deps.empty?
802
+ UI.section 'Fetching external sources' do
803
+ deps.sort.each do |dependency|
804
+ fetch_external_source(dependency, !pods.include?(dependency.root_name))
675
805
  end
676
806
  end
677
807
  end
678
808
 
679
809
  def verify_no_pods_with_different_sources!
680
- deps_with_different_sources = @podfile_dependency_cache.podfile_dependencies.group_by(&:root_name).
810
+ deps_with_different_sources = podfile_dependencies.group_by(&:root_name).
681
811
  select { |_root_name, dependencies| dependencies.map(&:external_source).uniq.count > 1 }
682
812
  deps_with_different_sources.each do |root_name, dependencies|
683
813
  raise Informative, 'There are multiple dependencies with different ' \
@@ -687,28 +817,26 @@ module Pod
687
817
  end
688
818
 
689
819
  def fetch_external_source(dependency, use_lockfile_options)
690
- checkout_options = lockfile.checkout_options_for_pod_named(dependency.root_name) if lockfile
691
- source = if checkout_options && use_lockfile_options
692
- ExternalSources.from_params(checkout_options, dependency, podfile.defined_in_file)
820
+ source = if use_lockfile_options && lockfile && checkout_options = lockfile.checkout_options_for_pod_named(dependency.root_name)
821
+ ExternalSources.from_params(checkout_options, dependency, podfile.defined_in_file, installation_options.clean?)
693
822
  else
694
- ExternalSources.from_dependency(dependency, podfile.defined_in_file)
695
- end
696
- source.can_cache = installation_options.clean?
823
+ ExternalSources.from_dependency(dependency, podfile.defined_in_file, installation_options.clean?)
824
+ end
697
825
  source.fetch(sandbox)
698
826
  end
699
827
 
700
- def dependencies_to_fetch
828
+ def dependencies_to_fetch(podfile_state)
701
829
  @deps_to_fetch ||= begin
702
830
  deps_to_fetch = []
703
- deps_with_external_source = @podfile_dependency_cache.podfile_dependencies.select(&:external_source)
831
+ deps_with_external_source = podfile_dependencies.select(&:external_source)
704
832
 
705
833
  if update_mode == :all
706
834
  deps_to_fetch = deps_with_external_source
707
835
  else
708
- deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) }
709
- deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) }
836
+ deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch(podfile_state).include?(dep.root_name) }
837
+ deps_to_fetch_if_needed = deps_with_external_source.select { |dep| podfile_state.unchanged.include?(dep.root_name) }
710
838
  deps_to_fetch += deps_to_fetch_if_needed.select do |dep|
711
- sandbox.specification(dep.root_name).nil? ||
839
+ sandbox.specification_path(dep.root_name).nil? ||
712
840
  !dep.external_source[:path].nil? ||
713
841
  !sandbox.pod_dir(dep.root_name).directory? ||
714
842
  checkout_requires_update?(dep)
@@ -725,15 +853,15 @@ module Pod
725
853
  locked_checkout_options != sandbox_checkout_options
726
854
  end
727
855
 
728
- def pods_to_fetch
856
+ def pods_to_fetch(podfile_state)
729
857
  @pods_to_fetch ||= begin
730
- pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
858
+ pods_to_fetch = podfile_state.added + podfile_state.changed
731
859
  if update_mode == :selected
732
- pods_to_fetch += update[:pods]
860
+ pods_to_fetch += pods_to_update[:pods]
733
861
  elsif update_mode == :all
734
- pods_to_fetch += result.podfile_state.unchanged + result.podfile_state.deleted
862
+ pods_to_fetch += podfile_state.unchanged + podfile_state.deleted
735
863
  end
736
- pods_to_fetch += @podfile_dependency_cache.podfile_dependencies.
864
+ pods_to_fetch += podfile_dependencies.
737
865
  select { |dep| Hash(dep.external_source).key?(:podspec) && sandbox.specification_path(dep.root_name).nil? }.
738
866
  map(&:root_name)
739
867
  pods_to_fetch
@@ -741,7 +869,7 @@ module Pod
741
869
  end
742
870
 
743
871
  def store_existing_checkout_options
744
- @podfile_dependency_cache.podfile_dependencies.select(&:external_source).each do |dep|
872
+ podfile_dependencies.select(&:external_source).each do |dep|
745
873
  if checkout_options = lockfile && lockfile.checkout_options_for_pod_named(dep.root_name)
746
874
  sandbox.store_checkout_source(dep.root_name, checkout_options)
747
875
  end
@@ -767,8 +895,8 @@ module Pod
767
895
  # @return [Hash{TargetDefinition => Array<Spec>}] the specifications
768
896
  # grouped by target.
769
897
  #
770
- def resolve_dependencies
771
- duplicate_dependencies = @podfile_dependency_cache.podfile_dependencies.group_by(&:name).
898
+ def resolve_dependencies(locked_dependencies)
899
+ duplicate_dependencies = podfile_dependencies.group_by(&:name).
772
900
  select { |_name, dependencies| dependencies.count > 1 }
773
901
  duplicate_dependencies.each do |name, dependencies|
774
902
  UI.warn "There are duplicate dependencies on `#{name}` in #{UI.path podfile.defined_in_file}:\n\n" \
@@ -777,7 +905,7 @@ module Pod
777
905
 
778
906
  resolver_specs_by_target = nil
779
907
  UI.section "Resolving dependencies of #{UI.path(podfile.defined_in_file) || 'Podfile'}" do
780
- resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources, specs_updated?)
908
+ resolver = Pod::Resolver.new(sandbox, podfile, locked_dependencies, sources, @specs_updated)
781
909
  resolver_specs_by_target = resolver.resolve
782
910
  resolver_specs_by_target.values.flatten(1).map(&:spec).each(&:validate_cocoapods_version)
783
911
  end
@@ -787,7 +915,7 @@ module Pod
787
915
  # Warns for any specification that is incompatible with its target.
788
916
  #
789
917
  # @param [Hash{TargetDefinition => Array<Spec>}] resolver_specs_by_target
790
- # the specifications grouped by target.
918
+ # the resolved specifications grouped by target.
791
919
  #
792
920
  # @return [Hash{TargetDefinition => Array<Spec>}] the specifications
793
921
  # grouped by target.
@@ -807,6 +935,9 @@ module Pod
807
935
 
808
936
  # Returns the list of all the resolved specifications.
809
937
  #
938
+ # @param [Hash{TargetDefinition => Array<Spec>}] resolver_specs_by_target
939
+ # the resolved specifications grouped by target.
940
+ #
810
941
  # @return [Array<Specification>] the list of the specifications.
811
942
  #
812
943
  def generate_specifications(resolver_specs_by_target)
@@ -819,70 +950,46 @@ module Pod
819
950
  # @return [SpecsState] the representation of the state of the manifest
820
951
  # specifications.
821
952
  #
822
- def generate_sandbox_state
953
+ def generate_sandbox_state(specifications)
823
954
  sandbox_state = nil
824
955
  UI.section 'Comparing resolved specification to the sandbox manifest' do
825
- sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode?, lockfile)
956
+ sandbox_analyzer = SandboxAnalyzer.new(sandbox, specifications, update_mode?)
826
957
  sandbox_state = sandbox_analyzer.analyze
827
958
  sandbox_state.print
828
959
  end
829
960
  sandbox_state
830
961
  end
831
962
 
832
- #-----------------------------------------------------------------------#
833
-
834
- # @!group Analysis internal products
835
-
836
- # @return [Molinillo::DependencyGraph<Dependency>] the dependencies
837
- # generated by the lockfile that prevent the resolver to update a
838
- # Pod.
839
- #
840
- attr_reader :locked_dependencies
841
-
842
- #-----------------------------------------------------------------------#
843
-
844
- public
845
-
846
- # Returns the sources used to query for specifications
847
- #
848
- # When no explicit Podfile sources or plugin sources are defined, this
849
- # defaults to the master spec repository.
850
- # available sources ({config.sources_manager.all}).
851
- #
852
- # @return [Array<Source>] the sources to be used in finding
853
- # specifications, as specified by the {#podfile} or all sources.
854
- #
855
- def sources
856
- @sources ||= begin
857
- sources = podfile.sources
858
- plugin_sources = @plugin_sources || []
859
-
860
- # Add any sources specified using the :source flag on individual dependencies.
861
- dependency_sources = @podfile_dependency_cache.podfile_dependencies.map(&:podspec_repo).compact
862
- all_dependencies_have_sources = dependency_sources.count == @podfile_dependency_cache.podfile_dependencies.count
863
-
864
- if all_dependencies_have_sources
865
- sources = dependency_sources
866
- elsif has_dependencies? && sources.empty? && plugin_sources.empty?
867
- sources = ['https://github.com/CocoaPods/Specs.git']
868
- else
869
- sources += dependency_sources
870
- end
871
-
872
- result = sources.uniq.map do |source_url|
873
- config.sources_manager.find_or_create_source_with_url(source_url)
874
- end
875
- unless plugin_sources.empty?
876
- result.insert(0, *plugin_sources)
963
+ class << self
964
+ # @param [Platform] platform
965
+ # The platform to build against
966
+ #
967
+ # @param [String, Nil] object_version
968
+ # The user project's object version, or nil if not available
969
+ #
970
+ # @return [Boolean] Whether the platform requires 64-bit architectures
971
+ #
972
+ def requires_64_bit_archs?(platform, object_version)
973
+ return false unless platform
974
+ case platform.name
975
+ when :osx
976
+ true
977
+ when :ios
978
+ if (version = object_version)
979
+ platform.deployment_target >= IOS_64_BIT_ONLY_VERSION && version.to_i < IOS_64_BIT_ONLY_PROJECT_VERSION
980
+ else
981
+ platform.deployment_target >= IOS_64_BIT_ONLY_VERSION
982
+ end
983
+ when :watchos
984
+ false
985
+ when :tvos
986
+ false
877
987
  end
878
- result
879
988
  end
880
989
  end
881
990
 
882
991
  #-----------------------------------------------------------------------#
883
992
 
884
- private
885
-
886
993
  # @!group Analysis sub-steps
887
994
 
888
995
  # Checks whether the platform is specified if not integrating