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.
- 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,60 @@
|
|
1
|
+
module Pod
|
2
|
+
class Specification
|
3
|
+
module YAMLSupport
|
4
|
+
|
5
|
+
# @return [String] the yaml representation of the specification.
|
6
|
+
#
|
7
|
+
def to_yaml
|
8
|
+
to_hash.to_yaml
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Hash] the hash representation of the specification including
|
12
|
+
# subspecs.
|
13
|
+
#
|
14
|
+
def to_hash
|
15
|
+
hash = attributes_hash.dup
|
16
|
+
hash["subspecs"] = subspecs.map { |spec| spec.to_hash } unless subspecs.empty?
|
17
|
+
hash
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Bool] Whether the specification can be converted to a hash
|
21
|
+
# without loss of information.
|
22
|
+
#
|
23
|
+
def safe_to_hash?
|
24
|
+
pre_install_callback.nil? && post_install_callback.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Configures a new specification from the given hash.
|
30
|
+
#
|
31
|
+
# @param [Hash] the hash which contains the information of the
|
32
|
+
# specification.
|
33
|
+
#
|
34
|
+
# @return [Specification] the specification
|
35
|
+
#
|
36
|
+
def self.from_hash(hash)
|
37
|
+
spec = Spec.new
|
38
|
+
attributes_hash = hash.dup
|
39
|
+
subspecs = attributes_hash.delete('subspecs')
|
40
|
+
spec.attributes_hash = attributes_hash
|
41
|
+
if subspecs
|
42
|
+
spec.subspecs = subspecs.map { |hash| Specification.from_hash(hash) }
|
43
|
+
end
|
44
|
+
spec
|
45
|
+
end
|
46
|
+
|
47
|
+
# Configures a new specification from the given YAML representation.
|
48
|
+
#
|
49
|
+
# @param [String] the YAML encoded hash which contains the information of
|
50
|
+
# the specification.
|
51
|
+
#
|
52
|
+
#
|
53
|
+
# @return [Specification] the specification
|
54
|
+
#
|
55
|
+
def self.from_yaml(yaml)
|
56
|
+
hash = YAML.load(yaml)
|
57
|
+
from_hash(hash)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,592 @@
|
|
1
|
+
require 'cocoapods-core/specification/consumer'
|
2
|
+
require 'cocoapods-core/specification/dsl'
|
3
|
+
require 'cocoapods-core/specification/linter'
|
4
|
+
require 'cocoapods-core/specification/root_attribute_accessors'
|
5
|
+
require 'cocoapods-core/specification/set'
|
6
|
+
require 'cocoapods-core/specification/yaml'
|
7
|
+
|
8
|
+
# TODO Temporary support
|
9
|
+
if RUBY_VERSION >= "1.9"
|
10
|
+
require 'rake/file_list'
|
11
|
+
else
|
12
|
+
require 'rake'
|
13
|
+
end
|
14
|
+
|
15
|
+
module Pod
|
16
|
+
|
17
|
+
# The Specification provides a DSL to describe a Pod. A pod is defined as a
|
18
|
+
# library originating from a source. A specification can support detailed
|
19
|
+
# attributes for modules of code through subspecs.
|
20
|
+
#
|
21
|
+
# Usually it is stored in files with `podspec` extension.
|
22
|
+
#
|
23
|
+
class Specification
|
24
|
+
|
25
|
+
include Pod::Specification::DSL
|
26
|
+
include Pod::Specification::DSL::Deprecations
|
27
|
+
include Pod::Specification::RootAttributesAccessors
|
28
|
+
include Pod::Specification::YAMLSupport
|
29
|
+
|
30
|
+
# @return [Specification] the parent of the specification unless the
|
31
|
+
# specification is a root.
|
32
|
+
#
|
33
|
+
attr_reader :parent
|
34
|
+
|
35
|
+
# @param [Specification] parent @see parent
|
36
|
+
#
|
37
|
+
# @param [String] name
|
38
|
+
# the name of the specification.
|
39
|
+
#
|
40
|
+
def initialize(parent = nil, name = nil)
|
41
|
+
@attributes_hash = {}
|
42
|
+
@subspecs = []
|
43
|
+
@consumers = {}
|
44
|
+
@parent = parent
|
45
|
+
attributes_hash['name'] = name
|
46
|
+
|
47
|
+
yield self if block_given?
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Hash] the hash that stores the information of the attributes of
|
51
|
+
# the specification.
|
52
|
+
#
|
53
|
+
attr_accessor :attributes_hash
|
54
|
+
|
55
|
+
# @return [Array<Specification>] The subspecs of the specification.
|
56
|
+
#
|
57
|
+
attr_accessor :subspecs
|
58
|
+
|
59
|
+
# Checks if a specification is equal to the given one according its name
|
60
|
+
# and to its version.
|
61
|
+
#
|
62
|
+
# @param [Specification] other
|
63
|
+
# the specification to compare with.
|
64
|
+
#
|
65
|
+
# @todo Not sure if comparing only the name and the version is the way to
|
66
|
+
# go. This is used by the installer to group specifications by root
|
67
|
+
# spec.
|
68
|
+
#
|
69
|
+
# @return [Bool] whether the specifications are equal.
|
70
|
+
#
|
71
|
+
def ==(other)
|
72
|
+
# TODO
|
73
|
+
# self.class === other &&
|
74
|
+
# attributes_hash == other.attributes_hash &&
|
75
|
+
# subspecs == other.subspecs &&
|
76
|
+
# pre_install_callback == other.pre_install_callback &&
|
77
|
+
# post_install_callback == other.post_install_callback
|
78
|
+
self.to_s == other.to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
# @see ==
|
82
|
+
#
|
83
|
+
def eql?(other)
|
84
|
+
self == other
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return the hash value for this specification according to its attributes
|
88
|
+
# hash.
|
89
|
+
#
|
90
|
+
# @note This function must have the property that a.eql?(b) implies
|
91
|
+
# a.hash == b.hash.
|
92
|
+
#
|
93
|
+
# @note This method is used by the Hash class.
|
94
|
+
#
|
95
|
+
# @return [Fixnum] The hash value.
|
96
|
+
#
|
97
|
+
def hash
|
98
|
+
to_s.hash
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [String] A string suitable for representing the specification in
|
102
|
+
# clients.
|
103
|
+
#
|
104
|
+
def to_s
|
105
|
+
"#{name} (#{version})"
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [String] A string suitable for debugging.
|
109
|
+
#
|
110
|
+
def inspect
|
111
|
+
"#<#{self.class.name} name=#{name.inspect}>"
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param [String] string_representation
|
115
|
+
# the string that describes a {Specification} generated from
|
116
|
+
# {Specification#to_s}.
|
117
|
+
#
|
118
|
+
# @example Input examples
|
119
|
+
#
|
120
|
+
# "libPusher (1.0)"
|
121
|
+
# "libPusher (HEAD based on 1.0)"
|
122
|
+
# "RestKit/JSON (1.0)"
|
123
|
+
#
|
124
|
+
# @return [Array<String, Version>] the name and the version of a
|
125
|
+
# pod.
|
126
|
+
#
|
127
|
+
def self.name_and_version_from_string(string_reppresenation)
|
128
|
+
match_data = string_reppresenation.match(/(\S*) \((.*)\)/)
|
129
|
+
name = match_data[1]
|
130
|
+
vers = Version.new(match_data[2])
|
131
|
+
[name, vers]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the root name of a specification.
|
135
|
+
#
|
136
|
+
# @param [String] the name of a specification or of a subspec.
|
137
|
+
#
|
138
|
+
# @return [String] the root name
|
139
|
+
#
|
140
|
+
def self.root_name(full_name)
|
141
|
+
full_name.split('/').first
|
142
|
+
end
|
143
|
+
|
144
|
+
#-------------------------------------------------------------------------#
|
145
|
+
|
146
|
+
public
|
147
|
+
|
148
|
+
# @!group Hierarchy
|
149
|
+
|
150
|
+
# @return [Specification] The root specification or itself if it is root.
|
151
|
+
#
|
152
|
+
def root
|
153
|
+
parent ? parent.root : self
|
154
|
+
end
|
155
|
+
|
156
|
+
# @return [Bool] whether the specification is root.
|
157
|
+
#
|
158
|
+
def root?
|
159
|
+
parent.nil?
|
160
|
+
end
|
161
|
+
|
162
|
+
# @return [Bool] whether the specification is a subspec.
|
163
|
+
#
|
164
|
+
def subspec?
|
165
|
+
!parent.nil?
|
166
|
+
end
|
167
|
+
|
168
|
+
#-------------------------------------------------------------------------#
|
169
|
+
|
170
|
+
public
|
171
|
+
|
172
|
+
# @!group Dependencies & Subspecs
|
173
|
+
|
174
|
+
# @return [Array<Specifications>] the recursive list of all the subspecs of
|
175
|
+
# a specification.
|
176
|
+
#
|
177
|
+
def recursive_subspecs
|
178
|
+
mapper = lambda do |spec|
|
179
|
+
spec.subspecs.map do |subspec|
|
180
|
+
[subspec, *mapper.call(subspec)]
|
181
|
+
end.flatten
|
182
|
+
end
|
183
|
+
mapper.call(self)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Returns the subspec with the given name or the receiver if the name is
|
187
|
+
# nil or equal to the name of the receiver.
|
188
|
+
#
|
189
|
+
# @param [String] relative_name
|
190
|
+
# the relative name of the subspecs starting from the receiver
|
191
|
+
# including the name of the receiver.
|
192
|
+
#
|
193
|
+
# @example Retrieving a subspec
|
194
|
+
#
|
195
|
+
# s.subspec_by_name('Pod/subspec').name #=> 'subspec'
|
196
|
+
#
|
197
|
+
# @return [Specification] the subspec with the given name or self.
|
198
|
+
#
|
199
|
+
def subspec_by_name(relative_name)
|
200
|
+
if relative_name.nil? || relative_name == base_name
|
201
|
+
self
|
202
|
+
else
|
203
|
+
remainder = relative_name[base_name.size+1..-1]
|
204
|
+
subspec_name = remainder.split('/').shift
|
205
|
+
subspec = subspecs.find { |s| s.name == "#{self.name}/#{subspec_name}" }
|
206
|
+
unless subspec
|
207
|
+
raise StandardError, "Unable to find a specification named " \
|
208
|
+
"`#{relative_name}` in `#{self.name}`."
|
209
|
+
end
|
210
|
+
subspec.subspec_by_name(remainder)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# @return [String] the name of the default subspec if provided.
|
215
|
+
#
|
216
|
+
def default_subspec
|
217
|
+
attributes_hash["default_subspec"]
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the dependencies on subspecs.
|
221
|
+
#
|
222
|
+
# @note A specification has a dependency on either the
|
223
|
+
# {#default_subspec} or each of its children subspecs that are
|
224
|
+
# compatible with its platform.
|
225
|
+
#
|
226
|
+
# @return [Array<Dependency>] the dependencies on subspecs.
|
227
|
+
#
|
228
|
+
def subspec_dependencies(platform = nil)
|
229
|
+
if default_subspec
|
230
|
+
specs = [subspec_by_name("#{name}/#{default_subspec}")]
|
231
|
+
else
|
232
|
+
specs = subspecs.compact
|
233
|
+
end
|
234
|
+
if platform
|
235
|
+
specs = specs.select { |s| s.supported_on_platform?(platform) }
|
236
|
+
end
|
237
|
+
specs = specs.map { |s| Dependency.new(s.name, version) }
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns the dependencies on other Pods or subspecs of other Pods.
|
241
|
+
#
|
242
|
+
# @param [Bool] all_platforms
|
243
|
+
# whether the dependencies should be returned for all platforms
|
244
|
+
# instead of the active one.
|
245
|
+
#
|
246
|
+
# @note External dependencies are inherited by subspecs
|
247
|
+
#
|
248
|
+
# @return [Array<Dependency>] the dependencies on other Pods.
|
249
|
+
#
|
250
|
+
def dependencies(platform = nil)
|
251
|
+
if platform
|
252
|
+
consumer(platform).dependencies || []
|
253
|
+
else
|
254
|
+
available_platforms.map do |spec_platform|
|
255
|
+
consumer(spec_platform).dependencies
|
256
|
+
end.flatten.uniq
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# @return [Array<Dependency>] all the dependencies of the specification.
|
261
|
+
#
|
262
|
+
def all_dependencies(platform = nil)
|
263
|
+
dependencies(platform) + subspec_dependencies(platform)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Returns a consumer to access the multi-platform attributes.
|
267
|
+
#
|
268
|
+
# @param [String, Symbol, Platform] platform
|
269
|
+
# he platform of the consumer
|
270
|
+
#
|
271
|
+
# @return [Specification::Consumer] the consumer for the given platform
|
272
|
+
#
|
273
|
+
def consumer(platform)
|
274
|
+
platform = platform.to_sym
|
275
|
+
@consumers[platform] ||= Consumer.new(self, platform)
|
276
|
+
end
|
277
|
+
|
278
|
+
#-------------------------------------------------------------------------#
|
279
|
+
|
280
|
+
public
|
281
|
+
|
282
|
+
# @!group DSL helpers
|
283
|
+
|
284
|
+
# @return [Bool] whether the specification should use a directory as it
|
285
|
+
# source.
|
286
|
+
#
|
287
|
+
def local?
|
288
|
+
!source.nil? && !source[:local].nil?
|
289
|
+
end
|
290
|
+
|
291
|
+
# @return [Bool] whether the specification is supported in the given
|
292
|
+
# platform.
|
293
|
+
#
|
294
|
+
# @overload supported_on_platform?(platform)
|
295
|
+
#
|
296
|
+
# @param [Platform] platform
|
297
|
+
# the platform which is checked for support.
|
298
|
+
#
|
299
|
+
# @overload supported_on_platform?(symbolic_name, deployment_target)
|
300
|
+
#
|
301
|
+
# @param [Symbol] symbolic_name
|
302
|
+
# the name of the platform which is checked for support.
|
303
|
+
#
|
304
|
+
# @param [String] deployment_target
|
305
|
+
# the deployment target which is checked for support.
|
306
|
+
#
|
307
|
+
def supported_on_platform?(*platform)
|
308
|
+
platform = Platform.new(*platform)
|
309
|
+
available_platforms.any? { |available| platform.supports?(available) }
|
310
|
+
end
|
311
|
+
|
312
|
+
# @return [Array<Platform>] The platforms that the Pod is supported on.
|
313
|
+
#
|
314
|
+
# @note If no platform is specified, this method returns all known
|
315
|
+
# platforms.
|
316
|
+
#
|
317
|
+
def available_platforms
|
318
|
+
names = supported_platform_names
|
319
|
+
names = PLATFORMS if names.empty?
|
320
|
+
names.map { |name| Platform.new(name, deployment_target(name)) }
|
321
|
+
end
|
322
|
+
|
323
|
+
# Returns the deployment target for the specified platform.
|
324
|
+
#
|
325
|
+
# @param [String] platform_name
|
326
|
+
# the symbolic name of the platform.
|
327
|
+
#
|
328
|
+
# @return [String] the deployment target
|
329
|
+
# @return [Nil] if not deployment target was specified for the platform.
|
330
|
+
#
|
331
|
+
def deployment_target(platform_name)
|
332
|
+
result = platform_hash[platform_name.to_s]
|
333
|
+
result ||= parent.deployment_target(platform_name) if parent
|
334
|
+
result
|
335
|
+
end
|
336
|
+
|
337
|
+
protected
|
338
|
+
|
339
|
+
# @return [Array[Symbol]] the symbolic name of the platform in which the
|
340
|
+
# specification is supported.
|
341
|
+
#
|
342
|
+
# @return [Nil] if the specification is supported on all the known
|
343
|
+
# platforms.
|
344
|
+
#
|
345
|
+
def supported_platform_names
|
346
|
+
result = platform_hash.keys
|
347
|
+
if result.empty? && parent
|
348
|
+
result = parent.supported_platform_names
|
349
|
+
end
|
350
|
+
result
|
351
|
+
end
|
352
|
+
|
353
|
+
# @return [Hash] the normalized hash which represents the platform
|
354
|
+
# information.
|
355
|
+
#
|
356
|
+
def platform_hash
|
357
|
+
case value = attributes_hash["platforms"]
|
358
|
+
when String
|
359
|
+
{ value => nil }
|
360
|
+
when Array
|
361
|
+
result = {}
|
362
|
+
value.each do |a_value|
|
363
|
+
result[a_value] = nil
|
364
|
+
end
|
365
|
+
result
|
366
|
+
when Hash
|
367
|
+
value
|
368
|
+
else
|
369
|
+
Hash.new
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
#-------------------------------------------------------------------------#
|
374
|
+
|
375
|
+
public
|
376
|
+
|
377
|
+
# @!group Hooks support
|
378
|
+
|
379
|
+
# @return [Proc] the pre install callback if defined.
|
380
|
+
#
|
381
|
+
attr_reader :pre_install_callback
|
382
|
+
|
383
|
+
# @return [Proc] the post install callback if defined.
|
384
|
+
#
|
385
|
+
attr_reader :post_install_callback
|
386
|
+
|
387
|
+
# Calls the pre install callback if defined.
|
388
|
+
#
|
389
|
+
# @param [Pod::LocalPod] pod
|
390
|
+
# the local pod instance that manages the files described by this
|
391
|
+
# specification.
|
392
|
+
#
|
393
|
+
# @param [Podfile::TargetDefinition] target_definition
|
394
|
+
# the target definition that required this specification as a
|
395
|
+
# dependency.
|
396
|
+
#
|
397
|
+
# @return [Bool] whether a pre install callback was specified and it was
|
398
|
+
# called.
|
399
|
+
#
|
400
|
+
def pre_install!(pod, target_definition)
|
401
|
+
return false unless @pre_install_callback
|
402
|
+
@pre_install_callback.call(pod, target_definition)
|
403
|
+
true
|
404
|
+
end
|
405
|
+
|
406
|
+
# Calls the post install callback if defined.
|
407
|
+
#
|
408
|
+
# @param [Pod::TargetInstaller] target_installer
|
409
|
+
# the target installer that is performing the installation of the
|
410
|
+
# pod.
|
411
|
+
#
|
412
|
+
# @return [Bool] whether a post install callback was specified and it was
|
413
|
+
# called.
|
414
|
+
#
|
415
|
+
def post_install!(target_installer)
|
416
|
+
return false unless @post_install_callback
|
417
|
+
@post_install_callback.call(target_installer)
|
418
|
+
true
|
419
|
+
end
|
420
|
+
|
421
|
+
#-------------------------------------------------------------------------#
|
422
|
+
|
423
|
+
public
|
424
|
+
|
425
|
+
# @!group DSL attribute writers
|
426
|
+
|
427
|
+
# Sets the value for the attribute with the given name.
|
428
|
+
#
|
429
|
+
# @param [Symbol] name
|
430
|
+
# the name of the attribute.
|
431
|
+
#
|
432
|
+
# @param [Object] value
|
433
|
+
# the value to store.
|
434
|
+
#
|
435
|
+
# @param [Symbol] platform.
|
436
|
+
# If provided the attribute is stored only for the given platform.
|
437
|
+
#
|
438
|
+
# @note If the provides value is Hash the keys are converted to a string.
|
439
|
+
#
|
440
|
+
# @return void
|
441
|
+
#
|
442
|
+
def store_attribute(name, value, platform_name = nil)
|
443
|
+
name = name.to_s
|
444
|
+
value = convert_keys_to_string(value) if value.is_a?(Hash)
|
445
|
+
if platform_name
|
446
|
+
platform_name = platform_name.to_s
|
447
|
+
attributes_hash[platform_name] ||= {}
|
448
|
+
attributes_hash[platform_name][name] = value
|
449
|
+
else
|
450
|
+
attributes_hash[name] = value
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# Defines the setters methods for the attributes providing support for the
|
455
|
+
# Ruby DSL.
|
456
|
+
#
|
457
|
+
DSL.attributes.values.each do |a|
|
458
|
+
define_method(a.writer_name) do |value|
|
459
|
+
store_attribute(a.name, value)
|
460
|
+
end
|
461
|
+
|
462
|
+
if a.writer_singular_form
|
463
|
+
alias_method(a.writer_singular_form, a.writer_name)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
private
|
468
|
+
|
469
|
+
# Converts the keys of the given hash to a string.
|
470
|
+
#
|
471
|
+
# @param [Object] value
|
472
|
+
# the value that needs to be stripped from the Symbols.
|
473
|
+
#
|
474
|
+
# @return [Hash] the hash with the strings instead of the keys.
|
475
|
+
#
|
476
|
+
def convert_keys_to_string(value)
|
477
|
+
return unless value
|
478
|
+
result = {}
|
479
|
+
value.each do |key, subvalue|
|
480
|
+
subvalue = convert_keys_to_string(subvalue) if subvalue.is_a?(Hash)
|
481
|
+
result[key.to_s] = subvalue
|
482
|
+
end
|
483
|
+
result
|
484
|
+
end
|
485
|
+
|
486
|
+
#-------------------------------------------------------------------------#
|
487
|
+
|
488
|
+
public
|
489
|
+
|
490
|
+
# @!group File representation
|
491
|
+
|
492
|
+
# @return [String] The SHA1 digest of the file in which the specification
|
493
|
+
# is defined.
|
494
|
+
#
|
495
|
+
# @return [Nil] If the specification is not defined in a file.
|
496
|
+
#
|
497
|
+
def checksum
|
498
|
+
require 'digest'
|
499
|
+
unless defined_in_file.nil?
|
500
|
+
checksum = Digest::SHA1.hexdigest(File.read(defined_in_file))
|
501
|
+
checksum = checksum.encode('UTF-8') if checksum.respond_to?(:encode)
|
502
|
+
checksum
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
# @return [String] the path where the specification is defined, if loaded
|
507
|
+
# from a file.
|
508
|
+
#
|
509
|
+
def defined_in_file
|
510
|
+
root? ? @defined_in_file : root.defined_in_file
|
511
|
+
end
|
512
|
+
|
513
|
+
# Loads a specification form the given path.
|
514
|
+
#
|
515
|
+
# @param [Pathname, String] path
|
516
|
+
# the path of the `podspec` file.
|
517
|
+
#
|
518
|
+
# @param [String] subspec_name
|
519
|
+
# the name of the specification that should be returned. If it is
|
520
|
+
# nil returns the root specification.
|
521
|
+
#
|
522
|
+
# @raise If the file doesn't return a Pods::Specification after
|
523
|
+
# evaluation.
|
524
|
+
#
|
525
|
+
# @return [Specification] the specification
|
526
|
+
#
|
527
|
+
def self.from_file(path, subspec_name = nil)
|
528
|
+
path = Pathname.new(path)
|
529
|
+
unless path.exist?
|
530
|
+
raise StandardError, "No podspec exists at path `#{path}`."
|
531
|
+
end
|
532
|
+
|
533
|
+
case path.extname
|
534
|
+
when '.podspec'
|
535
|
+
spec = ::Pod._eval_podspec(path)
|
536
|
+
unless spec.is_a?(Specification)
|
537
|
+
raise StandardError, "Invalid podspec file at path `#{path}`."
|
538
|
+
end
|
539
|
+
when '.yaml'
|
540
|
+
spec = Specification.from_yaml(path.read)
|
541
|
+
else
|
542
|
+
raise StandardError, "Unsupported specification format `#{path.extname}`."
|
543
|
+
end
|
544
|
+
|
545
|
+
spec.defined_in_file = path
|
546
|
+
spec.subspec_by_name(subspec_name)
|
547
|
+
end
|
548
|
+
|
549
|
+
# Sets the path of the `podspec` file used to load the specification.
|
550
|
+
#
|
551
|
+
# @param [String] file
|
552
|
+
# the `podspec` file.
|
553
|
+
#
|
554
|
+
# @return [void]
|
555
|
+
#
|
556
|
+
# @visibility private
|
557
|
+
#
|
558
|
+
def defined_in_file=(file)
|
559
|
+
unless root?
|
560
|
+
raise StandardError, "Defined in file can be set only for root specs."
|
561
|
+
end
|
562
|
+
@defined_in_file = file
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
|
567
|
+
#---------------------------------------------------------------------------#
|
568
|
+
|
569
|
+
Spec = Specification
|
570
|
+
|
571
|
+
# Evaluates the file at the given path in the namespace of the Pod module.
|
572
|
+
#
|
573
|
+
# @return [Object] it can return any object but, is expected to be called on
|
574
|
+
# `podspec` files that should return a #{Specification}.
|
575
|
+
#
|
576
|
+
# @private
|
577
|
+
#
|
578
|
+
def self._eval_podspec(path)
|
579
|
+
string = File.open(path, 'r:utf-8') { |f| f.read }
|
580
|
+
# Work around for Rubinius incomplete encoding in 1.9 mode
|
581
|
+
if string.respond_to?(:encoding) && string.encoding.name != "UTF-8"
|
582
|
+
string.encode!('UTF-8')
|
583
|
+
end
|
584
|
+
|
585
|
+
begin
|
586
|
+
eval(string, nil, path.to_s)
|
587
|
+
rescue Exception => e
|
588
|
+
raise DSLError.new("Invalid `#{path.basename}` file: #{e.message}",
|
589
|
+
path, e.backtrace)
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|