cocoapods-core 0.30.0 → 1.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +7 -10
  3. data/lib/cocoapods-core/build_type.rb +121 -0
  4. data/lib/cocoapods-core/cdn_source.rb +501 -0
  5. data/lib/cocoapods-core/core_ui.rb +4 -3
  6. data/lib/cocoapods-core/dependency.rb +100 -73
  7. data/lib/cocoapods-core/gem_version.rb +1 -2
  8. data/lib/cocoapods-core/github.rb +32 -5
  9. data/lib/cocoapods-core/http.rb +86 -0
  10. data/lib/cocoapods-core/lockfile.rb +161 -56
  11. data/lib/cocoapods-core/metrics.rb +47 -0
  12. data/lib/cocoapods-core/platform.rb +99 -11
  13. data/lib/cocoapods-core/podfile/dsl.rb +623 -124
  14. data/lib/cocoapods-core/podfile/target_definition.rb +662 -109
  15. data/lib/cocoapods-core/podfile.rb +138 -65
  16. data/lib/cocoapods-core/requirement.rb +37 -8
  17. data/lib/cocoapods-core/source/acceptor.rb +16 -13
  18. data/lib/cocoapods-core/source/aggregate.rb +79 -103
  19. data/lib/cocoapods-core/source/health_reporter.rb +9 -18
  20. data/lib/cocoapods-core/source/manager.rb +488 -0
  21. data/lib/cocoapods-core/source/metadata.rb +79 -0
  22. data/lib/cocoapods-core/source.rb +241 -70
  23. data/lib/cocoapods-core/specification/consumer.rb +187 -47
  24. data/lib/cocoapods-core/specification/dsl/attribute.rb +49 -85
  25. data/lib/cocoapods-core/specification/dsl/attribute_support.rb +6 -8
  26. data/lib/cocoapods-core/specification/dsl/deprecations.rb +9 -126
  27. data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +30 -20
  28. data/lib/cocoapods-core/specification/dsl.rb +943 -296
  29. data/lib/cocoapods-core/specification/json.rb +64 -23
  30. data/lib/cocoapods-core/specification/linter/analyzer.rb +218 -0
  31. data/lib/cocoapods-core/specification/linter/result.rb +128 -0
  32. data/lib/cocoapods-core/specification/linter.rb +310 -309
  33. data/lib/cocoapods-core/specification/root_attribute_accessors.rb +90 -39
  34. data/lib/cocoapods-core/specification/set/presenter.rb +35 -71
  35. data/lib/cocoapods-core/specification/set.rb +42 -96
  36. data/lib/cocoapods-core/specification.rb +368 -130
  37. data/lib/cocoapods-core/standard_error.rb +45 -24
  38. data/lib/cocoapods-core/trunk_source.rb +14 -0
  39. data/lib/cocoapods-core/vendor/requirement.rb +133 -53
  40. data/lib/cocoapods-core/vendor/version.rb +197 -156
  41. data/lib/cocoapods-core/vendor.rb +1 -5
  42. data/lib/cocoapods-core/version.rb +137 -42
  43. data/lib/cocoapods-core/yaml_helper.rb +334 -0
  44. data/lib/cocoapods-core.rb +10 -4
  45. metadata +100 -27
  46. data/lib/cocoapods-core/source/abstract_data_provider.rb +0 -71
  47. data/lib/cocoapods-core/source/file_system_data_provider.rb +0 -150
  48. data/lib/cocoapods-core/source/github_data_provider.rb +0 -143
  49. data/lib/cocoapods-core/specification/set/statistics.rb +0 -266
  50. data/lib/cocoapods-core/yaml_converter.rb +0 -192
@@ -1,5 +1,4 @@
1
1
  module Pod
2
-
3
2
  # The Lockfile stores information about the pods that were installed by
4
3
  # CocoaPods.
5
4
  #
@@ -11,7 +10,6 @@ module Pod
11
10
  # need to be installed or removed.
