cocoapods 1.4.0 → 1.5.0.beta.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +149 -0
  3. data/lib/cocoapods.rb +1 -0
  4. data/lib/cocoapods/command/outdated.rb +2 -2
  5. data/lib/cocoapods/command/repo/push.rb +5 -0
  6. data/lib/cocoapods/command/update.rb +21 -5
  7. data/lib/cocoapods/gem_version.rb +1 -1
  8. data/lib/cocoapods/generator/acknowledgements.rb +6 -3
  9. data/lib/cocoapods/generator/constant.rb +19 -0
  10. data/lib/cocoapods/generator/copy_resources_script.rb +15 -3
  11. data/lib/cocoapods/generator/embed_frameworks_script.rb +11 -2
  12. data/lib/cocoapods/generator/module_map.rb +56 -5
  13. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +19 -13
  14. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +4 -6
  15. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +25 -2
  16. data/lib/cocoapods/installer.rb +17 -8
  17. data/lib/cocoapods/installer/analyzer.rb +48 -38
  18. data/lib/cocoapods/installer/analyzer/analysis_result.rb +11 -0
  19. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +7 -6
  20. data/lib/cocoapods/installer/analyzer/pod_variant.rb +8 -8
  21. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +3 -3
  22. data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
  23. data/lib/cocoapods/installer/analyzer/specs_state.rb +16 -16
  24. data/lib/cocoapods/installer/analyzer/target_inspector.rb +7 -11
  25. data/lib/cocoapods/installer/pod_source_installer.rb +2 -3
  26. data/lib/cocoapods/installer/podfile_validator.rb +11 -10
  27. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +72 -28
  28. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +8 -2
  29. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +9 -0
  30. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +32 -24
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +97 -54
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +9 -11
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +4 -9
  34. data/lib/cocoapods/installer/xcode/target_validator.rb +32 -18
  35. data/lib/cocoapods/project.rb +32 -17
  36. data/lib/cocoapods/resolver.rb +59 -31
  37. data/lib/cocoapods/resolver/lazy_specification.rb +28 -18
  38. data/lib/cocoapods/sandbox.rb +2 -4
  39. data/lib/cocoapods/sandbox/file_accessor.rb +25 -9
  40. data/lib/cocoapods/sandbox/headers_store.rb +31 -6
  41. data/lib/cocoapods/sandbox/path_list.rb +36 -46
  42. data/lib/cocoapods/target.rb +7 -4
  43. data/lib/cocoapods/target/aggregate_target.rb +10 -8
  44. data/lib/cocoapods/target/pod_target.rb +87 -20
  45. data/lib/cocoapods/user_interface/error_report.rb +1 -1
  46. data/lib/cocoapods/user_interface/inspector_reporter.rb +4 -4
  47. data/lib/cocoapods/validator.rb +40 -29
  48. metadata +11 -9
@@ -55,12 +55,16 @@ module Pod
55
55
  includes_static_libs = !target.requires_frameworks?
56
56
  includes_static_libs ||= pod_targets.flat_map(&:file_accessors).any? { |fa| !fa.vendored_static_artifacts.empty? }
57
57
  config = {
58
+ 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
59
+ 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
60
+ 'HEADER_SEARCH_PATHS' => '$(inherited) ',
61
+ 'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
62
+ 'OTHER_CFLAGS' => '$(inherited) ',
58
63
  'OTHER_LDFLAGS' => '$(inherited) ' + XCConfigHelper.default_ld_flags(target, includes_static_libs),
64
+ 'OTHER_SWIFT_FLAGS' => '$(inherited) ',
59
65
  'PODS_PODFILE_DIR_PATH' => target.podfile_dir_relative_path,
60
66
  'PODS_ROOT' => target.relative_pods_root,
61
- 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
62
- 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
63
- 'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
67
+ 'SWIFT_INCLUDE_PATHS' => '$(inherited) ',
64
68
  }.merge(embedded_content_settings)
65
69
 
66
70
  @xcconfig = Xcodeproj::Config.new(config)
