cocoapods 0.39.0 → 1.0.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +261 -12
  3. data/lib/cocoapods.rb +1 -0
  4. data/lib/cocoapods/command.rb +1 -0
  5. data/lib/cocoapods/command/env.rb +66 -0
  6. data/lib/cocoapods/command/init.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +1 -1
  8. data/lib/cocoapods/command/project.rb +0 -4
  9. data/lib/cocoapods/command/repo/lint.rb +7 -6
  10. data/lib/cocoapods/command/repo/push.rb +22 -1
  11. data/lib/cocoapods/command/setup.rb +0 -24
  12. data/lib/cocoapods/command/spec/create.rb +3 -1
  13. data/lib/cocoapods/command/spec/edit.rb +14 -21
  14. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  15. data/lib/cocoapods/command/spec/lint.rb +1 -1
  16. data/lib/cocoapods/config.rb +1 -34
  17. data/lib/cocoapods/downloader.rb +9 -4
  18. data/lib/cocoapods/external_sources.rb +0 -4
  19. data/lib/cocoapods/external_sources/abstract_external_source.rb +38 -11
  20. data/lib/cocoapods/external_sources/path_source.rb +2 -2
  21. data/lib/cocoapods/gem_version.rb +2 -2
  22. data/lib/cocoapods/generator/acknowledgements.rb +1 -1
  23. data/lib/cocoapods/generator/acknowledgements/plist.rb +1 -1
  24. data/lib/cocoapods/generator/copy_resources_script.rb +28 -21
  25. data/lib/cocoapods/generator/info_plist_file.rb +34 -8
  26. data/lib/cocoapods/generator/module_map.rb +3 -18
  27. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +22 -10
  28. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +2 -1
  29. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +2 -1
  30. data/lib/cocoapods/hooks_manager.rb +3 -11
  31. data/lib/cocoapods/installer.rb +45 -25
  32. data/lib/cocoapods/installer/analyzer.rb +53 -25
  33. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +2 -13
  34. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +4 -0
  35. data/lib/cocoapods/installer/analyzer/target_inspector.rb +22 -19
  36. data/lib/cocoapods/installer/file_references_installer.rb +53 -6
  37. data/lib/cocoapods/installer/installation_options.rb +156 -0
  38. data/lib/cocoapods/installer/migrator.rb +1 -56
  39. data/lib/cocoapods/installer/pod_source_installer.rb +10 -8
  40. data/lib/cocoapods/installer/podfile_validator.rb +42 -1
  41. data/lib/cocoapods/installer/post_install_hooks_context.rb +19 -2
  42. data/lib/cocoapods/installer/target_installer.rb +6 -2
  43. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +6 -5
  44. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +82 -14
  45. data/lib/cocoapods/installer/user_project_integrator.rb +37 -16
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +14 -136
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +15 -22
  48. data/lib/cocoapods/project.rb +109 -19
  49. data/lib/cocoapods/resolver.rb +17 -15
  50. data/lib/cocoapods/resolver/lazy_specification.rb +4 -0
  51. data/lib/cocoapods/sandbox.rb +0 -32
  52. data/lib/cocoapods/sandbox/headers_store.rb +2 -2
  53. data/lib/cocoapods/sandbox/podspec_finder.rb +1 -1
  54. data/lib/cocoapods/sources_manager.rb +181 -50
  55. data/lib/cocoapods/target/aggregate_target.rb +17 -11
  56. data/lib/cocoapods/target/pod_target.rb +31 -4
  57. data/lib/cocoapods/user_interface.rb +32 -3
  58. data/lib/cocoapods/user_interface/error_report.rb +46 -36
  59. data/lib/cocoapods/validator.rb +132 -43
  60. metadata +164 -79
@@ -12,66 +12,11 @@ module Pod
12
12
  # The sandbox which should be migrated.
13
13
  #
14
14
  def migrate(sandbox)
15
- if sandbox.manifest
16
- migrate_to_0_34(sandbox) if installation_minor?('0.34', sandbox)
17
- migrate_to_0_36(sandbox) if installation_minor?('0.36', sandbox)
18
- end
15
+ return unless sandbox.manifest
19
16
  end
20
17
 
21
18
  # @!group Migration Steps
22
19
 