12
11
  #
13
12
  class Lockfile
14
-
15
13
  # @todo The symbols should be converted to a String and back to symbol
16
14
  # when reading (EXTERNAL SOURCES Download options)
17
15
 
@@ -39,8 +37,7 @@ module Pod
39
37
  #
40
38
  def self.from_file(path)
41
39
  return nil unless path.exist?
42
- require 'yaml'
43
- hash = File.open(path) { |f| YAML.load(f) }
40
+ hash = YAMLHelper.load_file(path)
44
41
  unless hash && hash.is_a?(Hash)
45
42
  raise Informative, "Invalid Lockfile in `#{path}`"
46
43
  end
@@ -53,7 +50,7 @@ module Pod
53
50
  #
54
51
  attr_accessor :defined_in_file
55
52
 
56
- # @return [Bool] Whether the Podfiles are equal.
53
+ # @return [Boolean] Whether the Podfiles are equal.
57
54
  #
58
55
  def ==(other)
59
56
  other && to_hash == other.to_hash
@@ -80,7 +77,7 @@ module Pod
80
77
 
81
78
  # Returns the version of the given Pod.
82
79
  #
83
- # @param [name] The name of the Pod (root name of the specification).
80
+ # @param [String] pod_name The name of the Pod (root name of the specification).
84
81
  #
85
82
  # @return [Version] The version of the pod.
86
83
  #
@@ -95,9 +92,21 @@ module Pod
95
92
  pod_versions[root_name]
96
93
  end
97
94
 
95
+ # Returns the source of the given Pod.
96
+ #
97
+ # @param [String] pod_name The name of the Pod (root name of the specification).
98
+ #
99
+ # @return [String] The source of the pod.
100
+ #
101
+ # @return [Nil] If there is no source stored for the given name.
102
+ #
103
+ def spec_repo(pod_name)
104
+ spec_repos_by_pod[pod_name]
105
+ end
106
+
98
107
  # Returns the checksum for the given Pod.
99
108
  #
100
- # @param [name] The name of the Pod (root name of the specification).
109
+ # @param [String] name The name of the Pod (root name of the specification).
101
110
  #
102
111
  # @return [String] The checksum of the specification for the given Pod.
103
112
  #
@@ -124,6 +133,17 @@ module Pod
124
133
  @dependencies
125
134
  end
126
135
 
136
+ # Returns pod names grouped by the spec repo they were sourced from.
137
+ #
138
+ # @return [Hash<String, Array<String>>] A hash, where the keys are spec
139
+ # repo source URLs (or names), and the values are arrays of pod names.
140
+ #
141
+ # @note It does not include pods that come from "external sources".
142
+ #
143
+ def pods_by_spec_repo
144
+ @pods_by_spec_repo ||= internal_data['SPEC REPOS'] || {}
145
+ end
146
+
127
147
  # Generates a dependency that requires the exact version of the Pod with the
128
148
  # given name.
129
149
  #
@@ -135,20 +155,38 @@ module Pod
135
155
  #
136
156
  # @raise If there is no version stored for the given name.
137
157
  #
138
- # @return [Dependency] the generated dependency.
158
+ # @return [Array<Dependency>] the generated dependency.
139
159
  #
140
- def dependency_to_lock_pod_named(name)
141
- dep = dependencies.find { |d| d.name == name || d.root_name == name }
142
- version = version(name)
160
+ def dependencies_to_lock_pod_named(name)
161
+ deps = dependencies.select { |d| d.root_name == name }
162
+ if deps.empty?
163
+ raise StandardError, "Attempt to lock the `#{name}` Pod without a " \
164
+ 'known dependency.'
165
+ end
143
166
 
144
- unless dep && version
145
- raise StandardError, "Attempt to lock the `#{name}` Pod without an " \
146
- "known dependency."
167
+ deps.map do |dep|
168
+ version = version(dep.name)
169
+ locked_dependency = dep.dup
170
+ locked_dependency.specific_version = version
171
+ locked_dependency
147
172
  end
