cocoapods-core 0.17.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +36 -0
- data/lib/cocoapods-core/core_ui.rb +19 -0
- data/lib/cocoapods-core/dependency.rb +295 -0
- data/lib/cocoapods-core/gem_version.rb +6 -0
- data/lib/cocoapods-core/lockfile.rb +440 -0
- data/lib/cocoapods-core/platform.rb +171 -0
- data/lib/cocoapods-core/podfile/dsl.rb +459 -0
- data/lib/cocoapods-core/podfile/target_definition.rb +503 -0
- data/lib/cocoapods-core/podfile.rb +345 -0
- data/lib/cocoapods-core/requirement.rb +15 -0
- data/lib/cocoapods-core/source/validator.rb +183 -0
- data/lib/cocoapods-core/source.rb +284 -0
- data/lib/cocoapods-core/specification/consumer.rb +356 -0
- data/lib/cocoapods-core/specification/dsl/attribute.rb +245 -0
- data/lib/cocoapods-core/specification/dsl/attribute_support.rb +76 -0
- data/lib/cocoapods-core/specification/dsl/deprecations.rb +47 -0
- data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +67 -0
- data/lib/cocoapods-core/specification/dsl.rb +1110 -0
- data/lib/cocoapods-core/specification/linter.rb +436 -0
- data/lib/cocoapods-core/specification/root_attribute_accessors.rb +152 -0
- data/lib/cocoapods-core/specification/set/presenter.rb +229 -0
- data/lib/cocoapods-core/specification/set/statistics.rb +277 -0
- data/lib/cocoapods-core/specification/set.rb +171 -0
- data/lib/cocoapods-core/specification/yaml.rb +60 -0
- data/lib/cocoapods-core/specification.rb +592 -0
- data/lib/cocoapods-core/standard_error.rb +84 -0
- data/lib/cocoapods-core/vendor/dependency.rb +264 -0
- data/lib/cocoapods-core/vendor/requirement.rb +208 -0
- data/lib/cocoapods-core/vendor/version.rb +333 -0
- data/lib/cocoapods-core/vendor.rb +56 -0
- data/lib/cocoapods-core/version.rb +99 -0
- data/lib/cocoapods-core/yaml_converter.rb +202 -0
- data/lib/cocoapods-core.rb +23 -0
- metadata +154 -0
@@ -0,0 +1,440 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
# The Lockfile stores information about the pods that were installed by
|
4
|
+
# CocoaPods.
|
5
|
+
#
|
6
|
+
# It is used in combination with the Podfile to resolve the exact version of
|
7
|
+
# the Pods that should be installed (i.e. to prevent `pod install` from
|
8
|
+
# upgrading dependencies).
|
9
|
+
#
|
10
|
+
# Moreover it is used as a manifest of an installation to detect which Pods
|
11
|
+
# need to be installed or removed.
|
12
|
+
#
|
13
|
+
class Lockfile
|
14
|
+
|
15
|
+
# TODO The symbols should be converted to a String and back to symbol
|
16
|
+
# when reading (EXTERNAL SOURCES Download options)
|
17
|
+
|
18
|
+
# @return [String] the hash used to initialize the Lockfile.
|
19
|
+
#
|
20
|
+
attr_reader :internal_data
|
21
|
+
|
22
|
+
# @param [Hash] hash
|
23
|
+
# a hash representation of the Lockfile.
|
24
|
+
#
|
25
|
+
def initialize(hash)
|
26
|
+
@internal_data = hash
|
27
|
+
end
|
28
|
+
|
29
|
+
# Loads a lockfile form the given path.
|
30
|
+
#
|
31
|
+
# @note This method returns nil if the given path doesn't exists.
|
32
|
+
#
|
33
|
+
# @raise If there is a syntax error loading the YAML data.
|
34
|
+
#
|
35
|
+
# @param [Pathname] path
|
36
|
+
# the path where the lockfile is serialized.
|
37
|
+
#
|
38
|
+
# @return [Lockfile] a new lockfile.
|
39
|
+
#
|
40
|
+
def self.from_file(path)
|
41
|
+
return nil unless path.exist?
|
42
|
+
begin
|
43
|
+
hash = YAML.load(File.open(path))
|
44
|
+
rescue Exception => e
|
45
|
+
raise StandardError, "Podfile.lock syntax error: #{e.inspect}"
|
46
|
+
end
|
47
|
+
lockfile = Lockfile.new(hash)
|
48
|
+
lockfile.defined_in_file = path
|
49
|
+
lockfile
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String] the file where the Lockfile is serialized.
|
53
|
+
#
|
54
|
+
attr_accessor :defined_in_file
|
55
|
+
|
56
|
+
# @return [String] a string representation suitable for UI output.
|
57
|
+
#
|
58
|
+
def to_s
|
59
|
+
"Podfile.lock"
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String] a string representation suitable for debugging.
|
63
|
+
#
|
64
|
+
def inspect
|
65
|
+
"#<#{self.class}>"
|
66
|
+
end
|
67
|
+
|
68
|
+
#-------------------------------------------------------------------------#
|
69
|
+
|
70
|
+
# !@group Accessing the Data
|
71
|
+
|
72
|
+
public
|
73
|
+
|
74
|
+
# @return [Array<String>] the names of the installed Pods.
|
75
|
+
#
|
76
|
+
def pod_names
|
77
|
+
generate_pod_names_and_versions unless @pod_names
|
78
|
+
@pod_names
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns the version of the given Pod.
|
82
|
+
#
|
83
|
+
# @param [name] The name of the Pod (root name of the specification).
|
84
|
+
#
|
85
|
+
# @return [Version] The version of the pod.
|
86
|
+
#
|
87
|
+
# @return [Nil] If there is no version stored for the given name.
|
88
|
+
#
|
89
|
+
def version(pod_name)
|
90
|
+
version = pod_versions[pod_name]
|
91
|
+
return version if version
|
92
|
+
pod_name = pod_versions.keys.find { |name| Specification.root_name(name) == pod_name }
|
93
|
+
pod_versions[pod_name]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the checksum for the given Pod.
|
97
|
+
#
|
98
|
+
# @param [name] The name of the Pod (root name of the specification).
|
99
|
+
#
|
100
|
+
# @return [String] The checksum of the specification for the given Pod.
|
101
|
+
#
|
102
|
+
# @return [Nil] If there is no checksum stored for the given name.
|
103
|
+
#
|
104
|
+
def checksum(name)
|
105
|
+
checksum_data[name]
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Array<Dependency>] the dependencies of the Podfile used for the
|
109
|
+
# last installation.
|
110
|
+
#
|
111
|
+
# @note It includes only the dependencies explicitly required in the
|
112
|
+
# podfile and not those triggered by the Resolver.
|
113
|
+
#
|
114
|
+
def dependencies
|
115
|
+
unless @dependencies
|
116
|
+
data = internal_data['DEPENDENCIES'] || []
|
117
|
+
@dependencies = data.map do |string|
|
118
|
+
dep = Dependency.from_string(string)
|
119
|
+
dep.external_source = external_sources_data[dep.root_name]
|
120
|
+
dep
|
121
|
+
end
|
122
|
+
end
|
123
|
+
@dependencies
|
124
|
+
end
|
125
|
+
|
126
|
+
# Generates a dependency that requires the exact version of the Pod with the
|
127
|
+
# given name.
|
128
|
+
#
|
129
|
+
# @param [String] name
|
130
|
+
# the name of the Pod
|
131
|
+
#
|
132
|
+
# @note The generated dependencies are by the Installer to prevent the
|
133
|
+
# Resolver from upgrading a Pod during an installation.
|
134
|
+
#
|
135
|
+
# @raise If there is no version stored for the given name.
|
136
|
+
#
|
137
|
+
# @return [Dependency] the generated dependency.
|
138
|
+
#
|
139
|
+
def dependency_to_lock_pod_named(name)
|
140
|
+
dep = dependencies.find { |d| d.name == name || d.root_name == name }
|
141
|
+
version = version(name)
|
142
|
+
|
143
|
+
unless dep
|
144
|
+
raise StandardError, "Attempt to lock the `#{name}` Pod without an known dependency."
|
145
|
+
end
|
146
|
+
|
147
|
+
unless version
|
148
|
+
raise StandardError, "Attempt to lock the `#{name}` Pod without an known version."
|
149
|
+
end
|
150
|
+
|
151
|
+
locked_dependency = dep.dup
|
152
|
+
locked_dependency.specific_version = version
|
153
|
+
locked_dependency
|
154
|
+
end
|
155
|
+
|
156
|
+
#--------------------------------------#
|
157
|
+
|
158
|
+
# !@group Accessing the internal data.
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
# @return [Array<String, Hash{String => Array[String]}>] the pods installed
|
163
|
+
# and their dependencies.
|
164
|
+
#
|
165
|
+
def generate_pod_names_and_versions
|
166
|
+
@pod_names = []
|
167
|
+
@pod_versions = {}
|
168
|
+
|
169
|
+
return unless pods = internal_data['PODS']
|
170
|
+
pods.each do |pod|
|
171
|
+
pod = pod.keys.first unless pod.is_a?(String)
|
172
|
+
name, version = Spec.name_and_version_from_string(pod)
|
173
|
+
@pod_names << name
|
174
|
+
@pod_versions[name] = version
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# @return [Hash{String => Hash}] a hash where the name of the pods are the
|
179
|
+
# keys and the values are the external source hash the dependency
|
180
|
+
# that required the pod.
|
181
|
+
#
|
182
|
+
def external_sources_data
|
183
|
+
@external_sources_data ||= internal_data["EXTERNAL SOURCES"] || {}
|
184
|
+
end
|
185
|
+
|
186
|
+
# @return [Hash{String => Version}] a Hash containing the name of the root
|
187
|
+
# specification of the installed Pods as the keys and their
|
188
|
+
# corresponding {Version} as the values.
|
189
|
+
#
|
190
|
+
def pod_versions
|
191
|
+
generate_pod_names_and_versions unless @pod_versions
|
192
|
+
@pod_versions
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [Hash{String => Version}] A Hash containing the checksums of the
|
196
|
+
# specification by the name of their root.
|
197
|
+
#
|
198
|
+
def checksum_data
|
199
|
+
internal_data['SPEC CHECKSUMS'] || {}
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
#-------------------------------------------------------------------------#
|
204
|
+
|
205
|
+
# !@group Comparison with a Podfile
|
206
|
+
|
207
|
+
public
|
208
|
+
|
209
|
+
# Analyzes the {Lockfile} and detects any changes applied to the {Podfile}
|
210
|
+
# since the last installation.
|
211
|
+
#
|
212
|
+
# For each Pod, it detects one state among the following:
|
213
|
+
#
|
214
|
+
# - added: Pods that weren't present in the Podfile.
|
215
|
+
# - changed: Pods that were present in the Podfile but changed:
|
216
|
+
# - Pods whose version is not compatible anymore with Podfile,
|
217
|
+
# - Pods that changed their head or external options.
|
218
|
+
# - removed: Pods that were removed form the Podfile.
|
219
|
+
# - unchanged: Pods that are still compatible with Podfile.
|
220
|
+
#
|
221
|
+
# @param [Podfile] podfile
|
222
|
+
# the podfile that should be analyzed.
|
223
|
+
#
|
224
|
+
# @return [Hash{Symbol=>Array[Strings]}] a hash where pods are grouped
|
225
|
+
# by the state in which they are.
|
226
|
+
#
|
227
|
+
# @todo Why do we look for compatibility instead of just comparing if the
|
228
|
+
# two dependencies are equal?
|
229
|
+
#
|
230
|
+
def detect_changes_with_podfile(podfile)
|
231
|
+
result = {}
|
232
|
+
[ :added, :changed, :removed, :unchanged ].each { |k| result[k] = [] }
|
233
|
+
|
234
|
+
installed_deps = dependencies.map { |d| dependency_to_lock_pod_named(d.name) }
|
235
|
+
all_dep_names = (dependencies + podfile.dependencies).map(&:name).uniq
|
236
|
+
all_dep_names.each do |name|
|
237
|
+
installed_dep = installed_deps.find { |d| d.name == name }
|
238
|
+
podfile_dep = podfile.dependencies.find { |d| d.name == name }
|
239
|
+
|
240
|
+
if installed_dep.nil? then key = :added
|
241
|
+
elsif podfile_dep.nil? then key = :removed
|
242
|
+
elsif podfile_dep.compatible?(installed_dep ) then key = :unchanged
|
243
|
+
else key = :changed
|
244
|
+
end
|
245
|
+
result[key] << name
|
246
|
+
end
|
247
|
+
result
|
248
|
+
end
|
249
|
+
|
250
|
+
#-------------------------------------------------------------------------#
|
251
|
+
|
252
|
+
# !@group Serialization
|
253
|
+
|
254
|
+
public
|
255
|
+
|
256
|
+
# Writes the Lockfile to the given path.
|
257
|
+
#
|
258
|
+
# @param [Pathname] path
|
259
|
+
# the path where the lockfile should be saved.
|
260
|
+
#
|
261
|
+
# @return [void]
|
262
|
+
#
|
263
|
+
def write_to_disk(path)
|
264
|
+
path.dirname.mkpath unless path.dirname.exist?
|
265
|
+
File.open(path, 'w') {|f| f.write(to_yaml) }
|
266
|
+
self.defined_in_file = path
|
267
|
+
end
|
268
|
+
|
269
|
+
# @return [Hash{String=>Array,Hash,String}] a hash reppresentation of the
|
270
|
+
# Lockfile.
|
271
|
+
#
|
272
|
+
# @example Output
|
273
|
+
#
|
274
|
+
# {
|
275
|
+
# 'PODS' => [ { BananaLib (1.0) => [monkey (< 1.0.9, ~> 1.0.1)] },
|
276
|
+
# "JSONKit (1.4)",
|
277
|
+
# "monkey (1.0.8)"]
|
278
|
+
# 'DEPENDENCIES' => [ "BananaLib (~> 1.0)",
|
279
|
+
# "JSONKit (from `path/JSONKit.podspec`)" ],
|
280
|
+
# 'EXTERNAL SOURCES' => { "JSONKit" => { :podspec => path/JSONKit.podspec } },
|
281
|
+
# 'SPEC CHECKSUMS' => { "BananaLib" => "439d9f683377ecf4a27de43e8cf3bce6be4df97b",
|
282
|
+
# "JSONKit", "92ae5f71b77c8dec0cd8d0744adab79d38560949" },
|
283
|
+
# 'COCOAPODS' => "0.17.0"
|
284
|
+
# }
|
285
|
+
#
|
286
|
+
#
|
287
|
+
def to_hash
|
288
|
+
hash = {}
|
289
|
+
internal_data.each do |key, value|
|
290
|
+
hash[key] = value unless value.empty?
|
291
|
+
end
|
292
|
+
hash
|
293
|
+
end
|
294
|
+
|
295
|
+
# @return [String] the YAML representation of the Lockfile, used for
|
296
|
+
# serialization.
|
297
|
+
#
|
298
|
+
# @note Empty root keys are discarded.
|
299
|
+
#
|
300
|
+
# @note The YAML string is prettified.
|
301
|
+
#
|
302
|
+
def to_yaml
|
303
|
+
keys_hint = [
|
304
|
+
"PODS",
|
305
|
+
"DEPENDENCIES",
|
306
|
+
"EXTERNAL SOURCES",
|
307
|
+
"SPEC CHECKSUMS",
|
308
|
+
"COCOAPODS"
|
309
|
+
]
|
310
|
+
YAMLConverter.convert_hash(to_hash, keys_hint, "\n\n")
|
311
|
+
end
|
312
|
+
|
313
|
+
#-------------------------------------------------------------------------#
|
314
|
+
|
315
|
+
class << self
|
316
|
+
|
317
|
+
# !@group Generation
|
318
|
+
|
319
|
+
public
|
320
|
+
|
321
|
+
# Generates a hash representation of the Lockfile generated from a given
|
322
|
+
# Podfile and the list of resolved Specifications. This representation is
|
323
|
+
# suitable for serialization.
|
324
|
+
#
|
325
|
+
# @param [Podfile] podfile
|
326
|
+
# the podfile that should be used to generate the lockfile.
|
327
|
+
#
|
328
|
+
# @param [Array<Specification>] specs
|
329
|
+
# an array containing the podspec that were generated by
|
330
|
+
# resolving the given podfile.
|
331
|
+
#
|
332
|
+
# @return [Lockfile] a new lockfile.
|
333
|
+
#
|
334
|
+
def generate(podfile, specs)
|
335
|
+
hash = {
|
336
|
+
'PODS' => generate_pods_data(podfile, specs),
|
337
|
+
'DEPENDENCIES' => generate_dependencies_data(podfile),
|
338
|
+
'EXTERNAL SOURCES' => generate_external_sources_data(podfile),
|
339
|
+
'SPEC CHECKSUMS' => generate_checksums(specs),
|
340
|
+
'COCOAPODS' => CORE_VERSION
|
341
|
+
}
|
342
|
+
Lockfile.new(hash)
|
343
|
+
end
|
344
|
+
|
345
|
+
#--------------------------------------#
|
346
|
+
|
347
|
+
private
|
348
|
+
|
349
|
+
# !@group Private helpers
|
350
|
+
|
351
|
+
# Generates the list of the installed Pods and their dependencies.
|
352
|
+
#
|
353
|
+
# @note The dependencies of iOS and OS X version of the same pod are
|
354
|
+
# merged.
|
355
|
+
#
|
356
|
+
# @todo Specifications should be stored per platform, otherwise they
|
357
|
+
# list dependencies which actually might not be used.
|
358
|
+
#
|
359
|
+
# @return [Array<Hash,String>] the generated data.
|
360
|
+
#
|
361
|
+
# @example Output
|
362
|
+
# [ {"BananaLib (1.0)"=>["monkey (< 1.0.9, ~> 1.0.1)"]},
|
363
|
+
# "monkey (1.0.8)" ]
|
364
|
+
#
|
365
|
+
#
|
366
|
+
def generate_pods_data(podfile, specs)
|
367
|
+
pod_and_deps = specs.map do |spec|
|
368
|
+
[spec.to_s, spec.all_dependencies.map(&:to_s).sort]
|
369
|
+
end.uniq
|
370
|
+
|
371
|
+
tmp = {}
|
372
|
+
pod_and_deps.each do |name, deps|
|
373
|
+
if tmp[name]
|
374
|
+
tmp[name].concat(deps).uniq!
|
375
|
+
else
|
376
|
+
tmp[name] = deps
|
377
|
+
end
|
378
|
+
end
|
379
|
+
pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
|
380
|
+
deps.empty? ? name : { name => deps }
|
381
|
+
end
|
382
|
+
pod_and_deps
|
383
|
+
end
|
384
|
+
|
385
|
+
# Generates the list of the dependencies of the Podfile.
|
386
|
+
#
|
387
|
+
# @example Output
|
388
|
+
# [ "BananaLib (~> 1.0)",
|
389
|
+
# "JSONKit (from `path/JSONKit.podspec')" ]
|
390
|
+
#
|
391
|
+
# @return [Array] the generated data.
|
392
|
+
#
|
393
|
+
def generate_dependencies_data(podfile)
|
394
|
+
podfile.dependencies.map{ |d| d.to_s }.sort
|
395
|
+
end
|
396
|
+
|
397
|
+
# Generates the information of the external sources.
|
398
|
+
#
|
399
|
+
# @example Output
|
400
|
+
# { "JSONKit"=>{:podspec=>"path/JSONKit.podspec"} }
|
401
|
+
#
|
402
|
+
# @return [Hash] a hash where the keys are the names of the pods and
|
403
|
+
# the values store the external source hashes of each
|
404
|
+
# dependency.
|
405
|
+
#
|
406
|
+
# @todo The downloader should generate an external source hash that
|
407
|
+
# should be store for dependencies in head mode and for those
|
408
|
+
# with external source.
|
409
|
+
#
|
410
|
+
def generate_external_sources_data(podfile)
|
411
|
+
deps = podfile.dependencies.select(&:external?)
|
412
|
+
deps = deps.sort { |d, other| d.name <=> other.name}
|
413
|
+
sources = {}
|
414
|
+
deps.each { |d| sources[d.root_name] = d.external_source }
|
415
|
+
sources
|
416
|
+
end
|
417
|
+
|
418
|
+
# Generates the relative to the checksum of the specifications.
|
419
|
+
#
|
420
|
+
# @example Output
|
421
|
+
# {
|
422
|
+
# "BananaLib"=>"9906b267592664126923875ce2c8d03824372c79",
|
423
|
+
# "JSONKit"=>"92ae5f71b77c8dec0cd8d0744adab79d38560949"
|
424
|
+
# }
|
425
|
+
#
|
426
|
+
# @return [Hash] a hash where the keys are the names of the root
|
427
|
+
# specifications and the values are the SHA1 digest of the
|
428
|
+
# podspec file.
|
429
|
+
#
|
430
|
+
def generate_checksums(specs)
|
431
|
+
checksums = {}
|
432
|
+
specs.select { |spec| !spec.defined_in_file.nil? }.each do |spec|
|
433
|
+
checksums[spec.root.name] = spec.checksum
|
434
|
+
end
|
435
|
+
checksums
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
# A Platform describes an SDK name and deployment target.
|
4
|
+
#
|
5
|
+
class Platform
|
6
|
+
|
7
|
+
# @return [Symbol, String] the name of the SDK represented by the platform.
|
8
|
+
#
|
9
|
+
def name
|
10
|
+
@symbolic_name
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Version] the deployment target of the platform.
|
14
|
+
#
|
15
|
+
attr_reader :deployment_target
|
16
|
+
|
17
|
+
# Constructs a platform from either another platform or by
|
18
|
+
# specifying the symbolic name and optionally the deployment target.
|
19
|
+
#
|
20
|
+
# @overload initialize(name, deployment_target)
|
21
|
+
#
|
22
|
+
# @param [Symbol, String] name
|
23
|
+
# the name of platform.
|
24
|
+
#
|
25
|
+
# @param [String, Version] deployment_target
|
26
|
+
# the optional deployment.
|
27
|
+
#
|
28
|
+
# @note If the deployment target is not provided a default deployment
|
29
|
+
# target will not be assigned.
|
30
|
+
#
|
31
|
+
# @example Initialization with symbol
|
32
|
+
#
|
33
|
+
# Platform.new(:ios)
|
34
|
+
# Platform.new(:ios, '4.3')
|
35
|
+
#
|
36
|
+
# @overload initialize(platform)
|
37
|
+
#
|
38
|
+
# @param [Platform] platform
|
39
|
+
# Another {Platform}.
|
40
|
+
#
|
41
|
+
# @example Initialization with another platform
|
42
|
+
#
|
43
|
+
# platform = Platform.new(:ios)
|
44
|
+
# Platform.new(platform)
|
45
|
+
#
|
46
|
+
def initialize(input, target = nil)
|
47
|
+
if input.is_a? Platform
|
48
|
+
@symbolic_name = input.name
|
49
|
+
@deployment_target = input.deployment_target
|
50
|
+
else
|
51
|
+
@symbolic_name = input.to_sym
|
52
|
+
target = target[:deployment_target] if target.is_a?(Hash)
|
53
|
+
@deployment_target = Version.create(target)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Convenience method to initialize an iOS platform.
|
58
|
+
#
|
59
|
+
# @return [Platform] an iOS platform.
|
60
|
+
#
|
61
|
+
def self.ios
|
62
|
+
new :ios
|
63
|
+
end
|
64
|
+
|
65
|
+
# Convenience method to initialize an OS X platform.
|
66
|
+
#
|
67
|
+
# @return [Platform] an OS X platform.
|
68
|
+
#
|
69
|
+
def self.osx
|
70
|
+
new :osx
|
71
|
+
end
|
72
|
+
|
73
|
+
# Checks if a platform is equivalent to another one or to a symbol
|
74
|
+
# representation.
|
75
|
+
#
|
76
|
+
# @param [Platform, Symbol] other
|
77
|
+
# the other platform to check.
|
78
|
+
#
|
79
|
+
# @note If a symbol is passed the comparison does not take into account
|
80
|
+
# the deployment target.
|
81
|
+
#
|
82
|
+
# @return [Boolean] whether two platforms are the equivalent.
|
83
|
+
#
|
84
|
+
def ==(other)
|
85
|
+
if other.is_a?(Symbol)
|
86
|
+
@symbolic_name == other
|
87
|
+
else
|
88
|
+
(name == other.name) && (deployment_target == other.deployment_target)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Checks whether a platform supports another one.
|
93
|
+
#
|
94
|
+
# In the context of operating system SDKs, a platform supports another
|
95
|
+
# one if they have the same name and the other platform has a minor or
|
96
|
+
# equal deployment target.
|
97
|
+
#
|
98
|
+
# @return [Bool] whether the platform supports another platform.
|
99
|
+
#
|
100
|
+
def supports?(other)
|
101
|
+
other = Platform.new(other)
|
102
|
+
if other.deployment_target && deployment_target
|
103
|
+
(other.name == name) && (other.deployment_target <= deployment_target)
|
104
|
+
else
|
105
|
+
other.name == name
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [String] a string representation that includes the deployment
|
110
|
+
# target.
|
111
|
+
#
|
112
|
+
def to_s
|
113
|
+
s = self.class.string_name(@symbolic_name)
|
114
|
+
s << " #{deployment_target}" if deployment_target
|
115
|
+
s
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [String] the debug representation.
|
119
|
+
#
|
120
|
+
def inspect
|
121
|
+
"#<#{self.class.name} name=#{name.inspect} " \
|
122
|
+
"deployment_target=#{deployment_target.inspect}>"
|
123
|
+
end
|
124
|
+
|
125
|
+
# @return [Symbol] a symbol representing the name of the platform.
|
126
|
+
#
|
127
|
+
def to_sym
|
128
|
+
name
|
129
|
+
end
|
130
|
+
|
131
|
+
# Compares the platform first by name and the by deployment_target for
|
132
|
+
# sorting.
|
133
|
+
#
|
134
|
+
# @param [Platform] other
|
135
|
+
# The other platform to compare.
|
136
|
+
#
|
137
|
+
# @return [Fixnum] -1, 0, or +1 depending on whether the receiver is less
|
138
|
+
# than, equal to, or greater than other.
|
139
|
+
#
|
140
|
+
def <=> other
|
141
|
+
name_sort = self.name.to_s <=> other.name.to_s
|
142
|
+
if name_sort.zero?
|
143
|
+
self.deployment_target <=> other.deployment_target
|
144
|
+
else
|
145
|
+
name_sort
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# @return [Bool] whether the platform requires legacy architectures for
|
150
|
+
# iOS.
|
151
|
+
#
|
152
|
+
def requires_legacy_ios_archs?
|
153
|
+
(name == :ios) && deployment_target && (deployment_target < Version.new("4.3"))
|
154
|
+
end
|
155
|
+
|
156
|
+
# Converts the symbolic name of a platform to a string name suitable to be
|
157
|
+
# presented to the user.
|
158
|
+
#
|
159
|
+
# @param [Symbol] symbolic_name
|
160
|
+
# the symbolic name of a platform.
|
161
|
+
#
|
162
|
+
# @return [String] The string that describes the name of the given symbol.
|
163
|
+
#
|
164
|
+
def self.string_name(symbolic_name)
|
165
|
+
case symbolic_name
|
166
|
+
when :ios then 'iOS'
|
167
|
+
when :osx then 'OS X'
|
168
|
+
else symbolic_name end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|