23
- # Migrates from CocoaPods versions previous to 0.34.
24
- #
25
- # @param [Sandbox] sandbox
26
- #
27
- def migrate_to_0_34(sandbox)
28
- UI.message('Migrating to CocoaPods 0.34') do
29
- delete(sandbox.root + 'Headers')
30
- make_path(sandbox.headers_root)
31
-
32
- sandbox.root.children.each do |child|
33
- relative = child.relative_path_from(sandbox.root)
34
- case relative.to_s
35
- when 'Manifest.lock', 'Pods.xcodeproj', 'Headers',
36
- 'Target Support Files', 'Local Podspecs'
37
- next
38
- when 'BuildHeaders', 'PublicHeaders'
39
- delete(child)
40
- else
41
- if child.directory? && child.extname != '.xcodeproj'
42
- next
43
- else
44
- delete(child)
45
- end
46
- end
47
- end
48
- end
49
-
50
- delete(Pathname(File.join(ENV['HOME'], 'Library/Caches/CocoaPods/Git')))
51
- end
52
-
53
- # Migrates from CocoaPods versions prior to 0.36.
54
- #
55
- # @param [Sandbox] sandbox
56
- #
57
- def migrate_to_0_36(sandbox)
58
- UI.message('Migrating to CocoaPods 0.36') do
59
- move(sandbox.root + 'Headers/Build', sandbox.root + 'Headers/Private')
60
-
61
- lockfile = sandbox.manifest.to_hash
62
- sandbox.specifications_root.children.each do |child|
63
- next unless child.basename.to_s =~ /\.podspec$/
64
- spec = Specification.from_file(child)
65
- child.delete
66
- child = Pathname("#{child}.json")
67
- File.open(child, 'w') { |f| f.write spec.to_pretty_json }
68
- lockfile['SPEC CHECKSUMS'][spec.name] = Specification.from_file(child).checksum
69
- end
70
- sandbox.manifest = Lockfile.new(lockfile)
71
- sandbox.manifest.write_to_disk(sandbox.manifest_path)
72
- end
73
- end
74
-
75
20
  # @!group Private helpers
76
21
 
77
22
  # Check whether a migration is required
@@ -17,14 +17,21 @@ module Pod
17
17
  #
18
18
  attr_reader :specs_by_platform
19
19
 
20
+ # @return [Boolean] Whether the installer is allowed to touch the cache.
21
+ #
22
+ attr_reader :can_cache
23
+ alias_method :can_cache?, :can_cache
24
+
20
25
  # Initialize a new instance
21
26
  #
22
27
  # @param [Sandbox] sandbox @see sandbox
23
28
  # @param [Hash{Symbol=>Array}] specs_by_platform @see specs_by_platform
29
+ # @param [Boolean] can_cache @see can_cache
24
30
  #
25
- def initialize(sandbox, specs_by_platform)
31
+ def initialize(sandbox, specs_by_platform, can_cache: true)
26
32
  @sandbox = sandbox
27
33
  @specs_by_platform = specs_by_platform
34
+ @can_cache = can_cache
28
35
  end
29
36
 
30
37
  # @return [String] A string suitable for debugging.
@@ -110,7 +117,7 @@ module Pod
110
117
  # @return [void]
111
118
  #
112
119
  def download_source
113
- download_result = Downloader.download(download_request, root)
120
+ download_result = Downloader.download(download_request, root, :can_cache => can_cache?)
114
121
 
115
122
  if (@specific_source = download_result.checkout_options) && specific_source != root_spec.source
116
123
  sandbox.store_checkout_source(root_spec.name, specific_source)
@@ -121,7 +128,6 @@ module Pod
121
128
  Downloader::Request.new(
122
129
  :spec => root_spec,
123
130
  :released => released?,
124
- :head => head_pod?,
125
131
  )
126
132
  end
127
133
 
@@ -174,12 +180,8 @@ module Pod
174
180
  sandbox.local?(root_spec.name)
175
181
  end
176
182
 
177
- def head_pod?
178
- sandbox.head_pod?(root_spec.name)
179
- end
180
-
181
183
  def released?
182
- !local? && !head_pod? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
184
+ !local? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
183
185
  end
184
186
 
185
187
  def each_source_file(file_accessors, &blk)
@@ -12,6 +12,10 @@ module Pod
12
12
  #
13
13
  attr_reader :errors
14
14
 
15
+ # @return [Array<String>] any warnings that have occured during the validation
16
+ #
17
+ attr_reader :warnings
18
+
15
19
  # Initialize a new instance
16
20
  # @param [Podfile] podfile
17
21
  # The podfile to validate
@@ -19,6 +23,7 @@ module Pod
19
23
  def initialize(podfile)
20
24
  @podfile = podfile
21
25
  @errors = []
26
+ @warnings = []
22
27
  @validated = false
23
28
  end
24
29
 
@@ -27,6 +32,8 @@ module Pod
27
32
  #
28
33
  def validate
