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
@@ -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
  #-------------------------------------------------------------------------#
@@ -133,19 +101,16 @@ module Pod
133
101
  #
134
102
  def resolver_specs_by_target
135
103
  @resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
136
- dependencies = {}
137
104
  @podfile_dependency_cache.target_definition_list.each do |target|
138
- specs = @podfile_dependency_cache.target_definition_dependencies(target).flat_map do |dep|
139
- name = dep.name
140
- node = @activated.vertex_named(name)
141
- (valid_dependencies_for_target_from_node(target, dependencies, node) << node).map { |s| [s, node.payload.test_specification?] }
142
- end
105
+ # can't use vertex.root? since that considers _all_ targets
106
+ explicit_dependencies = @podfile_dependency_cache.target_definition_dependencies(target).map(&:name).to_set
107
+ vertices = valid_dependencies_for_target(target)
143
108
 
144
- resolver_specs_by_target[target] = specs.
145
- group_by(&:first).
146
- map do |vertex, spec_test_only_tuples|
147
- test_only = spec_test_only_tuples.all? { |tuple| tuple[1] }
109
+ resolver_specs_by_target[target] = vertices.
110
+ map do |vertex|
148
111
  payload = vertex.payload
112
+ test_only = (!explicit_dependencies.include?(vertex.name) || payload.test_specification?) &&
113
+ (vertex.recursive_predecessors & vertices).all? { |v| !explicit_dependencies.include?(v.name) || v.payload.test_specification? }
149
114
  spec_source = payload.respond_to?(:spec_source) && payload.spec_source
150
115
  ResolverSpecification.new(payload, test_only, spec_source)
151
116
  end.
@@ -170,11 +135,11 @@ module Pod
170
135
  # @param [Dependency] dependency the dependency that is being searched for.
171
136
  #
172
137
  def search_for(dependency)
173
- @search ||= {}
174
138
  @search[dependency] ||= begin
175
139
  locked_requirement = requirement_for_locked_pod_named(dependency.name)
176
- additional_requirements = Array(locked_requirement)
177
- 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)
178
143
  end
179
144
  @search[dependency].dup
180
145
  end
@@ -235,31 +200,29 @@ module Pod
235
200
  def requirement_satisfied_by?(requirement, activated, spec)
236
201
  version = spec.version
237
202
  return false unless requirement.requirement.satisfied_by?(version)
238
- shared_possibility_versions, prerelease_requirement = possibility_versions_for_root_name(requirement, activated)
239
- return false if !shared_possibility_versions.empty? && !shared_possibility_versions.include?(version)
240
- return false if version.prerelease? && !prerelease_requirement
203
+ return false unless valid_possibility_version_for_root_name?(requirement, activated, spec)
241
204
  return false unless spec_is_platform_compatible?(activated, requirement, spec)
242
205
  true
243
206
  end
244
207
 
245
- def possibility_versions_for_root_name(requirement, activated)
246
- prerelease_requirement = requirement.prerelease? || requirement.external_source
247
- existing = activated.vertices.values.flat_map do |vertex|
208
+ def valid_possibility_version_for_root_name?(requirement, activated, spec)
209
+ return true if prerelease_requirement = requirement.prerelease? || requirement.external_source || !spec.version.prerelease?
210
+
211
+ activated.each do |vertex|
248
212
  next unless vertex.payload
249
213
  next unless Specification.root_name(vertex.name) == requirement.root_name
250
214
 
251
215
  prerelease_requirement ||= vertex.requirements.any? { |r| r.prerelease? || r.external_source }
252
216
 
253
- if vertex.payload.respond_to?(:possibilities)
254
- vertex.payload.possibilities.map(&:version)
255
- else
256
- vertex.payload.version
217
+ if vertex.payload.respond_to?(:version)
218
+ return true if vertex.payload.version == spec.version
219
+ break
257
220
  end
258
- end.compact
221
+ end
259
222
 
260
- [existing, prerelease_requirement]
223
+ prerelease_requirement
261
224
  end
262
- private :possibility_versions_for_root_name
225
+ private :valid_possibility_version_for_root_name?
263
226
 
264
227
  # Sort dependencies so that the ones that are easiest to resolve are first.
265
228
  # Easiest to resolve is (usually) defined by:
@@ -386,7 +349,7 @@ module Pod
386
349
  #
387
350
  def find_cached_set(dependency)
388
351
  name = dependency.root_name
389
- unless cached_sets[name]
352
+ cached_sets[name] ||= begin
390
353
  if dependency.external_source
