cocoapods 1.6.0.beta.1 → 1.6.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -4
  3. data/lib/cocoapods/command/cache/clean.rb +1 -1
  4. data/lib/cocoapods/command/init.rb +3 -1
  5. data/lib/cocoapods/command/outdated.rb +2 -2
  6. data/lib/cocoapods/executable.rb +1 -1
  7. data/lib/cocoapods/gem_version.rb +1 -1
  8. data/lib/cocoapods/generator/acknowledgements/plist.rb +3 -3
  9. data/lib/cocoapods/generator/app_target_helper.rb +2 -4
  10. data/lib/cocoapods/generator/copy_resources_script.rb +8 -3
  11. data/lib/cocoapods/generator/embed_frameworks_script.rb +24 -18
  12. data/lib/cocoapods/installer.rb +37 -21
  13. data/lib/cocoapods/installer/analyzer.rb +19 -13
  14. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +5 -0
  15. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +5 -0
  16. data/lib/cocoapods/installer/installation_options.rb +2 -0
  17. data/lib/cocoapods/installer/pod_source_installer.rb +1 -1
  18. data/lib/cocoapods/installer/post_install_hooks_context.rb +1 -1
  19. data/lib/cocoapods/installer/user_project_integrator.rb +6 -2
  20. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +42 -12
  21. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +2 -4
  22. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +14 -5
  23. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +12 -6
  24. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +22 -11
  25. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +29 -18
  26. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  27. data/lib/cocoapods/project.rb +2 -0
  28. data/lib/cocoapods/resolver.rb +42 -49
  29. data/lib/cocoapods/resolver/resolver_specification.rb +41 -0
  30. data/lib/cocoapods/sandbox.rb +21 -17
  31. data/lib/cocoapods/target/aggregate_target.rb +3 -1
  32. data/lib/cocoapods/target/build_settings.rb +35 -12
  33. data/lib/cocoapods/target/framework_paths.rb +36 -0
  34. data/lib/cocoapods/target/pod_target.rb +16 -17
  35. data/lib/cocoapods/validator.rb +18 -5
  36. metadata +18 -10
@@ -10,12 +10,18 @@ module Pod
10
10
  #
11
11
  attr_reader :target_installation_result
12
12
 
13
+ # @return [InstallationOptions] the installation options from the Podfile.
14
+ #
15
+ attr_reader :installation_options
16
+
13
17
  # Initialize a new instance
14
18
  #
15
19
  # @param [TargetInstallationResult] target_installation_result @see #target_installation_result
20
+ # @param [InstallationOptions] installation_options @see #installation_options
16
21
  #
17
- def initialize(target_installation_result)
22
+ def initialize(target_installation_result, installation_options)
18
23
  @target_installation_result = target_installation_result
24
+ @installation_options = installation_options
19
25
  end
20
26
 
21
27
  # Integrates the pod target.
@@ -53,17 +59,19 @@ module Pod
53
59
  #
54
60
  def add_copy_resources_script_phase(native_target, test_spec)
55
61
  script_path = "${PODS_ROOT}/#{target.copy_resources_script_path_for_test_spec(test_spec).relative_path_from(target.sandbox.root)}"
56
- resource_paths = target.dependent_targets_for_test_spec(test_spec).flat_map do |dependent_target|
57
- spec_paths_to_include = dependent_target.non_test_specs.map(&:name)
58
- spec_paths_to_include << test_spec.name if dependent_target == target
59
- dependent_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
60
- end
61
62
  input_paths = []
62
63
  output_paths = []
63
- unless resource_paths.empty?
64
- resource_paths_flattened = resource_paths.flatten.uniq
65
- input_paths = [script_path, *resource_paths_flattened]
66
- output_paths = UserProjectIntegrator::TargetIntegrator.resource_output_paths(resource_paths_flattened)
64
+ unless installation_options.disable_input_output_paths?
65
+ resource_paths = target.dependent_targets_for_test_spec(test_spec).flat_map do |dependent_target|
66
+ spec_paths_to_include = dependent_target.non_test_specs.map(&:name)
67
+ spec_paths_to_include << test_spec.name if dependent_target == target
68
+ dependent_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
69
+ end
70
+ unless resource_paths.empty?
71
+ resource_paths_flattened = resource_paths.flatten.uniq
72
+ input_paths = [script_path, *resource_paths_flattened]
73
+ output_paths = UserProjectIntegrator::TargetIntegrator.resource_output_paths(resource_paths_flattened)
74
+ end
67
75
  end