29
34
  validate_pod_directives
35
+ validate_no_abstract_only_pods!
36
+ validate_dependencies_are_present!
30
37
 
31
38
  @validated = true
32
39
  end
@@ -38,7 +45,7 @@ module Pod
38
45
  def valid?
39
46
  validate unless @validated
40
47
 
41
- @validated && errors.size == 0
48
+ @validated && errors.empty?
42
49
  end
43
50
 
44
51
  # A message describing any errors in the
@@ -54,6 +61,10 @@ module Pod
54
61
  errors << error
55
62
  end
56
63
 
64
+ def add_warning(warning)
65
+ warnings << warning
66
+ end
67
+
57
68
  def validate_pod_directives
58
69
  dependencies = podfile.target_definitions.flat_map do |_, target|
59
70
  target.dependencies
@@ -81,6 +92,36 @@ module Pod
81
92
  ' download strategies. This is not allowed'
82
93
  end
83
94
  end
95
+
96
+ # Warns the user if the podfile is empty.
97
+ #
98
+ # @note The workspace is created in any case and all the user projects
99
+ # are added to it, however the projects are not integrated as
100
+ # there is no way to discern between target definitions which are
101
+ # empty and target definitions which just serve the purpose to
102
+ # wrap other ones. This is not an issue because empty target
103
+ # definitions generate empty libraries.
104
+ #
105
+ # @return [void]
106
+ #
107
+ def validate_dependencies_are_present!
108
+ if podfile.target_definitions.values.all?(&:empty?)
109
+ add_warning 'The Podfile does not contain any dependencies.'
110
+ end
111
+ end
112
+
113
+ # Verifies that no dependencies in the Podfile will end up not being built
114
+ # at all. In other words, all dependencies _must_ belong to a non-abstract
115
+ # target, or be inherited by a target where `inheritance == complete`.
116
+ #
117
+ def validate_no_abstract_only_pods!
118
+ all_dependencies = podfile.dependencies
119
+ concrete_dependencies = podfile.target_definition_list.reject(&:abstract?).flat_map(&:dependencies).uniq
120
+ abstract_only_dependencies = all_dependencies - concrete_dependencies
121
+ abstract_only_dependencies.each do |dep|
122
+ add_error "The dependency `#{dep}` is not used in any concrete target."
123
+ end
124
+ end
84
125
  end
85
126
  end
86
127
  end
@@ -8,6 +8,14 @@ module Pod
8
8
  #
9
9
  attr_accessor :sandbox_root
10
10
 
11
+ # @return [Project] The Pods Xcode project.
12
+ #
13
+ attr_accessor :pods_project
14
+
15
+ # @return [Sandbox] The Sandbox for the project.
16
+ #
17
+ attr_accessor :sandbox
18
+
11
19
  # @return [Array<UmbrellaTargetDescription>] The list of
12
20
  # the CocoaPods umbrella targets generated by the installer.
13
21
  #
@@ -29,7 +37,7 @@ module Pod
29
37
  umbrella_targets_descriptions = []
30
38
  aggregate_targets.each do |umbrella|
31
39
  desc = UmbrellaTargetDescription.new
32
- desc.user_project_path = umbrella.user_project_path
40
+ desc.user_project = umbrella.user_project
33
41
  desc.user_target_uuids = umbrella.user_target_uuids
34
42
  desc.specs = umbrella.specs
35
43
  desc.platform_name = umbrella.platform.name
@@ -40,6 +48,8 @@ module Pod
40
48
 
41
49
  result = new
42
50
  result.sandbox_root = sandbox.root.to_s
51
+ result.pods_project = sandbox.project
52
+ result.sandbox = sandbox
43
53
  result.umbrella_targets = umbrella_targets_descriptions
44
54
  result
45
55
  end
@@ -47,10 +57,17 @@ module Pod
47
57
  # Pure data class which describes and umbrella target.
48
58
  #
49
59
  class UmbrellaTargetDescription
60
+ # @return [Xcodeproj::Project] The user project into which this target
61
+ # is integrated.
62
+ #
63
+ attr_accessor :user_project
64
+
50
65
  # @return [String] The path of the user project
51
66
  # integrated by this target.
52
67
  #
53
- attr_accessor :user_project_path
68
+ def user_project_path
69
+ user_project.path if user_project
70
+ end
54
71
 
55
72
  # @return [Array<String>] The list of the UUIDs of the
56
73
  # user targets integrated by this umbrella
@@ -39,14 +39,12 @@ module Pod
39
39
  product_type = target.product_type
40
40
  name = target.label
41
41
  platform = target.platform.name