391
354
  spec = sandbox.specification(name)
392
355
  unless spec
@@ -397,12 +360,13 @@ module Pod
397
360
  else
398
361
  set = create_set_from_sources(dependency)
399
362
  end
400
- cached_sets[name] = set
363
+
401
364
  unless set
402
365
  raise Molinillo::NoSuchDependencyError.new(dependency) # rubocop:disable Style/RaiseArgs
403
366
  end
367
+
368
+ set
404
369
  end
405
- cached_sets[name]
406
370
  end
407
371
 
408
372
  # @return [Requirement, Nil]
@@ -431,8 +395,11 @@ module Pod
431
395
  # @return [Source::Aggregate] The aggregate of the {#sources}.
432
396
  #
433
397
  def aggregate_for_dependency(dependency)
398
+ sources_manager = Config.instance.sources_manager
434
399
  if dependency && dependency.podspec_repo
435
- 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)
436
403
  else
437
404
  @aggregate ||= Source::Aggregate.new(sources)
438
405
  end
@@ -446,6 +413,7 @@ module Pod
446
413
  #
447
414
  def validate_platform(spec, target)
448
415
  return unless target_platform = target.platform
416
+ return unless @validated_platforms.add?([spec.object_id, target_platform])
449
417
  unless spec.available_platforms.any? { |p| target_platform.to_sym == p.to_sym }
450
418
  raise Informative, "The platform of the target `#{target.name}` " \
451
419
  "(#{target.platform}) is not compatible with `#{spec}`, which does " \
@@ -455,11 +423,6 @@ module Pod
455
423
 
456
424
  # Handles errors that come out of a {Molinillo::Resolver}.
457
425
  #
458
- # @todo The check for version conflicts coming from the {Lockfile}
459
- # requiring a pre-release version can be deleted for version 1.0,
460
- # as it is a migration step for Lockfiles coming from CocoaPods
461
- # versions before `0.35.0`.
462
- #
463
426
  # @return [void]
464
427
  #
465
428
  # @param [Molinillo::ResolverError] error
@@ -475,16 +438,7 @@ module Pod
475
438
  :version_for_spec => lambda(&:version),
476
439
  :additional_message_for_conflict => lambda do |o, name, conflict|
477
440
  local_pod_parent = conflict.requirement_trees.flatten.reverse.find(&:local?)
478
- lockfile_reqs = conflict.requirements[name_for_locking_dependency_source]
479
- if lockfile_reqs && lockfile_reqs.last && lockfile_reqs.last.prerelease? && !conflict.existing
480
- o << "\nDue to the previous naïve CocoaPods resolver, " \
481
- "you were using a pre-release version of `#{name}`, " \
482
- 'without explicitly asking for a pre-release version, which now leads to a conflict. ' \
483
- 'Please decide to either use that pre-release version by adding the ' \
484
- 'version requirement to your Podfile ' \
485
- "(e.g. `pod '#{name}', '#{lockfile_reqs.map(&:requirement).join("', '")}'`) " \
486
- "or revert to a stable version by running `pod update #{name}`."
487
- elsif local_pod_parent && !specifications_for_dependency(conflict.requirement).empty? && !conflict.possibility && conflict.locked_requirement
441
+ if local_pod_parent && !specifications_for_dependency(conflict.requirement).empty? && !conflict.possibility && conflict.locked_requirement
488
442
  # Conflict was caused by a requirement from a local dependency.
489
443
  # Tell user to use `pod update`.
490
444
  o << "\nIt seems like you've changed the constraints of dependency `#{name}` " \
@@ -528,6 +482,17 @@ module Pod
528
482
  end
529
483
  end,
530
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
531
496
  end
532
497
  raise type.new(message).tap { |e| e.set_backtrace(error.backtrace) }
533
498
  end
@@ -543,8 +508,12 @@ module Pod
543
508
  #
544
509
  # @return [Bool]
545
510
  def spec_is_platform_compatible?(dependency_graph, dependency, spec)
511
+ # This is safe since a pod will only be in locked dependencies if we're
512
+ # using the same exact version
513
+ return true if locked_dependencies.vertex_named(spec.name)
514
+
546
515
  vertex = dependency_graph.vertex_named(dependency.name)
547
- predecessors = vertex.recursive_predecessors.select(&:root)
516
+ predecessors = vertex.recursive_predecessors.select(&:root?)
548
517
  predecessors << vertex if vertex.root?
549
518
  platforms_to_satisfy = predecessors.flat_map(&:explicit_requirements).flat_map { |r| @platforms_by_dependency[r] }.uniq
