cocoapods 0.39.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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