173
+ end
148
174
 
149
- locked_dependency = dep.dup
150
- locked_dependency.specific_version = version
151
- locked_dependency
175
+ # Returns the specific checkout options for the external source of the pod
176
+ # with the given name.
177
+ #
178
+ # @example Output
179
+ # {:commit => "919903db28535c3f387c4bbaa6a3feae4428e993"
180
+ # :git => "https://github.com/luisdelarosa/AFRaptureXMLRequestOperation.git"}
181
+ #
182
+ # @return [Hash] a hash of the checkout options for the external source of
183
+ # the pod with the given name.
184
+ #
185
+ # @param [String] name
186
+ # the name of the Pod.
187
+ #
188
+ def checkout_options_for_pod_named(name)
189
+ checkout_options_data[name]
152
190
  end
153
191
 
154
192
  # @return [Version] The version of CocoaPods which generated this lockfile.
@@ -184,7 +222,14 @@ module Pod
184
222
  # that required the pod.
185
223
  #
186
224
  def external_sources_data
187
- @external_sources_data ||= internal_data["EXTERNAL SOURCES"] || {}
225
+ @external_sources_data ||= internal_data['EXTERNAL SOURCES'] || {}
226
+ end
227
+
228
+ # @return [Hash{String => Hash}] a hash where the name of the pods are the
229
+ # keys and the values are a hash of specific checkout options.
230
+ #
231
+ def checkout_options_data
232
+ @checkout_options_data ||= internal_data['CHECKOUT OPTIONS'] || {}
188
233
  end
189
234
 
190
235
  # @return [Hash{String => Version}] a Hash containing the name of the root
@@ -203,6 +248,17 @@ module Pod
203
248
  internal_data['SPEC CHECKSUMS'] || {}
204
249
  end
205
250
 
251
+ # @return [Hash{String => String}] A hash containing the spec repo used for the specification
252
+ # by the name of the root spec.
253
+ #
254
+ def spec_repos_by_pod
255
+ @spec_repos_by_pod ||= pods_by_spec_repo.each_with_object({}) do |(spec_repo, pods), spec_repos_by_pod|
256
+ pods.each do |pod|
257
+ spec_repos_by_pod[pod] = spec_repo
258
+ end
259
+ end
260
+ end
261
+
206
262
  #-------------------------------------------------------------------------#
207
263
 
208
264
  # !@group Comparison with a Podfile
@@ -217,7 +273,7 @@ module Pod
217
273
  # - added: Pods that weren't present in the Podfile.
218
274
  # - changed: Pods that were present in the Podfile but changed:
219
275
  # - Pods whose version is not compatible anymore with Podfile,
220
- # - Pods that changed their head or external options.
276
+ # - Pods that changed their external options.
221
277
  # - removed: Pods that were removed form the Podfile.
222
278
  # - unchanged: Pods that are still compatible with Podfile.
223
279
  #
@@ -234,13 +290,23 @@ module Pod
234
290
  result = {}
235
291
  [:added, :changed, :removed, :unchanged].each { |k| result[k] = [] }
236
292
 
237
- installed_deps = dependencies.map do |dep|
238
- dependency_to_lock_pod_named(dep.name)
293
+ installed_deps = {}
294
+ dependencies.each do |dep|
295
+ name = dep.root_name
296
+ installed_deps[name] ||= dependencies_to_lock_pod_named(name)
239
297
  end
240
- all_dep_names = (dependencies + podfile.dependencies).map(&:name).uniq
298
+
299
+ installed_deps = installed_deps.values.flatten(1).group_by(&:name)
300
+
301
+ podfile_dependencies = podfile.dependencies
302
+ podfile_dependencies_by_name = podfile_dependencies.group_by(&:name)
303
+
304
+ all_dep_names = (dependencies + podfile_dependencies).map(&:name).uniq
241
305
  all_dep_names.each do |name|
