cocoapods-core 1.6.2 → 1.7.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cocoapods-core.rb +1 -0
- data/lib/cocoapods-core/cdn_source.rb +292 -0
- data/lib/cocoapods-core/gem_version.rb +1 -1
- data/lib/cocoapods-core/lockfile.rb +11 -16
- data/lib/cocoapods-core/podfile.rb +1 -1
- data/lib/cocoapods-core/podfile/dsl.rb +50 -3
- data/lib/cocoapods-core/podfile/target_definition.rb +44 -4
- data/lib/cocoapods-core/source/manager.rb +13 -9
- data/lib/cocoapods-core/specification.rb +77 -13
- data/lib/cocoapods-core/specification/consumer.rb +16 -0
- data/lib/cocoapods-core/specification/dsl.rb +88 -11
- data/lib/cocoapods-core/specification/dsl/attribute.rb +9 -2
- data/lib/cocoapods-core/specification/json.rb +27 -14
- data/lib/cocoapods-core/specification/linter.rb +20 -3
- data/lib/cocoapods-core/specification/root_attribute_accessors.rb +17 -4
- data/lib/cocoapods-core/version.rb +3 -1
- data/lib/cocoapods-core/yaml_helper.rb +4 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d6029877133203026dca0a0536818e5799bb22a
|
4
|
+
data.tar.gz: 14c7457385e244d39a5fabff47257f702c6b5afe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b34c2e92c8d1125c7d30237ca3f8771195860817768873d4ca3c774a82d6d83cf2741e7ca81e21ec738ce6fdd3c14b442c4815dc11aab2260ae9416e9fdad437
|
7
|
+
data.tar.gz: 1e4bc919ec36bd8f87a92dae0ce64755103d4bcd04b510443a6ef87078c22352ac084470d5e95c6f02c883b940cf7f68c9c31d1e71bb05ca21011b983a1e495d
|
data/lib/cocoapods-core.rb
CHANGED
@@ -27,6 +27,7 @@ module Pod
|
|
27
27
|
autoload :Platform, 'cocoapods-core/platform'
|
28
28
|
autoload :Podfile, 'cocoapods-core/podfile'
|
29
29
|
autoload :Source, 'cocoapods-core/source'
|
30
|
+
autoload :CDNSource, 'cocoapods-core/cdn_source'
|
30
31
|
autoload :MasterSource, 'cocoapods-core/master_source'
|
31
32
|
autoload :Specification, 'cocoapods-core/specification'
|
32
33
|
autoload :StandardError, 'cocoapods-core/standard_error'
|
@@ -0,0 +1,292 @@
|
|
1
|
+
require 'cocoapods-core/source'
|
2
|
+
require 'rest'
|
3
|
+
require 'concurrent'
|
4
|
+
|
5
|
+
module Pod
|
6
|
+
# Subclass of Pod::Source to provide support for CDN-based Specs repositories
|
7
|
+
#
|
8
|
+
class CDNSource < Source
|
9
|
+
# @param [String] repo The name of the repository
|
10
|
+
#
|
11
|
+
def initialize(repo)
|
12
|
+
@check_existing_files_for_update = false
|
13
|
+
# Optimization: we initialize startup_time when the source is first initialized
|
14
|
+
# and then test file modification dates against it. Any file that was touched
|
15
|
+
# after the source was initialized, is considered fresh enough.
|
16
|
+
@startup_time = Time.new
|
17
|
+
|
18
|
+
@executor = Concurrent::ThreadPoolExecutor.new(
|
19
|
+
:min_threads => 1,
|
20
|
+
:max_threads => 200,
|
21
|
+
:max_queue => 0 # unbounded work queue
|
22
|
+
)
|
23
|
+
super(repo)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [String] The URL of the source.
|
27
|
+
#
|
28
|
+
def url
|
29
|
+
@url ||= File.read(repo.join('.url'))
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String] The type of the source.
|
33
|
+
#
|
34
|
+
def type
|
35
|
+
'CDN'
|
36
|
+
end
|
37
|
+
|
38
|
+
def refresh_metadata
|
39
|
+
if metadata.nil?
|
40
|
+
unless repo.exist?
|
41
|
+
raise Informative, "Unable to find a source named: `#{name}`"
|
42
|
+
end
|
43
|
+
|
44
|
+
specs_dir.mkpath
|
45
|
+
download_file('CocoaPods-version.yml')
|
46
|
+
end
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def preheat_existing_files
|
52
|
+
all_existing_files = [repo.join('**/*.yml'), repo.join('**/*.txt'), repo.join('**/*.json')].map(&Pathname.method(:glob)).flatten
|
53
|
+
loaders = all_existing_files.map { |f| f.relative_path_from(repo).to_s }.map do |file|
|
54
|
+
Concurrent::Promise.execute(:executor => @executor) do
|
55
|
+
download_file(file)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
Concurrent::Promise.zip(*loaders).wait!
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Pathname] The directory where the specs are stored.
|
62
|
+
#
|
63
|
+
def specs_dir
|
64
|
+
@specs_dir ||= repo + 'Specs'
|
65
|
+
end
|
66
|
+
|
67
|
+
# @!group Querying the source
|
68
|
+
#-------------------------------------------------------------------------#
|
69
|
+
|
70
|
+
# @return [Array<String>] the list of the name of all the Pods.
|
71
|
+
#
|
72
|
+
def pods
|
73
|
+
download_file('all_pods.txt')
|
74
|
+
local_file('all_pods.txt', &:to_a).map(&:chomp)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Array<Version>] all the available versions for the Pod, sorted
|
78
|
+
# from highest to lowest.
|
79
|
+
#
|
80
|
+
# @param [String] name
|
81
|
+
# the name of the Pod.
|
82
|
+
#
|
83
|
+
def versions(name)
|
84
|
+
return nil unless specs_dir
|
85
|
+
raise ArgumentError, 'No name' unless name
|
86
|
+
|
87
|
+
return @versions_by_name[name] unless @versions_by_name[name].nil?
|
88
|
+
|
89
|
+
pod_path_actual = pod_path(name)
|
90
|
+
pod_path_relative = relative_pod_path(name)
|
91
|
+
versions_file_path_relative = pod_path_relative.join(INDEX_FILE_NAME).to_s
|
92
|
+
download_file(versions_file_path_relative)
|
93
|
+
|
94
|
+
return nil unless pod_path_actual.join(INDEX_FILE_NAME).exist?
|
95
|
+
|
96
|
+
loaders = []
|
97
|
+
@versions_by_name[name] ||= local_file(versions_file_path_relative) do |file|
|
98
|
+
file.map do |v|
|
99
|
+
version = v.chomp
|
100
|
+
|
101
|
+
# Optimization: ensure all the podspec files at least exist. The correct one will get refreshed
|
102
|
+
# in #specification_path regardless.
|
103
|
+
podspec_version_path_relative = Pathname.new(version).join("#{name}.podspec.json")
|
104
|
+
unless pod_path_actual.join(podspec_version_path_relative).exist?
|
105
|
+
loaders << Concurrent::Promise.execute(:executor => @executor) do
|
106
|
+
download_file(pod_path_relative.join(podspec_version_path_relative).to_s)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
begin
|
110
|
+
Version.new(version) if version[0, 1] != '.'
|
111
|
+
rescue ArgumentError
|
112
|
+
raise Informative, 'An unexpected version directory ' \
|
113
|
+
"`#{version}` was encountered for the " \
|
114
|
+
"`#{pod_dir}` Pod in the `#{name}` repository."
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end.compact.sort.reverse
|
118
|
+
Concurrent::Promise.zip(*loaders).wait!
|
119
|
+
@versions_by_name[name]
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the path of the specification with the given name and version.
|
123
|
+
#
|
124
|
+
# @param [String] name
|
125
|
+
# the name of the Pod.
|
126
|
+
#
|
127
|
+
# @param [Version,String] version
|
128
|
+
# the version for the specification.
|
129
|
+
#
|
130
|
+
# @return [Pathname] The path of the specification.
|
131
|
+
#
|
132
|
+
def specification_path(name, version)
|
133
|
+
raise ArgumentError, 'No name' unless name
|
134
|
+
raise ArgumentError, 'No version' unless version
|
135
|
+
|
136
|
+
podspec_version_path_relative = Pathname.new(version.to_s).join("#{name}.podspec.json")
|
137
|
+
relative_podspec = relative_pod_path(name).join(podspec_version_path_relative).to_s
|
138
|
+
download_file(relative_podspec)
|
139
|
+
pod_path(name).join(podspec_version_path_relative)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [Array<Specification>] all the specifications contained by the
|
143
|
+
# source.
|
144
|
+
#
|
145
|
+
def all_specs
|
146
|
+
raise Informative, "Can't retrieve all the specs for a CDN-backed source, it will take forever"
|
147
|
+
end
|
148
|
+
|
149
|
+
# @!group Searching the source
|
150
|
+
#-------------------------------------------------------------------------#
|
151
|
+
|
152
|
+
# @return [Set] a set for a given dependency. The set is identified by the
|
153
|
+
# name of the dependency and takes into account subspecs.
|
154
|
+
#
|
155
|
+
# @note This method is optimized for fast lookups by name, i.e. it does
|
156
|
+
# *not* require iterating through {#pod_sets}
|
157
|
+
#
|
158
|
+
# @todo Rename to #load_set
|
159
|
+
#
|
160
|
+
def search(query)
|
161
|
+
unless specs_dir
|
162
|
+
raise Informative, "Unable to find a source named: `#{name}`"
|
163
|
+
end
|
164
|
+
if query.is_a?(Dependency)
|
165
|
+
query = query.root_name
|
166
|
+
end
|
167
|
+
|
168
|
+
found = download_file(relative_pod_path(query).join(INDEX_FILE_NAME).to_s)
|
169
|
+
|
170
|
+
if found
|
171
|
+
set = set(query)
|
172
|
+
set if set.specification_name == query
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# @return [Array<Set>] The list of the sets that contain the search term.
|
177
|
+
#
|
178
|
+
# @param [String] query
|
179
|
+
# the search term. Can be a regular expression.
|
180
|
+
#
|
181
|
+
# @param [Bool] full_text_search
|
182
|
+
# not supported due to performance reasons
|
183
|
+
#
|
184
|
+
# @note full text search requires to load the specification for each pod,
|
185
|
+
# and therefore not supported.
|
186
|
+
#
|
187
|
+
def search_by_name(query, full_text_search = false)
|
188
|
+
if full_text_search
|
189
|
+
raise Informative, "Can't perform full text search, it will take forever"
|
190
|
+
else
|
191
|
+
super(query)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Check update dates for all existing files.
|
196
|
+
# Does not download non-existing specs, since CDN-backed repo is updated live.
|
197
|
+
#
|
198
|
+
# @param [Bool] show_output
|
199
|
+
#
|
200
|
+
# @return [Array<String>] Always returns empty array, as it cannot know
|
201
|
+
# everything that actually changed.
|
202
|
+
#
|
203
|
+
def update(_show_output)
|
204
|
+
@check_existing_files_for_update = true
|
205
|
+
begin
|
206
|
+
preheat_existing_files
|
207
|
+
ensure
|
208
|
+
@check_existing_files_for_update = false
|
209
|
+
end
|
210
|
+
[]
|
211
|
+
end
|
212
|
+
|
213
|
+
def git?
|
214
|
+
# Long story here. This property is actually used solely by Source::Manager to determine
|
215
|
+
# which sources are updatable. Ideally, this would require a name change but @segiddins
|
216
|
+
# has pointed out that it is public and could break plugins.
|
217
|
+
# In any case, CDN-backed repos can be updated and therefore the value ought to be true.
|
218
|
+
true
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
# Index files contain all the sub directories in the directory, separated by
|
224
|
+
# a newline. We use those because you can't get a directory listing from a CDN.
|
225
|
+
INDEX_FILE_NAME = 'index.txt'.freeze
|
226
|
+
|
227
|
+
def local_file(partial_url)
|
228
|
+
File.open(repo.join(partial_url)) do |file|
|
229
|
+
yield file if block_given?
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def relative_pod_path(pod_name)
|
234
|
+
pod_path(pod_name).relative_path_from(repo)
|
235
|
+
end
|
236
|
+
|
237
|
+
def download_file(partial_url)
|
238
|
+
file_remote_url = url + partial_url.to_s
|
239
|
+
path = repo + partial_url
|
240
|
+
|
241
|
+
if File.exist?(path)
|
242
|
+
if @startup_time < File.mtime(path)
|
243
|
+
debug "CDN: #{name} Relative path: #{partial_url} modified during this run! Returning local"
|
244
|
+
return partial_url
|
245
|
+
end
|
246
|
+
|
247
|
+
unless @check_existing_files_for_update
|
248
|
+
debug "CDN: #{name} Relative path: #{partial_url} exists! Returning local because checking is only perfomed in repo update"
|
249
|
+
return partial_url
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
path.dirname.mkpath
|
254
|
+
|
255
|
+
etag_path = path.sub_ext(path.extname + '.etag')
|
256
|
+
|
257
|
+
etag = File.read(etag_path) if File.exist?(etag_path)
|
258
|
+
debug "CDN: #{name} Relative path: #{partial_url}, has ETag? #{etag}" unless etag.nil?
|
259
|
+
|
260
|
+
response = etag.nil? ? REST.get(file_remote_url) : REST.get(file_remote_url, 'If-None-Match' => etag)
|
261
|
+
|
262
|
+
case response.status_code
|
263
|
+
when 304
|
264
|
+
debug "CDN: #{name} Relative path not modified: #{partial_url}"
|
265
|
+
# We need to update the file modification date, as it is later used for freshness
|
266
|
+
# optimization. See #initialize for more information.
|
267
|
+
FileUtils.touch path
|
268
|
+
partial_url
|
269
|
+
when 200
|
270
|
+
File.open(path, 'w') { |f| f.write(response.body) }
|
271
|
+
|
272
|
+
etag_new = response.headers['etag'].first if response.headers.include?('etag')
|
273
|
+
debug "CDN: #{name} Relative path downloaded: #{partial_url}, save ETag: #{etag_new}"
|
274
|
+
File.open(etag_path, 'w') { |f| f.write(etag_new) } unless etag_new.nil?
|
275
|
+
partial_url
|
276
|
+
when 404
|
277
|
+
debug "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.status_code}"
|
278
|
+
nil
|
279
|
+
else
|
280
|
+
raise Informative, "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.status_code}"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def debug(message)
|
285
|
+
if defined?(Pod::UI)
|
286
|
+
Pod::UI.message(message)
|
287
|
+
else
|
288
|
+
CoreUI.puts(message)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
@@ -454,22 +454,17 @@ module Pod
|
|
454
454
|
#
|
455
455
|
#
|
456
456
|
def generate_pods_data(specs)
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
pod_and_deps.each do |name, deps|
|
463
|
-
if tmp[name]
|
464
|
-
tmp[name].concat(deps).uniq!
|
465
|
-
else
|
466
|
-
tmp[name] = deps
|
467
|
-
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
|
468
462
|
end
|
469
|
-
|
470
|
-
|
463
|
+
|
464
|
+
pod_and_deps = pods_and_deps_merged.map do |name, deps|
|
465
|
+
deps.empty? ? name : { name => YAMLHelper.sorted_array(deps.uniq) }
|
471
466
|
end
|
472
|
-
pod_and_deps
|
467
|
+
YAMLHelper.sorted_array(pod_and_deps)
|
473
468
|
end
|
474
469
|
|
475
470
|
# Generates the list of the dependencies of the Podfile.
|
@@ -481,7 +476,7 @@ module Pod
|
|
481
476
|
# @return [Array] the generated data.
|
482
477
|
#
|
483
478
|
def generate_dependencies_data(podfile)
|
484
|
-
podfile.dependencies.map(&:to_s)
|
479
|
+
YAMLHelper.sorted_array(podfile.dependencies.map(&:to_s))
|
485
480
|
end
|
486
481
|
|
487
482
|
# Generates the hash of spec repo sources used in the Podfile.
|
@@ -496,7 +491,7 @@ module Pod
|
|
496
491
|
key = source.url || source.name
|
497
492
|
key = key.downcase if source.name == Pod::MasterSource::MASTER_REPO_NAME
|
498
493
|
value = specs.map { |s| s.root.name }.uniq
|
499
|
-
[key, value]
|
494
|
+
[key, YAMLHelper.sorted_array(value)]
|
500
495
|
end.compact]
|
501
496
|
end
|
502
497
|
|
@@ -20,7 +20,7 @@ module Pod
|
|
20
20
|
# target 'MyApp' do
|
21
21
|
# pod 'ObjectiveSugar', '~> 0.5'
|
22
22
|
#
|
23
|
-
# target
|
23
|
+
# target 'MyAppTests' do
|
24
24
|
# inherit! :search_paths
|
25
25
|
# pod 'OCMock', '~> 2.0.1'
|
26
26
|
# end
|
@@ -112,6 +112,9 @@ module Pod
|
|
112
112
|
# specify in your version requirement. The example is equal to
|
113
113
|
# `>= 0.1.2` combined with `< 0.2.0` and will always match the
|
114
114
|
# latest known version matching your requirements.
|
115
|
+
# * `~> 0.1.3-beta.0` Beta and release versions for 0.1.3, release versions
|
116
|
+
# up to 0.2 excluding 0.2. Components separated by a dash (-)
|
117
|
+
# will not be considered for the version requirement.
|
115
118
|
#
|
116
119
|
# A list of version requirements can be specified for even more fine
|
117
120
|
# grained control.
|
@@ -182,6 +185,18 @@ module Pod
|
|
182
185
|
#
|
183
186
|
# pod 'QueryKit', :subspecs => ['Attribute', 'QuerySet']
|
184
187
|
#
|
188
|
+
# ### Test Specs
|
189
|
+
#
|
190
|
+
# Test specs can be optionally included via the `:testspecs` option. By default,
|
191
|
+
# none of a Pod's test specs are included.
|
192
|
+
#
|
193
|
+
# You may specify a list of test spec names to install using the following:
|
194
|
+
#
|
195
|
+
# pod 'AFNetworking', :testspecs => ['UnitTests', 'SomeOtherTests']
|
196
|
+
#
|
197
|
+
# The values provided to `:testspecs` correspond to the name provided to the
|
198
|
+
# `test_spec` DSL attribute in a Podspec.
|
199
|
+
#
|
185
200
|
# ------
|
186
201
|
#
|
187
202
|
# Dependencies can be obtained also from external sources.
|
@@ -753,8 +768,7 @@ module Pod
|
|
753
768
|
# @param [String] source
|
754
769
|
# The URL of a specs repository.
|
755
770
|
#
|
756
|
-
# @example Specifying to first use the Artsy repository and then the
|
757
|
-
# CocoaPods Master Repository
|
771
|
+
# @example Specifying to first use the Artsy repository and then the CocoaPods Master Repository
|
758
772
|
#
|
759
773
|
# source 'https://github.com/artsy/Specs.git'
|
760
774
|
# source 'https://github.com/CocoaPods/Specs.git'
|
@@ -847,6 +861,39 @@ module Pod
|
|
847
861
|
raise Informative, 'Specifying multiple `post_install` hooks is unsupported.' if @post_install_callback
|
848
862
|
@post_install_callback = block
|
849
863
|
end
|
864
|
+
|
865
|
+
# Specifies the Swift version requirements this target definition supports.
|
866
|
+
#
|
867
|
+
# **Note** These requirements are inherited from the parent, if specified and if none
|
868
|
+
# are specified at the root level then all versions are considered to be supported.
|
869
|
+
#
|
870
|
+
# @param [String, Version, Array<String>, Array<Version>] requirements
|
871
|
+
# The set of requirements this target supports.
|
872
|
+
#
|
873
|
+
# @example
|
874
|
+
#
|
875
|
+
# target 'MyApp' do
|
876
|
+
# supports_swift_versions '>= 3.0', '< 4.0'
|
877
|
+
# pod 'AFNetworking', '~> 1.0'
|
878
|
+
# end
|
879
|
+
#
|
880
|
+
# @example
|
881
|
+
#
|
882
|
+
# supports_swift_versions '>= 3.0', '< 4.0'
|
883
|
+
#
|
884
|
+
# target 'MyApp' do
|
885
|
+
# pod 'AFNetworking', '~> 1.0'
|
886
|
+
# end
|
887
|
+
#
|
888
|
+
# target 'ZipApp' do
|
889
|
+
# pod 'SSZipArchive'
|
890
|
+
# end
|
891
|
+
#
|
892
|
+
# @return [void]
|
893
|
+
#
|
894
|
+
def supports_swift_versions(*requirements)
|
895
|
+
current_target_definition.store_swift_version_requirements(*requirements)
|
896
|
+
end
|
850
897
|
end
|
851
898
|
end
|
852
899
|
end
|
@@ -140,7 +140,7 @@ module Pod
|
|
140
140
|
# Sets the path of the user project this target definition should link
|
141
141
|
# with.
|
142
142
|
#
|
143
|
-
# @param [String]
|
143
|
+
# @param [String] name
|
144
144
|
# The path of the project.
|
145
145
|
#
|
146
146
|
# @return [void]
|
@@ -393,6 +393,27 @@ module Pod
|
|
393
393
|
get_hash_value('swift_version')
|
394
394
|
end
|
395
395
|
|
396
|
+
# @return [Array<String>] the Swift version requirements this target definition enforces.
|
397
|
+
#
|
398
|
+
def swift_version_requirements
|
399
|
+
get_hash_value('swift_version_requirements')
|
400
|
+
end
|
401
|
+
|
402
|
+
# Queries the target if a version of Swift is supported or not.
|
403
|
+
#
|
404
|
+
# @param [Version] swift_version
|
405
|
+
# The Swift version to query against.
|
406
|
+
#
|
407
|
+
# @return [Boolean] Whether the target accepts the specified Swift version.
|
408
|
+
#
|
409
|
+
def supports_swift_version?(swift_version)
|
410
|
+
if swift_version_requirements.nil?
|
411
|
+
root? || parent.supports_swift_version?(swift_version)
|
412
|
+
else
|
413
|
+
Requirement.create(swift_version_requirements).satisfied_by?(swift_version)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
396
417
|
#--------------------------------------#
|
397
418
|
|
398
419
|
# Whether a specific pod should be linked to the target when building for
|
@@ -610,6 +631,17 @@ module Pod
|
|
610
631
|
set_platform(name, target)
|
611
632
|
end
|
612
633
|
|
634
|
+
# Stores the Swift version requirements to be used for this target.
|
635
|
+
#
|
636
|
+
# @param [String, Version, Array<String>, Array<Version>] requirements
|
637
|
+
# The set of requirements this target supports.
|
638
|
+
#
|
639
|
+
# @return [void]
|
640
|
+
#
|
641
|
+
def store_swift_version_requirements(*requirements)
|
642
|
+
set_hash_value('swift_version_requirements', requirements.flatten.map(&:to_s))
|
643
|
+
end
|
644
|
+
|
613
645
|
#--------------------------------------#
|
614
646
|
|
615
647
|
# Stores the dependency for a Pod with the given name.
|
@@ -742,6 +774,7 @@ module Pod
|
|
742
774
|
children
|
743
775
|
configuration_pod_whitelist
|
744
776
|
uses_frameworks
|
777
|
+
swift_version_requirements
|
745
778
|
inheritance
|
746
779
|
abstract
|
747
780
|
swift_version
|
@@ -860,6 +893,7 @@ module Pod
|
|
860
893
|
if inhibit_hash['all']
|
861
894
|
# Clean pods that are set to not inhibit inside parent if inhibit_all_warnings! was set.
|
862
895
|
parent_hash['not_for_pods'] = nil
|
896
|
+
inhibit_hash.delete('all') if parent_hash['all']
|
863
897
|
end
|
864
898
|
parent_hash.merge(inhibit_hash) do |_, l, r|
|
865
899
|
Array(l).concat(r).uniq
|
@@ -966,7 +1000,7 @@ module Pod
|
|
966
1000
|
# Removes :inhibit_warnings from the requirements list, and adds
|
967
1001
|
# the pod's name into internal hash for disabling warnings.
|
968
1002
|
#
|
969
|
-
# @param [String]
|
1003
|
+
# @param [String] name The name of the pod
|
970
1004
|
#
|
971
1005
|
# @param [Array] requirements
|
972
1006
|
# If :inhibit_warnings is the only key in the hash, the hash
|
@@ -988,7 +1022,7 @@ module Pod
|
|
988
1022
|
# Removes :modular_headers from the requirements list, and adds
|
989
1023
|
# the pods name into internal hash for modular headers.
|
990
1024
|
#
|
991
|
-
# @param [String]
|
1025
|
+
# @param [String] name The name of the pod
|
992
1026
|
#
|
993
1027
|
# @param [Array] requirements
|
994
1028
|
# If :modular_headers is the only key in the hash, the hash
|
@@ -1011,7 +1045,7 @@ module Pod
|
|
1011
1045
|
# and adds the pod's name into the internal hash for which pods should be
|
1012
1046
|
# linked in which configuration only.
|
1013
1047
|
#
|
1014
|
-
# @param [String]
|
1048
|
+
# @param [String] name The name of the pod
|
1015
1049
|
#
|
1016
1050
|
# @param [Array] requirements
|
1017
1051
|
# If :configurations is the only key in the hash, the hash
|
@@ -1048,6 +1082,7 @@ module Pod
|
|
1048
1082
|
|
1049
1083
|
subspecs = options.delete(:subspecs)
|
1050
1084
|
test_specs = options.delete(:testspecs)
|
1085
|
+
app_specs = options.delete(:appspecs)
|
1051
1086
|
|
1052
1087
|
subspecs.each do |ss|
|
1053
1088
|
store_pod("#{name}/#{ss}", *requirements.dup)
|
@@ -1058,6 +1093,11 @@ module Pod
|
|
1058
1093
|
store_pod("#{name}/#{ss}", *requirements_copy)
|
1059
1094
|
end if test_specs
|
1060
1095
|
|
1096
|
+
app_specs.each do |as|
|
1097
|
+
requirements_copy = requirements.map(&:dup)
|
1098
|
+
store_pod("#{name}/#{as}", *requirements_copy)
|
1099
|
+
end if app_specs
|
1100
|
+
|
1061
1101
|
requirements.pop if options.empty?
|
1062
1102
|
!subspecs.nil?
|
1063
1103
|
end
|
@@ -33,15 +33,12 @@ module Pod
|
|
33
33
|
# will be used.
|
34
34
|
#
|
35
35
|
def aggregate_for_dependency(dependency)
|
36
|
-
if dependency.podspec_repo
|
37
|
-
source = source_with_url(dependency.podspec_repo)
|
38
|
-
raise StandardError, '[Bug] Failed to find known source with the URL ' \
|
39
|
-
"#{dependency.podspec_repo.inspect}" if source.nil?
|
36
|
+
return aggregate if dependency.podspec_repo.nil?
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
source = source_with_url(dependency.podspec_repo)
|
39
|
+
return aggregate if source.nil?
|
40
|
+
|
41
|
+
aggregate_with_repos([source.repo])
|
45
42
|
end
|
46
43
|
|
47
44
|
# @return [Array<Source>] The list of the sources with the given names.
|
@@ -234,6 +231,10 @@ module Pod
|
|
234
231
|
# A hash containing changed specification paths for each source.
|
235
232
|
#
|
236
233
|
def update_search_index_if_needed_in_background(changed_spec_paths)
|
234
|
+
if Gem.win_platform?
|
235
|
+
update_search_index_if_needed(changed_spec_paths)
|
236
|
+
return
|
237
|
+
end
|
237
238
|
Process.fork do
|
238
239
|
Process.daemon
|
239
240
|
update_search_index_if_needed(changed_spec_paths)
|
@@ -283,7 +284,10 @@ module Pod
|
|
283
284
|
#
|
284
285
|
def source_from_path(path)
|
285
286
|
@sources_by_path ||= Hash.new do |hash, key|
|
286
|
-
hash[key] =
|
287
|
+
hash[key] = case
|
288
|
+
when (key + '.url').exist?
|
289
|
+
CDNSource.new(key)
|
290
|
+
when key.basename.to_s == Pod::MasterSource::MASTER_REPO_NAME
|
287
291
|
MasterSource.new(key)
|
288
292
|
else
|
289
293
|
Source.new(key)
|
@@ -37,13 +37,18 @@ module Pod
|
|
37
37
|
# @param [Bool] test_specification
|
38
38
|
# Whether the specification is a test specification
|
39
39
|
#
|
40
|
-
|
40
|
+
# @param [Bool] app_specification
|
41
|
+
# Whether the specification is an app specification
|
42
|
+
#
|
43
|
+
def initialize(parent = nil, name = nil, test_specification = false, app_specification: false)
|
44
|
+
raise StandardError, "#{self} can not be both an app and test specification." if test_specification && app_specification
|
41
45
|
@attributes_hash = {}
|
42
46
|
@subspecs = []
|
43
47
|
@consumers = {}
|
44
48
|
@parent = parent
|
45
49
|
@hash_value = nil
|
46
50
|
@test_specification = test_specification
|
51
|
+
@app_specification = app_specification
|
47
52
|
attributes_hash['name'] = name
|
48
53
|
attributes_hash['test_type'] = :unit if test_specification
|
49
54
|
|
@@ -74,6 +79,11 @@ module Pod
|
|
74
79
|
attr_accessor :test_specification
|
75
80
|
alias_method :test_specification?, :test_specification
|
76
81
|
|
82
|
+
# @return [Bool] If this specification is an app specification.
|
83
|
+
#
|
84
|
+
attr_accessor :app_specification
|
85
|
+
alias_method :app_specification?, :app_specification
|
86
|
+
|
77
87
|
# Checks if a specification is equal to the given one according its name
|
78
88
|
# and to its version.
|
79
89
|
#
|
@@ -221,8 +231,35 @@ module Pod
|
|
221
231
|
|
222
232
|
public
|
223
233
|
|
234
|
+
# @return [Symbol] Spec type of the current spec.
|
235
|
+
#
|
236
|
+
# @note see Attribute#SUPPORTED_SPEC_TYPES for the list of available spec_types.
|
237
|
+
#
|
238
|
+
def spec_type
|
239
|
+
return :app if app_specification?
|
240
|
+
return :test if test_specification?
|
241
|
+
|
242
|
+
:library
|
243
|
+
end
|
244
|
+
|
224
245
|
# @!group Dependencies & Subspecs
|
225
246
|
|
247
|
+
# @return [Bool] If this specification is a library specification.
|
248
|
+
#
|
249
|
+
# @note a library specification is a specification that is not of type app or test.
|
250
|
+
#
|
251
|
+
def library_specification?
|
252
|
+
!app_specification? && !test_specification?
|
253
|
+
end
|
254
|
+
|
255
|
+
# @return [Bool] If this specification is not a library specification.
|
256
|
+
#
|
257
|
+
# @note see #library_specification?
|
258
|
+
#
|
259
|
+
def non_library_specification?
|
260
|
+
!library_specification?
|
261
|
+
end
|
262
|
+
|
226
263
|
# @return [Symbol] the test type supported if this is a test specification.
|
227
264
|
#
|
228
265
|
def test_type
|
@@ -236,6 +273,20 @@ module Pod
|
|
236
273
|
subspecs.select(&:test_specification?)
|
237
274
|
end
|
238
275
|
|
276
|
+
# @return [Array<Specification>] the list of all the app subspecs of
|
277
|
+
# a specification.
|
278
|
+
#
|
279
|
+
def app_specs
|
280
|
+
subspecs.select(&:app_specification?)
|
281
|
+
end
|
282
|
+
|
283
|
+
# @return [Array<Specification>] the list of all the non libary (app or test) subspecs of
|
284
|
+
# a specification.
|
285
|
+
#
|
286
|
+
def non_library_specs
|
287
|
+
subspecs.select(&:non_library_specification?)
|
288
|
+
end
|
289
|
+
|
239
290
|
# @return [Array<Specification>] the recursive list of all the subspecs of
|
240
291
|
# a specification.
|
241
292
|
#
|
@@ -265,7 +316,7 @@ module Pod
|
|
265
316
|
#
|
266
317
|
# @return [Specification] the subspec with the given name or self.
|
267
318
|
#
|
268
|
-
def subspec_by_name(relative_name, raise_if_missing = true,
|
319
|
+
def subspec_by_name(relative_name, raise_if_missing = true, include_non_library_specifications = false)
|
269
320
|
if relative_name.nil? || relative_name == base_name
|
270
321
|
self
|
271
322
|
elsif relative_name.downcase == base_name.downcase
|
@@ -274,7 +325,7 @@ module Pod
|
|
274
325
|
else
|
275
326
|
remainder = relative_name[base_name.size + 1..-1]
|
276
327
|
subspec_name = remainder.split('/').shift
|
277
|
-
subspec = subspecs.find { |s| s.base_name == subspec_name && (
|
328
|
+
subspec = subspecs.find { |s| s.base_name == subspec_name && (include_non_library_specifications || !s.non_library_specification?) }
|
278
329
|
unless subspec
|
279
330
|
if raise_if_missing
|
280
331
|
raise Informative, 'Unable to find a specification named ' \
|
@@ -283,7 +334,7 @@ module Pod
|
|
283
334
|
return nil
|
284
335
|
end
|
285
336
|
end
|
286
|
-
subspec.subspec_by_name(remainder, raise_if_missing,
|
337
|
+
subspec.subspec_by_name(remainder, raise_if_missing, include_non_library_specifications)
|
287
338
|
end
|
288
339
|
end
|
289
340
|
|
@@ -307,7 +358,7 @@ module Pod
|
|
307
358
|
#
|
308
359
|
def subspec_dependencies(platform = nil)
|
309
360
|
specs = if default_subspecs.empty?
|
310
|
-
subspecs.compact.reject(&:
|
361
|
+
subspecs.compact.reject(&:non_library_specification?)
|
311
362
|
else
|
312
363
|
default_subspecs.map do |subspec_name|
|
313
364
|
root.subspec_by_name("#{name}/#{subspec_name}")
|
@@ -377,6 +428,13 @@ module Pod
|
|
377
428
|
end
|
378
429
|
end
|
379
430
|
|
431
|
+
# @return [Hash] The scheme value.
|
432
|
+
#
|
433
|
+
def scheme
|
434
|
+
value = attributes_hash['scheme'] || {}
|
435
|
+
Specification.convert_keys_to_symbol(value, :recursive => false)
|
436
|
+
end
|
437
|
+
|
380
438
|
#-------------------------------------------------------------------------#
|
381
439
|
|
382
440
|
public
|
@@ -520,30 +578,36 @@ module Pod
|
|
520
578
|
# @param [Object] value
|
521
579
|
# the value that needs to be stripped from the Symbols.
|
522
580
|
#
|
523
|
-
# @
|
581
|
+
# @param [Boolean] recursive
|
582
|
+
# whether to convert keys of nested hashes.
|
583
|
+
#
|
584
|
+
# @return [Hash] the hash with the keys as strings instead of symbols.
|
524
585
|
#
|
525
|
-
def self.convert_keys_to_string(value)
|
586
|
+
def self.convert_keys_to_string(value, recursive: true)
|
526
587
|
return unless value
|
527
588
|
result = {}
|
528
589
|
value.each do |key, subvalue|
|
529
|
-
subvalue = Specification.convert_keys_to_string(subvalue) if subvalue.is_a?(Hash)
|
590
|
+
subvalue = Specification.convert_keys_to_string(subvalue) if recursive && subvalue.is_a?(Hash)
|
530
591
|
result[key.to_s] = subvalue
|
531
592
|
end
|
532
593
|
result
|
533
594
|
end
|
534
595
|
|
535
|
-
# Converts the keys of the given hash to a
|
596
|
+
# Converts the keys of the given hash to a symbol.
|
536
597
|
#
|
537
598
|
# @param [Object] value
|
538
|
-
# the value that needs to be stripped from the
|
599
|
+
# the value that needs to be stripped from the Strings.
|
600
|
+
#
|
601
|
+
# @param [Boolean] recursive
|
602
|
+
# whether to convert keys of nested hashes.
|
539
603
|
#
|
540
|
-
# @return [Hash] the hash with the
|
604
|
+
# @return [Hash] the hash with the keys as symbols instead of strings.
|
541
605
|
#
|
542
|
-
def self.convert_keys_to_symbol(value)
|
606
|
+
def self.convert_keys_to_symbol(value, recursive: true)
|
543
607
|
return unless value
|
544
608
|
result = {}
|
545
609
|
value.each do |key, subvalue|
|
546
|
-
subvalue = Specification.convert_keys_to_symbol(subvalue) if subvalue.is_a?(Hash)
|
610
|
+
subvalue = Specification.convert_keys_to_symbol(subvalue) if recursive && subvalue.is_a?(Hash)
|
547
611
|
result[key.to_sym] = subvalue
|
548
612
|
end
|
549
613
|
result
|
@@ -9,6 +9,7 @@ module Pod
|
|
9
9
|
# - standardizing the attributes
|
10
10
|
# - handling multi-platform values
|
11
11
|
# - handle default values
|
12
|
+
# - handle automatic container wrapping of values
|
12
13
|
# - handle inherited values
|
13
14
|
#
|
14
15
|
# This class allows to store the values of the attributes in the
|
@@ -184,6 +185,10 @@ module Pod
|
|
184
185
|
#
|
185
186
|
spec_attr_accessor :script_phases
|
186
187
|
|
188
|
+
# @return [Hash] A hash that contains the scheme configuration.
|
189
|
+
#
|
190
|
+
spec_attr_accessor :scheme
|
191
|
+
|
187
192
|
# @return [Array<String>] A hash where the key represents the
|
188
193
|
# paths of the resources to copy and the values the paths of
|
189
194
|
# the resources that should be copied.
|
@@ -407,6 +412,17 @@ module Pod
|
|
407
412
|
end
|
408
413
|
end
|
409
414
|
|
415
|
+
# Converts the a scheme where keys are strings into symbols.
|
416
|
+
#
|
417
|
+
# @param [Hash] value.
|
418
|
+
# The value of the attribute as specified by the user.
|
419
|
+
#
|
420
|
+
# @return [Hash] the scheme with symbols as keys instead of strings or `nil` if the value is not a hash.
|
421
|
+
#
|
422
|
+
def _prepare_scheme(value)
|
423
|
+
Specification.convert_keys_to_symbol(value, :recursive => false) if value && value.is_a?(Hash)
|
424
|
+
end
|
425
|
+
|
410
426
|
# Ensures that the file patterns of the resource bundles are contained in
|
411
427
|
# an array.
|
412
428
|
#
|
@@ -129,18 +129,35 @@ module Pod
|
|
129
129
|
|
130
130
|
#------------------#
|
131
131
|
|
132
|
-
# @!method
|
132
|
+
# @!method swift_versions=(version)
|
133
133
|
#
|
134
|
-
# The
|
134
|
+
# The versions of Swift that the specification supports. A version of '4' will be treated as
|
135
|
+
# '4.0' by CocoaPods and not '4.1' or '4.2'.
|
136
|
+
#
|
137
|
+
# **Note** The Swift compiler mostly accepts major versions and sometimes will honor minor versions.
|
138
|
+
# While CocoaPods allows specifying a minor or patch version it might not be honored fully by the Swift compiler.
|
139
|
+
#
|
140
|
+
# @example
|
141
|
+
#
|
142
|
+
# spec.swift_versions = ['3.0']
|
135
143
|
#
|
136
144
|
# @example
|
137
145
|
#
|
138
|
-
# spec.
|
146
|
+
# spec.swift_versions = ['3.0', '4.0', '4.2']
|
147
|
+
#
|
148
|
+
# @example
|
139
149
|
#
|
140
|
-
#
|
150
|
+
# spec.swift_version = '3.0'
|
141
151
|
#
|
142
|
-
|
143
|
-
|
152
|
+
# @example
|
153
|
+
#
|
154
|
+
# spec.swift_version = '3.0', '4.0'
|
155
|
+
#
|
156
|
+
# @param [String, Array<String>] swift_versions
|
157
|
+
#
|
158
|
+
root_attribute :swift_versions,
|
159
|
+
:container => Array,
|
160
|
+
:singularize => true
|
144
161
|
|
145
162
|
#-----------------------------------------------------------------------#
|
146
163
|
|
@@ -660,8 +677,21 @@ module Pod
|
|
660
677
|
end
|
661
678
|
end
|
662
679
|
unless version_requirements.all? { |req| req.is_a?(String) }
|
663
|
-
|
680
|
+
version_requirements.each do |requirement|
|
681
|
+
if requirement.is_a?(Hash)
|
682
|
+
if !requirement[:path].nil?
|
683
|
+
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:path` option is not supported.'\
|
684
|
+
' `:path` can be used in the Podfile instead to override global dependencies.'
|
685
|
+
elsif !requirement[:git].nil?
|
686
|
+
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:git` option is not supported.'\
|
687
|
+
' `:git` can be used in the Podfile instead to override global dependencies.'
|
688
|
+
end
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
raise Informative, "Unsupported version requirements. #{version_requirements.inspect} is not valid."
|
664
693
|
end
|
694
|
+
|
665
695
|
attributes_hash['dependencies'] ||= {}
|
666
696
|
attributes_hash['dependencies'][name] = version_requirements
|
667
697
|
end
|
@@ -1230,10 +1260,10 @@ module Pod
|
|
1230
1260
|
#
|
1231
1261
|
# spec.resource_bundles = {
|
1232
1262
|
# 'MapBox' => ['MapView/Map/Resources/*.png'],
|
1233
|
-
# '
|
1263
|
+
# 'MapBoxOtherResources' => ['MapView/Map/OtherResources/*.png']
|
1234
1264
|
# }
|
1235
1265
|
#
|
1236
|
-
# @param [Hash{String=>String}] resource_bundles
|
1266
|
+
# @param [Hash{String=>String}, Hash{String=>Array<String>}] resource_bundles
|
1237
1267
|
# A hash where the keys are the names of the resource bundles
|
1238
1268
|
# and the values are their relative file patterns.
|
1239
1269
|
#
|
@@ -1443,10 +1473,11 @@ module Pod
|
|
1443
1473
|
#
|
1444
1474
|
# @param [Symbol, String] type
|
1445
1475
|
# The test type to use.
|
1476
|
+
#
|
1446
1477
|
attribute :test_type,
|
1447
1478
|
:types => [Symbol, String],
|
1448
1479
|
:multi_platform => false,
|
1449
|
-
:
|
1480
|
+
:spec_types => [:test]
|
1450
1481
|
|
1451
1482
|
# @!method requires_app_host=(flag)
|
1452
1483
|
#
|
@@ -1462,7 +1493,31 @@ module Pod
|
|
1462
1493
|
attribute :requires_app_host,
|
1463
1494
|
:types => [TrueClass, FalseClass],
|
1464
1495
|
:default_value => false,
|
1465
|
-
:
|
1496
|
+
:spec_types => [:test]
|
1497
|
+
|
1498
|
+
SCHEME_KEYS = [:launch_arguments, :environment_variables].freeze
|
1499
|
+
|
1500
|
+
# @!method scheme=(flag)
|
1501
|
+
#
|
1502
|
+
# Specifies the scheme configuration to be used for this specification.
|
1503
|
+
#
|
1504
|
+
# ---
|
1505
|
+
#
|
1506
|
+
# @example
|
1507
|
+
#
|
1508
|
+
# spec.scheme = { :launch_arguments => ['Arg1'] }
|
1509
|
+
#
|
1510
|
+
# @example
|
1511
|
+
#
|
1512
|
+
# spec.scheme = { :launch_arguments => ['Arg1', 'Arg2'], :environment_variables => { 'Key1' => 'Val1'} }
|
1513
|
+
#
|
1514
|
+
# @param [Hash] scheme
|
1515
|
+
# the scheme configuration to be used for this specification.
|
1516
|
+
#
|
1517
|
+
attribute :scheme,
|
1518
|
+
:types => [Hash],
|
1519
|
+
:container => Hash,
|
1520
|
+
:keys => SCHEME_KEYS
|
1466
1521
|
|
1467
1522
|
# Represents a test specification for the library. Here you can place all
|
1468
1523
|
# your tests for your podspec along with the test dependencies.
|
@@ -1486,6 +1541,28 @@ module Pod
|
|
1486
1541
|
subspec
|
1487
1542
|
end
|
1488
1543
|
|
1544
|
+
# Represents an app specification for the library. Here you can place all
|
1545
|
+
# your app source files for your podspec along with the app dependencies.
|
1546
|
+
#
|
1547
|
+
# ---
|
1548
|
+
#
|
1549
|
+
# @example
|
1550
|
+
#
|
1551
|
+
# Pod::Spec.new do |spec|
|
1552
|
+
# spec.name = 'NSAttributedString+CCLFormat'
|
1553
|
+
#
|
1554
|
+
# spec.app_spec do |app_spec|
|
1555
|
+
# app_spec.source_files = 'NSAttributedString+CCLFormat.m'
|
1556
|
+
# app_spec.dependency 'AFNetworking'
|
1557
|
+
# end
|
1558
|
+
# end
|
1559
|
+
#
|
1560
|
+
def app_spec(name = 'App', &block)
|
1561
|
+
appspec = Specification.new(self, name, :app_specification => true, &block)
|
1562
|
+
@subspecs << appspec
|
1563
|
+
appspec
|
1564
|
+
end
|
1565
|
+
|
1489
1566
|
#------------------#
|
1490
1567
|
|
1491
1568
|
# @!method default_subspecs=(subspec_array)
|
@@ -7,6 +7,10 @@ module Pod
|
|
7
7
|
class Attribute
|
8
8
|
require 'active_support/inflector/inflections'
|
9
9
|
|
10
|
+
# Spec types currently supported.
|
11
|
+
#
|
12
|
+
SUPPORTED_SPEC_TYPES = [:library, :app, :test].freeze
|
13
|
+
|
10
14
|
# @return [Symbol] the name of the attribute.
|
11
15
|
#
|
12
16
|
attr_reader :name
|
@@ -31,7 +35,7 @@ module Pod
|
|
31
35
|
|
32
36
|
@multi_platform = options.delete(:multi_platform) { true }
|
33
37
|
@root_only = options.delete(:root_only) { false }
|
34
|
-
@
|
38
|
+
@spec_types = options.delete(:spec_types) { SUPPORTED_SPEC_TYPES }
|
35
39
|
@inherited = options.delete(:inherited) { @root_only }
|
36
40
|
@required = options.delete(:required) { false }
|
37
41
|
@singularize = options.delete(:singularize) { false }
|
@@ -46,6 +50,9 @@ module Pod
|
|
46
50
|
unless options.empty?
|
47
51
|
raise StandardError, "Unrecognized options: #{options} for #{self}"
|
48
52
|
end
|
53
|
+
unless (@spec_types - SUPPORTED_SPEC_TYPES).empty?
|
54
|
+
raise StandardError, "Unrecognized spec type option: #{@spec_types} for #{self}"
|
55
|
+
end
|
49
56
|
end
|
50
57
|
|
51
58
|
# @return [String] A string representation suitable for UI.
|
@@ -126,7 +133,7 @@ module Pod
|
|
126
133
|
# test specifications.
|
127
134
|
#
|
128
135
|
def test_only?
|
129
|
-
@
|
136
|
+
@spec_types == [:test]
|
130
137
|
end
|
131
138
|
|
132
139
|
# @return [Bool] whether the attribute is multi-platform and should
|
@@ -26,13 +26,15 @@ module Pod
|
|
26
26
|
platforms = Hash[available_platforms.map { |p| [p.name.to_s, p.deployment_target && p.deployment_target.to_s] }]
|
27
27
|
hash['platforms'] = platforms
|
28
28
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
specs_by_type = subspecs.group_by(&:spec_type)
|
30
|
+
all_appspecs = specs_by_type[:app] || []
|
31
|
+
all_testspecs = specs_by_type[:test] || []
|
32
|
+
all_subspecs = specs_by_type[:library] || []
|
33
|
+
|
34
|
+
hash['testspecs'] = all_testspecs.map(&:to_hash) unless all_testspecs.empty?
|
35
|
+
hash['appspecs'] = all_appspecs.map(&:to_hash) unless all_appspecs.empty?
|
36
|
+
hash['subspecs'] = all_subspecs.map(&:to_hash) unless all_subspecs.empty?
|
37
|
+
|
36
38
|
hash
|
37
39
|
end
|
38
40
|
end
|
@@ -61,22 +63,33 @@ module Pod
|
|
61
63
|
#
|
62
64
|
# @return [Specification] the specification
|
63
65
|
#
|
64
|
-
def self.from_hash(hash, parent = nil)
|
65
|
-
spec = Spec.new(parent)
|
66
|
+
def self.from_hash(hash, parent = nil, test_specification: false, app_specification: false)
|
66
67
|
attributes_hash = hash.dup
|
68
|
+
spec = Spec.new(parent, nil, test_specification, :app_specification => app_specification)
|
67
69
|
subspecs = attributes_hash.delete('subspecs')
|
68
70
|
testspecs = attributes_hash.delete('testspecs')
|
69
|
-
|
71
|
+
appspecs = attributes_hash.delete('appspecs')
|
72
|
+
|
73
|
+
## backwards compatibility with 1.3.0
|
70
74
|
spec.test_specification = !attributes_hash['test_type'].nil?
|
71
|
-
|
72
|
-
|
75
|
+
|
76
|
+
testspecs.each { |ts| ts['test_specification'] = true; } unless testspecs.nil?
|
77
|
+
appspecs.each { |ts| ts['app_specification'] = true; } unless appspecs.nil?
|
78
|
+
|
79
|
+
spec.attributes_hash = attributes_hash
|
80
|
+
spec.subspecs.concat(subspecs_from_hash(spec, subspecs, false, false))
|
81
|
+
spec.subspecs.concat(subspecs_from_hash(spec, testspecs, true, false))
|
82
|
+
spec.subspecs.concat(subspecs_from_hash(spec, appspecs, false, true))
|
83
|
+
|
73
84
|
spec
|
74
85
|
end
|
75
86
|
|
76
|
-
def self.subspecs_from_hash(spec, subspecs)
|
87
|
+
def self.subspecs_from_hash(spec, subspecs, test_specification, app_specification)
|
77
88
|
return [] if subspecs.nil?
|
78
89
|
subspecs.map do |s_hash|
|
79
|
-
Specification.from_hash(s_hash, spec
|
90
|
+
Specification.from_hash(s_hash, spec,
|
91
|
+
:test_specification => test_specification,
|
92
|
+
:app_specification => app_specification)
|
80
93
|
end
|
81
94
|
end
|
82
95
|
|
@@ -401,8 +401,8 @@ module Pod
|
|
401
401
|
keys = script_phase.keys
|
402
402
|
unrecognized_keys = keys - Specification::ALL_SCRIPT_PHASE_KEYS
|
403
403
|
unless unrecognized_keys.empty?
|
404
|
-
results.add_error('script_phases', "Unrecognized
|
405
|
-
"Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS}`.")
|
404
|
+
results.add_error('script_phases', "Unrecognized option(s) `#{unrecognized_keys.join(', ')}` in script phase `#{script_phase[:name]}`. " \
|
405
|
+
"Available options are `#{Specification::ALL_SCRIPT_PHASE_KEYS.join(', ')}`.")
|
406
406
|
end
|
407
407
|
missing_required_keys = Specification::SCRIPT_PHASE_REQUIRED_KEYS - keys
|
408
408
|
unless missing_required_keys.empty?
|
@@ -410,7 +410,24 @@ module Pod
|
|
410
410
|
end
|
411
411
|
unless Specification::EXECUTION_POSITION_KEYS.include?(script_phase[:execution_position])
|
412
412
|
results.add_error('script_phases', "Invalid execution position value `#{script_phase[:execution_position]}` in shell script `#{script_phase[:name]}`. " \
|
413
|
-
"Available options are `#{Specification::EXECUTION_POSITION_KEYS}`.")
|
413
|
+
"Available options are `#{Specification::EXECUTION_POSITION_KEYS.join(', ')}`.")
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
# Performs validation related to the `scheme` attribute.
|
419
|
+
#
|
420
|
+
def _validate_scheme(s)
|
421
|
+
unless s.empty?
|
422
|
+
if consumer.spec.subspec? && consumer.spec.library_specification?
|
423
|
+
results.add_error('scheme', 'Scheme configuration is not currently supported for subspecs.')
|
424
|
+
return
|
425
|
+
end
|
426
|
+
if s.key?(:launch_arguments) && !s[:launch_arguments].is_a?(Array)
|
427
|
+
results.add_error('scheme', 'Expected an array for key `launch_arguments`.')
|
428
|
+
end
|
429
|
+
if s.key?(:environment_variables) && !s[:environment_variables].is_a?(Hash)
|
430
|
+
results.add_error('scheme', 'Expected a hash for key `environment_variables`.')
|
414
431
|
end
|
415
432
|
end
|
416
433
|
end
|
@@ -40,12 +40,25 @@ module Pod
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
# @
|
43
|
+
# @deprecated in favor of #swift_versions
|
44
|
+
#
|
45
|
+
# @return [Version] The Swift version specified by the specification.
|
44
46
|
#
|
45
47
|
def swift_version
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
swift_versions.last
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Array<Version>] The Swift versions supported by the specification.
|
52
|
+
#
|
53
|
+
def swift_versions
|
54
|
+
@swift_versions ||= begin
|
55
|
+
swift_versions = Array(attributes_hash['swift_versions'])
|
56
|
+
# Pre 1.7.0, the DSL was singularized as it supported only a single version of Swift. In 1.7.0 the DSL
|
57
|
+
# is now pluralized always and a specification can support multiple versions of Swift. This ensures
|
58
|
+
# we parse the old JSON serialized format and include it as part of the Swift versions supported.
|
59
|
+
swift_versions << attributes_hash['swift_version'] unless attributes_hash['swift_version'].nil?
|
60
|
+
swift_versions.map { |swift_version| Version.new(swift_version) }.uniq.sort
|
61
|
+
end
|
49
62
|
end
|
50
63
|
|
51
64
|
# @return [Requirement] The CocoaPods version required to use the specification.
|
@@ -221,7 +221,9 @@ module Pod
|
|
221
221
|
return 1 if rhs.nil?
|
222
222
|
end
|
223
223
|
|
224
|
-
|
224
|
+
if comparison = lhs <=> rhs
|
225
|
+
return comparison
|
226
|
+
end
|
225
227
|
return 1 if lhs.is_a?(String) && rhs.is_a?(Numeric)
|
226
228
|
return -1 if lhs.is_a?(Numeric) && rhs.is_a?(String)
|
227
229
|
end
|
@@ -239,6 +239,8 @@ module Pod
|
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
242
|
+
public
|
243
|
+
|
242
244
|
# Sorts an array according to the string representation of it values.
|
243
245
|
# This method allows to sort arrays which contains strings or hashes.
|
244
246
|
#
|
@@ -259,6 +261,8 @@ module Pod
|
|
259
261
|
end.map(&:first)
|
260
262
|
end
|
261
263
|
|
264
|
+
private
|
265
|
+
|
262
266
|
# Returns the string representation of a value useful for sorting.
|
263
267
|
#
|
264
268
|
# @param [String, Symbol, Array, Hash] value
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eloy Duran
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-02-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- LICENSE
|
88
88
|
- README.md
|
89
89
|
- lib/cocoapods-core.rb
|
90
|
+
- lib/cocoapods-core/cdn_source.rb
|
90
91
|
- lib/cocoapods-core/core_ui.rb
|
91
92
|
- lib/cocoapods-core/dependency.rb
|
92
93
|
- lib/cocoapods-core/gem_version.rb
|