@@ -139,13 +143,15 @@ module Pod
139
143
  "#{target.build_product_path}/Headers"
140
144
  end
141
145
  build_settings = {
146
+ # TODO: remove quote imports in CocoaPods 2.0
142
147
  # Make framework headers discoverable by `import "…"`
143
- 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(framework_header_search_paths, '-iquote'),
148
+ 'OTHER_CFLAGS' => XCConfigHelper.quote(framework_header_search_paths, '-iquote'),
144
149
  }
145
150
  if pod_targets.any? { |t| !t.should_build? }
146
151
  # Make library headers discoverable by `#import "…"`
147
152
  library_header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
148
- build_settings['HEADER_SEARCH_PATHS'] = '$(inherited) ' + XCConfigHelper.quote(library_header_search_paths)
153
+ # TODO: remove quote imports in CocoaPods 2.0
154
+ build_settings['HEADER_SEARCH_PATHS'] = XCConfigHelper.quote(library_header_search_paths)
149
155
  build_settings['OTHER_CFLAGS'] += ' ' + XCConfigHelper.quote(library_header_search_paths, '-isystem')
150
156
  end
151
157
  build_settings
@@ -153,21 +159,22 @@ module Pod
153
159
  # Make headers discoverable from $PODS_ROOT/Headers directory
154
160
  header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
155
161
  {
162
+ # TODO: remove quote imports in CocoaPods 2.0
156
163
  # by `#import "…"`
157
- 'HEADER_SEARCH_PATHS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths),
164
+ 'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_paths),
158
165
  # by `#import <…>`
159
- 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'),
166
+ 'OTHER_CFLAGS' => XCConfigHelper.quote(header_search_paths, '-isystem'),
160
167
  }
161
168
  end
162
169
  end
163
170
 
164
171
  private
165
172
 
166
- # Add build settings, which ensure that the pod targets can be imported
167
- # from the integrating target by all sort of imports, which are:
168
- # - `#import <…>`
169
- # - `#import "…"`
170
- # - `@import …;` / `import …`
173
+ # Add build settings, which ensure that the pod targets can be imported from the integrating target.
174
+ # For >= 1.5.0 we use modular (stricter) header search paths this means that the integrated target will only be
175
+ # able to import public headers using `<>` or `@import` notation, but never import any private headers.
176
+ #
177
+ # For < 1.5.0 legacy header search paths the same rules apply: It's the wild west.
171
178
  #
172
179
  def generate_settings_to_import_pod_targets
173
180
  @xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(target, pod_targets)
@@ -176,7 +183,6 @@ module Pod
176
183
  generator = AggregateXCConfig.new(search_paths_target, configuration_name)
177
184
  @xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(nil, search_paths_target.pod_targets)
178
185
  @xcconfig.merge!(generator.settings_to_import_pod_targets)
179
-
180
186
  # Propagate any HEADER_SEARCH_PATHS settings from the search paths.
181
187
  XCConfigHelper.propagate_header_search_paths_from_search_paths(search_paths_target, @xcconfig)
182
188
  end
@@ -44,22 +44,20 @@ module Pod
44
44
  # @return [Xcodeproj::Config]
45
45
  #
46
46
  def generate
47
- target_search_paths = target.build_headers.search_paths(target.platform)
48
- sandbox_search_paths = target.sandbox.public_headers.search_paths(target.platform)
49
- search_paths = target_search_paths.concat(sandbox_search_paths).uniq
50
-
51
47
  config = {
52
48
  'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
53
49
  'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
54
- 'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(search_paths),
50
+ 'HEADER_SEARCH_PATHS' => '$(inherited) ' + XCConfigHelper.quote(target.header_search_paths(@test_xcconfig)),
55
51
  'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
52
+ 'OTHER_CFLAGS' => '$(inherited) ',
56
53
  'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target, @test_xcconfig),
54
+ 'OTHER_SWIFT_FLAGS' => '$(inherited) ',
57
55
  'PODS_ROOT' => '${SRCROOT}',
58
56
  'PODS_TARGET_SRCROOT' => target.pod_target_srcroot,
59
57
  'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
60
58
  'SKIP_INSTALL' => 'YES',
61
59
  'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) ',
62
- # 'USE_HEADERMAP' => 'NO'
60
+ 'SWIFT_INCLUDE_PATHS' => '$(inherited) ',
63
61
  }