242
- installed_dep = installed_deps.find { |d| d.name == name }
243
- podfile_dep = podfile.dependencies.find { |d| d.name == name }
306
+ installed_dep = installed_deps[name]
307
+ installed_dep &&= installed_dep.first
308
+ podfile_dep = podfile_dependencies_by_name[name]
309
+ podfile_dep &&= podfile_dep.first
244
310
 
245
311
  if installed_dep.nil? then key = :added
246
312
  elsif podfile_dep.nil? then key = :removed
@@ -267,8 +333,17 @@ module Pod
267
333
  #
268
334
  def write_to_disk(path)
269
335
  path.dirname.mkpath unless path.dirname.exist?
270
- File.open(path, 'w') { |f| f.write(to_yaml) }
271
336
  self.defined_in_file = path
337
+ # rubocop:disable Lint/RescueException
338
+ # rubocop:disable Lint/HandleExceptions
339
+ begin
340
+ existing = Lockfile.from_file(path)
341
+ return if existing == self
342
+ rescue Exception
343
+ end
344
+ path.open('w') { |f| f.write(to_yaml) }
345
+ # rubocop:enable Lint/HandleExceptions
346
+ # rubocop:enable Lint/RescueException
272
347
  end
273
348
 
274
349
  # @return [Hash{String=>Array,Hash,String}] a hash representation of the
@@ -285,6 +360,7 @@ module Pod
285
360
  # 'EXTERNAL SOURCES' => { "JSONKit" => { :podspec => path/JSONKit.podspec } },
286
361
  # 'SPEC CHECKSUMS' => { "BananaLib" => "439d9f683377ecf4a27de43e8cf3bce6be4df97b",
287
362
  # "JSONKit", "92ae5f71b77c8dec0cd8d0744adab79d38560949" },
363
+ # 'PODFILE CHECKSUM' => "439d9f683377ecf4a27de43e8cf3bce6be4df97b",
288
364
  # 'COCOAPODS' => "0.17.0"
289
365
  # }
290
366
  #
@@ -292,11 +368,25 @@ module Pod
292
368
  def to_hash
293
369
  hash = {}
294
370
  internal_data.each do |key, value|
295
- hash[key] = value unless value.empty?
371
+ hash[key] = value unless value.nil? || value.empty?
296
372
  end
297
373
  hash
298
374
  end
299
375
 
376
+ # @return [Array<String>] The order in which the hash keys should appear in
377
+ # a serialized Lockfile.
378
+ #
379
+ HASH_KEY_ORDER = [
380
+ 'PODS',
381
+ 'DEPENDENCIES',
382
+ 'SPEC REPOS',
383
+ 'EXTERNAL SOURCES',
384
+ 'CHECKOUT OPTIONS',
385
+ 'SPEC CHECKSUMS',
386
+ 'PODFILE CHECKSUM',
387
+ 'COCOAPODS',
388
+ ].map(&:freeze).freeze
389
+
300
390
  # @return [String] the YAML representation of the Lockfile, used for
301
391
  # serialization.
302
392
  #
@@ -305,20 +395,12 @@ module Pod
305
395
  # @note The YAML string is prettified.
306
396
  #
307
397
  def to_yaml
308
- keys_hint = [
309
- "PODS",
310
- "DEPENDENCIES",
311
- "EXTERNAL SOURCES",
312
- "SPEC CHECKSUMS",
313
- "COCOAPODS",
314
- ]
315
- YAMLConverter.convert_hash(to_hash, keys_hint, "\n\n")
398
+ YAMLHelper.convert_hash(to_hash, HASH_KEY_ORDER, "\n\n")
316
399
  end
317
400
 
318
401
  #-------------------------------------------------------------------------#
319
402
 
320
403
  class << self
321
-
322
404
  # !@group Generation