68
76
  UserProjectIntegrator::TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
69
77
  UserProjectIntegrator::TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths, output_paths)
@@ -75,17 +83,20 @@ module Pod
75
83
  #
76
84
  def add_embed_frameworks_script_phase(native_target, test_spec)
77
85
  script_path = "${PODS_ROOT}/#{target.embed_frameworks_script_path_for_test_spec(test_spec).relative_path_from(target.sandbox.root)}"
78
- framework_paths = target.dependent_targets_for_test_spec(test_spec).flat_map do |dependent_target|
79
- spec_paths_to_include = dependent_target.non_test_specs.map(&:name)
80
- spec_paths_to_include << test_spec.name if dependent_target == target
81
- dependent_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
82
- end
83
86
  input_paths = []
84
87
  output_paths = []
85
- unless framework_paths.empty?
86
- input_paths = [script_path, *framework_paths.flat_map { |fw| [fw[:input_path], fw[:dsym_input_path]] }.compact]
87
- output_paths = framework_paths.flat_map { |fw| [fw[:output_path], fw[:dsym_output_path]] }.compact
88
+ unless installation_options.disable_input_output_paths?
89
+ framework_paths = target.dependent_targets_for_test_spec(test_spec).flat_map do |dependent_target|
90
+ spec_paths_to_include = dependent_target.non_test_specs.map(&:name)
91
+ spec_paths_to_include << test_spec.name if dependent_target == target
92
+ dependent_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
93
+ end
94
+ unless framework_paths.empty?
95
+ input_paths = [script_path, *framework_paths.flat_map { |fw| [fw.source_path, fw.dsym_path] }.compact]
96
+ output_paths = UserProjectIntegrator::TargetIntegrator.framework_output_paths(framework_paths)
97
+ end
88
98
  end
99
+
89
100
  UserProjectIntegrator::TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
90
101
  UserProjectIntegrator::TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths, output_paths)
91
102
  end
@@ -112,7 +112,7 @@ module Pod
112
112
  end.compact
113
113
 
114
114
  unless error_messages.empty?
115
- raise Informative, "Unable to determine Swift version for the following pods:\n\n #{error_messages.join('\n')}"
115
+ raise Informative, "Unable to determine Swift version for the following pods:\n\n#{error_messages.join("\n")}"
116
116
  end
117
117
  end
118
118
 
@@ -252,6 +252,8 @@ module Pod
252
252
  file_ref.xc_language_specification_identifier = 'xcode.lang.ruby'
253
253
  file_ref.explicit_file_type = 'text.script.ruby'
254
254
  file_ref.last_known_file_type = 'text'
255
+ file_ref.tab_width = '2'
256
+ file_ref.indent_width = '2'
255
257
  end
256
258
 
257
259
  # Adds a new build configuration to the project and populates it with
@@ -1,5 +1,4 @@
1
1
  require 'molinillo'
2
- require 'cocoapods/resolver/lazy_specification'
3
2
 
4
3
  module Pod
5
4
  class NoSpecFoundError < Informative
@@ -12,43 +11,8 @@ module Pod
12
11
  # by target for a given Podfile.
13
12
  #
14
13
  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
14
+ require 'cocoapods/resolver/lazy_specification'
15
+ require 'cocoapods/resolver/resolver_specification'
52
16
 
53
17
  include Pod::Installer::InstallationOptions::Mixin
54
18
 
@@ -97,7 +61,11 @@ module Pod
97
61
  @specs_updated = specs_updated
98
62
  @podfile_dependency_cache = podfile_dependency_cache
99
63
  @platforms_by_dependency = Hash.new { |h, k| h[k] = [] }
64
+
100
65
  @cached_sets = {}
66
+ @podfile_requirements_by_root_name = @podfile_dependency_cache.podfile_dependencies.group_by(&:root_name).each_value { |a| a.map!(&:requirement) }
67
+ @search = {}
68
+ @validated_platforms = Set.new
101
69
  end
102
70
 
103
71
  #-------------------------------------------------------------------------#
