cocoapods-core 0.17.0.rc1

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 (36) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +36 -0
  4. data/lib/cocoapods-core/core_ui.rb +19 -0
  5. data/lib/cocoapods-core/dependency.rb +295 -0
  6. data/lib/cocoapods-core/gem_version.rb +6 -0
  7. data/lib/cocoapods-core/lockfile.rb +440 -0
  8. data/lib/cocoapods-core/platform.rb +171 -0
  9. data/lib/cocoapods-core/podfile/dsl.rb +459 -0
  10. data/lib/cocoapods-core/podfile/target_definition.rb +503 -0
  11. data/lib/cocoapods-core/podfile.rb +345 -0
  12. data/lib/cocoapods-core/requirement.rb +15 -0
  13. data/lib/cocoapods-core/source/validator.rb +183 -0
  14. data/lib/cocoapods-core/source.rb +284 -0
  15. data/lib/cocoapods-core/specification/consumer.rb +356 -0
  16. data/lib/cocoapods-core/specification/dsl/attribute.rb +245 -0
  17. data/lib/cocoapods-core/specification/dsl/attribute_support.rb +76 -0
  18. data/lib/cocoapods-core/specification/dsl/deprecations.rb +47 -0
  19. data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +67 -0
  20. data/lib/cocoapods-core/specification/dsl.rb +1110 -0
  21. data/lib/cocoapods-core/specification/linter.rb +436 -0
  22. data/lib/cocoapods-core/specification/root_attribute_accessors.rb +152 -0
  23. data/lib/cocoapods-core/specification/set/presenter.rb +229 -0
  24. data/lib/cocoapods-core/specification/set/statistics.rb +277 -0
  25. data/lib/cocoapods-core/specification/set.rb +171 -0
  26. data/lib/cocoapods-core/specification/yaml.rb +60 -0
  27. data/lib/cocoapods-core/specification.rb +592 -0
  28. data/lib/cocoapods-core/standard_error.rb +84 -0
  29. data/lib/cocoapods-core/vendor/dependency.rb +264 -0
  30. data/lib/cocoapods-core/vendor/requirement.rb +208 -0
  31. data/lib/cocoapods-core/vendor/version.rb +333 -0
  32. data/lib/cocoapods-core/vendor.rb +56 -0
  33. data/lib/cocoapods-core/version.rb +99 -0
  34. data/lib/cocoapods-core/yaml_converter.rb +202 -0
  35. data/lib/cocoapods-core.rb +23 -0
  36. metadata +154 -0