64
62
 
65
63
  @xcconfig = Xcodeproj::Config.new(config)
@@ -140,8 +140,7 @@ module Pod
140
140
  #
141
141
  def self.links_dependency?(aggregate_target, pod_target)
142
142
  return true if aggregate_target.nil? || aggregate_target.target_definition.inheritance == 'complete'
143
- targets = aggregate_target.pod_targets - aggregate_target.search_paths_aggregate_targets.flat_map(&:pod_targets)
144
- targets.include?(pod_target)
143
+ aggregate_target.pod_targets_to_link.include?(pod_target)
145
144
  end
146
145
 
147
146
  # Adds build settings for dynamic vendored frameworks and libraries.
@@ -329,19 +328,43 @@ module Pod
329
328
  build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
330
329
  end
331
330
 
331
+ module_map_files = []
332
332
  unless dependent_targets.empty?
333
333
  framework_search_paths = []
334
334
  library_search_paths = []
335
+ swift_import_paths = []
335
336
  dependent_targets.each do |dependent_target|
336
337
  if dependent_target.requires_frameworks?
337
338
  framework_search_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
338
339
  else
339
340
  library_search_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
341
+ if dependent_target.defines_module?
342
+ module_map_file = if dependent_target.uses_swift?
343
+ # for swift, we have a custom build phase that copies in the module map, appending the .Swift module
344
+ "${PODS_CONFIGURATION_BUILD_DIR}/#{dependent_target.label}/#{dependent_target.product_module_name}.modulemap"
345
+ else
346
+ "${PODS_ROOT}/#{dependent_target.module_map_path.relative_path_from(dependent_target.sandbox.root)}"
347
+ end
348
+ module_map_files << %(-fmodule-map-file="#{module_map_file}")
349
+ swift_import_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE) if dependent_target.uses_swift?
350
+ end
340
351
  end
341
352
  end
353
+
342
354
  build_settings['FRAMEWORK_SEARCH_PATHS'] = XCConfigHelper.quote(framework_search_paths.uniq)
343
355
  build_settings['LIBRARY_SEARCH_PATHS'] = XCConfigHelper.quote(library_search_paths.uniq)
356
+ build_settings['SWIFT_INCLUDE_PATHS'] = XCConfigHelper.quote(swift_import_paths.uniq)
357
+ end
358
+
359
+ other_swift_flags = module_map_files.tap(&:uniq!).flat_map { |f| ['-Xcc', f] }
360
+ if target.is_a?(PodTarget) && !target.requires_frameworks? && target.defines_module?
361
+ # make it possible for a mixed swift/objc static library to be able to import the objc from within swift
362
+ other_swift_flags += ['-import-underlying-module', '-Xcc', '-fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}"']
344
363
  end
364
+ # unconditionally set these, because of (the possibility of) having to add the pod targets own module map file
365
+ build_settings['OTHER_CFLAGS'] = module_map_files.join(' ')
366
+ build_settings['OTHER_SWIFT_FLAGS'] = other_swift_flags.join(' ')
367
+
345
368
  build_settings
346
369
  end
347
370
 
@@ -219,8 +219,8 @@ module Pod
219
219
  # generated as result of the analyzer.
220
220
  #
221
221
  def pod_targets
222
- aggregate_target_pod_targets = aggregate_targets.map(&:pod_targets).flatten
223
- test_dependent_targets = aggregate_target_pod_targets.map(&:test_dependent_targets).flatten
222
+ aggregate_target_pod_targets = aggregate_targets.flat_map(&:pod_targets)
223
+ test_dependent_targets = aggregate_target_pod_targets.flat_map(&:test_dependent_targets)
224
224
  (aggregate_target_pod_targets + test_dependent_targets).uniq