@@ -167,11 +135,11 @@ module Pod
167
135
  # @param [Dependency] dependency the dependency that is being searched for.
168
136
  #
169
137
  def search_for(dependency)
170
- @search ||= {}
171
138
  @search[dependency] ||= begin
172
139
  locked_requirement = requirement_for_locked_pod_named(dependency.name)
173
- additional_requirements = Array(locked_requirement)
174
- specifications_for_dependency(dependency, additional_requirements)
140
+ podfile_deps = Array(@podfile_requirements_by_root_name[dependency.root_name])
141
+ podfile_deps << locked_requirement if locked_requirement
142
+ specifications_for_dependency(dependency, podfile_deps)
175
143
  end
176
144
  @search[dependency].dup
177
145
  end
@@ -238,7 +206,7 @@ module Pod
238
206
  end
239
207
 
240
208
  def valid_possibility_version_for_root_name?(requirement, activated, spec)
241
- prerelease_requirement = requirement.prerelease? || requirement.external_source || !spec.version.prerelease?
209
+ return true if prerelease_requirement = requirement.prerelease? || requirement.external_source || !spec.version.prerelease?
242
210
 
243
211
  activated.each do |vertex|
244
212
  next unless vertex.payload
@@ -381,7 +349,7 @@ module Pod
381
349
  #
382
350
  def find_cached_set(dependency)
383
351
  name = dependency.root_name
384
- unless cached_sets[name]
352
+ cached_sets[name] ||= begin
385
353
  if dependency.external_source
386
354
  spec = sandbox.specification(name)
387
355
  unless spec
@@ -392,12 +360,13 @@ module Pod
392
360
  else
393
361
  set = create_set_from_sources(dependency)
394
362
  end
395
- cached_sets[name] = set
363
+
396
364
  unless set
397
365
  raise Molinillo::NoSuchDependencyError.new(dependency) # rubocop:disable Style/RaiseArgs
398
366
  end
367
+
368
+ set
399
369
  end
400
- cached_sets[name]
401
370
  end
402
371
 
403
372
  # @return [Requirement, Nil]
@@ -426,8 +395,11 @@ module Pod
426
395
  # @return [Source::Aggregate] The aggregate of the {#sources}.
427
396
  #
428
397
  def aggregate_for_dependency(dependency)
398
+ sources_manager = Config.instance.sources_manager
429
399
  if dependency && dependency.podspec_repo
430
- return Config.instance.sources_manager.aggregate_for_dependency(dependency)
400
+ sources_manager.aggregate_for_dependency(dependency)
401
+ elsif (locked_vertex = @locked_dependencies.vertex_named(dependency.name)) && (locked_dependency = locked_vertex.payload) && locked_dependency.podspec_repo
402
+ sources_manager.aggregate_for_dependency(locked_dependency)
431
403
  else
432
404
  @aggregate ||= Source::Aggregate.new(sources)
433
405
  end
@@ -441,6 +413,7 @@ module Pod
441
413
  #
442
414
  def validate_platform(spec, target)
443
415
  return unless target_platform = target.platform
416
+ return unless @validated_platforms.add?([spec.object_id, target_platform])
444
417
  unless spec.available_platforms.any? { |p| target_platform.to_sym == p.to_sym }
445
418
  raise Informative, "The platform of the target `#{target.name}` " \
446
419
  "(#{target.platform}) is not compatible with `#{spec}`, which does " \
@@ -509,6 +482,17 @@ module Pod
509
482
  end
510
483
  end,
511
484
  )
485
+ when Molinillo::NoSuchDependencyError
486
+ message += <<-EOS
487
+
488
+
489
+ You have either:
490
+ * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
491
+ * mistyped the name or version.
492
+ * not added the source repo that hosts the Podspec to your Podfile.
493
+
494
+ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
495
+ EOS
512
496
  end
513
497
  raise type.new(message).tap { |e| e.set_backtrace(error.backtrace) }
514
498
  end
@@ -569,17 +553,26 @@ module Pod
569
553
  end
570
554
  end
571
555
 
556
+ EdgeAndPlatform = Struct.new(:edge, :target_platform)
557
+ private_constant :EdgeAndPlatform
558
+
572
559
  # Whether the given `edge` should be followed to find dependencies for the
573
560
  # given `target_platform`.
574
561
  #
575
562
  # @return [Bool]