550
519
 
@@ -566,32 +535,44 @@ module Pod
566
535
  # An array of target-appropriate nodes whose `payload`s are
567
536
  # dependencies for `target`.
568
537
  #
569
- def valid_dependencies_for_target_from_node(target, dependencies, node)
570
- dependencies[[node.name, target.platform]] ||= begin
571
- validate_platform(node.payload, target)
572
- dependency_nodes = []
573
- node.outgoing_edges.each do |edge|
574
- next unless edge_is_valid_for_target_platform?(edge, target.platform)
575
- dependency_nodes << edge.destination
576
- end
538
+ def valid_dependencies_for_target(target)
539
+ dependencies = Set.new
540
+ @podfile_dependency_cache.target_definition_dependencies(target).each do |dep|
541
+ node = @activated.vertex_named(dep.name)
542
+ add_valid_dependencies_from_node(node, target, dependencies)
543
+ end
544
+ dependencies
545
+ end
577
546
 
578
- dependency_nodes.flat_map do |item|
579
- valid_dependencies_for_target_from_node(target, dependencies, item)
580
- end.concat dependency_nodes
547
+ def add_valid_dependencies_from_node(node, target, dependencies)
548
+ return unless dependencies.add?(node)
549
+ validate_platform(node.payload, target)
550
+ node.outgoing_edges.each do |edge|
551
+ next unless edge_is_valid_for_target_platform?(edge, target.platform)
552
+ add_valid_dependencies_from_node(edge.destination, target, dependencies)
581
553
  end
582
554
  end
583
555
 
556
+ EdgeAndPlatform = Struct.new(:edge, :target_platform)
557
+ private_constant :EdgeAndPlatform
558
+
584
559
  # Whether the given `edge` should be followed to find dependencies for the
585
560
  # given `target_platform`.
586
561
  #
587
562
  # @return [Bool]
588
563
  #
589
564
  def edge_is_valid_for_target_platform?(edge, target_platform)
590
- 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
591
569
 
592
- edge.origin.payload.all_dependencies(target_platform).any? do |dep|
593
- 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
594
573
  end
574
+
575
+ @edge_validity[EdgeAndPlatform.new(edge, target_platform)]
595
576
  end
596
577
  end
597
578
  end
@@ -1,4 +1,4 @@
1
- autoload :MachO, 'macho'
1
+ require 'macho'
2
2
 
3
3
  module Pod
4
4
  class Sandbox
@@ -33,8 +33,8 @@ module Pod
33
33
 
34
34
  # Initialize a new instance
35
35
  #
36
- # @param [Sandbox::PathList, Pathname] path_list @see path_list
37
- # @param [Specification::Consumer] spec_consumer @see spec_consumer
36
+ # @param [Sandbox::PathList, Pathname] path_list @see #path_list
37
+ # @param [Specification::Consumer] spec_consumer @see #spec_consumer
38
38
  #
39
39
  def initialize(path_list, spec_consumer)
40
40
  if path_list.is_a?(PathList)
@@ -106,6 +106,13 @@ module Pod
106
106
  source_files - arc_source_files
107
107
  end
108
108
 
109
+ # @return [Array<Pathname] the source files that do not match any of the
110
+ # recognized file extensions
111
+ def other_source_files
112
+ extensions = SOURCE_FILE_EXTENSIONS
113
+ source_files.reject { |f| extensions.include?(f.extname) }
114
+ end
115
+
109
116
  # @return [Array<Pathname>] the headers of the specification.
110
117
  #
111
118
  def headers
@@ -413,9 +420,7 @@ module Pod
413
420
  #
414
421
  def expanded_paths(patterns, options = {})
415
422
  return [] if patterns.empty?
416
- result = []
417
- result << path_list.glob(patterns, options)
418
- result.flatten.compact.uniq
423
+ path_list.glob(patterns, options).flatten.compact.uniq
419
424
  end
420
425
 
421
426
  # @param [Pathname] binary
@@ -16,7 +16,7 @@ module Pod
16
16
  #
17
17
  attr_reader :sandbox
18
18
 
19
- # @param [Sandbox] @see sandbox
19
+ # @param [Sandbox] @see #sandbox
20
20
  #
21
21
  # @param [String] relative_path
22
22
  # the relative path to the sandbox root and hence to the Pods
@@ -54,7 +54,7 @@ module Pod
54
54
  return @search_paths_cache[key] if @search_paths_cache.key?(key)
55
55
  search_paths = @search_paths.select do |entry|
56
56
  matches_platform = entry[:platform] == platform.name