42
- deployment_target = target.platform.deployment_target.to_s
43
42
  language = target.uses_swift? ? :swift : :objc
44
43
  @native_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
45
44
 
46
45
  product_name = target.product_name
47
46
  product = @native_target.product_reference
48
47
  product.name = product_name
49
- product.path = product_name
50
48
 
51
49
  target.user_build_configurations.each do |bc_name, type|
52
50
  @native_target.add_build_configuration(bc_name, type)
@@ -59,6 +57,12 @@ module Pod
59
57
  target.native_target = @native_target
60
58
  end
61
59
 
60
+ # @return [String] The deployment target.
61
+ #
62
+ def deployment_target
63
+ target.platform.deployment_target.to_s
64
+ end
65
+
62
66
  # Returns the customized build settings which are overridden in the build
63
67
  # settings of the user target.
64
68
  #
@@ -43,11 +43,12 @@ module Pod
43
43
  #
44
44
  def custom_build_settings
45
45
  settings = {
46
- 'OTHER_LDFLAGS' => '',
47
- 'OTHER_LIBTOOLFLAGS' => '',
48
- 'PODS_ROOT' => '$(SRCROOT)',
49
- 'SKIP_INSTALL' => 'YES',
50
- 'MACH_O_TYPE' => 'staticlib',
46
+ 'MACH_O_TYPE' => 'staticlib',
47
+ 'OTHER_LDFLAGS' => '',
48
+ 'OTHER_LIBTOOLFLAGS' => '',
49
+ 'PODS_ROOT' => '$(SRCROOT)',
50
+ 'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
51
+ 'SKIP_INSTALL' => 'YES',
51
52
  }
52
53
  super.merge(settings)
53
54
  end
@@ -22,11 +22,15 @@ module Pod
22
22
  create_xcconfig_file
23
23
  if target.requires_frameworks?
24
24
  create_info_plist_file
25
- create_module_map do |generator|
26
- generator.private_headers += target.file_accessors.flat_map(&:private_headers).map(&:basename)
27
- end
25
+ create_module_map
28
26
  create_umbrella_header do |generator|
29
- generator.imports += target.file_accessors.flat_map(&:public_headers).map(&:basename)
27
+ if header_mappings_dir
28
+ generator.imports += target.file_accessors.flat_map(&:public_headers).map do |pathname|
29
+ pathname.relative_path_from(header_mappings_dir)
30
+ end
31
+ else
32
+ generator.imports += target.file_accessors.flat_map(&:public_headers).map(&:basename)
33
+ end
30
34
  end
31
35
  end
32
36
  create_prefix_header
@@ -60,6 +64,11 @@ module Pod
60
64
  # @note The Frameworks are used only for presentation purposes as the
61
65
  # xcconfig is the authoritative source about their information.
62
66
  #
67
+ # @note Core Data model directories (.xcdatamodeld) defined in the `resources`
68
+ # property are currently added to the `Copy Resources` build phase like
69
+ # all other resources. The Xcode UI adds these to the `Compile Sources`
70
+ # build phase, but they will compile correctly either way.
71
+ #
63
72
  # @return [void]
64
73
  #
65
74
  def add_files_to_build_phases
@@ -83,15 +92,7 @@ module Pod
83
92
 
84
93
  header_file_refs = headers.map { |sf| project.reference_for_path(sf) }
85
94
  native_target.add_file_references(header_file_refs) do |build_file|
86
- # Set added headers as public if needed
87
- build_file.settings ||= {}
88
- if public_headers.include?(build_file.file_ref.real_path)
89
- build_file.settings['ATTRIBUTES'] = ['Public']
90
- elsif private_headers.include?(build_file.file_ref.real_path)
91
- build_file.settings['ATTRIBUTES'] = ['Private']
92
- else
93
- build_file.settings['ATTRIBUTES'] = ['Project']
94
- end
95
+ add_header(build_file, public_headers, private_headers)
95
96
  end
96
97
 
97
98
  other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) }
@@ -103,6 +104,10 @@ module Pod
103
104
  project.reference_for_path(res)
104
105
  end
105
106
 
107
+ # Some nested files are not directly present in the Xcode project, such as the contents
108
+ # of an .xcdatamodeld directory. These files will return nil file references.
109
+ resource_refs.compact!
110
+
106
111
  native_target.add_resources(resource_refs)
107
112
  end
108
113
  end
@@ -112,12 +117,31 @@ module Pod
112
117
  # @note The source files are grouped by Pod and in turn by subspec
113
118
  # (recursively) in the resources group.
114
119
  #