225
225
  end
226
226
 
@@ -321,8 +321,17 @@ module Pod
321
321
  root_specs.sort_by(&:name).each do |spec|
322
322
  if pods_to_install.include?(spec.name)
323
323
  if sandbox_state.changed.include?(spec.name) && sandbox.manifest
324
- previous = sandbox.manifest.version(spec.name)
325
- title = "Installing #{spec.name} #{spec.version} (was #{previous})"
324
+ current_version = spec.version
325
+ previous_version = sandbox.manifest.version(spec.name)
326
+ has_changed_version = current_version != previous_version
327
+ current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
328
+ current_repo &&= current_repo.url || current_repo.name
329
+ previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
330
+ has_changed_repo = !previous_spec_repo.nil? && current_repo && (current_repo != previous_spec_repo)
331
+ title = "Installing #{spec.name} #{spec.version}"
332
+ title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
333
+ title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
334
+ title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
326
335
  else
327
336
  title = "Installing #{spec}"
328
337
  end
@@ -429,7 +438,7 @@ module Pod
429
438
  end
430
439
 
431
440
  def print_post_install_message
432
- podfile_dependencies = podfile.dependencies.uniq.size
441
+ podfile_dependencies = analysis_result.podfile_dependency_cache.podfile_dependencies.size
433
442
  pods_installed = root_specs.size
434
443
  title_options = { :verbose_prefix => '-> '.green }
435
444
  UI.titled_section('Pod installation complete! ' \
@@ -548,9 +557,9 @@ module Pod
548
557
  # @return [void]
549
558
  #
550
559
  def write_lockfiles
551
- external_source_pods = podfile.dependencies.select(&:external_source).map(&:root_name).uniq
560
+ external_source_pods = analysis_result.podfile_dependency_cache.podfile_dependencies.select(&:external_source).map(&:root_name).uniq
552
561
  checkout_options = sandbox.checkout_sources.select { |root_name, _| external_source_pods.include? root_name }
553
- @lockfile = Lockfile.generate(podfile, analysis_result.specifications, checkout_options)
562
+ @lockfile = Lockfile.generate(podfile, analysis_result.specifications, checkout_options, analysis_result.specs_by_source)
554
563
 
555
564
  UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
556
565
  @lockfile.write_to_disk(config.lockfile_path)
@@ -651,7 +660,7 @@ module Pod
651
660
  #
652
661
  def development_pod_targets
653
662
  pod_targets.select do |pod_target|
654
- sandbox.development_pods.keys.include?(pod_target.pod_name)
663
+ sandbox.local?(pod_target.pod_name)
655
664
  end
656
665
  end
657
666
 
@@ -10,11 +10,12 @@ module Pod
10
10
  delegate_installation_options { podfile }
11
11
 
12
12
  autoload :AnalysisResult, 'cocoapods/installer/analyzer/analysis_result'
13
- autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
14
- autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
15
13
  autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer'
14
+ autoload :PodfileDependencyCache, 'cocoapods/installer/analyzer/podfile_dependency_cache'
16
15
  autoload :PodVariant, 'cocoapods/installer/analyzer/pod_variant'
17
16
  autoload :PodVariantSet, 'cocoapods/installer/analyzer/pod_variant_set'
17
+ autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
18
+ autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
18
19
  autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result'
19
20
  autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector'
20
21
 
@@ -54,6 +55,7 @@ module Pod
54
55
  @has_dependencies = true
55
56
  @test_pod_target_analyzer_cache = {}
56
57
  @test_pod_target_key = Struct.new(:name, :pod_targets)
58
+ @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
57
59
  end
58
60
 
59
61
  # Performs the analysis.
@@ -71,6 +73,7 @@ module Pod
71
73
  validate_podfile!
72
74
  validate_lockfile_version!
73
75
  @result = AnalysisResult.new
76
+ @result.podfile_dependency_cache = @podfile_dependency_cache
74
77
  if installation_options.integrate_targets?
75
78
  @result.target_inspections = inspect_targets_to_integrate
76
79
  else
@@ -90,6 +93,8 @@ module Pod
90
93
  @result.specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
91
94
  hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
92
95
  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] ||= [] }