323
405
 
324
406
  public
@@ -336,12 +418,15 @@ module Pod
336
418
  #
337
419
  # @return [Lockfile] a new lockfile.
338
420
  #
339
- def generate(podfile, specs)
421
+ def generate(podfile, specs, checkout_options, spec_repos = {})
340
422
  hash = {
341
423
  'PODS' => generate_pods_data(specs),
342
424
  'DEPENDENCIES' => generate_dependencies_data(podfile),
425
+ 'SPEC REPOS' => generate_spec_repos(spec_repos),
343
426
  'EXTERNAL SOURCES' => generate_external_sources_data(podfile),
427
+ 'CHECKOUT OPTIONS' => checkout_options,
344
428
  'SPEC CHECKSUMS' => generate_checksums(specs),
429
+ 'PODFILE CHECKSUM' => podfile.checksum,
345
430
  'COCOAPODS' => CORE_VERSION,
346
431
  }
347
432
  Lockfile.new(hash)
@@ -369,22 +454,17 @@ module Pod
369
454
  #
370
455
  #
371
456
  def generate_pods_data(specs)
372
- pod_and_deps = specs.map do |spec|
373
- [spec.to_s, spec.all_dependencies.map(&:to_s).sort]
374
- end.uniq
375
-
376
- tmp = {}
377
- pod_and_deps.each do |name, deps|
378
- if tmp[name]
379
- tmp[name].concat(deps).uniq!
380
- else
381
- tmp[name] = deps
382
- end
457
+ pods_and_deps_merged = specs.reduce({}) do |result, spec|
458
+ name = spec.to_s
459
+ result[name] ||= []
460
+ result[name].concat(spec.all_dependencies.map(&:to_s))
461
+ result
383
462
  end
384
- pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
385
- deps.empty? ? name : { name => deps }
463
+
464
+ pod_and_deps = pods_and_deps_merged.map do |name, deps|
465
+ deps.empty? ? name : { name => YAMLHelper.sorted_array(deps.uniq) }
386
466
  end
387
- pod_and_deps
467
+ YAMLHelper.sorted_array(pod_and_deps)
388
468
  end
389
469
 
390
470
  # Generates the list of the dependencies of the Podfile.
@@ -396,7 +476,36 @@ module Pod
396
476
  # @return [Array] the generated data.
397
477
  #
398
478
  def generate_dependencies_data(podfile)
399
- podfile.dependencies.map { |d| d.to_s }.sort
479
+ YAMLHelper.sorted_array(podfile.dependencies.map(&:to_s))
480
+ end
481
+
482
+ # Generates the hash of spec repo sources used in the Podfile.
483
+ #
484
+ # @example Output
485
+ # { "https://github.com/cocoapods/cocoapods.git" => ["Alamofire", "Moya"] }
486
+ #
487
+ def generate_spec_repos(spec_repos)
488
+ output = Hash.new {|h, k| h[k] = Array.new(0)}
489
+ spec_repos.each do |source, specs|
490
+ next unless source
491
+ next if specs.empty?
492
+ key = source.url || source.name
493
+
494
+ # save `trunk` as 'trunk' so that the URL itself can be changed without lockfile churn
495
+ key = Pod::TrunkSource::TRUNK_REPO_NAME if source.name == Pod::TrunkSource::TRUNK_REPO_NAME
496
+
497
+ value = specs.map { |s| s.root.name }
498
+
499
+ if output.has_key?(key)
500
+ value = value + output[key]
501
+ end
502
+
503
+ if value.length > 0
504
+ output[key] = YAMLHelper.sorted_array(value.uniq)
505
+ end
506
+ end
507
+
508
+ output.compact
400
509
  end
401
510
 
402
511
  # Generates the information of the external sources.
@@ -408,10 +517,6 @@ module Pod
408
517
  # the values store the external source hashes of each
409
518
  # dependency.
410
519
  #