120
+ # @note Core Data model directories (.xcdatamodeld) are currently added to the
121
+ # `Copy Resources` build phase like all other resources. The Xcode UI adds
122
+ # these to the `Compile Sources` build phase, but they will compile
123
+ # correctly either way.
124
+ #
115
125
  # @return [void]
116
126
  #
117
127
  def add_resources_bundle_targets
118
128
  target.file_accessors.each do |file_accessor|
119
129
  file_accessor.resource_bundles.each do |bundle_name, paths|
120
- file_references = paths.map { |sf| project.reference_for_path(sf) }
130
+ file_references = paths.map do |path|
131
+ ref = project.reference_for_path(path)
132
+
133
+ # Some nested files are not directly present in the Xcode project, such as the contents
134
+ # of an .xcdatamodeld directory. These files are implicitly included by including their
135
+ # parent directory.
136
+ next if ref.nil?
137
+
138
+ # For variant groups, the variant group itself is added, not its members.
139
+ next ref.parent if ref.parent.is_a?(Xcodeproj::Project::Object::PBXVariantGroup)
140
+
141
+ ref
142
+ end
143
+ file_references = file_references.uniq.compact
144
+
121
145
  label = target.resources_bundle_target_label(bundle_name)
122
146
  bundle_target = project.new_resources_bundle(label, file_accessor.spec_consumer.platform_name)
123
147
  bundle_target.product_reference.tap do |bundle_product|
@@ -130,6 +154,7 @@ module Pod
130
154
  target.user_build_configurations.each do |bc_name, type|
131
155
  bundle_target.add_build_configuration(bc_name, type)
132
156
  end
157
+ bundle_target.deployment_target = deployment_target
133
158
 
134
159
  target.resource_bundle_targets << bundle_target
135
160
 
@@ -140,8 +165,18 @@ module Pod
140
165
  end
141
166
  end
142
167
 
168
+ # Create Info.plist file for bundle
169
+ path = target.info_plist_path
170
+ path.dirname.mkdir unless path.dirname.exist?
171
+ info_plist_path = path.dirname + "ResourceBundle-#{bundle_name}-#{path.basename}"
172
+ generator = Generator::InfoPlistFile.new(target)
173
+ generator.save_as(info_plist_path)
174
+ add_file_to_support_group(info_plist_path)
175
+
143
176
  bundle_target.build_configurations.each do |c|
144
177
  c.build_settings['PRODUCT_NAME'] = bundle_name
178
+ relative_info_plist_path = info_plist_path.relative_path_from(sandbox.root)
179
+ c.build_settings['INFOPLIST_FILE'] = relative_info_plist_path.to_s
145
180
  if target.requires_frameworks? && target.scoped?
146
181
  c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
147
182
  end
@@ -285,6 +320,39 @@ module Pod
285
320
  @custom_module_map ||= target.file_accessors.first.module_map
286
321
  end
287
322
 
323
+ def header_mappings_dir
324
+ return @header_mappings_dir if defined?(@header_mappings_dir)
325
+ file_accessor = target.file_accessors.first
326
+ @header_mappings_dir = if dir = file_accessor.spec_consumer.header_mappings_dir
327
+ file_accessor.path_list.root + dir
328
+ end
329
+ end
330
+
331
+ def add_header(build_file, public_headers, private_headers)
332
+ file_ref = build_file.file_ref
333
+ acl = if public_headers.include?(file_ref.real_path)
334
+ 'Public'
335
+ elsif private_headers.include?(file_ref.real_path)
336
+ 'Private'
337
+ else
338
+ 'Project'
339
+ end
340
+
341
+ if target.requires_frameworks? && header_mappings_dir
342
+ relative_path = file_ref.real_path.relative_path_from(header_mappings_dir)
343
+ sub_dir = relative_path.dirname
344
+ copy_phase_name = "Copy #{sub_dir} #{acl} Headers"
345
+ copy_phase = native_target.copy_files_build_phases.find { |bp| bp.name == copy_phase_name } ||
346
+ native_target.new_copy_files_build_phase(copy_phase_name)
347
+ copy_phase.symbol_dst_subfolder_spec = :products_directory
348
+ copy_phase.dst_path = "$(#{acl.upcase}_HEADERS_FOLDER_PATH)/#{sub_dir}"
349
+ copy_phase.add_file_reference(file_ref, true)
350
+ else
351
+ build_file.settings ||= {}
352
+ build_file.settings['ATTRIBUTES'] = [acl]
353
+ end
354
+ end
355
+
288
356
  #-----------------------------------------------------------------------#
289
357
  end
290
358
  end