93
98
  @result
94
99
  end
95
100
 
@@ -184,7 +189,7 @@ module Pod
184
189
  alias_method :specs_updated?, :specs_updated
185
190
 
186
191
  def validate_podfile!
187
- validator = Installer::PodfileValidator.new(podfile)
192
+ validator = Installer::PodfileValidator.new(podfile, @podfile_dependency_cache)
188
193
  validator.validate
189
194
 
190
195
  unless validator.valid?
@@ -232,7 +237,7 @@ module Pod
232
237
  pods_state
233
238
  else
234
239
  state = SpecsState.new
235
- state.added.merge(podfile.dependencies.map(&:root_name))
240
+ state.added.merge(@podfile_dependency_cache.podfile_dependencies.map(&:root_name))
236
241
  state
237
242
  end
238
243
  end
@@ -335,18 +340,18 @@ module Pod
335
340
  end
336
341
 
337
342
  unless embedded_targets_missing_hosts.empty?
338
- embedded_targets_missing_hosts_product_types = Set.new embedded_targets_missing_hosts.map(&:user_targets).flatten.map(&:symbol_type)
343
+ embedded_targets_missing_hosts_product_types = Set.new embedded_targets_missing_hosts.flat_map(&:user_targets).map(&:symbol_type)
344
+ target_names = embedded_targets_missing_hosts.map do |target|
345
+ target.name.sub('Pods-', '') # Make the target names more recognizable to the user
346
+ end.join ', '
339
347
  # If the targets missing hosts are only frameworks, then this is likely
340
348
  # a project for doing framework development. In that case, just warn that
341
349
  # the frameworks that these targets depend on won't be integrated anywhere
342
350
  if embedded_targets_missing_hosts_product_types.subset?(Set.new([:framework, :static_library]))
343
- UI.warn 'The Podfile contains framework or static library targets, for which the Podfile does not contain host targets (targets which embed the framework).' \
351
+ UI.warn "The Podfile contains framework or static library targets (#{target_names}), for which the Podfile does not contain host targets (targets which embed the framework)." \
344
352
  "\n" \
345
353
  'If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).'
346
354
  else
347
- target_names = embedded_targets_missing_hosts.map do |target|
348
- target.name.sub('Pods-', '') # Make the target names more recognizable to the user
349
- end.join ', '
350
355
  raise Informative, "Unable to find host target(s) for #{target_names}. Please add the host targets for the embedded targets to the Podfile." \
351
356
  "\n" \
352
357
  'Certain kinds of targets require a host target. A host target is a "parent" target which embeds a "child" target. These are example types of targets that need a host target:' \
@@ -393,8 +398,7 @@ module Pod
393
398
  embedded_targets = aggregate_targets.select(&:requires_host_target?)
394
399
  analyze_host_targets_in_podfile(aggregate_targets, embedded_targets)
395
400
 
396
- use_frameworks_embedded_targets = embedded_targets.select(&:requires_frameworks?)
397
- non_use_frameworks_embedded_targets = embedded_targets.reject(&:requires_frameworks?)
401
+ use_frameworks_embedded_targets, non_use_frameworks_embedded_targets = embedded_targets.partition(&:requires_frameworks?)
398
402
  aggregate_targets.each do |target|
399
403
  # For targets that require frameworks, we always have to copy their pods to their
400
404
  # host targets because those frameworks will all be loaded from the host target's bundle
@@ -406,9 +410,9 @@ module Pod
406
410
  end
407
411
  end
408
412
  aggregate_targets.each do |target|
409
- target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
413
+ target.search_paths_aggregate_targets.concat(aggregate_targets.select do |aggregate_target|
410
414
  target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
411
- end
415
+ end).freeze
412
416
  end