57
- matches_target = target_name.nil? || (entry[:path].basename.to_s == target_name)
57
+ matches_target = target_name.nil? || (File.basename(entry[:path]) == target_name)
58
58
  matches_platform && matches_target
59
59
  end
60
60
  headers_dir = root.relative_path_from(sandbox.root).dirname
@@ -63,7 +63,7 @@ module Pod
63
63
  paths << "${PODS_ROOT}/#{headers_dir}/#{@relative_path}" if !use_modular_headers || @visibility_scope == :public
64
64
  paths << "${PODS_ROOT}/#{headers_dir}/#{entry[:path]}" if !use_modular_headers || @visibility_scope == :private
65
65
  paths
66
- end.uniq
66
+ end.tap(&:uniq!).freeze
67
67
  end
68
68
 
69
69
  # Removes the directory as it is regenerated from scratch during each
@@ -96,8 +96,9 @@ module Pod
96
96
  # @return [Array<Pathname>]
97
97
  #
98
98
  def add_files(namespace, relative_header_paths)
99
+ root.join(namespace).mkpath unless relative_header_paths.empty?
99
100
  relative_header_paths.map do |relative_header_path|
100
- add_file(namespace, relative_header_path)
101
+ add_file(namespace, relative_header_path, :mkdir => false)
101
102
  end
102
103
  end
103
104
 
@@ -115,9 +116,9 @@ module Pod
115
116
  #
116
117
  # @return [Pathname]
117
118
  #
118
- def add_file(namespace, relative_header_path)
119
+ def add_file(namespace, relative_header_path, mkdir: true)
119
120
  namespaced_path = root + namespace
120
- namespaced_path.mkpath unless File.exist?(namespaced_path)
121
+ namespaced_path.mkpath if mkdir
121
122
 
122
123
  absolute_source = (sandbox.root + relative_header_path)
123
124
  source = absolute_source.relative_path_from(namespaced_path)
@@ -128,7 +129,7 @@ module Pod
128
129
  # Adds an header search path to the sandbox.
129
130
  #
130
131
  # @param [Pathname] path
131
- # the path tho add.
132
+ # the path to add.
132
133
  #
133
134
  # @param [String] platform
134
135
  # the platform the search path applies to
@@ -136,7 +137,7 @@ module Pod
136
137
  # @return [void]
137
138
  #
138
139
  def add_search_path(path, platform)
139
- @search_paths << { :platform => platform.name, :path => (Pathname.new(@relative_path) + path) }
140
+ @search_paths << { :platform => platform.name, :path => File.join(@relative_path, path) }
140
141
  end
141
142
 
142
143
  #-----------------------------------------------------------------------#
@@ -16,11 +16,11 @@ module Pod
16
16
  # @return [Pathname] The root of the list whose files and directories
17
17
  # are used to perform the matching operations.
18
18
  #
19
- attr_accessor :root
19
+ attr_reader :root
20
20
 
21
21
  # Initialize a new instance
22
22
  #
23
- # @param [Pathname] root The root of the PathList.
23
+ # @param [Pathname] root @see #root
24
24
  #
25
25
  def initialize(root)
26
26
  root_dir = ActiveSupport::Multibyte::Unicode.normalize(root.to_s)
@@ -88,7 +88,8 @@ module Pod
88
88
  # @return [Array<Pathname>]
89
89
  #
90
90
  def glob(patterns, options = {})
91
- relative_glob(patterns, options).map { |p| root.join(p) }
91
+ cache_key = options.merge(:patterns => patterns)
92
+ @glob_cache[cache_key] ||= relative_glob(patterns, options).map { |p| root.join(p) }
92
93
  end
93
94
 
94
95
  # The list of relative paths that are case insensitively matched by a
@@ -115,10 +116,6 @@ module Pod
115
116
  def relative_glob(patterns, options = {})
116
117
  return [] if patterns.empty?
117
118
 
118
- cache_key = options.merge(:patterns => patterns)
119
- cached_value = @glob_cache[cache_key]
120
- return cached_value if cached_value
121
-
122
119
  dir_pattern = options[:dir_pattern]
123
120
  exclude_patterns = options[:exclude_patterns]
124
121
  include_dirs = options[:include_dirs]
@@ -155,7 +152,7 @@ module Pod
155
152
  exclude_options = { :dir_pattern => '**/*', :include_dirs => include_dirs }
156
153
  list -= relative_glob(exclude_patterns, exclude_options)
157
154
  end
158
- @glob_cache[cache_key] = list
155
+ list
159
156
  end