576
563
  #
577
564
  def edge_is_valid_for_target_platform?(edge, target_platform)
578
- requirement_name = edge.requirement.name
565
+ @edge_validity ||= Hash.new do |hash, edge_and_platform|
566
+ e = edge_and_platform.edge
567
+ platform = edge_and_platform.target_platform
568
+ requirement_name = e.requirement.name
579
569
 
580
- edge.origin.payload.all_dependencies(target_platform).any? do |dep|
581
- dep.name == requirement_name
570
+ hash[edge_and_platform] = e.origin.payload.all_dependencies(platform).any? do |dep|
571
+ dep.name == requirement_name
572
+ end
582
573
  end
574
+
575
+ @edge_validity[EdgeAndPlatform.new(edge, target_platform)]
583
576
  end
584
577
  end
585
578
  end
@@ -0,0 +1,41 @@
1
+ module Pod
2
+ class Resolver
3
+ # A small container that wraps a resolved specification for a given target definition. Additional metadata
4
+ # is included here such as if the specification is only used by tests.
5
+ #
6
+ class ResolverSpecification
7
+ # @return [Specification] the specification that was resolved
8
+ #
9
+ attr_reader :spec
10
+
11
+ # @return [Source] the spec repo source the specification came from
12
+ #
13
+ attr_reader :source
14
+
15
+ # @return [Bool] whether this resolved specification is only used by tests.
16
+ #
17
+ attr_reader :used_by_tests_only
18
+ alias used_by_tests_only? used_by_tests_only
19
+
20
+ def initialize(spec, used_by_tests_only, source)
21
+ @spec = spec
22
+ @used_by_tests_only = used_by_tests_only
23
+ @source = source
24
+ end
25
+
26
+ def name
27
+ spec.name
28
+ end
29
+
30
+ def root
31
+ spec.root
32
+ end
33
+
34
+ def ==(other)
35
+ self.class == other.class &&
36
+ spec == other.spec &&
37
+ used_by_tests_only? == other.used_by_tests_only?
38
+ end
39
+ end
40
+ end
41
+ end
@@ -254,25 +254,29 @@ module Pod
254
254
  file_name = json ? "#{name}.podspec.json" : "#{name}.podspec"
255
255
  output_path = specifications_root + file_name
256
256
 
257
- case podspec
258
- when String
259
- output_path.open('w') { |f| f.puts(podspec) }
260
- when Pathname
261
- unless podspec.exist?
262
- raise Informative, "No podspec found for `#{name}` in #{podspec}"
257
+ spec =
258
+ case podspec
259
+ when String
260
+ output_path.open('w') { |f| f.puts(podspec) }
261
+ Specification.from_file(output_path)
262
+ when Pathname
263
+ unless podspec.exist?
264
+ raise Informative, "No podspec found for `#{name}` in #{podspec}"
265
+ end
266
+ FileUtils.copy(podspec, output_path)
267
+ Specification.from_file(podspec)
268
+ when Specification
269
+ raise ArgumentError, 'can only store Specification objects as json' unless json
270
+ output_path.open('w') { |f| f.puts(podspec.to_pretty_json) }
271
+ podspec.dup
272
+ else
273
+ raise ArgumentError, "Unknown type for podspec: #{podspec.inspect}"
263
274
  end
264
- spec = Specification.from_file(podspec)
265
- FileUtils.copy(podspec, output_path)
266
- when Specification
267
- raise ArgumentError, 'can only store Specification objects as json' unless json
268
- output_path.open('w') { |f| f.puts(podspec.to_pretty_json) }
269
- spec = podspec.dup
270
- else
271
- raise ArgumentError, "Unknown type for podspec: #{podspec.inspect}"
272
- end
273
275
 
274
- spec ||= Specification.from_file(output_path)
275
- spec.defined_in_file ||= output_path
276
+ # we force the file to be the file in the sandbox, so specs that have been serialized to
277
+ # json maintain a consistent checksum.
278
+ # this is safe to do because `spec` is always a clean instance
279
+ spec.defined_in_file = output_path
276
280
 
277
281
  unless spec.name == name
278
282
  raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
@@ -1,3 +1,5 @@
1
+ require 'cocoapods/target/framework_paths'
2
+
1
3
  module Pod
2
4
  # Stores the information relative to the target used to cluster the targets