413
417
  end
414
418
 
@@ -510,8 +514,9 @@ module Pod
510
514
  hash[name] = values.sort_by { |pt| pt.specs.count }
511
515
  end
512
516
  pod_targets.each do |target|
513
- dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, all_resolver_specs).group_by(&:root)
514
- test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_resolver_specs).group_by(&:root)
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)
515
520
  test_dependencies.delete_if { |k| dependencies.key? k }
516
521
  target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
517
522
  target.test_dependent_targets = filter_dependencies(test_dependencies, pod_targets_by_name, target)
@@ -525,8 +530,9 @@ module Pod
525
530
  end
526
531
 
527
532
  pod_targets.each do |target|
528
- dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, specs.map(&:spec)).group_by(&:root)
529
- test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, specs.map(&:spec)).group_by(&:root)
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)
530
536
  test_dependencies.delete_if { |k| dependencies.key? k }
531
537
  target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
532
538
  target.test_dependent_targets = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
@@ -564,16 +570,22 @@ module Pod
564
570
  #
565
571
  def transitive_dependencies_for_specs(specs, platform, all_specs)
566
572
  return [] if specs.empty? || all_specs.empty?
567
- dependent_specs = specs.flat_map do |spec|
568
- spec.consumer(platform).dependencies.flat_map do |dependency|
569
- all_specs.find do |s|
573
+
574
+ 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
570
579
  next false if specs.include?(s)
571
- s.name == dependency.name
580
+ true
572
581
  end
573
- end.compact
574
- end.uniq
582
+ dependent_specs << match if match
583
+ end
584
+ end
585
+
575
586
  remaining_specs = all_specs - dependent_specs
576
- dependent_specs + transitive_dependencies_for_specs(dependent_specs, platform, remaining_specs)
587
+
588
+ dependent_specs.union transitive_dependencies_for_specs(dependent_specs, platform, remaining_specs)
577
589
  end
578
590
 
579
591
  # Create a target for each spec group
@@ -624,7 +636,7 @@ module Pod
624
636
  else
625
637
  pods_to_update = result.podfile_state.changed + result.podfile_state.deleted
626
638
  pods_to_update += update[:pods] if update_mode == :selected
627
- local_pod_names = podfile.dependencies.select(&:local?).map(&:root_name)
639
+ local_pod_names = @podfile_dependency_cache.podfile_dependencies.select(&:local?).map(&:root_name)
628
640
  pods_to_unlock = local_pod_names.reject do |pod_name|
629
641
  sandbox.specification(pod_name).checksum == lockfile.checksum(pod_name)
630
642
  end
@@ -665,7 +677,7 @@ module Pod
665
677
  end
666
678
 
667
679
  def verify_no_pods_with_different_sources!
668
- deps_with_different_sources = podfile.dependencies.group_by(&:root_name).
680
+ deps_with_different_sources = @podfile_dependency_cache.podfile_dependencies.group_by(&:root_name).
669
681
  select { |_root_name, dependencies| dependencies.map(&:external_source).uniq.count > 1 }
670
682
  deps_with_different_sources.each do |root_name, dependencies|
671
683
  raise Informative, 'There are multiple dependencies with different ' \
@@ -688,7 +700,7 @@ module Pod
688
700
  def dependencies_to_fetch
689
701
  @deps_to_fetch ||= begin
690
702
  deps_to_fetch = []
691
- deps_with_external_source = podfile.dependencies.select(&:external_source)
703
+ deps_with_external_source = @podfile_dependency_cache.podfile_dependencies.select(&:external_source)
692
704
 
693
705
  if update_mode == :all
694
706
  deps_to_fetch = deps_with_external_source
@@ -721,7 +733,7 @@ module Pod
721
733
  elsif update_mode == :all
722
734
  pods_to_fetch += result.podfile_state.unchanged + result.podfile_state.deleted
723
735
  end