@@ -0,0 +1,503 @@
1
+ module Pod
2
+ class Podfile
3
+
4
+ # The TargetDefinition stores the information of a CocoaPods static
5
+ # library. The target definition can be linked with one or more targets of
6
+ # the user project.
7
+ #
8
+ # Target definitions can be nested and by default inherit the dependencies
9
+ # of the parent.
10
+ #
11
+ class TargetDefinition
12
+
13
+ # @return [String, Symbol] the name of the target definition.
14
+ #
15
+ attr_reader :name
16
+
17
+ # @return [TargetDefinition, Podfile] the parent target definition or the
18
+ # Podfile if the receiver is root.
19
+ #
20
+ attr_reader :parent
21
+
22
+ # @param [String, Symbol]
23
+ # name @see name
24
+ #
25
+ # @param [TargetDefinition] parent
26
+ # @see parent
27
+ #
28
+ # @option options [Bool] :exclusive
29
+ # @see exclusive?
30
+ #
31
+ def initialize(name, parent, internal_hash = {})
32
+ @name = name
33
+ @parent = parent
34
+ @internal_hash = internal_hash
35
+ @children = []
36
+
37
+ if parent.is_a?(TargetDefinition)
38
+ parent.children << self
39
+ end
40
+ end
41
+
42
+ # @return [Array<TargetDefinition>] the children target definitions.
43
+ #
44
+ attr_reader :children
45
+
46
+ # @return [Array<TargetDefinition>] the targets definition descending
47
+ # from this one.
48
+ #
49
+ def recursive_children
50
+ (children + children.map(&:recursive_children)).flatten
51
+ end
52
+
53
+ # @return [Bool] Whether the target definition is root.
54
+ #
55
+ def root?
56
+ parent.is_a?(Podfile) || parent.nil?
57
+ end
58
+
59
+ # @return [TargetDefinition] The root target definition.
60
+ #
61
+ def root
62
+ if root?
63
+ self
64
+ else
65
+ parent.root
66
+ end
67
+ end
68
+
69
+ # @return [Podfile] The podfile that contains the specification for this
70
+ # target definition.
71
+ #
72
+ def podfile
73
+ root.parent
74
+ end
75
+
76
+ # @return [Array<Dependency>] The list of the dependencies of the target
77
+ # definition including the inherited ones.
78
+ #
79
+ def dependencies
80
+ non_inherited_dependencies + ((exclusive? || parent.nil?) ? [] : parent.dependencies)
81
+ end
82
+
83
+ # @return [Array] The list of the dependencies of the target definition,
84
+ # excluding inherited ones.
85
+ #
86
+ def non_inherited_dependencies
87
+ pod_dependencies.concat(podspec_dependencies)
88
+ end
89
+
90
+ # @return [Bool] Whether the target definition has at least one
91
+ # dependency, excluding inherited ones.
92
+ #
93
+ def empty?
94
+ non_inherited_dependencies.empty?
95
+ end
96
+
97
+ # @return [String] The label of the target definition according to its
98
+ # name.
99
+ #
100
+ def label
101
+ if root? && name == :default
102
+ "Pods"
103
+ elsif exclusive? || parent.nil?
104
+ "Pods-#{name}"
105
+ else
106
+ "#{parent.label}-#{name}"
107
+ end
108
+ end
109
+
110
+ # @return [String] A string representation suitable for UI.
111
+ #
112
+ def to_s
113
+ "`#{label}` target definition"
114
+ end
115
+
116
+ # @return [String] A string representation suitable for debug.
117
+ #
118
+ def inspect
119
+ "#<#{self.class} label=#{label}>"
120
+ end
121
+
122
+ #-----------------------------------------------------------------------#
123
+
124
+ public
125
+
126
+ # @!group Attributes
127
+
128
+ # Returns whether the target definition should inherit the dependencies
129
+ # of the parent.
130
+ #
131
+ # @note A target is always `exclusive` if it is root.
132
+ #
133
+ # @note A target is always `exclusive` if the `platform` does
134
+ # not match the parent's `platform`.
135
+ #
136
+ # @return [Bool] whether is exclusive.
137
+ #
138
+ def exclusive?
139
+ if root?
140
+ true
141
+ else
142
+ get_hash_value('exclusive') || ( platform && parent && parent.platform != platform )
143
+ end
144
+ end
145
+
146
+ # Sets whether the target definition is exclusive.
147
+ #
148
+ # @param [Bool] flag
149
+ # Whether the definition is exclusive.
150
+ #
151
+ # @return [void]
152
+ #
153
+ def exclusive=(flag)
154
+ set_hash_value('exclusive', flag)
155
+ end
156
+
157
+ #--------------------------------------#
158
+
159
+ # @return [Array<String>] the list of the names of the Xcode targets with
160
+ # which this target definition should be linked with.
161
+ #
162
+ def link_with
163
+ get_hash_value('link_with')
164
+ end
165
+
166
+ # Sets the client targets that should be integrated by this definition.
167
+ #
168
+ # @param [Array<String>] targets
169
+ # The list of the targets names.
170
+ #
171
+ # @return [void]
172
+ #
173
+ def link_with=(targets)
174
+ set_hash_value('link_with', Array(targets).map(&:to_s))
175
+ end
176
+
177
+ #--------------------------------------#
178
+
179
+ # @return [String] the path of the project this target definition should
180
+ # link with.
181
+ #
182
+ def user_project_path
183
+ path = get_hash_value('user_project_path')
184
+ if path
185
+ File.extname(path) == '.xcodeproj' ? path : "#{path}.xcodeproj"
186
+ else
187
+ parent.user_project_path unless root?
188
+ end
189
+ end
190
+
191
+ # Sets the path of the user project this target definition should link
192
+ # with.
193
+ #
194
+ # @param [String] path
195
+ # The path of the project.
196
+ #
197
+ # @return [void]
198
+ #
199
+ def user_project_path=(path)
200
+ set_hash_value('user_project_path', path)
201
+ end
202
+
203
+ #--------------------------------------#
204
+
205
+ # @return [Hash{String => symbol}] A hash where the keys are the name of
206
+ # the build configurations and the values a symbol that
207
+ # represents their type (`:debug` or `:release`).
208
+ #
209
+ def build_configurations
210
+ get_hash_value('build_configurations') || (parent.build_configurations unless root?)
211
+ end
212
+
213
+ # Sets the build configurations for this target.
214
+ #
215
+ # @return [Hash{String => Symbol}] hash
216
+ # A hash where the keys are the name of the build configurations
217
+ # and the values the type.
218
+ #
219
+ # @return [void]
220
+ #
221
+ def build_configurations=(hash)
222
+ set_hash_value('build_configurations', hash) unless hash.empty?
223
+ end
224
+
225
+ #--------------------------------------#
226
+
227
+ # @return [Bool] whether the target definition should silence all the
228
+ # warnings with a compiler flag.
229
+ #
230
+ def inhibit_all_warnings?
231
+ get_hash_value('inhibit_all_warnings') || (parent.inhibit_all_warnings? unless root?)
232
+ end
233
+
234
+ # Sets whether the target definition should inhibit the warnings during
235
+ # compilation.
236
+ #
237
+ # @param [Bool] flag
238
+ # Whether the warnings should be suppressed.
239
+ #
240
+ # @return [void]
241
+ #
242
+ def inhibit_all_warnings=(flag)
243
+ set_hash_value('inhibit_all_warnings', flag)
244
+ end
245
+
246
+ #--------------------------------------#
247
+
248
+ # @return [Platform] the platform of the target definition.
249
+ #
250
+ # @note If no deployment target has been specified a default value is
251
+ # provided.
252
+ #
253
+ def platform
254
+ name_or_hash = get_hash_value('platform')
255
+ if name_or_hash
256
+ if name_or_hash.is_a?(Hash)
257
+ name = name_or_hash.keys.first.to_sym
258
+ target = name_or_hash.values.first
259
+ else
260
+ name = name_or_hash.to_sym
261
+ end
262
+ target ||= (name == :ios ? '4.3' : '10.6')
263
+ Platform.new(name, target)
264
+ else
265
+ parent.platform unless root?
266
+ end
267
+ end
268
+
269
+ # Sets the platform of the target definition.
270
+ #
271
+ # @param [Symbol] name
272
+ # The name of the platform.
273
+ #
274
+ # @param [String] target
275
+ # The deployment target of the platform.
276
+ #
277
+ # @raise When the name of the platform is unsupported.
278
+ #
279
+ # @return [void]
280
+ #
281
+ def set_platform(name, target = nil)
282
+ unless [:ios, :osx].include?(name)
283
+ raise StandardError, "Unsupported platform `#{name}`. Platform must be `:ios` or `:osx`."
284
+ end
285
+
286
+ if target
287
+ value = {name.to_s => target}
288
+ else
289
+ value = name.to_s
290
+ end
291
+ set_hash_value('platform', value)
292
+ end
293
+
294
+ #--------------------------------------#
295
+
296
+ # Stores the dependency for a Pod with the given name.
297
+ #
298
+ # @param [String] name
299
+ # The name of the Pod
300
+ #
301
+ # @param [Array<String, Hash>] requirements
302
+ # The requirements and the options of the dependency.
303
+ #
304
+ # @note The dependencies are stored as an array. To simplify the YAML
305
+ # representation if they have requirements they are represented
306
+ # as a Hash, otherwise only the String of the name is added to
307
+ # the array.
308
+ #
309
+ # @todo This needs urgently a rename.
310
+ #
311
+ # @return [void]
312
+ #
313
+ def store_pod(name, *requirements)
314
+ if requirements && !requirements.empty?
315
+ pod = { name => requirements }
316
+ else
317
+ pod = name
318
+ end
319
+ get_hash_value('dependencies', []) << pod
320
+ end
321
+
322
+ #--------------------------------------#
323
+
324
+ # Stores the podspec whose dependencies should be included by the
325
+ # target.
326
+ #
327
+ # @param [Hash] options
328
+ # The options used to find the podspec (either by name or by
329
+ # path). If nil the podspec is auto-detected (i.e. the first one
330
+ # in the folder of the Podfile)
331
+ #
332
+ # @note The storage of this information is optimized for YAML
333
+ # readability.
334
+ #
335
+ # @todo This needs urgently a rename.
336
+ #
337
+ # @return [void]
338
+ #
339
+ def store_podspec(options = nil)
340
+ if options
341
+ unless options.keys.all? { |key| [:name, :path].include?(key) }
342
+ raise StandardError, "Unrecognized options for the podspec method `#{options}`"
343
+ end
344
+ get_hash_value('podspecs', []) << options
345
+ else
346
+ get_hash_value('podspecs', []) << { :autodetect => true }
347
+ end
348
+ end
349
+
350
+ #-----------------------------------------------------------------------#
351
+
352
+ public
353
+
354
+ # @!group Representations
355
+
356
+ # @return [Array] The keys used by the hash representation of the
357
+ # target definition.
358
+ #
359
+ HASH_KEYS = [
360
+ 'platform',
361
+ 'podspecs',
362
+ 'exclusive',
363
+ 'link_with',
364
+ 'inhibit_all_warnings',
365
+ 'user_project_path',
366
+ 'build_configurations',
367
+ 'dependencies',
368
+ 'children'
369
+ ].freeze
370
+
371
+ # @return [Hash] The hash representation of the target definition.
372
+ #
373
+ def to_hash
374
+ hash = internal_hash.dup
375
+ unless children.empty?
376
+ hash['children'] = Hash[children.map { |child| [child.name, child.to_hash] }]
377
+ end
378
+ hash
379
+ end
380
+
381
+ # Configures a new target definition from the given hash.
382
+ #
383
+ # @param [Hash] the hash which contains the information of the
384
+ # Podfile.
385
+ #
386
+ # @return [TargetDefinition] the new target definition
387
+ #
388
+ def self.from_hash(name, hash, parent)
389
+ internal_hash = hash.dup
390
+ children_hashes = internal_hash.delete('children') || {}
391
+ definition = TargetDefinition.new(name, parent, internal_hash)
392
+ children_hashes.each do |child_name, child_hash|
393
+ TargetDefinition.from_hash(child_name, child_hash, definition)
394
+ end
395
+ definition
396
+ end
397
+
398
+ #-----------------------------------------------------------------------#
399
+
400
+ private
401
+
402
+ # @!group Private helpers
403
+
404
+ # @return [Array<TargetDefinition>]
405
+ #
406
+ attr_writer :children
407
+
408
+ # @return [Hash] The hash which store the attributes of the target
409
+ # definition.
410
+ #
411
+ attr_accessor :internal_hash
412
+
413
+ # Set a value in the internal hash of the target definition for the given
414
+ # key.
415
+ #
416
+ # @param [String] key
417
+ # The key for which to store the value.
418
+ #
419
+ # @param [Object] value
420
+ # The value to store.
421
+ #
422
+ # @raise If the key is not recognized.
423
+ #
424
+ # @return [void]
425
+ #
426
+ def set_hash_value(key, value)
427
+ raise StandardError, "Unsupported hash key `#{key}`" unless HASH_KEYS.include?(key)
428
+ internal_hash[key] = value
429
+ end
430
+
431
+ # Returns the value for the given key in the internal hash of the target
432
+ # definition.
433
+ #
434
+ # @param [String] key
435
+ # The key for which the value is needed.
436
+ #
437
+ # @param [Object] base_value
438
+ # The value to set if they key is nil. Useful for collections.
439
+ #
440
+ # @raise If the key is not recognized.
441
+ #
442
+ # @return [Object] The value for the key.
443
+ #
444
+ def get_hash_value(key, base_value = nil)
445
+ raise StandardError, "Unsupported hash key `#{key}`" unless HASH_KEYS.include?(key)
446
+ internal_hash[key] ||= base_value
447
+ end
448
+
449
+ # @return [Array<Dependency>] The dependencies specified by the user for
450
+ # this target definition.
451
+ #
452
+ def pod_dependencies
453
+ pods = get_hash_value('dependencies') || []
454
+ pods.map do |name_or_hash|
455
+ if name_or_hash.is_a?(Hash)
456
+ name = name_or_hash.keys.first
457
+ requirements = name_or_hash.values.first
458
+ Dependency.new(name, *requirements)
459
+ else
460
+ Dependency.new(name_or_hash)
461
+ end
462
+ end
463
+ end
464
+
465
+ # @return [Array<Dependency>] The dependencies inherited by the podspecs.
466
+ #
467
+ def podspec_dependencies
468
+ podspecs = get_hash_value('podspecs') || []
469
+ podspecs.map do |options|
470
+ file = podspec_path_from_options(options)
471
+ spec = Specification.from_file(file)
472
+ all_specs = [spec, *spec.recursive_subspecs]
473
+ all_specs.map{ |s| s.dependencies(platform) }
474
+
475
+ end.flatten.uniq
476
+ end
477
+
478
+ # The path of the podspec with the given options.
479
+ #
480
+ # @param [Hash] options
481
+ # The options to use for finding the podspec. The supported keys
482
+ # are: `:name`, `:path`, `:autodetect`.
483
+ #
484
+ # @return [Pathname] The path.
485
+ #
486
+ def podspec_path_from_options(options)
487
+ if path = options[:path]
488
+ path_with_ext = File.extname(path) == '.podspec' ? path : "#{path}.podspec"
489
+ path_without_tilde = path_with_ext.gsub('~', ENV['HOME'])
490
+ file = podfile.defined_in_file.dirname + path_without_tilde
491
+ elsif name = options[:name]
492
+ name = File.extname(name) == '.podspec' ? name : "#{name}.podspec"
493
+ file = podfile.defined_in_file.dirname + name
494
+ elsif options[:autodetect]
495
+ file = Pathname.glob(podfile.defined_in_file.dirname + '*.podspec').first
496
+ end
497
+ end
498
+
499
+ #-----------------------------------------------------------------------#
500
+
501
+ end
502
+ end
503
+ end