3
5
  # of the single Pods. The client targets will then depend on this one.
@@ -222,7 +224,7 @@ module Pod
222
224
  !framework_paths_by_config.values.all?(&:empty?)
223
225
  end
224
226
 
225
- # @return [Hash{String => Array<Hash{Symbol => [String]}>}] The vendored dynamic artifacts and framework target
227
+ # @return [Hash{String => Array<FrameworkPaths>}] The vendored dynamic artifacts and framework target
226
228
  # input and output paths grouped by config
227
229
  #
228
230
  def framework_paths_by_config
@@ -552,7 +552,7 @@ module Pod
552
552
 
553
553
  # @return [Array<String>]
554
554
  define_build_settings_method :weak_frameworks_to_import, :memoized => true, :sorted => true, :uniqued => true do
555
- []
555
+ spec_consumers.flat_map(&:weak_frameworks)
556
556
  end
557
557
 
558
558
  # @return [Array<String>]
@@ -564,6 +564,12 @@ module Pod
564
564
  paths
565
565
  end
566
566
 
567
+ # @return [String]
568
+ define_build_settings_method :framework_header_search_path, :memoized => true do
569
+ return unless target.requires_frameworks?
570
+ "#{target.build_product_path}/Headers"
571
+ end
572
+
567
573
  # @return [Array<String>]
568
574
  define_build_settings_method :vendored_framework_search_paths, :memoized => true do
569
575
  file_accessors.flat_map(&:vendored_frameworks).map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
@@ -690,6 +696,11 @@ module Pod
690
696
  target.header_search_paths(:include_dependent_targets_for_test_spec => test_spec)
691
697
  end
692
698
 
699
+ # @return [Array<String>]
700
+ define_build_settings_method :public_header_search_paths, :memoized => true, :sorted => true do
701
+ target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig?, :include_private_headers => false)
702
+ end
703
+
693
704
  #-------------------------------------------------------------------------#
694
705
 
695
706
  # @!group Swift
@@ -907,6 +918,12 @@ module Pod
907
918
  paths.concat target.sandbox.public_headers.search_paths(target.platform)
908
919
  end
909
920
 
921
+ # Make frameworks headers discoverable with any syntax (quotes,
922
+ # brackets, @import, etc.)
923
+ paths.concat pod_targets.
924
+ select { |pt| pt.requires_frameworks? && pt.should_build? }.
925
+ map { |pt| pt.build_settings.framework_header_search_path }
926
+
910
927
  paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).header_search_paths }
911
928
 
912
929
  paths
@@ -915,18 +932,24 @@ module Pod
915
932
  # @return [Array<String>]
916
933
  define_build_settings_method :other_cflags, :build_setting => true, :memoized => true do
917
934
  flags = super()
918
- flags +
919
- header_search_paths.flat_map { |p| ['-isystem', p] } +
920
- framework_header_paths_for_iquote.flat_map { |p| ['-iquote', p] }
921
- end
922
935
 
923
- # @return [Array<String>]
924
- define_build_settings_method :framework_header_paths_for_iquote, :memoized => true, :sorted => true, :uniqued => true do
925
- paths = pod_targets.
926
- select { |pt| pt.should_build? && pt.requires_frameworks? }.
927
- map { |pt| "#{pt.build_product_path}/Headers" }
928
- paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).framework_header_paths_for_iquote }
929
- paths
936
+ pod_targets_inhibiting_warnings = pod_targets.select(&:inhibit_warnings?)
937
+
938
+ silenced_headers = []
939
+ silenced_frameworks = []
940
+ pod_targets_inhibiting_warnings.each do |pt|
941
+ if pt.requires_frameworks? && pt.should_build?
942
+ silenced_headers.append pt.build_settings.framework_header_search_path
943
+ else
944
+ silenced_headers.concat pt.build_settings.public_header_search_paths
945
+ end
946
+ silenced_frameworks.concat pt.build_settings.framework_search_paths_to_import
947
+ end
948
+
949
+ flags += silenced_headers.uniq.flat_map { |p| ['-isystem', p] }
950
+ flags += silenced_frameworks.uniq.flat_map { |p| ['-iframework', p] }
951
+
952
+ flags
930
953
  end
931
954
 
932
955
  # @return [Array<String>]