724
- pods_to_fetch += podfile.dependencies.
736
+ pods_to_fetch += @podfile_dependency_cache.podfile_dependencies.
725
737
  select { |dep| Hash(dep.external_source).key?(:podspec) && sandbox.specification_path(dep.root_name).nil? }.
726
738
  map(&:root_name)
727
739
  pods_to_fetch
@@ -729,7 +741,7 @@ module Pod
729
741
  end
730
742
 
731
743
  def store_existing_checkout_options
732
- podfile.dependencies.select(&:external_source).each do |dep|
744
+ @podfile_dependency_cache.podfile_dependencies.select(&:external_source).each do |dep|
733
745
  if checkout_options = lockfile && lockfile.checkout_options_for_pod_named(dep.root_name)
734
746
  sandbox.store_checkout_source(dep.root_name, checkout_options)
735
747
  end
@@ -756,7 +768,7 @@ module Pod
756
768
  # grouped by target.
757
769
  #
758
770
  def resolve_dependencies
759
- duplicate_dependencies = podfile.dependencies.group_by(&:name).
771
+ duplicate_dependencies = @podfile_dependency_cache.podfile_dependencies.group_by(&:name).
760
772
  select { |_name, dependencies| dependencies.count > 1 }
761
773
  duplicate_dependencies.each do |name, dependencies|
762
774
  UI.warn "There are duplicate dependencies on `#{name}` in #{UI.path podfile.defined_in_file}:\n\n" \
@@ -765,8 +777,7 @@ module Pod
765
777
 
766
778
  resolver_specs_by_target = nil
767
779
  UI.section "Resolving dependencies of #{UI.path(podfile.defined_in_file) || 'Podfile'}" do
768
- resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources)
769
- resolver.specs_updated = specs_updated?
780
+ resolver = Resolver.new(sandbox, podfile, locked_dependencies, sources, specs_updated?)
770
781
  resolver_specs_by_target = resolver.resolve
771
782
  resolver_specs_by_target.values.flatten(1).map(&:spec).each(&:validate_cocoapods_version)
772
783
  end
@@ -847,8 +858,8 @@ module Pod
847
858
  plugin_sources = @plugin_sources || []
848
859
 
849
860
  # Add any sources specified using the :source flag on individual dependencies.
850
- dependency_sources = podfile.dependencies.map(&:podspec_repo).compact
851
- all_dependencies_have_sources = dependency_sources.count == podfile.dependencies.count
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
852
863
 
853
864
  if all_dependencies_have_sources
854
865
  sources = dependency_sources
@@ -880,7 +891,7 @@ module Pod
880
891
  #
881
892
  def verify_platforms_specified!
882
893
  unless installation_options.integrate_targets?
883
- podfile.target_definition_list.each do |target_definition|
894
+ @podfile_dependency_cache.target_definition_list.each do |target_definition|
884
895
  if !target_definition.empty? && target_definition.platform.nil?
885
896
  raise Informative, 'It is necessary to specify the platform in the Podfile if not integrating.'
886
897
  end
@@ -899,7 +910,7 @@ module Pod
899
910
  def inspect_targets_to_integrate
900
911
  inspection_result = {}
901
912
  UI.section 'Inspecting targets to integrate' do
902
- inspectors = podfile.target_definition_list.map do |target_definition|
913
+ inspectors = @podfile_dependency_cache.target_definition_list.map do |target_definition|
903
914
  next if target_definition.abstract?
904
915
  TargetInspector.new(target_definition, config.installation_root)
905
916
  end.compact
@@ -907,8 +918,7 @@ module Pod
907
918
  project = Xcodeproj::Project.open(project_path)
908
919
  target_inspectors.each do |inspector|
909
920
  target_definition = inspector.target_definition
910
- inspector.user_project = project
911
- results = inspector.compute_results
921
+ results = inspector.compute_results(project)
912
922
  inspection_result[target_definition] = results
913
923
  UI.message('Using `ARCHS` setting to build architectures of ' \
914
924
  "target `#{target_definition.label}`: (`#{results.archs.join('`, `')}`)")