160
157
 
161
158
  #-----------------------------------------------------------------------#
@@ -52,7 +52,7 @@ module Pod
52
52
 
53
53
  # Initialize a new instance
54
54
  #
55
- # @param [String, Pathname] root @see root
55
+ # @param [String, Pathname] root @see #root
56
56
  #
57
57
  def initialize(root)
58
58
  FileUtils.mkdir_p(root)
@@ -62,6 +62,7 @@ module Pod
62
62
  @checkout_sources = {}
63
63
  @development_pods = {}
64
64
  @pods_with_absolute_path = []
65
+ @stored_podspecs = {}
65
66
  end
66
67
 
67
68
  # @return [Lockfile] the manifest which contains the information about the
@@ -209,9 +210,9 @@ module Pod
209
210
  # @return [Specification] the specification if the file is found.
210
211
  #
211
212
  def specification(name)
212
- if file = specification_path(name)
213
- original_path = development_pods[name]
214
- Specification.from_file(original_path || file)
213
+ @stored_podspecs[name] ||= if file = specification_path(name)
214
+ original_path = development_pods[name]
215
+ Specification.from_file(original_path || file)
215
216
  end
216
217
  end
217
218
 
@@ -242,7 +243,7 @@ module Pod
242
243
  # @param [String] name
243
244
  # the name of the pod
244
245
  #
245
- # @param [String, Pathname] podspec
246
+ # @param [String, Pathname, Specification] podspec
246
247
  # The contents of the specification (String) or the path to a
247
248
  # podspec file (Pathname).
248
249
  #
@@ -252,23 +253,35 @@ module Pod
252
253
  def store_podspec(name, podspec, _external_source = false, json = false)
253
254
  file_name = json ? "#{name}.podspec.json" : "#{name}.podspec"
254
255
  output_path = specifications_root + file_name
255
- output_path.dirname.mkpath
256
- if podspec.is_a?(String)
257
- output_path.open('w') { |f| f.puts(podspec) }
258
- else
259
- unless podspec.exist?
260
- raise Informative, "No podspec found for `#{name}` in #{podspec}"
256
+
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}"
261
274
  end
262
- FileUtils.copy(podspec, output_path)
263
- end
264
275
 
265
- Dir.chdir(podspec.is_a?(Pathname) ? File.dirname(podspec) : Dir.pwd) do
266
- spec = Specification.from_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
267
280
 
268
- unless spec.name == name
269
- raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
270
- end
281
+ unless spec.name == name
282
+ raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
271
283
  end
284
+ @stored_podspecs[spec.name] = spec
272
285
  end
273
286
 
274
287
  #-------------------------------------------------------------------------#
@@ -367,8 +380,6 @@ module Pod
367
380
  # @return [Hash{String=>Pathname}] The path of the Pods' podspecs with a local source
368
381
  # grouped by their root name.
369
382
  #
370
- # @todo Rename (e.g. `pods_with_local_path`)
371
- #
372
383
  attr_reader :development_pods
373
384
 
374
385
  # Checks if a Pod is locally sourced?
@@ -393,28 +404,5 @@ module Pod
393
404
  end
394
405
 
395
406
  #-------------------------------------------------------------------------#
396
-
397
- public
398
-
399
- # @!group Pods Helpers
400
-
401
- # Creates the file accessors for the given Pod Targets.
402
- #
403
- # @param [Array<PodTarget>] pod_targets
404
- # The Pod Targets to create file accessors for.
405
- #
406
- def create_file_accessors(pod_targets)
407
- pod_targets.each do |pod_target|
408
- pod_root = pod_dir(pod_target.root_spec.name)
409
- path_list = PathList.new(pod_root)
410
- file_accessors = pod_target.specs.map do |spec|
411
- FileAccessor.new(path_list, spec.consumer(pod_target.platform))
412
- end
413
- pod_target.file_accessors ||= []
414
- pod_target.file_accessors.concat(file_accessors)
415
- end
416
- end
417
-
418
- #-------------------------------------------------------------------------#
419
407
  end
420
408
  end
@@ -31,7 +31,7 @@ module Pod
31
31
  "named `#{name}`.\n"
32
32
  message << "(#{e})\n" if Config.instance.verbose?
33
33
  message << 'You can try adding it manually in ' \
34
- '`~/.cocoapods/repos` or via `pod repo add`.'
34
+ "`#{Config.instance.repos_dir}` or via `pod repo add`."
35
35
  raise Informative, message
36
36
  ensure
37
37
  UI.title_level = previous_title_level