411
- # @todo The downloader should generate an external source hash that
412
- # should be store for dependencies in head mode and for those
413
- # with external source.
414
- #
415
520
  def generate_external_sources_data(podfile)
416
521
  deps = podfile.dependencies.select(&:external?)
417
522
  deps = deps.sort { |d, other| d.name <=> other.name }
@@ -434,7 +539,7 @@ module Pod
434
539
  #
435
540
  def generate_checksums(specs)
436
541
  checksums = {}
437
- specs.select { |spec| !spec.defined_in_file.nil? }.each do |spec|
542
+ specs.select(&:defined_in_file).each do |spec|
438
543
  checksums[spec.root.name] = spec.checksum
439
544
  end
440
545
  checksums
@@ -0,0 +1,47 @@
1
+ module Pod
2
+ # Allows to access metrics about pods.
3
+ #
4
+ # This class is stored in Core because it might be used by web services.
5
+ #
6
+ module Metrics
7
+ # Returns the metrics of a pod.
8
+ #
9
+ # @param [String] name
10
+ # The name of the pod.
11
+ #
12
+ # @return [Hash] The metrics for the pod.
13
+ #
14
+ def self.pod(name)
15
+ peform_request("http://metrics.cocoapods.org/api/v1/pods/#{name}")
16
+ end
17
+
18
+ private
19
+
20
+ # @!group Private helpers
21
+ #-------------------------------------------------------------------------#
22
+
23
+ # Performs a get request with the given URL.
24
+ #
25
+ # @param [String] url
26
+ # The URL of the resource.
27
+ #
28
+ # @return [Array, Hash] The information of the resource as Ruby objects.
29
+ #
30
+ def self.peform_request(url)
31
+ require 'rest'
32
+ require 'json'
33
+ headers = { 'User-Agent' => "CocoaPods #{Pod::CORE_VERSION}" }
34
+ response = REST.get(url, headers)
35
+ body = JSON.parse(response.body)
36
+ if response.ok?
37
+ body
38
+ else
39
+ CoreUI.warn "Request to #{url} failed - #{response.status_code}"
40
+ CoreUI.warn body['message']
41
+ nil
42
+ end
43
+ end
44
+
45
+ #-------------------------------------------------------------------------#
46
+ end
47
+ end
@@ -1,14 +1,11 @@
1
1
  module Pod
2
-
3
2
  # A Platform describes an SDK name and deployment target.
4
3
  #
5
4
  class Platform
6
-
7
5
  # @return [Symbol, String] the name of the SDK represented by the platform.
8
6
  #
9
- def name
10
- @symbolic_name
11
- end
7
+ attr_reader :symbolic_name
8
+ alias_method :name, :symbolic_name
12
9
 
13
10
  # @return [Version] the deployment target of the platform.
14
11
  #
@@ -48,7 +45,19 @@ module Pod
48
45
  @symbolic_name = input.name
49
46
  @deployment_target = input.deployment_target
50
47
  else
51
- @symbolic_name = input.to_sym
48
+ input = input.to_s.downcase
49
+
50
+ name = case input
51
+ when 'macos'
52
+ # Allow `Platform.new('macos')` to be equivalent to `Platform.macos`
53
+ 'osx'
54
+ when 'xros'
55
+ # Compatibility with older references to 'xrOS'
56
+ 'visionos'
57
+ else
58
+ input
59
+ end
60
+ @symbolic_name = name.to_sym
52
61
  target = target[:deployment_target] if target.is_a?(Hash)
53
62
  @deployment_target = Version.create(target)
54
63
  end
@@ -70,6 +79,46 @@ module Pod
70
79
  new :osx
71
80
  end
72
81
 
