cocoapods-core 1.7.5 → 1.8.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 -1
- data/lib/cocoapods-core/cdn_source.rb +80 -22
- data/lib/cocoapods-core/dependency.rb +2 -25
- data/lib/cocoapods-core/gem_version.rb +1 -1
- data/lib/cocoapods-core/http.rb +11 -9
- data/lib/cocoapods-core/lockfile.rb +1 -1
- data/lib/cocoapods-core/podfile/dsl.rb +33 -33
- data/lib/cocoapods-core/podfile/target_definition.rb +43 -0
- data/lib/cocoapods-core/source.rb +14 -3
- data/lib/cocoapods-core/source/manager.rb +46 -16
- data/lib/cocoapods-core/specification.rb +23 -9
- data/lib/cocoapods-core/specification/consumer.rb +38 -6
- data/lib/cocoapods-core/specification/dsl.rb +70 -3
- data/lib/cocoapods-core/specification/linter.rb +41 -11
- data/lib/cocoapods-core/specification/linter/analyzer.rb +4 -0
- data/lib/cocoapods-core/specification/root_attribute_accessors.rb +6 -6
- data/lib/cocoapods-core/trunk_source.rb +14 -0
- data/lib/cocoapods-core/version.rb +3 -4
- metadata +17 -3
- data/lib/cocoapods-core/master_source.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3b9cb102f03fac7ec166a52c1d0b47a4b0bcefec61664061dc1136b96db2d81
|
4
|
+
data.tar.gz: a568022e39121dae7ee044b60d58369e543698e6261f5bfc1dafb3469da18512
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4f4dad80c9d988f64f83235c53ebc0e532207cda1fb0a7704248d97a4ad733e26831c42f39e2a80fd2a46ceda271ce39fd2c7d76bbff1f0f42a2116ac364473
|
7
|
+
data.tar.gz: 73492f7437077ac6f9bfda2edae47a56868b3a3fefb3fc1f37cd6eb739593cd57accb2256a198950ffb3b912f9449807cceb354850c83e1f7c3c137a1db5d4ba
|
data/lib/cocoapods-core.rb
CHANGED
@@ -28,7 +28,7 @@ module Pod
|
|
28
28
|
autoload :Podfile, 'cocoapods-core/podfile'
|
29
29
|
autoload :Source, 'cocoapods-core/source'
|
30
30
|
autoload :CDNSource, 'cocoapods-core/cdn_source'
|
31
|
-
autoload :
|
31
|
+
autoload :TrunkSource, 'cocoapods-core/trunk_source'
|
32
32
|
autoload :Specification, 'cocoapods-core/specification'
|
33
33
|
autoload :StandardError, 'cocoapods-core/standard_error'
|
34
34
|
autoload :YAMLHelper, 'cocoapods-core/yaml_helper'
|
@@ -6,8 +6,8 @@ module Pod
|
|
6
6
|
# Subclass of Pod::Source to provide support for CDN-based Specs repositories
|
7
7
|
#
|
8
8
|
class CDNSource < Source
|
9
|
-
MAX_CDN_NETWORK_THREADS = 50
|
10
|
-
MAX_NUMBER_OF_RETRIES = 5
|
9
|
+
MAX_CDN_NETWORK_THREADS = (ENV['MAX_CDN_NETWORK_THREADS'] || 50).to_i
|
10
|
+
MAX_NUMBER_OF_RETRIES = (ENV['COCOAPODS_CDN_MAX_NUMBER_OF_RETRIES'] || 5).to_i
|
11
11
|
|
12
12
|
# @param [String] repo The name of the repository
|
13
13
|
#
|
@@ -20,7 +20,7 @@ module Pod
|
|
20
20
|
|
21
21
|
@executor = Concurrent::ThreadPoolExecutor.new(
|
22
22
|
:min_threads => 5,
|
23
|
-
:max_threads =>
|
23
|
+
:max_threads => MAX_CDN_NETWORK_THREADS,
|
24
24
|
:max_queue => 0 # unbounded work queue
|
25
25
|
)
|
26
26
|
|
@@ -32,7 +32,7 @@ module Pod
|
|
32
32
|
# @return [String] The URL of the source.
|
33
33
|
#
|
34
34
|
def url
|
35
|
-
@url ||= File.read(repo.join('.url'))
|
35
|
+
@url ||= File.read(repo.join('.url')).chomp.chomp('/') + '/'
|
36
36
|
end
|
37
37
|
|
38
38
|
# @return [String] The type of the source.
|
@@ -44,7 +44,8 @@ module Pod
|
|
44
44
|
def refresh_metadata
|
45
45
|
if metadata.nil?
|
46
46
|
unless repo.exist?
|
47
|
-
|
47
|
+
debug "CDN: Repo #{name} does not exist!"
|
48
|
+
return
|
48
49
|
end
|
49
50
|
|
50
51
|
specs_dir.mkpath
|
@@ -55,8 +56,9 @@ module Pod
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def preheat_existing_files
|
58
|
-
|
59
|
-
|
59
|
+
files_to_update = files_definitely_to_update + deprecated_local_podspecs - ['deprecated_podspecs.txt']
|
60
|
+
debug "CDN: #{name} Going to update #{files_to_update.count} files"
|
61
|
+
loaders = files_to_update.map do |file|
|
60
62
|
Concurrent::Promises.future_on(@executor) do
|
61
63
|
download_file(file)
|
62
64
|
end
|
@@ -67,6 +69,17 @@ module Pod
|
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
72
|
+
def files_definitely_to_update
|
73
|
+
Pathname.glob(repo.join('**/*.{txt,yml}')).map { |f| f.relative_path_from(repo).to_s }
|
74
|
+
end
|
75
|
+
|
76
|
+
def deprecated_local_podspecs
|
77
|
+
download_file('deprecated_podspecs.txt')
|
78
|
+
local_file('deprecated_podspecs.txt', &:to_a).
|
79
|
+
map { |f| Pathname.new(f.chomp) }.
|
80
|
+
select { |f| repo.join(f).exist? }
|
81
|
+
end
|
82
|
+
|
70
83
|
# @return [Pathname] The directory where the specs are stored.
|
71
84
|
#
|
72
85
|
def specs_dir
|
@@ -143,6 +156,10 @@ module Pod
|
|
143
156
|
def specification_path(name, version)
|
144
157
|
raise ArgumentError, 'No name' unless name
|
145
158
|
raise ArgumentError, 'No version' unless version
|
159
|
+
unless versions(name).include?(Version.new(version))
|
160
|
+
raise StandardError, "Unable to find the specification #{name} " \
|
161
|
+
"(#{version}) in the #{self.name} source."
|
162
|
+
end
|
146
163
|
|
147
164
|
podspec_version_path_relative = Pathname.new(version.to_s).join("#{name}.podspec.json")
|
148
165
|
relative_podspec = relative_pod_path(name).join(podspec_version_path_relative).to_s
|
@@ -202,14 +219,21 @@ module Pod
|
|
202
219
|
# the search term. Can be a regular expression.
|
203
220
|
#
|
204
221
|
# @param [Bool] full_text_search
|
205
|
-
#
|
222
|
+
# performed using Algolia
|
206
223
|
#
|
207
224
|
# @note full text search requires to load the specification for each pod,
|
208
225
|
# and therefore not supported.
|
209
226
|
#
|
210
227
|
def search_by_name(query, full_text_search = false)
|
211
228
|
if full_text_search
|
212
|
-
|
229
|
+
require 'algoliasearch'
|
230
|
+
begin
|
231
|
+
algolia_result = algolia_search_index.search(query, :attributesToRetrieve => 'name')
|
232
|
+
names = algolia_result['hits'].map { |r| r['name'] }
|
233
|
+
names.map { |n| set(n) }.reject { |s| s.versions.compact.empty? }
|
234
|
+
rescue Algolia::AlgoliaError => e
|
235
|
+
raise Informative, "CDN: #{name} - Cannot perform full-text search because Algolia returned an error: #{e}"
|
236
|
+
end
|
213
237
|
else
|
214
238
|
super(query)
|
215
239
|
end
|
@@ -233,14 +257,18 @@ module Pod
|
|
233
257
|
[]
|
234
258
|
end
|
235
259
|
|
236
|
-
def
|
237
|
-
# Long story here. This property is actually used solely by Source::Manager to determine
|
238
|
-
# which sources are updatable. Ideally, this would require a name change but @segiddins
|
239
|
-
# has pointed out that it is public and could break plugins.
|
240
|
-
# In any case, CDN-backed repos can be updated and therefore the value ought to be true.
|
260
|
+
def updateable?
|
241
261
|
true
|
242
262
|
end
|
243
263
|
|
264
|
+
def git?
|
265
|
+
false
|
266
|
+
end
|
267
|
+
|
268
|
+
def indexable?
|
269
|
+
false
|
270
|
+
end
|
271
|
+
|
244
272
|
private
|
245
273
|
|
246
274
|
def ensure_versions_file_loaded(fragment)
|
@@ -261,6 +289,18 @@ module Pod
|
|
261
289
|
end
|
262
290
|
end
|
263
291
|
|
292
|
+
def algolia_search_index
|
293
|
+
@index ||= begin
|
294
|
+
require 'algoliasearch'
|
295
|
+
|
296
|
+
raise Informative, "Cannot perform full-text search in repo #{name} because it's missing Algolia config" if download_file('AlgoliaSearch.yml').nil?
|
297
|
+
algolia_config = YAMLHelper.load_string(local_file('AlgoliaSearch.yml', &:read))
|
298
|
+
|
299
|
+
client = Algolia::Client.new(:application_id => algolia_config['application_id'], :api_key => algolia_config['api_key'])
|
300
|
+
Algolia::Index.new(algolia_config['index'], client)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
264
304
|
def index_file_name_for_fragment(fragment)
|
265
305
|
fragment_joined = fragment.join('_')
|
266
306
|
fragment_joined = '_' + fragment_joined unless fragment.empty?
|
@@ -305,18 +345,20 @@ module Pod
|
|
305
345
|
etag = File.read(etag_path) if File.exist?(etag_path)
|
306
346
|
debug "CDN: #{name} Relative path: #{partial_url}, has ETag? #{etag}" unless etag.nil?
|
307
347
|
|
308
|
-
|
348
|
+
download_retrying_retryable_errors(partial_url, file_remote_url, etag)
|
309
349
|
end
|
310
350
|
|
311
|
-
def
|
351
|
+
def download_retrying_retryable_errors(partial_url, file_remote_url, etag, retries = MAX_NUMBER_OF_RETRIES)
|
312
352
|
path = repo + partial_url
|
313
353
|
etag_path = path.sub_ext(path.extname + '.etag')
|
314
354
|
|
315
|
-
response = download_retrying_connection_errors(partial_url, file_remote_url, etag)
|
355
|
+
response = download_retrying_connection_errors(partial_url, file_remote_url, etag, retries)
|
316
356
|
|
317
357
|
case response.status_code
|
318
358
|
when 301
|
319
|
-
|
359
|
+
redirect_location = response.headers['location'].first
|
360
|
+
debug "CDN: #{name} Redirecting from #{file_remote_url} to #{redirect_location}"
|
361
|
+
download_retrying_retryable_errors(partial_url, redirect_location, etag)
|
320
362
|
when 304
|
321
363
|
debug "CDN: #{name} Relative path not modified: #{partial_url}"
|
322
364
|
# We need to update the file modification date, as it is later used for freshness
|
@@ -333,16 +375,32 @@ module Pod
|
|
333
375
|
when 404
|
334
376
|
debug "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.status_code}"
|
335
377
|
nil
|
378
|
+
when 502, 503, 504
|
379
|
+
if retries <= 1
|
380
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.status_code}"
|
381
|
+
else
|
382
|
+
sleep_for(backoff_time(retries))
|
383
|
+
download_retrying_retryable_errors(partial_url, file_remote_url, etag, retries - 1)
|
384
|
+
end
|
336
385
|
else
|
337
|
-
raise Informative, "CDN: #{name}
|
386
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.status_code}"
|
338
387
|
end
|
339
388
|
end
|
340
389
|
|
341
|
-
def
|
390
|
+
def backoff_time(retries)
|
391
|
+
current_retry = MAX_NUMBER_OF_RETRIES - retries
|
392
|
+
4 * 2**current_retry
|
393
|
+
end
|
394
|
+
|
395
|
+
def sleep_for(seconds)
|
396
|
+
sleep(seconds)
|
397
|
+
end
|
398
|
+
|
399
|
+
def download_retrying_connection_errors(partial_url, file_remote_url, etag, retries)
|
342
400
|
etag.nil? ? REST.get(file_remote_url) : REST.get(file_remote_url, 'If-None-Match' => etag)
|
343
401
|
rescue REST::Error => e
|
344
|
-
if retries <=
|
345
|
-
raise Informative, "CDN: #{name}
|
402
|
+
if retries <= 1
|
403
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url}, error: #{e}"
|
346
404
|
else
|
347
405
|
debug "CDN: #{name} Relative path: #{partial_url} error: #{e} - retrying"
|
348
406
|
download_retrying_connection_errors(partial_url, file_remote_url, etag, retries - 1)
|
@@ -69,20 +69,6 @@ module Pod
|
|
69
69
|
#
|
70
70
|
# Dependency.new('Artsy+UILabels', '~> 1.0', :source => 'https://github.com/Artsy/Specs.git')
|
71
71
|
#
|
72
|
-
# @overload initialize(name, is_head)
|
73
|
-
#
|
74
|
-
# @param [String] name
|
75
|
-
# the name of the Pod.
|
76
|
-
#
|
77
|
-
# @param [Symbol] is_head
|
78
|
-
# a symbol that can be `:head` or nil.
|
79
|
-
#
|
80
|
-
# @todo Remove `:head` code once everyone has migrated past CocoaPods 1.0.
|
81
|
-
#
|
82
|
-
# @example Initialization with the head option
|
83
|
-
#
|
84
|
-
# Dependency.new('RestKit', :head)
|
85
|
-
#
|
86
72
|
def initialize(name = nil, *requirements)
|
87
73
|
if requirements.last.is_a?(Hash)
|
88
74
|
additional_params = requirements.pop.select { |_, v| !v.nil? }
|
@@ -122,10 +108,6 @@ module Pod
|
|
122
108
|
# @return [Requirement] the requirement of this dependency (a set of
|
123
109
|
# one or more version restrictions).
|
124
110
|
#
|
125
|
-
# @todo The specific version is stripped from head information because
|
126
|
-
# because its string representation would not parse. It would
|
127
|
-
# be better to add something like Version#display_string.
|
128
|
-
#
|
129
111
|
def requirement
|
130
112
|
if specific_version
|
131
113
|
Requirement.new(Version.new(specific_version.version))
|
@@ -291,8 +273,8 @@ module Pod
|
|
291
273
|
# @return [Bool] Whether the dependency has any pre-release requirements
|
292
274
|
#
|
293
275
|
def prerelease?
|
294
|
-
@prerelease
|
295
|
-
|
276
|
+
return @prerelease if defined?(@prerelease)
|
277
|
+
@prerelease = requirement.requirements.any? { |_op, version| version.prerelease? }
|
296
278
|
end
|
297
279
|
|
298
280
|
# Checks whether the dependency would be satisfied by the specification
|
@@ -357,8 +339,6 @@ module Pod
|
|
357
339
|
# part by clients that need to create a dependency equal to the
|
358
340
|
# original one.
|
359
341
|
#
|
360
|
-
# @todo Remove the `HEAD` code once everyone has migrated past 1.0.
|
361
|
-
#
|
362
342
|
# @return [Dependency] the dependency described by the string.
|
363
343
|
#
|
364
344
|
def self.from_string(string)
|
@@ -367,9 +347,6 @@ module Pod
|
|
367
347
|
version = match_data[2]
|
368
348
|
version = version.gsub(/[()]/, '') if version
|
369
349
|
case version
|
370
|
-
when / HEAD( \(based on #{Pod::Version::VERSION_PATTERN}\))?/
|
371
|
-
CoreUI.warn "Ignoring obsolete `HEAD` specifier in `#{string}`"
|
372
|
-
Dependency.new(name)
|
373
350
|
when nil, /from `(.*)(`|')/
|
374
351
|
Dependency.new(name)
|
375
352
|
else
|
data/lib/cocoapods-core/http.rb
CHANGED
@@ -8,11 +8,11 @@ module Pod
|
|
8
8
|
#
|
9
9
|
# @return [string]
|
10
10
|
#
|
11
|
-
def self.get_actual_url(url)
|
11
|
+
def self.get_actual_url(url, user_agent = nil)
|
12
12
|
redirects = 0
|
13
13
|
|
14
14
|
loop do
|
15
|
-
response = perform_head_request(url)
|
15
|
+
response = perform_head_request(url, user_agent)
|
16
16
|
|
17
17
|
if [301, 302, 303, 307, 308].include? response.status_code
|
18
18
|
location = response.headers['location'].first
|
@@ -38,12 +38,12 @@ module Pod
|
|
38
38
|
#
|
39
39
|
# @return [REST::response]
|
40
40
|
#
|
41
|
-
def self.validate_url(url)
|
41
|
+
def self.validate_url(url, user_agent = nil)
|
42
42
|
return nil unless url =~ /^#{URI.regexp}$/
|
43
43
|
|
44
44
|
begin
|
45
|
-
url = get_actual_url(url)
|
46
|
-
resp = perform_head_request(url)
|
45
|
+
url = get_actual_url(url, user_agent)
|
46
|
+
resp = perform_head_request(url, user_agent)
|
47
47
|
rescue SocketError, URI::InvalidURIError, REST::Error, REST::Error::Connection
|
48
48
|
resp = nil
|
49
49
|
end
|
@@ -59,17 +59,19 @@ module Pod
|
|
59
59
|
#
|
60
60
|
# @return [REST::response]
|
61
61
|
#
|
62
|
-
def self.perform_head_request(url)
|
62
|
+
def self.perform_head_request(url, user_agent)
|
63
63
|
require 'rest'
|
64
64
|
|
65
|
-
|
65
|
+
user_agent ||= USER_AGENT
|
66
|
+
|
67
|
+
resp = ::REST.head(url, 'User-Agent' => user_agent)
|
66
68
|
|
67
69
|
if resp.status_code >= 400
|
68
|
-
resp = ::REST.get(url, 'User-Agent' =>
|
70
|
+
resp = ::REST.get(url, 'User-Agent' => user_agent,
|
69
71
|
'Range' => 'bytes=0-0')
|
70
72
|
|
71
73
|
if resp.status_code >= 400
|
72
|
-
resp = ::REST.get(url, 'User-Agent' =>
|
74
|
+
resp = ::REST.get(url, 'User-Agent' => user_agent)
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
@@ -489,7 +489,7 @@ module Pod
|
|
489
489
|
next unless source
|
490
490
|
next if specs.empty?
|
491
491
|
key = source.url || source.name
|
492
|
-
key =
|
492
|
+
key = Pod::TrunkSource::TRUNK_REPO_NAME if source.name == Pod::TrunkSource::TRUNK_REPO_NAME
|
493
493
|
value = specs.map { |s| s.root.name }.uniq
|
494
494
|
[key, YAMLHelper.sorted_array(value)]
|
495
495
|
end.compact]
|
@@ -687,6 +687,39 @@ module Pod
|
|
687
687
|
current_target_definition.use_frameworks!(flag)
|
688
688
|
end
|
689
689
|
|
690
|
+
# Specifies the Swift version requirements this target definition supports.
|
691
|
+
#
|
692
|
+
# **Note** These requirements are inherited from the parent, if specified and if none
|
693
|
+
# are specified at the root level then all versions are considered to be supported.
|
694
|
+
#
|
695
|
+
# @param [String, Version, Array<String>, Array<Version>] requirements
|
696
|
+
# The set of requirements this target supports.
|
697
|
+
#
|
698
|
+
# @example
|
699
|
+
#
|
700
|
+
# target 'MyApp' do
|
701
|
+
# supports_swift_versions '>= 3.0', '< 4.0'
|
702
|
+
# pod 'AFNetworking', '~> 1.0'
|
703
|
+
# end
|
704
|
+
#
|
705
|
+
# @example
|
706
|
+
#
|
707
|
+
# supports_swift_versions '>= 3.0', '< 4.0'
|
708
|
+
#
|
709
|
+
# target 'MyApp' do
|
710
|
+
# pod 'AFNetworking', '~> 1.0'
|
711
|
+
# end
|
712
|
+
#
|
713
|
+
# target 'ZipApp' do
|
714
|
+
# pod 'SSZipArchive'
|
715
|
+
# end
|
716
|
+
#
|
717
|
+
# @return [void]
|
718
|
+
#
|
719
|
+
def supports_swift_versions(*requirements)
|
720
|
+
current_target_definition.store_swift_version_requirements(*requirements)
|
721
|
+
end
|
722
|
+
|
690
723
|
#-----------------------------------------------------------------------#
|
691
724
|
|
692
725
|
# @!group Workspace
|
@@ -869,39 +902,6 @@ module Pod
|
|
869
902
|
raise Informative, 'Specifying multiple `post_install` hooks is unsupported.' if @post_install_callback
|
870
903
|
@post_install_callback = block
|
871
904
|
end
|
872
|
-
|
873
|
-
# Specifies the Swift version requirements this target definition supports.
|
874
|
-
#
|
875
|
-
# **Note** These requirements are inherited from the parent, if specified and if none
|
876
|
-
# are specified at the root level then all versions are considered to be supported.
|
877
|
-
#
|
878
|
-
# @param [String, Version, Array<String>, Array<Version>] requirements
|
879
|
-
# The set of requirements this target supports.
|
880
|
-
#
|
881
|
-
# @example
|
882
|
-
#
|
883
|
-
# target 'MyApp' do
|
884
|
-
# supports_swift_versions '>= 3.0', '< 4.0'
|
885
|
-
# pod 'AFNetworking', '~> 1.0'
|
886
|
-
# end
|
887
|
-
#
|
888
|
-
# @example
|
889
|
-
#
|
890
|
-
# supports_swift_versions '>= 3.0', '< 4.0'
|
891
|
-
#
|
892
|
-
# target 'MyApp' do
|
893
|
-
# pod 'AFNetworking', '~> 1.0'
|
894
|
-
# end
|
895
|
-
#
|
896
|
-
# target 'ZipApp' do
|
897
|
-
# pod 'SSZipArchive'
|
898
|
-
# end
|
899
|
-
#
|
900
|
-
# @return [void]
|
901
|
-
#
|
902
|
-
def supports_swift_versions(*requirements)
|
903
|
-
current_target_definition.store_swift_version_requirements(*requirements)
|
904
|
-
end
|
905
905
|
end
|
906
906
|
end
|
907
907
|
end
|
@@ -296,6 +296,20 @@ module Pod
|
|
296
296
|
|
297
297
|
#--------------------------------------#
|
298
298
|
|
299
|
+
# @return [String] The project name to use for the given pod name or `nil` if none specified.
|
300
|
+
#
|
301
|
+
# @note When querying for a subspec then use the root pod spec name instead as this is what's stored.
|
302
|
+
#
|
303
|
+
def project_name_for_pod(pod_name)
|
304
|
+
if root?
|
305
|
+
raw_project_names_hash[pod_name]
|
306
|
+
else
|
307
|
+
raw_project_names_hash[pod_name] || parent.project_name_for_pod(pod_name)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
#--------------------------------------#
|
312
|
+
#
|
299
313
|
# @return [Bool] whether the target definition should inhibit warnings
|
300
314
|
# for a single pod. If inhibit_all_warnings is true, it will
|
301
315
|
# return true for any asked pod.
|
@@ -666,6 +680,7 @@ module Pod
|
|
666
680
|
parse_inhibit_warnings(name, requirements)
|
667
681
|
parse_modular_headers(name, requirements)
|
668
682
|
parse_configuration_whitelist(name, requirements)
|
683
|
+
parse_project_name(name, requirements)
|
669
684
|
|
670
685
|
if requirements && !requirements.empty?
|
671
686
|
pod = { name => requirements }
|
@@ -769,6 +784,7 @@ module Pod
|
|
769
784
|
use_modular_headers
|
770
785
|
user_project_path
|
771
786
|
build_configurations
|
787
|
+
project_names
|
772
788
|
dependencies
|
773
789
|
script_phases
|
774
790
|
children
|
@@ -1041,6 +1057,33 @@ module Pod
|
|
1041
1057
|
requirements.pop if options.empty?
|
1042
1058
|
end
|
1043
1059
|
|
1060
|
+
# Removes :project_name from the requirements list, and adds
|
1061
|
+
# the pods name into internal hash.
|
1062
|
+
#
|
1063
|
+
# @param [String] name The name of the pod
|
1064
|
+
#
|
1065
|
+
# @param [Array] requirements
|
1066
|
+
# If :project_name is the only key in the hash, the hash
|
1067
|
+
# should be destroyed because it confuses Gem::Dependency.
|
1068
|
+
#
|
1069
|
+
# @return [void]
|
1070
|
+
#
|
1071
|
+
def parse_project_name(name, requirements)
|
1072
|
+
options = requirements.last
|
1073
|
+
return requirements unless options.is_a?(Hash)
|
1074
|
+
|
1075
|
+
project_name = options.delete(:project_name)
|
1076
|
+
pod_name = Specification.root_name(name)
|
1077
|
+
raw_project_names_hash[pod_name] = project_name if project_name
|
1078
|
+
|
1079
|
+
requirements.pop if options.empty?
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
def raw_project_names_hash
|
1083
|
+
get_hash_value('project_names', {})
|
1084
|
+
end
|
1085
|
+
private :raw_project_names_hash
|
1086
|
+
|
1044
1087
|
# Removes :configurations or :configuration from the requirements list,
|
1045
1088
|
# and adds the pod's name into the internal hash for which pods should be
|
1046
1089
|
# linked in which configuration only.
|
@@ -16,6 +16,9 @@ module Pod
|
|
16
16
|
# "#{SPEC_NAME}/#{VERSION}/#{SPEC_NAME}.podspec"
|
17
17
|
#
|
18
18
|
class Source
|
19
|
+
# The default branch in which the specs are stored
|
20
|
+
DEFAULT_SPECS_BRANCH = 'master'.freeze
|
21
|
+
|
19
22
|
# @return [Pod::Source::Metadata] The metadata for this source.
|
20
23
|
#
|
21
24
|
attr_reader :metadata
|
@@ -55,7 +58,7 @@ module Pod
|
|
55
58
|
# @return [String] The type of the source.
|
56
59
|
#
|
57
60
|
def type
|
58
|
-
'file system'
|
61
|
+
git? ? 'git' : 'file system'
|
59
62
|
end
|
60
63
|
|
61
64
|
alias_method :to_s, :name
|
@@ -353,8 +356,16 @@ module Pod
|
|
353
356
|
diff_until_commit_hash(prev_commit_hash)
|
354
357
|
end
|
355
358
|
|
359
|
+
def updateable?
|
360
|
+
git?
|
361
|
+
end
|
362
|
+
|
356
363
|
def git?
|
357
|
-
!repo_git(%w(rev-parse HEAD)).empty?
|
364
|
+
repo.join('.git').exist? && !repo_git(%w(rev-parse HEAD)).empty?
|
365
|
+
end
|
366
|
+
|
367
|
+
def indexable?
|
368
|
+
true
|
358
369
|
end
|
359
370
|
|
360
371
|
def verify_compatibility!
|
@@ -435,7 +446,7 @@ module Pod
|
|
435
446
|
|
436
447
|
def git_tracking_branch
|
437
448
|
path = repo.join('.git', 'cocoapods_branch')
|
438
|
-
path.file? ? path.read.strip :
|
449
|
+
path.file? ? path.read.strip : DEFAULT_SPECS_BRANCH
|
439
450
|
end
|
440
451
|
|
441
452
|
def diff_until_commit_hash(commit_hash)
|
@@ -58,10 +58,17 @@ module Pod
|
|
58
58
|
aggregate.sources
|
59
59
|
end
|
60
60
|
|
61
|
+
# @return [Array<Source>] The list of all the non-indexable sources known to this
|
62
|
+
# installation of CocoaPods.
|
63
|
+
#
|
64
|
+
def all_non_indexable
|
65
|
+
aggregate.sources.reject(&:indexable?)
|
66
|
+
end
|
67
|
+
|
61
68
|
# @return [Array<Source>] The CocoaPods Master Repo source.
|
62
69
|
#
|
63
70
|
def master
|
64
|
-
sources([Pod::
|
71
|
+
sources([Pod::TrunkSource::TRUNK_REPO_NAME]).select { |s| s.repo.directory? }
|
65
72
|
end
|
66
73
|
|
67
74
|
# @!group Master repo
|
@@ -69,7 +76,7 @@ module Pod
|
|
69
76
|
# @return [Pathname] The path of the master repo.
|
70
77
|
#
|
71
78
|
def master_repo_dir
|
72
|
-
source_dir(Pod::
|
79
|
+
source_dir(Pod::TrunkSource::TRUNK_REPO_NAME)
|
73
80
|
end
|
74
81
|
|
75
82
|
# @return [Bool] Checks if the master repo is usable.
|
@@ -122,9 +129,15 @@ module Pod
|
|
122
129
|
end
|
123
130
|
found_set_names = query_word_results_hash.values.reduce(:&)
|
124
131
|
found_set_names ||= []
|
132
|
+
|
133
|
+
sets_from_non_indexable = all_non_indexable.map { |s| s.search_by_name(query, true) }.flatten
|
134
|
+
|
135
|
+
found_set_names += sets_from_non_indexable.map(&:name).flatten.uniq
|
136
|
+
|
125
137
|
sets = found_set_names.map do |name|
|
126
138
|
aggregate.representative_set(name)
|
127
139
|
end
|
140
|
+
|
128
141
|
# Remove nil values because representative_set return nil if no pod is found in any of the sources.
|
129
142
|
sets.compact!
|
130
143
|
else
|
@@ -182,7 +195,7 @@ module Pod
|
|
182
195
|
#
|
183
196
|
def updated_search_index
|
184
197
|
index = stored_search_index || {}
|
185
|
-
|
198
|
+
indexable_sources.each do |source|
|
186
199
|
source_name = source.name
|
187
200
|
unless index[source_name]
|
188
201
|
CoreUI.print "Creating search index for spec repo '#{source_name}'.."
|
@@ -203,6 +216,7 @@ module Pod
|
|
203
216
|
search_index = stored_search_index
|
204
217
|
return unless search_index
|
205
218
|
changed_spec_paths.each_pair do |source, spec_paths|
|
219
|
+
next unless source.indexable?
|
206
220
|
index_for_source = search_index[source.name]
|
207
221
|
next unless index_for_source && !spec_paths.empty?
|
208
222
|
updated_pods = source.pods_for_specification_paths(spec_paths)
|
@@ -290,10 +304,10 @@ module Pod
|
|
290
304
|
def source_from_path(path)
|
291
305
|
@sources_by_path ||= Hash.new do |hash, key|
|
292
306
|
hash[key] = case
|
307
|
+
when key.basename.to_s == Pod::TrunkSource::TRUNK_REPO_NAME
|
308
|
+
TrunkSource.new(key)
|
293
309
|
when (key + '.url').exist?
|
294
310
|
CDNSource.new(key)
|
295
|
-
when key.basename.to_s == Pod::MasterSource::MASTER_REPO_NAME
|
296
|
-
MasterSource.new(key)
|
297
311
|
else
|
298
312
|
Source.new(key)
|
299
313
|
end
|
@@ -312,27 +326,33 @@ module Pod
|
|
312
326
|
@aggregates_by_repos[repos] ||= Source::Aggregate.new(sources)
|
313
327
|
end
|
314
328
|
|
315
|
-
# @return [Source] The
|
329
|
+
# @return [Source] The updateable source with the given name. If no updateable source
|
316
330
|
# with given name is found it raises.
|
317
331
|
#
|
318
332
|
# @param [String] name
|
319
333
|
# The name of the source.
|
320
334
|
#
|
321
|
-
def
|
335
|
+
def updateable_source_named(name)
|
322
336
|
specified_source = sources([name]).first
|
323
337
|
unless specified_source
|
324
338
|
raise Informative, "Unable to find the `#{name}` repo."
|
325
339
|
end
|
326
|
-
unless specified_source.
|
327
|
-
raise Informative, "The `#{name}` repo is not a
|
340
|
+
unless specified_source.updateable?
|
341
|
+
raise Informative, "The `#{name}` repo is not a updateable repo."
|
328
342
|
end
|
329
343
|
specified_source
|
330
344
|
end
|
331
345
|
|
332
|
-
# @return [Source] The list of the
|
346
|
+
# @return [Source] The list of the updateable sources.
|
333
347
|
#
|
334
|
-
def
|
335
|
-
all.select(&:
|
348
|
+
def updateable_sources
|
349
|
+
all.select(&:updateable?)
|
350
|
+
end
|
351
|
+
|
352
|
+
# @return [Source] The list of the indexable sources.
|
353
|
+
#
|
354
|
+
def indexable_sources
|
355
|
+
all.select(&:indexable?)
|
336
356
|
end
|
337
357
|
|
338
358
|
# @return [Pathname] The path of the source with the given name.
|
@@ -350,13 +370,17 @@ module Pod
|
|
350
370
|
# The URL of the source.
|
351
371
|
#
|
352
372
|
def source_with_url(url)
|
353
|
-
url = url
|
373
|
+
url = canonic_url(url)
|
354
374
|
url = 'https://github.com/cocoapods/specs' if url =~ %r{github.com[:/]+cocoapods/specs}
|
355
375
|
all.find do |source|
|
356
|
-
source.url && source.url
|
376
|
+
source.url && canonic_url(source.url) == url
|
357
377
|
end
|
358
378
|
end
|
359
379
|
|
380
|
+
def canonic_url(url)
|
381
|
+
url.downcase.gsub(/\.git$/, '').gsub(%r{\/$}, '')
|
382
|
+
end
|
383
|
+
|
360
384
|
# Returns a suitable repository name for `url`.
|
361
385
|
#
|
362
386
|
# @example A GitHub.com URL
|
@@ -394,8 +418,8 @@ module Pod
|
|
394
418
|
end
|
395
419
|
|
396
420
|
case url.to_s.downcase
|
397
|
-
when %r{
|
398
|
-
base = Pod::
|
421
|
+
when %r{https://#{Regexp.quote(trunk_repo_hostname)}}i
|
422
|
+
base = Pod::TrunkSource::TRUNK_REPO_NAME
|
399
423
|
when %r{github.com[:/]+(.+)/(.+)}
|
400
424
|
base = Regexp.last_match[1]
|
401
425
|
when %r{^\S+@(\S+)[:/]+(.+)$}
|
@@ -416,6 +440,12 @@ module Pod
|
|
416
440
|
end
|
417
441
|
name
|
418
442
|
end
|
443
|
+
|
444
|
+
# Returns hostname for for `trunk` URL.
|
445
|
+
#
|
446
|
+
def trunk_repo_hostname
|
447
|
+
URI.parse(TrunkSource::TRUNK_REPO_URL).host.downcase.freeze
|
448
|
+
end
|
419
449
|
end
|
420
450
|
end
|
421
451
|
end
|
@@ -125,8 +125,9 @@ module Pod
|
|
125
125
|
# clients.
|
126
126
|
#
|
127
127
|
def to_s
|
128
|
-
|
129
|
-
|
128
|
+
specified_version = raw_version || ''
|
129
|
+
if name && !specified_version.empty?
|
130
|
+
"#{name} (#{specified_version})"
|
130
131
|
elsif name
|
131
132
|
name
|
132
133
|
else
|
@@ -203,6 +204,13 @@ module Pod
|
|
203
204
|
gsub(/[^a-zA-Z0-9_]/, '_').gsub(/_+/, '_')
|
204
205
|
end
|
205
206
|
|
207
|
+
# @return [Object, Nil]
|
208
|
+
# the raw value specified for the version attribute, or nil
|
209
|
+
#
|
210
|
+
def raw_version
|
211
|
+
root.attributes_hash['version']
|
212
|
+
end
|
213
|
+
|
206
214
|
#-------------------------------------------------------------------------#
|
207
215
|
|
208
216
|
public
|
@@ -435,6 +443,12 @@ module Pod
|
|
435
443
|
Specification.convert_keys_to_symbol(value, :recursive => false)
|
436
444
|
end
|
437
445
|
|
446
|
+
# @return [Hash] The Info.plist value.
|
447
|
+
#
|
448
|
+
def info_plist
|
449
|
+
attributes_hash['info_plist'] || {}
|
450
|
+
end
|
451
|
+
|
438
452
|
#-------------------------------------------------------------------------#
|
439
453
|
|
440
454
|
public
|
@@ -689,18 +703,18 @@ module Pod
|
|
689
703
|
def self.from_string(spec_contents, path, subspec_name = nil)
|
690
704
|
path = Pathname.new(path).expand_path
|
691
705
|
spec = nil
|
692
|
-
|
693
|
-
|
694
|
-
|
706
|
+
case path.extname
|
707
|
+
when '.podspec'
|
708
|
+
Dir.chdir(path.parent.directory? ? path.parent : Dir.pwd) do
|
695
709
|
spec = ::Pod._eval_podspec(spec_contents, path)
|
696
710
|
unless spec.is_a?(Specification)
|
697
711
|
raise Informative, "Invalid podspec file at path `#{path}`."
|
698
712
|
end
|
699
|
-
when '.json'
|
700
|
-
spec = Specification.from_json(spec_contents)
|
701
|
-
else
|
702
|
-
raise Informative, "Unsupported specification format `#{path.extname}` for spec at `#{path}`."
|
703
713
|
end
|
714
|
+
when '.json'
|
715
|
+
spec = Specification.from_json(spec_contents)
|
716
|
+
else
|
717
|
+
raise Informative, "Unsupported specification format `#{path.extname}` for spec at `#{path}`."
|
704
718
|
end
|
705
719
|
|
706
720
|
spec.defined_in_file = path
|
@@ -110,6 +110,10 @@ module Pod
|
|
110
110
|
merge_values(attr, value_for_attribute(:xcconfig), value_for_attribute(:user_target_xcconfig))
|
111
111
|
end
|
112
112
|
|
113
|
+
# @return [Hash{String => String}] the Info.plist values for the current specification
|
114
|
+
#
|
115
|
+
spec_attr_accessor :info_plist
|
116
|
+
|
113
117
|
# @return [String] The contents of the prefix header.
|
114
118
|
#
|
115
119
|
spec_attr_accessor :prefix_header_contents
|
@@ -144,6 +148,10 @@ module Pod
|
|
144
148
|
spec_attr_accessor :requires_app_host
|
145
149
|
alias_method :requires_app_host?, :requires_app_host
|
146
150
|
|
151
|
+
# @return [String] Name of the app host this spec requires
|
152
|
+
#
|
153
|
+
spec_attr_accessor :app_host_name
|
154
|
+
|
147
155
|
# @return [Symbol] the test type supported by this specification.
|
148
156
|
#
|
149
157
|
spec_attr_accessor :test_type
|
@@ -309,12 +317,7 @@ module Pod
|
|
309
317
|
r.compact
|
310
318
|
elsif attr.container == Hash
|
311
319
|
existing_value.merge(new_value) do |_, old, new|
|
312
|
-
|
313
|
-
r = [*old] + [*new]
|
314
|
-
r.compact
|
315
|
-
else
|
316
|
-
old + ' ' + new
|
317
|
-
end
|
320
|
+
merge_hash_value(attr, old, new)
|
318
321
|
end
|
319
322
|
else
|
320
323
|
new_value
|
@@ -349,6 +352,35 @@ module Pod
|
|
349
352
|
end
|
350
353
|
end
|
351
354
|
|
355
|
+
private
|
356
|
+
|
357
|
+
# Merges two values in a hash together based on the needs of the attribute
|
358
|
+
#
|
359
|
+
# @param [Specification::DSL::Attribute] attr
|
360
|
+
# the attribute for which that value is needed.
|
361
|
+
#
|
362
|
+
# @param [Object] old the value from the original hash
|
363
|
+
#
|
364
|
+
# @param [Object] new the value from the new hash
|
365
|
+
#
|
366
|
+
# @return [Object] the merged value
|
367
|
+
#
|
368
|
+
def merge_hash_value(attr, old, new)
|
369
|
+
case attr.name
|
370
|
+
when :info_plist
|
371
|
+
new
|
372
|
+
when ->(name) { spec.non_library_specification? && [:pod_target_xcconfig, :user_target_xcconfig, :xcconfig].include?(name) }
|
373
|
+
new
|
374
|
+
else
|
375
|
+
if new.is_a?(Array) || old.is_a?(Array)
|
376
|
+
r = Array(old) + Array(new)
|
377
|
+
r.compact
|
378
|
+
else
|
379
|
+
old + ' ' + new
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
352
384
|
# @!group Preparing Values
|
353
385
|
#-----------------------------------------------------------------------#
|
354
386
|
|
@@ -305,7 +305,7 @@ module Pod
|
|
305
305
|
:git => [:tag, :branch, :commit, :submodules].freeze,
|
306
306
|
:svn => [:folder, :tag, :revision].freeze,
|
307
307
|
:hg => [:revision].freeze,
|
308
|
-
:http => [:flatten, :type, :sha256, :sha1].freeze,
|
308
|
+
:http => [:flatten, :type, :sha256, :sha1, :headers].freeze,
|
309
309
|
}.freeze
|
310
310
|
|
311
311
|
# @!method source=(source)
|
@@ -704,6 +704,39 @@ module Pod
|
|
704
704
|
|
705
705
|
#------------------#
|
706
706
|
|
707
|
+
# @!method info_plist=(info_plist)
|
708
|
+
#
|
709
|
+
# Key-Value pairs to add to the generated `Info.plist`.
|
710
|
+
#
|
711
|
+
# The values will be merged with the default values that
|
712
|
+
# CocoaPods generates, overriding any duplicates.
|
713
|
+
#
|
714
|
+
# For library specs, the values will be merged into the generated Info.plist
|
715
|
+
# for libraries that are integrated using frameworks. It will have no effect
|
716
|
+
# for static libraries.
|
717
|
+
#
|
718
|
+
# Subspecs (other than app and test specs) are not supported.
|
719
|
+
#
|
720
|
+
# For app specs, the values will be merged into the application host's `Info.plist`.
|
721
|
+
#
|
722
|
+
# For test specs, the values will be merged into the test bundle's `Info.plist`.
|
723
|
+
#
|
724
|
+
# @example
|
725
|
+
#
|
726
|
+
# spec.info_plist = {
|
727
|
+
# 'CFBundleIdentifier' => 'com.myorg.MyLib',
|
728
|
+
# 'MY_VAR' => 'SOME_VALUE'
|
729
|
+
# }
|
730
|
+
#
|
731
|
+
# @param [Hash] info_plist
|
732
|
+
# The Info.plist values for the Pod.
|
733
|
+
#
|
734
|
+
attribute :info_plist,
|
735
|
+
:container => Hash,
|
736
|
+
:inherited => false
|
737
|
+
|
738
|
+
#------------------#
|
739
|
+
|
707
740
|
# @!method requires_arc=(flag)
|
708
741
|
#
|
709
742
|
# `requires_arc` allows you to specify which source_files use ARC.
|
@@ -1155,7 +1188,8 @@ module Pod
|
|
1155
1188
|
#
|
1156
1189
|
# ---
|
1157
1190
|
#
|
1158
|
-
# These are
|
1191
|
+
# These patterns are matched against the source files to include headers
|
1192
|
+
# that will be exposed to the user’s project and
|
1159
1193
|
# from which documentation will be generated. When the library is built,
|
1160
1194
|
# these headers will appear in the build directory. If no public headers
|
1161
1195
|
# are specified then **all** the headers in source_files are considered
|
@@ -1470,7 +1504,7 @@ module Pod
|
|
1470
1504
|
|
1471
1505
|
# The list of the test types currently supported.
|
1472
1506
|
#
|
1473
|
-
SUPPORTED_TEST_TYPES = [:unit].freeze
|
1507
|
+
SUPPORTED_TEST_TYPES = [:unit, :ui].freeze
|
1474
1508
|
|
1475
1509
|
# The test type this specification supports. This only applies to test specifications.
|
1476
1510
|
#
|
@@ -1508,6 +1542,39 @@ module Pod
|
|
1508
1542
|
:default_value => false,
|
1509
1543
|
:spec_types => [:test]
|
1510
1544
|
|
1545
|
+
# @!method app_host_name=(name)
|
1546
|
+
#
|
1547
|
+
# The app specification to use as an app host, if necessary.
|
1548
|
+
#
|
1549
|
+
# @note
|
1550
|
+
#
|
1551
|
+
# You must depend on that app spec using `test_spec.dependency 'PodName'`.
|
1552
|
+
#
|
1553
|
+
# @example
|
1554
|
+
#
|
1555
|
+
# Pod::Spec.new do |spec|
|
1556
|
+
# spec.name = 'NSAttributedString+CCLFormat'
|
1557
|
+
#
|
1558
|
+
# spec.test_spec do |test_spec|
|
1559
|
+
# test_spec.source_files = 'NSAttributedString+CCLFormatTests.m'
|
1560
|
+
# test_spec.requires_app_host = true
|
1561
|
+
# test_spec.app_host_name = 'NSAttributedString+CCLFormat/App'
|
1562
|
+
# test_spec.dependency 'NSAttributedString+CCLFormat/App'
|
1563
|
+
# end
|
1564
|
+
#
|
1565
|
+
# spec.app_spec 'App' do |app_spec|
|
1566
|
+
# app_spec.source_files = 'NSAttributedString+CCLFormat.m'
|
1567
|
+
# app_spec.dependency 'AFNetworking'
|
1568
|
+
# end
|
1569
|
+
# end
|
1570
|
+
#
|
1571
|
+
# @param [String] name
|
1572
|
+
# The app specification to use as an app host, if necessary.
|
1573
|
+
#
|
1574
|
+
attribute :app_host_name,
|
1575
|
+
:types => [String],
|
1576
|
+
:spec_types => [:test]
|
1577
|
+
|
1511
1578
|
SCHEME_KEYS = [:launch_arguments, :environment_variables].freeze
|
1512
1579
|
|
1513
1580
|
# @!method scheme=(flag)
|
@@ -121,15 +121,19 @@ module Pod
|
|
121
121
|
def check_required_attributes
|
122
122
|
attributes = DSL.attributes.values.select(&:required?)
|
123
123
|
attributes.each do |attr|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
124
|
+
begin
|
125
|
+
value = spec.send(attr.name)
|
126
|
+
unless value && (!value.respond_to?(:empty?) || !value.empty?)
|
127
|
+
if attr.name == :license
|
128
|
+
results.add_warning('attributes', 'Missing required attribute ' \
|
129
|
+
"`#{attr.name}`.")
|
130
|
+
else
|
131
|
+
results.add_error('attributes', 'Missing required attribute ' \
|
132
|
+
"`#{attr.name}`.")
|
133
|
+
end
|
132
134
|
end
|
135
|
+
rescue => exception
|
136
|
+
results.add_error('attributes', "Unable to parse attribute `#{attr.name}` due to error: #{exception}")
|
133
137
|
end
|
134
138
|
end
|
135
139
|
end
|
@@ -187,9 +191,13 @@ module Pod
|
|
187
191
|
attributes.each do |attr|
|
188
192
|
validation_hook = "_validate_#{attr.name}"
|
189
193
|
next unless respond_to?(validation_hook, true)
|
190
|
-
|
191
|
-
|
192
|
-
|
194
|
+
begin
|
195
|
+
value = target.send(attr.name)
|
196
|
+
next unless value
|
197
|
+
send(validation_hook, value)
|
198
|
+
rescue => e
|
199
|
+
results.add_error(attr.name, "Unable to validate due to exception: #{e}")
|
200
|
+
end
|
193
201
|
end
|
194
202
|
end
|
195
203
|
|
@@ -350,6 +358,7 @@ module Pod
|
|
350
358
|
# Performs validations related to the `source` attribute.
|
351
359
|
#
|
352
360
|
def _validate_source(s)
|
361
|
+
return unless s.is_a?(Hash)
|
353
362
|
if git = s[:git]
|
354
363
|
tag, commit = s.values_at(:tag, :commit)
|
355
364
|
version = spec.version.to_s
|
@@ -394,6 +403,18 @@ module Pod
|
|
394
403
|
end
|
395
404
|
end
|
396
405
|
|
406
|
+
def _validate_app_host_name(n)
|
407
|
+
unless consumer.requires_app_host?
|
408
|
+
results.add_error('app_host_name', '`requires_app_host` must be set to ' \
|
409
|
+
'`true` when `app_host_name` is specified.')
|
410
|
+
end
|
411
|
+
|
412
|
+
unless consumer.dependencies.map(&:name).include?(n)
|
413
|
+
results.add_error('app_host_name', "The app host name (#{n}) specified by `#{consumer.spec.name}` could " \
|
414
|
+
'not be found. You must explicitly declare a dependency on that app spec.')
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
397
418
|
# Performs validations related to the `script_phases` attribute.
|
398
419
|
#
|
399
420
|
def _validate_script_phases(s)
|
@@ -482,6 +503,15 @@ module Pod
|
|
482
503
|
end
|
483
504
|
end
|
484
505
|
|
506
|
+
# @param [Hash,Object] value
|
507
|
+
#
|
508
|
+
def _validate_info_plist(value)
|
509
|
+
return if value.empty?
|
510
|
+
if consumer.spec.subspec? && consumer.spec.library_specification?
|
511
|
+
results.add_error('info_plist', 'Info.plist configuration is not currently supported for subspecs.')
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
485
515
|
#-----------------------------------------------------------------------#
|
486
516
|
|
487
517
|
# @!group All specs validation helpers
|
@@ -181,6 +181,10 @@ module Pod
|
|
181
181
|
end
|
182
182
|
|
183
183
|
def validate_attribute_hash_keys(attribute, value)
|
184
|
+
unless value.is_a?(Hash)
|
185
|
+
results.add_error(attribute.name, "Unsupported type `#{value.class}`, expected `Hash`")
|
186
|
+
return
|
187
|
+
end
|
184
188
|
major_keys = value.keys & attribute.keys.keys
|
185
189
|
if major_keys.count.zero?
|
186
190
|
results.add_warning('keys', "Missing primary key for `#{attribute.name}` " \
|
@@ -27,11 +27,6 @@ module Pod
|
|
27
27
|
|
28
28
|
# @return [Version] The version of the Pod.
|
29
29
|
#
|
30
|
-
# @todo The version is memoized because the Resolvers sets the head
|
31
|
-
# state on it. This information should be stored in the
|
32
|
-
# specification instance and the lockfile should have a more
|
33
|
-
# robust handling of head versions (like a dedicated section).
|
34
|
-
#
|
35
30
|
def version
|
36
31
|
if root?
|
37
32
|
@version ||= Version.new(attributes_hash['version'])
|
@@ -131,7 +126,12 @@ module Pod
|
|
131
126
|
# should be retrieved.
|
132
127
|
#
|
133
128
|
def source
|
134
|
-
|
129
|
+
value = attributes_hash['source']
|
130
|
+
if value && value.is_a?(Hash)
|
131
|
+
Specification.convert_keys_to_symbol(value)
|
132
|
+
else
|
133
|
+
value
|
134
|
+
end
|
135
135
|
end
|
136
136
|
|
137
137
|
# @return [String] A short description of the Pod.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pod
|
2
|
+
class TrunkSource < CDNSource
|
3
|
+
# On-disk master repo name
|
4
|
+
TRUNK_REPO_NAME = 'trunk'.freeze
|
5
|
+
|
6
|
+
# Remote CDN repo URL
|
7
|
+
TRUNK_REPO_URL = 'https://cdn.cocoapods.org/'.freeze
|
8
|
+
|
9
|
+
def url
|
10
|
+
@url ||= TRUNK_REPO_URL
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -68,7 +68,8 @@ module Pod
|
|
68
68
|
# For more info, see: http://semver.org
|
69
69
|
#
|
70
70
|
def prerelease?
|
71
|
-
@prerelease
|
71
|
+
return @prerelease if defined?(@prerelease)
|
72
|
+
@prerelease = @version =~ /[a-zA-Z\-]/
|
72
73
|
end
|
73
74
|
|
74
75
|
# @return [Bool] Whether a string representation is correct.
|
@@ -205,7 +206,7 @@ module Pod
|
|
205
206
|
compare = proc do |segments, other_segments, is_pre_release|
|
206
207
|
limit = [segments.size, other_segments.size].max
|
207
208
|
|
208
|
-
(
|
209
|
+
0.upto(limit) do |i|
|
209
210
|
lhs = segments[i]
|
210
211
|
rhs = other_segments[i]
|
211
212
|
|
@@ -224,8 +225,6 @@ module Pod
|
|
224
225
|
if comparison = lhs <=> rhs
|
225
226
|
return comparison
|
226
227
|
end
|
227
|
-
return 1 if lhs.is_a?(String) && rhs.is_a?(Numeric)
|
228
|
-
return -1 if lhs.is_a?(Numeric) && rhs.is_a?(String)
|
229
228
|
end
|
230
229
|
end
|
231
230
|
|
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.8.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-08-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -59,6 +59,20 @@ dependencies:
|
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 2.0.4
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: algoliasearch
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
type: :runtime
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
62
76
|
- !ruby/object:Gem::Dependency
|
63
77
|
name: bacon
|
64
78
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,7 +108,6 @@ files:
|
|
94
108
|
- lib/cocoapods-core/github.rb
|
95
109
|
- lib/cocoapods-core/http.rb
|
96
110
|
- lib/cocoapods-core/lockfile.rb
|
97
|
-
- lib/cocoapods-core/master_source.rb
|
98
111
|
- lib/cocoapods-core/metrics.rb
|
99
112
|
- lib/cocoapods-core/platform.rb
|
100
113
|
- lib/cocoapods-core/podfile.rb
|
@@ -122,6 +135,7 @@ files:
|
|
122
135
|
- lib/cocoapods-core/specification/set.rb
|
123
136
|
- lib/cocoapods-core/specification/set/presenter.rb
|
124
137
|
- lib/cocoapods-core/standard_error.rb
|
138
|
+
- lib/cocoapods-core/trunk_source.rb
|
125
139
|
- lib/cocoapods-core/vendor.rb
|
126
140
|
- lib/cocoapods-core/vendor/requirement.rb
|
127
141
|
- lib/cocoapods-core/vendor/version.rb
|
@@ -1,8 +0,0 @@
|
|
1
|
-
module Pod
|
2
|
-
class MasterSource < Source
|
3
|
-
# For now, the MasterSource behaves exactly the same as any other Source.
|
4
|
-
# In the future we may apply separate logic to the MasterSource that doesn't
|
5
|
-
# depend on the file system.
|
6
|
-
MASTER_REPO_NAME = 'master'.freeze
|
7
|
-
end
|
8
|
-
end
|