cocoapods-core 0.30.0 → 1.15.2
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 +5 -5
- data/README.md +7 -10
- data/lib/cocoapods-core/build_type.rb +121 -0
- data/lib/cocoapods-core/cdn_source.rb +501 -0
- data/lib/cocoapods-core/core_ui.rb +4 -3
- data/lib/cocoapods-core/dependency.rb +100 -73
- data/lib/cocoapods-core/gem_version.rb +1 -2
- data/lib/cocoapods-core/github.rb +32 -5
- data/lib/cocoapods-core/http.rb +86 -0
- data/lib/cocoapods-core/lockfile.rb +161 -56
- data/lib/cocoapods-core/metrics.rb +47 -0
- data/lib/cocoapods-core/platform.rb +99 -11
- data/lib/cocoapods-core/podfile/dsl.rb +623 -124
- data/lib/cocoapods-core/podfile/target_definition.rb +662 -109
- data/lib/cocoapods-core/podfile.rb +138 -65
- data/lib/cocoapods-core/requirement.rb +37 -8
- data/lib/cocoapods-core/source/acceptor.rb +16 -13
- data/lib/cocoapods-core/source/aggregate.rb +79 -103
- data/lib/cocoapods-core/source/health_reporter.rb +9 -18
- data/lib/cocoapods-core/source/manager.rb +488 -0
- data/lib/cocoapods-core/source/metadata.rb +79 -0
- data/lib/cocoapods-core/source.rb +241 -70
- data/lib/cocoapods-core/specification/consumer.rb +187 -47
- data/lib/cocoapods-core/specification/dsl/attribute.rb +49 -85
- data/lib/cocoapods-core/specification/dsl/attribute_support.rb +6 -8
- data/lib/cocoapods-core/specification/dsl/deprecations.rb +9 -126
- data/lib/cocoapods-core/specification/dsl/platform_proxy.rb +30 -20
- data/lib/cocoapods-core/specification/dsl.rb +943 -296
- data/lib/cocoapods-core/specification/json.rb +64 -23
- data/lib/cocoapods-core/specification/linter/analyzer.rb +218 -0
- data/lib/cocoapods-core/specification/linter/result.rb +128 -0
- data/lib/cocoapods-core/specification/linter.rb +310 -309
- data/lib/cocoapods-core/specification/root_attribute_accessors.rb +90 -39
- data/lib/cocoapods-core/specification/set/presenter.rb +35 -71
- data/lib/cocoapods-core/specification/set.rb +42 -96
- data/lib/cocoapods-core/specification.rb +368 -130
- data/lib/cocoapods-core/standard_error.rb +45 -24
- data/lib/cocoapods-core/trunk_source.rb +14 -0
- data/lib/cocoapods-core/vendor/requirement.rb +133 -53
- data/lib/cocoapods-core/vendor/version.rb +197 -156
- data/lib/cocoapods-core/vendor.rb +1 -5
- data/lib/cocoapods-core/version.rb +137 -42
- data/lib/cocoapods-core/yaml_helper.rb +334 -0
- data/lib/cocoapods-core.rb +10 -4
- metadata +100 -27
- data/lib/cocoapods-core/source/abstract_data_provider.rb +0 -71
- data/lib/cocoapods-core/source/file_system_data_provider.rb +0 -150
- data/lib/cocoapods-core/source/github_data_provider.rb +0 -143
- data/lib/cocoapods-core/specification/set/statistics.rb +0 -266
- data/lib/cocoapods-core/yaml_converter.rb +0 -192
@@ -1,5 +1,4 @@
|
|
1
1
|
module Pod
|
2
|
-
|
3
2
|
# The Dependency allows to specify dependencies of a {Podfile} or a
|
4
3
|
# {Specification} on a Pod. It stores the name of the dependency, version
|
5
4
|
# requirements and external sources information.
|
@@ -10,7 +9,6 @@ module Pod
|
|
10
9
|
# [MIT license](https://github.com/rubygems/rubygems/blob/master/MIT.txt).
|
11
10
|
#
|
12
11
|
class Dependency
|
13
|
-
|
14
12
|
# @return [String] The name of the Pod described by this dependency.
|
15
13
|
#
|
16
14
|
attr_accessor :name
|
@@ -21,12 +19,10 @@ module Pod
|
|
21
19
|
#
|
22
20
|
attr_accessor :external_source
|
23
21
|
|
24
|
-
# @return [
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
28
|
-
attr_accessor :head
|
29
|
-
alias_method :head?, :head
|
22
|
+
# @return [String] The source URL of the podspec repo to use to resolve
|
23
|
+
# this dependency. If not set then the standard source list
|
24
|
+
# should be used to resolve the dependency.
|
25
|
+
attr_accessor :podspec_repo
|
30
26
|
|
31
27
|
# @overload initialize(name, requirements)
|
32
28
|
#
|
@@ -54,36 +50,48 @@ module Pod
|
|
54
50
|
# @example Initialization with an external source.
|
55
51
|
#
|
56
52
|
# Dependency.new('libPusher', {:git => 'example.com/repo.git'})
|
57
|
-
# Dependency.new('libPusher', {:path
|
53
|
+
# Dependency.new('libPusher', {:path => 'path/to/folder'})
|
58
54
|
# Dependency.new('libPusher', {:podspec => 'example.com/libPusher.podspec'})
|
59
55
|
#
|
60
|
-
# @overload initialize(name,
|
56
|
+
# @overload initialize(name, requirements, podspec_repo)
|
61
57
|
#
|
62
58
|
# @param [String] name
|
63
59
|
# the name of the Pod.
|
64
60
|
#
|
65
|
-
# @param [
|
66
|
-
#
|
61
|
+
# @param [Array, Version, String, Requirement] requirements
|
62
|
+
# an array specifying the version requirements of the
|
63
|
+
# dependency.
|
64
|
+
#
|
65
|
+
# @param [Hash] podspec_repo
|
66
|
+
# The URL of the specific podspec repo to resolve this dependency from.
|
67
67
|
#
|
68
|
-
# @example Initialization with
|
68
|
+
# @example Initialization with a specific podspec repo
|
69
69
|
#
|
70
|
-
# Dependency.new('
|
70
|
+
# Dependency.new('Artsy+UILabels', '~> 1.0', :source => 'https://github.com/Artsy/Specs.git')
|
71
71
|
#
|
72
72
|
def initialize(name = nil, *requirements)
|
73
73
|
if requirements.last.is_a?(Hash)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
additional_params = requirements.pop.select { |_, v| !v.nil? }
|
75
|
+
additional_params = nil if additional_params.empty?
|
76
|
+
|
77
|
+
if additional_params && @podspec_repo = additional_params[:source]
|
78
|
+
# This dependency specifies the exact source podspec repo to use.
|
79
|
+
additional_params.delete(:source)
|
80
|
+
unless additional_params.empty?
|
81
|
+
raise Informative, 'A dependency with a specified podspec repo may ' \
|
82
|
+
"not include other source parameters (#{name})."
|
83
|
+
end
|
84
|
+
elsif @external_source = additional_params
|
85
|
+
unless requirements.empty?
|
86
|
+
raise Informative, 'A dependency with an external source may not ' \
|
87
|
+
"specify version requirements (#{name})."
|
88
|
+
end
|
78
89
|
end
|
79
90
|
|
80
91
|
elsif requirements.last == :head
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
raise Informative, "A `:head` dependency may not specify version " \
|
85
|
-
"requirements (#{name})."
|
86
|
-
end
|
92
|
+
raise Informative, '`:head` dependencies have been removed. Please use ' \
|
93
|
+
"normal external source dependencies (`:git => 'GIT_REPO_URL'`) " \
|
94
|
+
"instead of `:head` for `#{name}`."
|
87
95
|
end
|
88
96
|
|
89
97
|
if requirements.length == 1 && requirements.first.is_a?(Requirement)
|
@@ -91,44 +99,47 @@ module Pod
|
|
91
99
|
end
|
92
100
|
@name = name
|
93
101
|
@requirement = Requirement.create(requirements)
|
102
|
+
@specific_requirement ||= nil
|
103
|
+
@external_source ||= nil
|
94
104
|
end
|
95
105
|
|
96
106
|
# @return [Version] whether the dependency points to a specific version.
|
97
107
|
#
|
98
|
-
|
108
|
+
attr_reader :specific_version
|
99
109
|
|
100
110
|
# @return [Requirement] the requirement of this dependency (a set of
|
101
111
|
# one or more version restrictions).
|
102
112
|
#
|
103
|
-
# @todo The specific version is stripped from head information because
|
104
|
-
# because its string representation would not parse. It would
|
105
|
-
# be better to add something like Version#display_string.
|
106
|
-
#
|
107
113
|
def requirement
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
114
|
+
@specific_requirement || @requirement
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param [Version] version the specific version to point to
|
118
|
+
#
|
119
|
+
def specific_version=(version)
|
120
|
+
@specific_version = version
|
121
|
+
@specific_requirement = if version
|
122
|
+
Requirement.new(Version.new(version.version))
|
123
|
+
end
|
113
124
|
end
|
114
125
|
|
115
|
-
# @return [
|
126
|
+
# @return [Boolean] whether the dependency points to a subspec.
|
116
127
|
#
|
117
128
|
def subspec_dependency?
|
118
129
|
@name.include?('/')
|
119
130
|
end
|
120
131
|
|
121
|
-
# @return [
|
132
|
+
# @return [Boolean] whether the dependency points to an external source.
|
122
133
|
#
|
123
134
|
def external?
|
124
135
|
!@external_source.nil?
|
125
136
|
end
|
126
137
|
|
127
|
-
# @return [
|
138
|
+
# @return [Boolean] whether the dependency points to a local path.
|
128
139
|
#
|
129
140
|
def local?
|
130
141
|
if external_source
|
131
|
-
|
142
|
+
external_source[:path]
|
132
143
|
end
|
133
144
|
end
|
134
145
|
|
@@ -174,28 +185,27 @@ module Pod
|
|
174
185
|
# @note This is used by the Lockfile to check if a stored dependency is
|
175
186
|
# still compatible with the Podfile.
|
176
187
|
#
|
177
|
-
# @return [
|
188
|
+
# @return [Boolean] whether the dependency is compatible with the given one.
|
178
189
|
#
|
179
190
|
def compatible?(other)
|
180
191
|
return false unless name == other.name
|
181
|
-
return false unless head? == other.head?
|
182
192
|
return false unless external_source == other.external_source
|
183
193
|
|
184
|
-
other.requirement.requirements.all? do |
|
194
|
+
other.requirement.requirements.all? do |_operator, version|
|
185
195
|
requirement.satisfied_by? Version.new(version)
|
186
196
|
end
|
187
197
|
end
|
188
198
|
|
189
|
-
# @return [
|
199
|
+
# @return [Boolean] whether the dependency is equal to another taking into
|
190
200
|
# account the loaded specification, the head options and the
|
191
201
|
# external source.
|
192
202
|
#
|
193
203
|
def ==(other)
|
194
204
|
self.class == other.class &&
|
195
205
|
name == other.name &&
|
196
|
-
|
197
|
-
|
198
|
-
|
206
|
+
external_source == other.external_source &&
|
207
|
+
podspec_repo == other.podspec_repo &&
|
208
|
+
requirement == other.requirement
|
199
209
|
end
|
200
210
|
alias_method :eql?, :==
|
201
211
|
|
@@ -218,35 +228,60 @@ module Pod
|
|
218
228
|
# @param [Dependency] other
|
219
229
|
# the other dependency to merge with.
|
220
230
|
#
|
221
|
-
# @note If one of the
|
231
|
+
# @note If one of the dependencies specifies an external source or is head,
|
222
232
|
# the resulting dependency preserves this attributes.
|
223
233
|
#
|
224
|
-
# @return [Dependency] a dependency (not
|
225
|
-
# includes
|
234
|
+
# @return [Dependency] a dependency (not necessarily a new instance) that
|
235
|
+
# also includes the version requirements of the given one.
|
226
236
|
#
|
227
237
|
def merge(other)
|
228
238
|
unless name == other.name
|
229
239
|
raise ArgumentError, "#{self} and #{other} have different names"
|
230
240
|
end
|
241
|
+
|
231
242
|
default = Requirement.default
|
232
243
|
self_req = requirement
|
233
244
|
other_req = other.requirement
|
234
245
|
|
235
|
-
if other_req == default
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
246
|
+
req = if other_req == default
|
247
|
+
self_req
|
248
|
+
elsif self_req == default
|
249
|
+
other_req
|
250
|
+
else
|
251
|
+
self_req.as_list.concat(other_req.as_list)
|
252
|
+
end
|
253
|
+
|
254
|
+
opts = {}
|
242
255
|
|
243
|
-
dep.head = head? || other.head?
|
244
256
|
if external_source || other.external_source
|
245
|
-
|
246
|
-
|
247
|
-
|
257
|
+
opts.
|
258
|
+
merge!(external_source || {}).
|
259
|
+
merge!(other.external_source || {})
|
260
|
+
|
261
|
+
req_to_set = req
|
262
|
+
req = []
|
263
|
+
end
|
264
|
+
|
265
|
+
if podspec_repo && other.podspec_repo && podspec_repo != other.podspec_repo
|
266
|
+
raise ArgumentError, "#{self} and #{other} have different podspec repos"
|
267
|
+
end
|
268
|
+
|
269
|
+
if repo = podspec_repo || other.podspec_repo
|
270
|
+
opts[:source] = repo
|
271
|
+
end
|
272
|
+
|
273
|
+
self.class.new(name, *req, opts).tap do |dep|
|
274
|
+
dep.instance_variable_set(:@requirement, Requirement.create(req_to_set)) if req_to_set
|
248
275
|
end
|
249
|
-
|
276
|
+
end
|
277
|
+
|
278
|
+
# Whether the dependency has any pre-release requirements
|
279
|
+
#
|
280
|
+
# @return [Boolean] Whether the dependency has any pre-release requirements
|
281
|
+
#
|
282
|
+
def prerelease?
|
283
|
+
return @prerelease if defined?(@prerelease)
|
284
|
+
@prerelease = requirement.requirements.any? { |_op, version| version.prerelease? }
|
250
285
|
end
|
251
286
|
|
252
287
|
# Checks whether the dependency would be satisfied by the specification
|
@@ -258,7 +293,7 @@ module Pod
|
|
258
293
|
# @param [String, Version] version
|
259
294
|
# The proposed version.
|
260
295
|
#
|
261
|
-
# @return [
|
296
|
+
# @return [Boolean] Whether the dependency is satisfied.
|
262
297
|
#
|
263
298
|
def match?(name, version)
|
264
299
|
return false unless self.name == name
|
@@ -282,7 +317,6 @@ module Pod
|
|
282
317
|
# "libPusher (= 1.0)"
|
283
318
|
# "libPusher (~> 1.0.1)"
|
284
319
|
# "libPusher (> 1.0, < 2.0)"
|
285
|
-
# "libPusher (HEAD)"
|
286
320
|
# "libPusher (from `www.example.com')"
|
287
321
|
# "libPusher (defined in Podfile)"
|
288
322
|
# "RestKit/JSON"
|
@@ -293,8 +327,6 @@ module Pod
|
|
293
327
|
version = ''
|
294
328
|
if external?
|
295
329
|
version << external_source_description(external_source)
|
296
|
-
elsif head?
|
297
|
-
version << 'HEAD'
|
298
330
|
elsif requirement != Requirement.default
|
299
331
|
version << requirement.to_s
|
300
332
|
end
|
@@ -317,17 +349,15 @@ module Pod
|
|
317
349
|
# @return [Dependency] the dependency described by the string.
|
318
350
|
#
|
319
351
|
def self.from_string(string)
|
320
|
-
match_data = string.match(/(
|
352
|
+
match_data = string.match(/((?:\s?[^\s(])+)( (?:.*))?/)
|
321
353
|
name = match_data[1]
|
322
354
|
version = match_data[2]
|
323
355
|
version = version.gsub(/[()]/, '') if version
|
324
356
|
case version
|
325
|
-
when nil
|
357
|
+
when nil, /from `(.*)(`|')/
|
326
358
|
Dependency.new(name)
|
327
|
-
when /HEAD/
|
328
|
-
Dependency.new(name, :head)
|
329
359
|
else
|
330
|
-
version_requirements =
|
360
|
+
version_requirements = version.split(',') if version
|
331
361
|
Dependency.new(name, version_requirements)
|
332
362
|
end
|
333
363
|
end
|
@@ -336,7 +366,7 @@ module Pod
|
|
336
366
|
#
|
337
367
|
def inspect
|
338
368
|
"<#{self.class} name=#{name} requirements=#{requirement} " \
|
339
|
-
"external_source=#{external_source || 'nil'}>"
|
369
|
+
"source=#{podspec_repo || 'nil'} external_source=#{external_source || 'nil'}>"
|
340
370
|
end
|
341
371
|
|
342
372
|
#--------------------------------------#
|
@@ -369,13 +399,10 @@ module Pod
|
|
369
399
|
desc = "`#{source[:podspec]}`"
|
370
400
|
elsif source.key?(:path)
|
371
401
|
desc = "`#{source[:path]}`"
|
372
|
-
elsif source.key?(:local)
|
373
|
-
desc = "`#{source[:local]}`"
|
374
402
|
else
|
375
403
|
desc = "`#{source}`"
|
376
404
|
end
|
377
405
|
"from #{desc}"
|
378
406
|
end
|
379
407
|
end
|
380
|
-
|
381
408
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
module Pod
|
2
|
-
|
3
2
|
# Allows to access information about the GitHub repos.
|
4
3
|
#
|
5
4
|
# This class is stored in Core because it might be used by web services.
|
6
5
|
#
|
7
6
|
module GitHub
|
8
|
-
|
9
7
|
# Returns the information of a user.
|
10
8
|
#
|
11
9
|
# @param [String] login
|
@@ -78,6 +76,36 @@ module Pod
|
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
79
|
+
# Returns whether the repository has been updated since a given commit.
|
80
|
+
# If the request fails, the response will be true as the API is still in
|
81
|
+
# beta and likely to change.
|
82
|
+
#
|
83
|
+
# @param [String] url @see #repo
|
84
|
+
#
|
85
|
+
# @param [String] commit
|
86
|
+
# The current HEAD commit.
|
87
|
+
#
|
88
|
+
# @return [Boolean] Whether the repository has been updated since the commit.
|
89
|
+
#
|
90
|
+
def self.modified_since_commit(url, commit)
|
91
|
+
return true unless repo_id = normalized_repo_id(url)
|
92
|
+
require 'rest'
|
93
|
+
request_url = "https://api.github.com/repos/#{repo_id}/commits/master"
|
94
|
+
headers = {
|
95
|
+
'User-Agent' => 'CocoaPods',
|
96
|
+
'Accept' => 'application/vnd.github.v3.sha',
|
97
|
+
'If-None-Match' => %("#{commit}"),
|
98
|
+
}
|
99
|
+
|
100
|
+
begin
|
101
|
+
response = REST.get(request_url, headers)
|
102
|
+
code = response.status_code
|
103
|
+
code != 304
|
104
|
+
rescue
|
105
|
+
raise Informative, "Failed to connect to GitHub to update the #{repo_id} specs repo - Please check if you are offline, or that GitHub is down"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
81
109
|
private
|
82
110
|
|
83
111
|
# @!group Private helpers
|
@@ -103,7 +131,7 @@ module Pod
|
|
103
131
|
# @return [Nil] if the given url is not a valid github repo url.
|
104
132
|
#
|
105
133
|
def self.repo_id_from_url(url)
|
106
|
-
url[%r{github.com
|
134
|
+
url[%r{github.com[/:]([^/]*/(?:(?!\.git)[^/])*)\.*}, 1]
|
107
135
|
end
|
108
136
|
|
109
137
|
# Performs a get request with the given URL.
|
@@ -116,7 +144,7 @@ module Pod
|
|
116
144
|
def self.peform_request(url)
|
117
145
|
require 'rest'
|
118
146
|
require 'json'
|
119
|
-
headers = {
|
147
|
+
headers = { 'User-Agent' => 'CocoaPods' }
|
120
148
|
response = REST.get(url, headers)
|
121
149
|
body = JSON.parse(response.body)
|
122
150
|
if response.ok?
|
@@ -129,6 +157,5 @@ module Pod
|
|
129
157
|
end
|
130
158
|
|
131
159
|
#-------------------------------------------------------------------------#
|
132
|
-
|
133
160
|
end
|
134
161
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
# Handles HTTP requests
|
5
|
+
#
|
6
|
+
module HTTP
|
7
|
+
# Resolve potential redirects and return the final URL.
|
8
|
+
#
|
9
|
+
# @return [string]
|
10
|
+
#
|
11
|
+
def self.get_actual_url(url, user_agent = nil)
|
12
|
+
redirects = 0
|
13
|
+
|
14
|
+
loop do
|
15
|
+
response = perform_head_request(url, user_agent)
|
16
|
+
|
17
|
+
if [301, 302, 303, 307, 308].include? response.status_code
|
18
|
+
location = response.headers['location'].first
|
19
|
+
|
20
|
+
if location =~ %r{://}
|
21
|
+
url = location
|
22
|
+
else
|
23
|
+
url = URI.join(url, location).to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
redirects += 1
|
27
|
+
else
|
28
|
+
break
|
29
|
+
end
|
30
|
+
|
31
|
+
break unless redirects < MAX_HTTP_REDIRECTS
|
32
|
+
end
|
33
|
+
|
34
|
+
url
|
35
|
+
end
|
36
|
+
|
37
|
+
# Performs validation of a URL
|
38
|
+
#
|
39
|
+
# @return [REST::response]
|
40
|
+
#
|
41
|
+
def self.validate_url(url, user_agent = nil)
|
42
|
+
return nil unless url =~ /^#{URI.regexp}$/
|
43
|
+
|
44
|
+
begin
|
45
|
+
url = get_actual_url(url, user_agent)
|
46
|
+
resp = perform_head_request(url, user_agent)
|
47
|
+
rescue SocketError, URI::InvalidURIError, REST::Error, REST::Error::Connection
|
48
|
+
resp = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
resp
|
52
|
+
end
|
53
|
+
|
54
|
+
#-------------------------------------------------------------------------#
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Does a HEAD request and in case of any errors a GET request
|
59
|
+
#
|
60
|
+
# @return [REST::response]
|
61
|
+
#
|
62
|
+
def self.perform_head_request(url, user_agent)
|
63
|
+
require 'rest'
|
64
|
+
|
65
|
+
user_agent ||= USER_AGENT
|
66
|
+
|
67
|
+
resp = ::REST.head(url, 'User-Agent' => user_agent)
|
68
|
+
|
69
|
+
if resp.status_code >= 400
|
70
|
+
resp = ::REST.get(url, 'User-Agent' => user_agent,
|
71
|
+
'Range' => 'bytes=0-0')
|
72
|
+
|
73
|
+
if resp.status_code >= 400
|
74
|
+
resp = ::REST.get(url, 'User-Agent' => user_agent)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
resp
|
79
|
+
end
|
80
|
+
|
81
|
+
MAX_HTTP_REDIRECTS = 3
|
82
|
+
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.43.40 (KHTML, like Gecko) Version/8.0 Safari/538.43.40'
|
83
|
+
|
84
|
+
#-------------------------------------------------------------------------#
|
85
|
+
end
|
86
|
+
end
|