cocoapods-core 1.8.4 → 1.9.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/cocoapods-core.rb +1 -0
- data/lib/cocoapods-core/build_type.rb +121 -0
- data/lib/cocoapods-core/cdn_source.rb +148 -80
- data/lib/cocoapods-core/gem_version.rb +1 -1
- data/lib/cocoapods-core/platform.rb +4 -0
- data/lib/cocoapods-core/podfile/dsl.rb +31 -3
- data/lib/cocoapods-core/podfile/target_definition.rb +39 -9
- data/lib/cocoapods-core/specification.rb +30 -3
- data/lib/cocoapods-core/specification/dsl.rb +47 -19
- data/lib/cocoapods-core/specification/dsl/attribute_support.rb +2 -2
- data/lib/cocoapods-core/specification/linter.rb +3 -0
- data/lib/cocoapods-core/specification/linter/analyzer.rb +9 -2
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 767b9681ebb1b555c9750c0fb6ceafa498dd5193a5a509e7560e3c395ef7093e
|
4
|
+
data.tar.gz: ad41c838f0582b8ae978b180f35f2cfc32c321dcb47f8f8591abd3843f61598c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6e61b8cd239ea526a301f6a340b043ecc4fa02be1e6985e728bbff0376aea1389f45e689b6bcef170300e80fdde978c48d20392fafa30d9902443e157b42ec9
|
7
|
+
data.tar.gz: 4eb1ba7d93173e723207bfdfb9488d5fda243cdf2c7cba14b76e96a7a46929747f80ed6d7fd5efd6d707faee99433b9846d5d567b290fa52899755e0d4196c93
|
data/lib/cocoapods-core.rb
CHANGED
@@ -0,0 +1,121 @@
|
|
1
|
+
module Pod
|
2
|
+
class BuildType
|
3
|
+
# @return [Array<Symbol>] known packaging options.
|
4
|
+
#
|
5
|
+
KNOWN_PACKAGING_OPTIONS = %i(library framework).freeze
|
6
|
+
|
7
|
+
# @return [Array<Symbol>] known linking options.
|
8
|
+
#
|
9
|
+
KNOWN_LINKAGE_OPTIONS = %i(static dynamic).freeze
|
10
|
+
|
11
|
+
# @return [Symbol] the packaging for this build type, one of #KNOWN_PACKAGING_OPTIONS
|
12
|
+
#
|
13
|
+
attr_reader :packaging
|
14
|
+
|
15
|
+
# @return [Symbol] the linkage for this build type, one of #KNOWN_LINKAGE_OPTIONS
|
16
|
+
#
|
17
|
+
attr_reader :linkage
|
18
|
+
|
19
|
+
attr_reader :hash
|
20
|
+
|
21
|
+
def initialize(linkage: :static, packaging: :library)
|
22
|
+
unless KNOWN_LINKAGE_OPTIONS.include?(linkage)
|
23
|
+
raise ArgumentError, "Invalid linkage option #{linkage.inspect}, valid options are #{KNOWN_LINKAGE_OPTIONS.inspect}"
|
24
|
+
end
|
25
|
+
unless KNOWN_PACKAGING_OPTIONS.include?(packaging)
|
26
|
+
raise ArgumentError, "Invalid packaging option #{packaging.inspect}, valid options are #{KNOWN_PACKAGING_OPTIONS.inspect}"
|
27
|
+
end
|
28
|
+
@packaging = packaging
|
29
|
+
@linkage = linkage
|
30
|
+
@hash = packaging.hash ^ linkage.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [BuildType] the build type for a dynamic library
|
34
|
+
def self.dynamic_library
|
35
|
+
new(:linkage => :dynamic, :packaging => :library)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [BuildType] the build type for a static library
|
39
|
+
#
|
40
|
+
def self.static_library
|
41
|
+
new(:linkage => :static, :packaging => :library)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [BuildType] the build type for a dynamic framework
|
45
|
+
#
|
46
|
+
def self.dynamic_framework
|
47
|
+
new(:linkage => :dynamic, :packaging => :framework)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [BuildType] the build type for a static framework
|
51
|
+
#
|
52
|
+
def self.static_framework
|
53
|
+
new(:linkage => :static, :packaging => :framework)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Boolean] whether the target is built dynamically
|
57
|
+
#
|
58
|
+
def dynamic?
|
59
|
+
linkage == :dynamic
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Boolean] whether the target is built statically
|
63
|
+
#
|
64
|
+
def static?
|
65
|
+
linkage == :static
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Boolean] whether the target is built as a framework
|
69
|
+
#
|
70
|
+
def framework?
|
71
|
+
packaging == :framework
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [Boolean] whether the target is built as a library
|
75
|
+
#
|
76
|
+
def library?
|
77
|
+
packaging == :library
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Boolean] whether the target is built as a dynamic framework
|
81
|
+
#
|
82
|
+
def dynamic_framework?
|
83
|
+
dynamic? && framework?
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [Boolean] whether the target is built as a dynamic library
|
87
|
+
#
|
88
|
+
def dynamic_library?
|
89
|
+
dynamic? && library?
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Boolean] whether the target is built as a static framework
|
93
|
+
#
|
94
|
+
def static_framework?
|
95
|
+
static? && framework?
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Boolean] whether the target is built as a static library
|
99
|
+
#
|
100
|
+
def static_library?
|
101
|
+
static? && library?
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
"#{linkage} #{packaging}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_hash
|
109
|
+
{ :linkage => linkage, :packaging => packaging }
|
110
|
+
end
|
111
|
+
|
112
|
+
def inspect
|
113
|
+
"#<#{self.class} linkage=#{linkage} packaging=#{packaging}>"
|
114
|
+
end
|
115
|
+
|
116
|
+
def ==(other)
|
117
|
+
linkage == other.linkage &&
|
118
|
+
packaging == other.packaging
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
require 'cocoapods-core/source'
|
2
2
|
require 'rest'
|
3
3
|
require 'concurrent'
|
4
|
+
require 'typhoeus'
|
5
|
+
require 'netrc'
|
4
6
|
|
5
7
|
module Pod
|
6
8
|
# Subclass of Pod::Source to provide support for CDN-based Specs repositories
|
7
9
|
#
|
8
10
|
class CDNSource < Source
|
9
|
-
|
11
|
+
include Concurrent
|
12
|
+
|
10
13
|
MAX_NUMBER_OF_RETRIES = (ENV['COCOAPODS_CDN_MAX_NUMBER_OF_RETRIES'] || 5).to_i
|
14
|
+
# Single thread executor for all network activity.
|
15
|
+
HYDRA_EXECUTOR = Concurrent::SingleThreadExecutor.new
|
16
|
+
|
17
|
+
private_constant :HYDRA_EXECUTOR
|
11
18
|
|
12
19
|
# @param [String] repo The name of the repository
|
13
20
|
#
|
@@ -18,12 +25,6 @@ module Pod
|
|
18
25
|
# after the source was initialized, is considered fresh enough.
|
19
26
|
@startup_time = Time.new
|
20
27
|
|
21
|
-
@executor = Concurrent::ThreadPoolExecutor.new(
|
22
|
-
:min_threads => 5,
|
23
|
-
:max_threads => MAX_CDN_NETWORK_THREADS,
|
24
|
-
:max_queue => 0 # unbounded work queue
|
25
|
-
)
|
26
|
-
|
27
28
|
@version_arrays_by_fragment_by_name = {}
|
28
29
|
|
29
30
|
super(repo)
|
@@ -58,14 +59,14 @@ module Pod
|
|
58
59
|
def preheat_existing_files
|
59
60
|
files_to_update = files_definitely_to_update + deprecated_local_podspecs - ['deprecated_podspecs.txt']
|
60
61
|
debug "CDN: #{name} Going to update #{files_to_update.count} files"
|
61
|
-
loaders = files_to_update.map do |file|
|
62
|
-
Concurrent::Promises.future_on(@executor) do
|
63
|
-
download_file(file)
|
64
|
-
end
|
65
|
-
end
|
66
62
|
|
67
|
-
|
68
|
-
|
63
|
+
concurrent_requests_catching_errors do
|
64
|
+
# Queue all tasks first
|
65
|
+
loaders = files_to_update.map do |file|
|
66
|
+
download_file_async(file)
|
67
|
+
end
|
68
|
+
# Block and wait for all to complete running on Hydra
|
69
|
+
Promises.zip_futures_on(HYDRA_EXECUTOR, *loaders).wait!
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
@@ -117,27 +118,30 @@ module Pod
|
|
117
118
|
|
118
119
|
return nil if @version_arrays_by_fragment_by_name[fragment][name].nil?
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
121
|
+
concurrent_requests_catching_errors do
|
122
|
+
loaders = []
|
123
|
+
|
124
|
+
@versions_by_name[name] ||= @version_arrays_by_fragment_by_name[fragment][name].map do |version|
|
125
|
+
# Optimization: ensure all the podspec files at least exist. The correct one will get refreshed
|
126
|
+
# in #specification_path regardless.
|
127
|
+
podspec_version_path_relative = Pathname.new(version).join("#{name}.podspec.json")
|
128
|
+
|
129
|
+
unless pod_path_actual.join(podspec_version_path_relative).exist?
|
130
|
+
# Queue all podspec download tasks first
|
131
|
+
loaders << download_file_async(pod_path_relative.join(podspec_version_path_relative).to_s)
|
128
132
|
end
|
129
|
-
end
|
130
|
-
begin
|
131
|
-
Version.new(version) if version[0, 1] != '.'
|
132
|
-
rescue ArgumentError
|
133
|
-
raise Informative, 'An unexpected version directory ' \
|
134
|
-
"`#{version}` was encountered for the " \
|
135
|
-
"`#{pod_path_actual}` Pod in the `#{name}` repository."
|
136
|
-
end
|
137
|
-
end.compact.sort.reverse
|
138
133
|
|
139
|
-
|
140
|
-
|
134
|
+
begin
|
135
|
+
Version.new(version) if version[0, 1] != '.'
|
136
|
+
rescue ArgumentError
|
137
|
+
raise Informative, 'An unexpected version directory ' \
|
138
|
+
"`#{version}` was encountered for the " \
|
139
|
+
"`#{pod_path_actual}` Pod in the `#{name}` repository."
|
140
|
+
end
|
141
|
+
end.compact.sort.reverse
|
142
|
+
|
143
|
+
# Block and wait for all to complete running on Hydra
|
144
|
+
Promises.zip_futures_on(HYDRA_EXECUTOR, *loaders).wait!
|
141
145
|
end
|
142
146
|
|
143
147
|
@versions_by_name[name]
|
@@ -323,18 +327,25 @@ module Pod
|
|
323
327
|
end
|
324
328
|
|
325
329
|
def download_file(partial_url)
|
330
|
+
# Block the main thread waiting for Hydra to finish
|
331
|
+
#
|
332
|
+
# Used for single-file downloads
|
333
|
+
download_file_async(partial_url).wait!
|
334
|
+
end
|
335
|
+
|
336
|
+
def download_file_async(partial_url)
|
326
337
|
file_remote_url = URI.encode(url + partial_url.to_s)
|
327
338
|
path = repo + partial_url
|
328
339
|
|
329
340
|
if File.exist?(path)
|
330
341
|
if @startup_time < File.mtime(path)
|
331
342
|
debug "CDN: #{name} Relative path: #{partial_url} modified during this run! Returning local"
|
332
|
-
return partial_url
|
343
|
+
return Promises.fulfilled_future(partial_url, HYDRA_EXECUTOR)
|
333
344
|
end
|
334
345
|
|
335
346
|
unless @check_existing_files_for_update
|
336
347
|
debug "CDN: #{name} Relative path: #{partial_url} exists! Returning local because checking is only perfomed in repo update"
|
337
|
-
return partial_url
|
348
|
+
return Promises.fulfilled_future(partial_url, HYDRA_EXECUTOR)
|
338
349
|
end
|
339
350
|
end
|
340
351
|
|
@@ -345,46 +356,68 @@ module Pod
|
|
345
356
|
etag = File.read(etag_path) if File.exist?(etag_path)
|
346
357
|
debug "CDN: #{name} Relative path: #{partial_url}, has ETag? #{etag}" unless etag.nil?
|
347
358
|
|
348
|
-
|
359
|
+
download_and_save_with_retries_async(partial_url, file_remote_url, etag)
|
349
360
|
end
|
350
361
|
|
351
|
-
def
|
362
|
+
def download_and_save_with_retries_async(partial_url, file_remote_url, etag, retries = MAX_NUMBER_OF_RETRIES)
|
352
363
|
path = repo + partial_url
|
353
364
|
etag_path = path.sub_ext(path.extname + '.etag')
|
354
365
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
366
|
+
download_task = download_typhoeus_impl_async(file_remote_url, etag).then do |response|
|
367
|
+
case response.response_code
|
368
|
+
when 301
|
369
|
+
redirect_location = response.headers['location']
|
370
|
+
debug "CDN: #{name} Redirecting from #{file_remote_url} to #{redirect_location}"
|
371
|
+
download_and_save_with_retries_async(partial_url, redirect_location, etag)
|
372
|
+
when 304
|
373
|
+
debug "CDN: #{name} Relative path not modified: #{partial_url}"
|
374
|
+
# We need to update the file modification date, as it is later used for freshness
|
375
|
+
# optimization. See #initialize for more information.
|
376
|
+
FileUtils.touch path
|
377
|
+
partial_url
|
378
|
+
when 200
|
379
|
+
File.open(path, 'w') { |f| f.write(response.response_body) }
|
380
|
+
|
381
|
+
etag_new = response.headers['etag']
|
382
|
+
debug "CDN: #{name} Relative path downloaded: #{partial_url}, save ETag: #{etag_new}"
|
383
|
+
File.open(etag_path, 'w') { |f| f.write(etag_new) } unless etag_new.nil?
|
384
|
+
partial_url
|
385
|
+
when 404
|
386
|
+
debug "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.response_code}"
|
387
|
+
nil
|
388
|
+
when 502, 503, 504
|
389
|
+
# Retryable HTTP errors, usually related to server overloading
|
390
|
+
if retries <= 1
|
391
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}"
|
392
|
+
else
|
393
|
+
debug "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}, retries: #{retries - 1}"
|
394
|
+
exponential_backoff_async(retries).then do
|
395
|
+
download_and_save_with_retries_async(partial_url, file_remote_url, etag, retries - 1)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
when 0
|
399
|
+
# Non-HTTP errors, usually network layer
|
400
|
+
if retries <= 1
|
401
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.return_message}"
|
402
|
+
else
|
403
|
+
debug "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.return_message}, retries: #{retries - 1}"
|
404
|
+
exponential_backoff_async(retries).then do
|
405
|
+
download_and_save_with_retries_async(partial_url, file_remote_url, etag, retries - 1)
|
406
|
+
end
|
407
|
+
end
|
381
408
|
else
|
382
|
-
|
383
|
-
download_retrying_retryable_errors(partial_url, file_remote_url, etag, retries - 1)
|
409
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}"
|
384
410
|
end
|
385
|
-
else
|
386
|
-
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.status_code}"
|
387
411
|
end
|
412
|
+
|
413
|
+
# Calling `Future#run` flattens the chained futures created by retries or redirects
|
414
|
+
#
|
415
|
+
# Does not, in fact, run the task - that is already happening in Hydra at this point
|
416
|
+
download_task.run
|
417
|
+
end
|
418
|
+
|
419
|
+
def exponential_backoff_async(retries)
|
420
|
+
sleep_async(backoff_time(retries))
|
388
421
|
end
|
389
422
|
|
390
423
|
def backoff_time(retries)
|
@@ -392,19 +425,38 @@ module Pod
|
|
392
425
|
4 * 2**current_retry
|
393
426
|
end
|
394
427
|
|
395
|
-
def
|
396
|
-
sleep
|
397
|
-
|
428
|
+
def sleep_async(seconds)
|
429
|
+
# Async sleep to avoid blocking either the main or the Hydra thread
|
430
|
+
Promises.schedule_on(HYDRA_EXECUTOR, seconds)
|
431
|
+
end
|
432
|
+
|
433
|
+
def download_typhoeus_impl_async(file_remote_url, etag)
|
434
|
+
# Create a prefereably HTTP/2 request - the protocol is ultimately responsible for picking
|
435
|
+
# the maximum supported protocol
|
436
|
+
# When debugging with proxy, use the following extra options:
|
437
|
+
# :proxy => 'http://localhost:8888',
|
438
|
+
# :ssl_verifypeer => false,
|
439
|
+
# :ssl_verifyhost => 0,
|
440
|
+
request = Typhoeus::Request.new(
|
441
|
+
file_remote_url,
|
442
|
+
:method => :get,
|
443
|
+
:http_version => :httpv2_0,
|
444
|
+
:timeout => 10,
|
445
|
+
:connecttimeout => 10,
|
446
|
+
:accept_encoding => 'gzip',
|
447
|
+
:netrc => :optional,
|
448
|
+
:netrc_file => Netrc.default_path,
|
449
|
+
:headers => etag.nil? ? {} : { 'If-None-Match' => etag },
|
450
|
+
)
|
398
451
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url}, error: #{e}"
|
404
|
-
else
|
405
|
-
debug "CDN: #{name} Relative path: #{partial_url} error: #{e} - retrying"
|
406
|
-
download_retrying_connection_errors(partial_url, file_remote_url, etag, retries - 1)
|
452
|
+
future = Promises.resolvable_future_on(HYDRA_EXECUTOR)
|
453
|
+
queue_request(request)
|
454
|
+
request.on_complete do |response|
|
455
|
+
future.fulfill(response)
|
407
456
|
end
|
457
|
+
|
458
|
+
# This `Future` should never reject, network errors are exposed on `Typhoeus::Response`
|
459
|
+
future
|
408
460
|
end
|
409
461
|
|
410
462
|
def debug(message)
|
@@ -415,11 +467,27 @@ module Pod
|
|
415
467
|
end
|
416
468
|
end
|
417
469
|
|
418
|
-
def
|
470
|
+
def concurrent_requests_catching_errors
|
419
471
|
yield
|
420
|
-
rescue
|
472
|
+
rescue MultipleErrors => e
|
473
|
+
# aggregated error message from `Concurrent`
|
421
474
|
errors = e.errors
|
422
475
|
raise Informative, "CDN: #{name} Repo update failed - #{e.errors.size} error(s):\n#{errors.join("\n")}"
|
423
476
|
end
|
477
|
+
|
478
|
+
def queue_request(request)
|
479
|
+
@hydra ||= Typhoeus::Hydra.new
|
480
|
+
|
481
|
+
# Queue the request into the Hydra (libcurl reactor).
|
482
|
+
@hydra.queue(request)
|
483
|
+
|
484
|
+
# Cycle the reactor on a separate thread
|
485
|
+
#
|
486
|
+
# The way it works is that if more requests are queued while Hydra is in the `#run`
|
487
|
+
# method, it will keep executing them
|
488
|
+
#
|
489
|
+
# The upcoming calls to `#run` will simply run empty.
|
490
|
+
HYDRA_EXECUTOR.post(@hydra, &:run)
|
491
|
+
end
|
424
492
|
end
|
425
493
|
end
|
@@ -45,6 +45,10 @@ module Pod
|
|
45
45
|
@symbolic_name = input.name
|
46
46
|
@deployment_target = input.deployment_target
|
47
47
|
else
|
48
|
+
# Allow `Platform.new('macos')` to be equivalent to `Platform.macos`
|
49
|
+
if input == 'macos'
|
50
|
+
input = 'osx'
|
51
|
+
end
|
48
52
|
@symbolic_name = input.to_sym
|
49
53
|
target = target[:deployment_target] if target.is_a?(Hash)
|
50
54
|
@deployment_target = Version.create(target)
|
@@ -422,6 +422,9 @@ module Pod
|
|
422
422
|
# specifies the position of which this script phase should be executed. The currently supported values are:
|
423
423
|
# `:before_compile`, `:after_compile` and `:any` which is the default.
|
424
424
|
#
|
425
|
+
# @option options [String] :dependency_file
|
426
|
+
# specifies the dependency file to use for this script phase.
|
427
|
+
#
|
425
428
|
# @return [void]
|
426
429
|
#
|
427
430
|
def script_phase(options)
|
@@ -677,14 +680,39 @@ module Pod
|
|
677
680
|
current_target_definition.use_modular_headers_for_all_pods = true
|
678
681
|
end
|
679
682
|
|
680
|
-
# Use frameworks instead of static libraries for Pods.
|
683
|
+
# Use frameworks instead of static libraries for Pods. When using frameworks, you may also specify the `:linkage`
|
684
|
+
# style to use, either `:static` or `:dynamic`.
|
681
685
|
#
|
682
686
|
# ------
|
683
687
|
#
|
684
688
|
# This attribute is inherited by child target definitions.
|
685
689
|
#
|
686
|
-
|
687
|
-
|
690
|
+
# @param [Boolean, Hash] option
|
691
|
+
# The option to use for configuring packaging and linkage style.
|
692
|
+
#
|
693
|
+
# @example
|
694
|
+
#
|
695
|
+
# target 'MyApp' do
|
696
|
+
# use_frameworks!
|
697
|
+
# pod 'AFNetworking', '~> 1.0'
|
698
|
+
# end
|
699
|
+
#
|
700
|
+
# @example
|
701
|
+
#
|
702
|
+
# target 'MyApp' do
|
703
|
+
# use_frameworks! :linkage => :dynamic
|
704
|
+
# pod 'AFNetworking', '~> 1.0'
|
705
|
+
# end
|
706
|
+
#
|
707
|
+
# target 'ZipApp' do
|
708
|
+
# use_frameworks! :linkage => :static
|
709
|
+
# pod 'SSZipArchive'
|
710
|
+
# end
|
711
|
+
#
|
712
|
+
# @return [void]
|
713
|
+
#
|
714
|
+
def use_frameworks!(option = true)
|
715
|
+
current_target_definition.use_frameworks!(option)
|
688
716
|
end
|
689
717
|
|
690
718
|
# Specifies the Swift version requirements this target definition supports.
|
@@ -365,25 +365,54 @@ module Pod
|
|
365
365
|
|
366
366
|
#--------------------------------------#
|
367
367
|
|
368
|
-
#
|
368
|
+
# The (desired) build type for the pods integrated in this target definition. Defaults to static libraries and can
|
369
|
+
# only be overridden through Pod::Podfile::DSL#use_frameworks!.
|
370
|
+
#
|
371
|
+
# @return [BuildType]
|
372
|
+
#
|
373
|
+
def build_type
|
374
|
+
value = get_hash_value('uses_frameworks', root? ? BuildType.static_library : parent.build_type)
|
375
|
+
case value
|
376
|
+
when true, false
|
377
|
+
value ? BuildType.dynamic_framework : BuildType.static_library
|
378
|
+
when Hash
|
379
|
+
BuildType.new(:linkage => value.fetch(:linkage), :packaging => value.fetch(:packaging))
|
380
|
+
when BuildType
|
381
|
+
value
|
382
|
+
else
|
383
|
+
raise ArgumentError, "Got `#{value.inspect}`, should be a boolean, hash or BuildType."
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Sets whether the target definition's pods should be built as frameworks.
|
369
388
|
#
|
370
|
-
# @param
|
371
|
-
#
|
389
|
+
# @param [Boolean, Hash] option
|
390
|
+
# Whether pods that are integrated in this target should be built as frameworks. If the option is a
|
391
|
+
# boolean then the value affects both packaging and linkage styles. If set to true, then dynamic frameworks
|
392
|
+
# are used and if it's set to false, then static libraries are used. If the option is a hash then
|
393
|
+
# `:framework` packaging is implied and the user configures the `:linkage` style to use.
|
372
394
|
#
|
373
395
|
# @return [void]
|
374
396
|
#
|
375
|
-
def use_frameworks!(
|
376
|
-
|
397
|
+
def use_frameworks!(option = true)
|
398
|
+
value = case option
|
399
|
+
when true, false
|
400
|
+
option ? BuildType.dynamic_framework : BuildType.static_library
|
401
|
+
when Hash
|
402
|
+
BuildType.new(:linkage => option.fetch(:linkage), :packaging => :framework)
|
403
|
+
else
|
404
|
+
raise ArgumentError, "Got `#{option.inspect}`, should be a boolean or hash."
|
405
|
+
end
|
406
|
+
set_hash_value('uses_frameworks', value.to_hash)
|
377
407
|
end
|
378
408
|
|
379
|
-
# @return [Bool] whether the target definition should
|
380
|
-
# a framework.
|
409
|
+
# @return [Bool] whether the target definition pods should be built as frameworks.
|
381
410
|
#
|
382
411
|
def uses_frameworks?
|
383
412
|
if internal_hash['uses_frameworks'].nil?
|
384
413
|
root? ? false : parent.uses_frameworks?
|
385
414
|
else
|
386
|
-
|
415
|
+
build_type.framework?
|
387
416
|
end
|
388
417
|
end
|
389
418
|
|
@@ -737,7 +766,8 @@ module Pod
|
|
737
766
|
# @param [Hash] options
|
738
767
|
# The options to use for this script phase. The required keys
|
739
768
|
# are: `:name`, `:script`, while the optional keys are:
|
740
|
-
# `:shell_path`, `:input_files`, `:output_files`, `:show_env_vars_in_log` and
|
769
|
+
# `:shell_path`, `:input_files`, `:output_files`, `:show_env_vars_in_log`, `:execution_position` and
|
770
|
+
# `:dependency_file`.
|
741
771
|
#
|
742
772
|
# @return [void]
|
743
773
|
#
|
@@ -346,11 +346,17 @@ module Pod
|
|
346
346
|
end
|
347
347
|
end
|
348
348
|
|
349
|
-
# @return [Array<String
|
349
|
+
# @return [Array<String>, Symbol] the name(s) of the default subspecs if provided or :none for no default subspecs.
|
350
350
|
#
|
351
351
|
def default_subspecs
|
352
352
|
# TODO: remove singular form and update the JSON specs.
|
353
|
-
Array(attributes_hash['default_subspecs'] || attributes_hash['default_subspec'])
|
353
|
+
value = Array(attributes_hash['default_subspecs'] || attributes_hash['default_subspec'])
|
354
|
+
first = value.first
|
355
|
+
if first == :none || first == 'none'
|
356
|
+
first.to_sym
|
357
|
+
else
|
358
|
+
value
|
359
|
+
end
|
354
360
|
end
|
355
361
|
|
356
362
|
# Returns the dependencies on subspecs.
|
@@ -367,6 +373,8 @@ module Pod
|
|
367
373
|
def subspec_dependencies(platform = nil)
|
368
374
|
specs = if default_subspecs.empty?
|
369
375
|
subspecs.compact.reject(&:non_library_specification?)
|
376
|
+
elsif default_subspecs == :none
|
377
|
+
[]
|
370
378
|
else
|
371
379
|
default_subspecs.map do |subspec_name|
|
372
380
|
root.subspec_by_name("#{name}/#{subspec_name}")
|
@@ -403,10 +411,29 @@ module Pod
|
|
403
411
|
dependencies(platform) + subspec_dependencies(platform)
|
404
412
|
end
|
405
413
|
|
414
|
+
# Returns whether a dependency is whitelisted for the given configuration.
|
415
|
+
#
|
416
|
+
# @param [Pod::Dependency] dependency
|
417
|
+
# the dependency verify.
|
418
|
+
#
|
419
|
+
# @param [Symbol, String] configuration
|
420
|
+
# the configuration to check against.
|
421
|
+
#
|
422
|
+
# @return [Bool] whether the dependency is whitelisted or not.
|
423
|
+
#
|
424
|
+
def dependency_whitelisted_for_configuration?(dependency, configuration)
|
425
|
+
inherited = -> { root? ? true : parent.dependency_whitelisted_for_configuration?(dependency, configuration) }
|
426
|
+
|
427
|
+
return inherited[] unless configuration_whitelist = attributes_hash['configuration_pod_whitelist']
|
428
|
+
return inherited[] unless whitelist_for_pod = configuration_whitelist[dependency.name]
|
429
|
+
|
430
|
+
whitelist_for_pod.include?(configuration.to_s.downcase)
|
431
|
+
end
|
432
|
+
|
406
433
|
# Returns a consumer to access the multi-platform attributes.
|
407
434
|
#
|
408
435
|
# @param [String, Symbol, Platform] platform
|
409
|
-
#
|
436
|
+
# the platform of the consumer
|
410
437
|
#
|
411
438
|
# @return [Specification::Consumer] the consumer for the given platform
|
412
439
|
#
|
@@ -653,6 +653,12 @@ module Pod
|
|
653
653
|
# spec.dependency 'AFNetworking', '~> 1.0'
|
654
654
|
#
|
655
655
|
# @example
|
656
|
+
# spec.dependency 'AFNetworking', '~> 1.0', :configurations => ['Debug']
|
657
|
+
#
|
658
|
+
# @example
|
659
|
+
# spec.dependency 'AFNetworking', '~> 1.0', :configurations => :debug
|
660
|
+
#
|
661
|
+
# @example
|
656
662
|
# spec.dependency 'RestKit/CoreData', '~> 0.20.0'
|
657
663
|
#
|
658
664
|
# @example
|
@@ -676,16 +682,22 @@ module Pod
|
|
676
682
|
end
|
677
683
|
end
|
678
684
|
end
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
685
|
+
|
686
|
+
configurations_option = version_requirements.find { |option| option.is_a?(Hash) && option.key?(:configurations) }
|
687
|
+
whitelisted_configurations = if configurations_option
|
688
|
+
version_requirements.delete(configurations_option)
|
689
|
+
Array(configurations_option.delete(:configurations)).map { |c| c.to_s.downcase }
|
690
|
+
end
|
691
|
+
|
692
|
+
dependency_options = version_requirements.reject { |req| req.is_a?(String) }
|
693
|
+
dependency_options.each do |dependency_option|
|
694
|
+
if dependency_option.is_a?(Hash)
|
695
|
+
if !dependency_option[:path].nil?
|
696
|
+
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:path` option is not supported.'\
|
697
|
+
' `:path` can be used in the Podfile instead to override global dependencies.'
|
698
|
+
elsif !dependency_option[:git].nil?
|
699
|
+
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:git` option is not supported.'\
|
700
|
+
' `:git` can be used in the Podfile instead to override global dependencies.'
|
689
701
|
end
|
690
702
|
end
|
691
703
|
|
@@ -694,6 +706,15 @@ module Pod
|
|
694
706
|
|
695
707
|
attributes_hash['dependencies'] ||= {}
|
696
708
|
attributes_hash['dependencies'][name] = version_requirements
|
709
|
+
|
710
|
+
unless whitelisted_configurations.nil?
|
711
|
+
if (extras = whitelisted_configurations - %w(debug release)) && !extras.empty?
|
712
|
+
raise Informative, "Only `Debug` & `Release` are allowed under configurations for dependency on `#{name}`. " \
|
713
|
+
"Found #{extras.map { |configuration| "`#{configuration}`" }.to_sentence}."
|
714
|
+
end
|
715
|
+
attributes_hash['configuration_pod_whitelist'] ||= {}
|
716
|
+
attributes_hash['configuration_pod_whitelist'][name] = whitelisted_configurations
|
717
|
+
end
|
697
718
|
end
|
698
719
|
|
699
720
|
def dependency=(args)
|
@@ -1024,7 +1045,7 @@ module Pod
|
|
1024
1045
|
SCRIPT_PHASE_REQUIRED_KEYS = [:name, :script].freeze
|
1025
1046
|
|
1026
1047
|
SCRIPT_PHASE_OPTIONAL_KEYS = [:shell_path, :input_files, :output_files, :input_file_lists, :output_file_lists,
|
1027
|
-
:show_env_vars_in_log, :execution_position].freeze
|
1048
|
+
:show_env_vars_in_log, :execution_position, :dependency_file].freeze
|
1028
1049
|
|
1029
1050
|
EXECUTION_POSITION_KEYS = [:before_compile, :after_compile, :any].freeze
|
1030
1051
|
|
@@ -1575,7 +1596,7 @@ module Pod
|
|
1575
1596
|
:types => [String],
|
1576
1597
|
:spec_types => [:test]
|
1577
1598
|
|
1578
|
-
SCHEME_KEYS = [:launch_arguments, :environment_variables].freeze
|
1599
|
+
SCHEME_KEYS = [:launch_arguments, :environment_variables, :code_coverage].freeze
|
1579
1600
|
|
1580
1601
|
# @!method scheme=(flag)
|
1581
1602
|
#
|
@@ -1648,9 +1669,12 @@ module Pod
|
|
1648
1669
|
# @!method default_subspecs=(subspec_array)
|
1649
1670
|
#
|
1650
1671
|
# An array of subspecs names that should be used as preferred dependency.
|
1651
|
-
# If not specified a
|
1672
|
+
# If not specified, a specification requires all of its subspecs as
|
1652
1673
|
# dependencies.
|
1653
1674
|
#
|
1675
|
+
# You may use the value `:none` to specify that none of the subspecs are
|
1676
|
+
# required to compile this pod and that all subspecs are optional.
|
1677
|
+
#
|
1654
1678
|
# ---
|
1655
1679
|
#
|
1656
1680
|
# A Pod should make available the full library by default. Users can
|
@@ -1666,17 +1690,21 @@ module Pod
|
|
1666
1690
|
# spec.default_subspec = 'Core'
|
1667
1691
|
#
|
1668
1692
|
# @example
|
1693
|
+
#
|
1669
1694
|
# spec.default_subspecs = 'Core', 'UI'
|
1670
1695
|
#
|
1671
|
-
# @
|
1696
|
+
# @example
|
1697
|
+
#
|
1698
|
+
# spec.default_subspecs = :none
|
1699
|
+
#
|
1700
|
+
# @param [Array<String>, String, Symbol] subspec_names
|
1672
1701
|
# An array of subspec names that should be inherited as
|
1673
1702
|
# dependency.
|
1674
1703
|
#
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
:root_only => true
|
1704
|
+
root_attribute :default_subspecs,
|
1705
|
+
:container => Array,
|
1706
|
+
:types => [Array, String, Symbol],
|
1707
|
+
:singularize => true
|
1680
1708
|
|
1681
1709
|
#-----------------------------------------------------------------------#
|
1682
1710
|
|
@@ -17,7 +17,7 @@ module Pod
|
|
17
17
|
# multi-platform, they don't have inheritance, and they never have a
|
18
18
|
# default value.
|
19
19
|
#
|
20
|
-
# @param [String] name
|
20
|
+
# @param [Symbol, String] name
|
21
21
|
# The name of the attribute.
|
22
22
|
#
|
23
23
|
# @param [Hash] options
|
@@ -36,7 +36,7 @@ module Pod
|
|
36
36
|
# Regular attributes in general support inheritance and multi-platform
|
37
37
|
# values, so resolving them for a given specification is not trivial.
|
38
38
|
#
|
39
|
-
# @param [String] name
|
39
|
+
# @param [Symbol, String] name
|
40
40
|
# The name of the attribute.
|
41
41
|
#
|
42
42
|
# @param [Hash] options
|
@@ -450,6 +450,9 @@ module Pod
|
|
450
450
|
if s.key?(:environment_variables) && !s[:environment_variables].is_a?(Hash)
|
451
451
|
results.add_error('scheme', 'Expected a hash for key `environment_variables`.')
|
452
452
|
end
|
453
|
+
if s.key?(:code_coverage) && ![true, false].include?(s[:code_coverage])
|
454
|
+
results.add_error('scheme', 'Expected a boolean for key `code_coverage`.')
|
455
|
+
end
|
453
456
|
end
|
454
457
|
end
|
455
458
|
|
@@ -28,6 +28,14 @@ module Pod
|
|
28
28
|
|
29
29
|
attr_reader :results
|
30
30
|
|
31
|
+
# @return [Array<String>] Keys that are valid but have been deprecated.
|
32
|
+
#
|
33
|
+
DEPRECATED_KEYS = ['swift_version'].freeze
|
34
|
+
|
35
|
+
# @return [Array<String>] Keys that are only used for internal purposes.
|
36
|
+
#
|
37
|
+
INTERNAL_KEYS = ['configuration_pod_whitelist'].freeze
|
38
|
+
|
31
39
|
# Checks the attributes hash for any unknown key which might be the
|
32
40
|
# result of a misspelling in a JSON file.
|
33
41
|
#
|
@@ -42,8 +50,7 @@ module Pod
|
|
42
50
|
def check_attributes
|
43
51
|
attributes_keys = Pod::Specification::DSL.attributes.keys.map(&:to_s)
|
44
52
|
platform_keys = Specification::DSL::PLATFORMS.map(&:to_s)
|
45
|
-
|
46
|
-
valid_keys = attributes_keys + platform_keys + deprecated_keys
|
53
|
+
valid_keys = attributes_keys + platform_keys + DEPRECATED_KEYS + INTERNAL_KEYS
|
47
54
|
attributes_hash = consumer.spec.attributes_hash
|
48
55
|
keys = attributes_hash.keys
|
49
56
|
Specification::DSL::PLATFORMS.each do |platform|
|
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.9.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-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -87,6 +87,34 @@ dependencies:
|
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '1.1'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: typhoeus
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
97
|
+
type: :runtime
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: netrc
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.11'
|
111
|
+
type: :runtime
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.11'
|
90
118
|
- !ruby/object:Gem::Dependency
|
91
119
|
name: bacon
|
92
120
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,6 +143,7 @@ files:
|
|
115
143
|
- LICENSE
|
116
144
|
- README.md
|
117
145
|
- lib/cocoapods-core.rb
|
146
|
+
- lib/cocoapods-core/build_type.rb
|
118
147
|
- lib/cocoapods-core/cdn_source.rb
|
119
148
|
- lib/cocoapods-core/core_ui.rb
|
120
149
|
- lib/cocoapods-core/dependency.rb
|