82
+ # Convenience method to initialize a macOS platform.
83
+ #
84
+ # @return [Platform] a macOS platform.
85
+ #
86
+ def self.macos
87
+ osx
88
+ end
89
+
90
+ # Convenience method to initialize a tvOS platform.
91
+ #
92
+ # @return [Platform] a tvOS platform.
93
+ #
94
+ def self.tvos
95
+ new :tvos
96
+ end
97
+
98
+ # Convenience method to initialize a visionOS platform.
99
+ #
100
+ # @return [Platform] a visionOS platform.
101
+ #
102
+ def self.visionos
103
+ new :visionos
104
+ end
105
+
106
+ # Convenience method to initialize a watchOS platform.
107
+ #
108
+ # @return [Platform] a watchOS platform.
109
+ #
110
+ def self.watchos
111
+ new :watchos
112
+ end
113
+
114
+ # Convenience method to get all available platforms.
115
+ #
116
+ # @return [Array<Platform>] list of platforms.
117
+ #
118
+ def self.all
119
+ [ios, osx, watchos, visionos, tvos]
120
+ end
121
+
73
122
  # Checks if a platform is equivalent to another one or to a symbol
74
123
  # representation.
75
124
  #
@@ -89,13 +138,25 @@ module Pod
89
138
  end
90
139
  end
91
140
 
141
+ # (see #==)
142
+ alias_method :eql?, :==
143
+
144
+ # Hashes the instance by the platform name and deployment target.
145
+ #
146
+ # This adds support to make instances usable as Hash keys.
147
+ #
148
+ # @!visibility private
149
+ def hash
150
+ name.hash ^ deployment_target.hash
151
+ end
152
+
92
153
  # Checks whether a platform supports another one.
93
154
  #
94
155
  # In the context of operating system SDKs, a platform supports another
95
156
  # one if they have the same name and the other platform has a minor or
96
157
  # equal deployment target.
97
158
  #
98
- # @return [Bool] whether the platform supports another platform.
159
+ # @return [Boolean] whether the platform supports another platform.
99
160
  #
100
161
  def supports?(other)
101
162
  other = Platform.new(other)
@@ -146,17 +207,40 @@ module Pod
146
207
  end
147
208
  end
148
209
 
149
- # @return [Bool] whether the platform requires legacy architectures for
210
+ # @return [Boolean] whether the platform requires legacy architectures for
150
211
  # iOS.
151
212
  #
152
213
  def requires_legacy_ios_archs?
153
214
  if name == :ios
154
- deployment_target && (deployment_target < Version.new("4.3"))
215
+ deployment_target && (deployment_target < Version.new('4.3'))
155
216
  else
156
217
  false
157
218
  end
158
219
  end
159
220
 
221
+ # @return [Boolean] whether the platform supports dynamic frameworks.
222
+ #
223
+ def supports_dynamic_frameworks?
224
+ if name == :ios
225
+ deployment_target && (deployment_target >= Version.new(8.0))
226
+ else
227
+ true
228
+ end
229
+ end
230
+
231
+ # @return [String] The string that describes the #symbolic_name.
232
+ #
233
+ def string_name
234
+ self.class.string_name(symbolic_name)
235
+ end
236
+
237
+ # @return [String] The string that describes the #symbolic_name,
238
+ # which doesn't contain spaces and is so safe to use in
239
+ # paths which might not be quoted or escaped consequently.
240
+ def safe_string_name
241
+ string_name.tr(' ', '')
242
+ end
243
+
160
244
  # Converts the symbolic name of a platform to a string name suitable to be
161
245
  # presented to the user.
162
246
  #
@@ -168,8 +252,12 @@ module Pod
168
252
  def self.string_name(symbolic_name)
169
253
  case symbolic_name
170
254
  when :ios then 'iOS'
171
- when :osx then 'OS X'
172
- else symbolic_name.to_s end
255
+ when :osx then 'macOS'
256
+ when :watchos then 'watchOS'
257
+ when :tvos then 'tvOS'
258
+ when :visionos then 'visionOS'
259
+ else symbolic_name.to_s
260
+ end
173
261
  end
174
262
  end
175
263
  end