cocoapods-core 0.17.0.rc1

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 +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