rubygems-update 2.0.17 → 2.1.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.autotest +1 -1
- data/History.txt +82 -153
- data/Manifest.txt +35 -9
- data/Rakefile +35 -36
- data/lib/rubygems.rb +106 -18
- data/lib/rubygems/available_set.rb +68 -0
- data/lib/rubygems/basic_specification.rb +139 -0
- data/lib/rubygems/command_manager.rb +37 -40
- data/lib/rubygems/commands/cert_command.rb +78 -29
- data/lib/rubygems/commands/cleanup_command.rb +2 -2
- data/lib/rubygems/commands/contents_command.rb +101 -58
- data/lib/rubygems/commands/dependency_command.rb +94 -53
- data/lib/rubygems/commands/environment_command.rb +70 -53
- data/lib/rubygems/commands/fetch_command.rb +1 -2
- data/lib/rubygems/commands/help_command.rb +85 -55
- data/lib/rubygems/commands/install_command.rb +84 -42
- data/lib/rubygems/commands/outdated_command.rb +2 -12
- data/lib/rubygems/commands/owner_command.rb +6 -0
- data/lib/rubygems/commands/pristine_command.rb +26 -16
- data/lib/rubygems/commands/sources_command.rb +85 -70
- data/lib/rubygems/commands/uninstall_command.rb +32 -2
- data/lib/rubygems/commands/update_command.rb +111 -75
- data/lib/rubygems/config_file.rb +15 -3
- data/lib/rubygems/core_ext/kernel_require.rb +9 -31
- data/lib/rubygems/defaults.rb +8 -0
- data/lib/rubygems/dependency.rb +4 -2
- data/lib/rubygems/dependency_installer.rb +180 -170
- data/lib/rubygems/dependency_resolver.rb +191 -526
- data/lib/rubygems/dependency_resolver/activation_request.rb +109 -0
- data/lib/rubygems/dependency_resolver/api_set.rb +65 -0
- data/lib/rubygems/dependency_resolver/api_specification.rb +36 -0
- data/lib/rubygems/dependency_resolver/composed_set.rb +18 -0
- data/lib/rubygems/dependency_resolver/current_set.rb +16 -0
- data/lib/rubygems/dependency_resolver/dependency_conflict.rb +85 -0
- data/lib/rubygems/dependency_resolver/dependency_request.rb +51 -0
- data/lib/rubygems/dependency_resolver/index_set.rb +59 -0
- data/lib/rubygems/dependency_resolver/index_specification.rb +53 -0
- data/lib/rubygems/dependency_resolver/installed_specification.rb +38 -0
- data/lib/rubygems/dependency_resolver/installer_set.rb +130 -0
- data/lib/rubygems/exceptions.rb +88 -1
- data/lib/rubygems/ext/builder.rb +1 -1
- data/lib/rubygems/gem_runner.rb +17 -9
- data/lib/rubygems/gemcutter_utilities.rb +72 -42
- data/lib/rubygems/install_default_message.rb +12 -0
- data/lib/rubygems/install_update_options.rb +3 -0
- data/lib/rubygems/installer.rb +55 -30
- data/lib/rubygems/name_tuple.rb +18 -7
- data/lib/rubygems/package.rb +50 -25
- data/lib/rubygems/package/tar_test_case.rb +9 -9
- data/lib/rubygems/package/tar_writer.rb +35 -12
- data/lib/rubygems/package_task.rb +2 -5
- data/lib/rubygems/path_support.rb +10 -0
- data/lib/rubygems/platform.rb +9 -3
- data/lib/rubygems/psych_additions.rb +1 -1
- data/lib/rubygems/remote_fetcher.rb +9 -276
- data/lib/rubygems/request.rb +267 -0
- data/lib/rubygems/request_set.rb +123 -125
- data/lib/rubygems/request_set/gem_dependency_api.rb +39 -0
- data/lib/rubygems/security.rb +32 -23
- data/lib/rubygems/security/policy.rb +35 -9
- data/lib/rubygems/security/signer.rb +2 -2
- data/lib/rubygems/server.rb +8 -16
- data/lib/rubygems/source.rb +25 -14
- data/lib/rubygems/source/installed.rb +28 -0
- data/lib/rubygems/source/local.rb +122 -0
- data/lib/rubygems/source/specific_file.rb +28 -0
- data/lib/rubygems/source_local.rb +2 -89
- data/lib/rubygems/source_specific_file.rb +2 -26
- data/lib/rubygems/spec_fetcher.rb +11 -11
- data/lib/rubygems/specification.rb +186 -198
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +88 -30
- data/lib/rubygems/ssl_certs/Entrust_net-Secure-Server-Certification-Authority.pem +90 -0
- data/lib/rubygems/ssl_certs/{GeoTrustGlobalCA.pem → GeoTrust_Global_CA.pem} +20 -20
- data/lib/rubygems/ssl_certs/VerisignClass3PublicPrimaryCertificationAuthority-G2.pem +57 -0
- data/lib/rubygems/stub_specification.rb +119 -0
- data/lib/rubygems/test_case.rb +117 -49
- data/lib/rubygems/uninstaller.rb +14 -9
- data/lib/rubygems/uri_formatter.rb +39 -0
- data/lib/rubygems/util/list.rb +44 -0
- data/lib/rubygems/version.rb +15 -5
- data/lib/rubygems/version_option.rb +8 -2
- data/test/rubygems/ca_cert.pem +23 -0
- data/test/rubygems/client.pem +49 -0
- data/test/rubygems/encrypted_private_key.pem +30 -0
- data/test/rubygems/invalid_client.pem +49 -0
- data/test/rubygems/specifications/bar-0.0.2.gemspec +9 -0
- data/test/rubygems/specifications/foo-0.0.1.gemspec +0 -0
- data/test/rubygems/test_gem.rb +76 -454
- data/test/rubygems/test_gem_command_manager.rb +23 -21
- data/test/rubygems/test_gem_commands_cert_command.rb +154 -14
- data/test/rubygems/test_gem_commands_cleanup_command.rb +15 -0
- data/test/rubygems/test_gem_commands_contents_command.rb +32 -4
- data/test/rubygems/test_gem_commands_environment_command.rb +9 -1
- data/test/rubygems/test_gem_commands_fetch_command.rb +2 -28
- data/test/rubygems/test_gem_commands_help_command.rb +6 -3
- data/test/rubygems/test_gem_commands_install_command.rb +2 -65
- data/test/rubygems/test_gem_commands_owner_command.rb +49 -0
- data/test/rubygems/test_gem_commands_pristine_command.rb +30 -0
- data/test/rubygems/test_gem_commands_sources_command.rb +1 -1
- data/test/rubygems/test_gem_commands_uninstall_command.rb +33 -0
- data/test/rubygems/test_gem_commands_update_command.rb +2 -1
- data/test/rubygems/test_gem_config_file.rb +12 -0
- data/test/rubygems/test_gem_dependency_installer.rb +58 -65
- data/test/rubygems/test_gem_dependency_resolver.rb +6 -3
- data/test/rubygems/test_gem_dependency_resolver_dependency_conflict.rb +36 -0
- data/test/rubygems/test_gem_ext_builder.rb +2 -4
- data/test/rubygems/test_gem_ext_ext_conf_builder.rb +7 -2
- data/test/rubygems/test_gem_gem_runner.rb +17 -13
- data/test/rubygems/test_gem_gemcutter_utilities.rb +6 -19
- data/test/rubygems/test_gem_impossible_dependencies_error.rb +41 -0
- data/test/rubygems/test_gem_install_update_options.rb +4 -1
- data/test/rubygems/test_gem_installer.rb +31 -2
- data/test/rubygems/test_gem_name_tuple.rb +22 -0
- data/test/rubygems/test_gem_package.rb +122 -11
- data/test/rubygems/test_gem_package_old.rb +8 -0
- data/test/rubygems/test_gem_package_tar_reader.rb +9 -8
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +1 -1
- data/test/rubygems/test_gem_package_tar_writer.rb +78 -56
- data/test/rubygems/test_gem_package_task.rb +2 -23
- data/test/rubygems/test_gem_path_support.rb +17 -0
- data/test/rubygems/test_gem_platform.rb +18 -0
- data/test/rubygems/test_gem_remote_fetcher.rb +106 -385
- data/test/rubygems/test_gem_request.rb +239 -0
- data/test/rubygems/test_gem_requirement.rb +9 -11
- data/test/rubygems/test_gem_security.rb +58 -2
- data/test/rubygems/test_gem_security_policy.rb +42 -1
- data/test/rubygems/test_gem_security_signer.rb +13 -1
- data/test/rubygems/test_gem_security_trust_dir.rb +5 -1
- data/test/rubygems/test_gem_server.rb +1 -105
- data/test/rubygems/test_gem_source.rb +4 -14
- data/test/rubygems/test_gem_source_local.rb +4 -4
- data/test/rubygems/test_gem_source_specific_file.rb +1 -1
- data/test/rubygems/test_gem_spec_fetcher.rb +0 -12
- data/test/rubygems/test_gem_specification.rb +452 -28
- data/test/rubygems/test_gem_stub_specification.rb +30 -0
- data/test/rubygems/test_gem_uninstaller.rb +14 -0
- data/test/rubygems/test_gem_uri_formatter.rb +20 -0
- data/test/rubygems/test_gem_version.rb +23 -13
- data/test/rubygems/test_gem_version_option.rb +63 -1
- data/test/rubygems/test_require.rb +0 -12
- data/util/create_encrypted_key.rb +16 -0
- metadata +161 -23
- metadata.gz.sig +0 -0
- data/CVE-2013-4287.txt +0 -36
- data/CVE-2013-4363.txt +0 -45
- data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
- data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
- data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
- data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
- data/test/rubygems/test_bundled_ca.rb +0 -59
- data/util/update_bundled_ca_certificates.rb +0 -103
@@ -1,575 +1,240 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rubygems/dependency'
|
3
3
|
require 'rubygems/exceptions'
|
4
|
+
require 'rubygems/util/list'
|
4
5
|
|
5
6
|
require 'uri'
|
6
7
|
require 'net/http'
|
7
8
|
|
8
|
-
|
9
|
+
##
|
10
|
+
# Given a set of Gem::Dependency objects as +needed+ and a way to query the
|
11
|
+
# set of available specs via +set+, calculates a set of ActivationRequest
|
12
|
+
# objects which indicate all the specs that should be activated to meet the
|
13
|
+
# all the requirements.
|
9
14
|
|
10
|
-
|
11
|
-
# Indicates which dependencies were incompatible.
|
12
|
-
#
|
13
|
-
class DependencyResolutionError < Gem::Exception
|
14
|
-
def initialize(conflict)
|
15
|
-
@conflict = conflict
|
16
|
-
a, b = conflicting_dependencies
|
15
|
+
class Gem::DependencyResolver
|
17
16
|
|
18
|
-
|
19
|
-
|
17
|
+
##
|
18
|
+
# Contains all the conflicts encountered while doing resolution
|
20
19
|
|
21
|
-
|
20
|
+
attr_reader :conflicts
|
22
21
|
|
23
|
-
|
24
|
-
@conflict.conflicting_dependencies
|
25
|
-
end
|
26
|
-
end
|
22
|
+
attr_accessor :development
|
27
23
|
|
28
|
-
|
29
|
-
# no spec.
|
30
|
-
#
|
31
|
-
class UnsatisfiableDepedencyError < Gem::Exception
|
32
|
-
def initialize(dep)
|
33
|
-
super "unable to find any gem matching dependency '#{dep}'"
|
24
|
+
attr_reader :missing
|
34
25
|
|
35
|
-
|
36
|
-
|
26
|
+
##
|
27
|
+
# When a missing dependency, don't stop. Just go on and record what was
|
28
|
+
# missing.
|
37
29
|
|
38
|
-
|
39
|
-
end
|
30
|
+
attr_accessor :soft_missing
|
40
31
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
class ImpossibleDependenciesError < Gem::Exception
|
45
|
-
def initialize(request, conflicts)
|
46
|
-
s = conflicts.size == 1 ? "" : "s"
|
47
|
-
super "detected #{conflicts.size} conflict#{s} with dependency '#{request.dependency}'"
|
48
|
-
@request = request
|
49
|
-
@conflicts = conflicts
|
50
|
-
end
|
32
|
+
def self.compose_sets *sets
|
33
|
+
Gem::DependencyResolver::ComposedSet.new(*sets)
|
34
|
+
end
|
51
35
|
|
52
|
-
|
53
|
-
|
54
|
-
|
36
|
+
##
|
37
|
+
# Provide a DependencyResolver that queries only against the already
|
38
|
+
# installed gems.
|
55
39
|
|
56
|
-
|
40
|
+
def self.for_current_gems needed
|
41
|
+
new needed, Gem::DependencyResolver::CurrentSet.new
|
57
42
|
end
|
58
43
|
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
# that should be activated to meet the all the requirements.
|
44
|
+
##
|
45
|
+
# Create DependencyResolver object which will resolve the tree starting
|
46
|
+
# with +needed+ Depedency objects.
|
63
47
|
#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
@version = Gem::Version.new api_data[:number]
|
78
|
-
@dependencies = api_data[:dependencies].map do |name, ver|
|
79
|
-
Gem::Dependency.new name, ver.split(/\s*,\s*/)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
attr_reader :name, :version, :dependencies
|
84
|
-
|
85
|
-
def == other # :nodoc:
|
86
|
-
self.class === other and
|
87
|
-
@set == other.set and
|
88
|
-
@name == other.name and
|
89
|
-
@version == other.version and
|
90
|
-
@dependencies == other.dependencies
|
91
|
-
end
|
92
|
-
|
93
|
-
def full_name
|
94
|
-
"#{@name}-#{@version}"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# The global rubygems pool, available via the rubygems.org API.
|
99
|
-
# Returns instances of APISpecification.
|
100
|
-
#
|
101
|
-
class APISet
|
102
|
-
def initialize
|
103
|
-
@data = Hash.new { |h,k| h[k] = [] }
|
104
|
-
@dep_uri = URI 'https://rubygems.org/api/v1/dependencies'
|
105
|
-
end
|
106
|
-
|
107
|
-
# Return data for all versions of the gem +name+.
|
108
|
-
#
|
109
|
-
def versions(name)
|
110
|
-
if @data.key?(name)
|
111
|
-
return @data[name]
|
112
|
-
end
|
113
|
-
|
114
|
-
uri = @dep_uri + "?gems=#{name}"
|
115
|
-
str = Gem::RemoteFetcher.fetcher.fetch_path uri
|
116
|
-
|
117
|
-
Marshal.load(str).each do |ver|
|
118
|
-
@data[ver[:name]] << ver
|
119
|
-
end
|
120
|
-
|
121
|
-
@data[name]
|
122
|
-
end
|
123
|
-
|
124
|
-
# Return an array of APISpecification objects matching
|
125
|
-
# DependencyRequest +req+.
|
126
|
-
#
|
127
|
-
def find_all(req)
|
128
|
-
res = []
|
129
|
-
|
130
|
-
versions(req.name).each do |ver|
|
131
|
-
if req.dependency.match? req.name, ver[:number]
|
132
|
-
res << APISpecification.new(self, ver)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
res
|
137
|
-
end
|
138
|
-
|
139
|
-
# A hint run by the resolver to allow the Set to fetch
|
140
|
-
# data for DependencyRequests +reqs+.
|
141
|
-
#
|
142
|
-
def prefetch(reqs)
|
143
|
-
names = reqs.map { |r| r.dependency.name }
|
144
|
-
needed = names.find_all { |d| !@data.key?(d) }
|
145
|
-
|
146
|
-
return if needed.empty?
|
147
|
-
|
148
|
-
uri = @dep_uri + "?gems=#{needed.sort.join ','}"
|
149
|
-
str = Gem::RemoteFetcher.fetcher.fetch_path uri
|
150
|
-
|
151
|
-
Marshal.load(str).each do |ver|
|
152
|
-
@data[ver[:name]] << ver
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# Represents a possible Specification object returned
|
158
|
-
# from IndexSet. Used to delay needed to download full
|
159
|
-
# Specification objects when only the +name+ and +version+
|
160
|
-
# are needed.
|
161
|
-
#
|
162
|
-
class IndexSpecification
|
163
|
-
def initialize(set, name, version, source, plat)
|
164
|
-
@set = set
|
165
|
-
@name = name
|
166
|
-
@version = version
|
167
|
-
@source = source
|
168
|
-
@platform = plat
|
169
|
-
|
170
|
-
@spec = nil
|
171
|
-
end
|
172
|
-
|
173
|
-
attr_reader :name, :version, :source
|
174
|
-
|
175
|
-
def full_name
|
176
|
-
"#{@name}-#{@version}"
|
177
|
-
end
|
178
|
-
|
179
|
-
def spec
|
180
|
-
@spec ||= @set.load_spec(@name, @version, @source)
|
181
|
-
end
|
182
|
-
|
183
|
-
def dependencies
|
184
|
-
spec.dependencies
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# The global rubygems pool represented via the traditional
|
189
|
-
# source index.
|
190
|
-
#
|
191
|
-
class IndexSet
|
192
|
-
def initialize
|
193
|
-
@f = Gem::SpecFetcher.fetcher
|
194
|
-
|
195
|
-
@all = Hash.new { |h,k| h[k] = [] }
|
196
|
-
|
197
|
-
list, _ = @f.available_specs(:released)
|
198
|
-
list.each do |uri, specs|
|
199
|
-
specs.each do |n|
|
200
|
-
@all[n.name] << [uri, n]
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
@specs = {}
|
205
|
-
end
|
206
|
-
|
207
|
-
# Return an array of IndexSpecification objects matching
|
208
|
-
# DependencyRequest +req+.
|
209
|
-
#
|
210
|
-
def find_all(req)
|
211
|
-
res = []
|
212
|
-
|
213
|
-
name = req.dependency.name
|
214
|
-
|
215
|
-
@all[name].each do |uri, n|
|
216
|
-
if req.dependency.match? n
|
217
|
-
res << IndexSpecification.new(self, n.name, n.version,
|
218
|
-
uri, n.platform)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
res
|
223
|
-
end
|
224
|
-
|
225
|
-
# No prefetching needed since we load the whole index in
|
226
|
-
# initially.
|
227
|
-
#
|
228
|
-
def prefetch(gems)
|
229
|
-
end
|
230
|
-
|
231
|
-
# Called from IndexSpecification to get a true Specification
|
232
|
-
# object.
|
233
|
-
#
|
234
|
-
def load_spec(name, ver, source)
|
235
|
-
key = "#{name}-#{ver}"
|
236
|
-
@specs[key] ||= source.fetch_spec(Gem::NameTuple.new(name, ver))
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
# A set which represents the installed gems. Respects
|
241
|
-
# all the normal settings that control where to look
|
242
|
-
# for installed gems.
|
243
|
-
#
|
244
|
-
class CurrentSet
|
245
|
-
def find_all(req)
|
246
|
-
req.dependency.matching_specs
|
247
|
-
end
|
248
|
-
|
249
|
-
def prefetch(gems)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
# Create DependencyResolver object which will resolve
|
254
|
-
# the tree starting with +needed+ Depedency objects.
|
255
|
-
#
|
256
|
-
# +set+ is an object that provides where to look for
|
257
|
-
# specifications to satisify the Dependencies. This
|
258
|
-
# defaults to IndexSet, which will query rubygems.org.
|
259
|
-
#
|
260
|
-
def initialize(needed, set=IndexSet.new)
|
261
|
-
@set = set || IndexSet.new # Allow nil to mean IndexSet
|
262
|
-
@needed = needed
|
263
|
-
|
264
|
-
@conflicts = nil
|
265
|
-
end
|
266
|
-
|
267
|
-
# Provide a DependencyResolver that queries only against
|
268
|
-
# the already installed gems.
|
269
|
-
#
|
270
|
-
def self.for_current_gems(needed)
|
271
|
-
new needed, CurrentSet.new
|
272
|
-
end
|
273
|
-
|
274
|
-
# Contains all the conflicts encountered while doing resolution
|
275
|
-
#
|
276
|
-
attr_reader :conflicts
|
277
|
-
|
278
|
-
# Proceed with resolution! Returns an array of ActivationRequest
|
279
|
-
# objects.
|
280
|
-
#
|
281
|
-
def resolve
|
282
|
-
@conflicts = []
|
283
|
-
|
284
|
-
needed = @needed.map { |n| DependencyRequest.new(n, nil) }
|
285
|
-
|
286
|
-
res = resolve_for needed, []
|
287
|
-
|
288
|
-
if res.kind_of? DependencyConflict
|
289
|
-
raise DependencyResolutionError.new(res)
|
290
|
-
end
|
291
|
-
|
292
|
-
res
|
293
|
-
end
|
294
|
-
|
295
|
-
# Used internally to indicate that a dependency conflicted
|
296
|
-
# with a spec that would be activated.
|
297
|
-
#
|
298
|
-
class DependencyConflict
|
299
|
-
def initialize(dependency, activated, failed_dep=dependency)
|
300
|
-
@dependency = dependency
|
301
|
-
@activated = activated
|
302
|
-
@failed_dep = failed_dep
|
303
|
-
end
|
304
|
-
|
305
|
-
attr_reader :dependency, :activated
|
306
|
-
|
307
|
-
# Return the Specification that listed the dependency
|
308
|
-
#
|
309
|
-
def requester
|
310
|
-
@failed_dep.requester
|
311
|
-
end
|
312
|
-
|
313
|
-
def for_spec?(spec)
|
314
|
-
@dependency.name == spec.name
|
315
|
-
end
|
48
|
+
# +set+ is an object that provides where to look for specifications to
|
49
|
+
# satisify the Dependencies. This defaults to IndexSet, which will query
|
50
|
+
# rubygems.org.
|
51
|
+
|
52
|
+
def initialize needed, set = nil
|
53
|
+
@set = set || Gem::DependencyResolver::IndexSet.new
|
54
|
+
@needed = needed
|
55
|
+
|
56
|
+
@conflicts = nil
|
57
|
+
@development = false
|
58
|
+
@missing = []
|
59
|
+
@soft_missing = false
|
60
|
+
end
|
316
61
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
end
|
62
|
+
def requests s, act, reqs=nil
|
63
|
+
s.dependencies.reverse_each do |d|
|
64
|
+
next if d.type == :development and not @development
|
65
|
+
reqs = Gem::List.new Gem::DependencyResolver::DependencyRequest.new(d, act), reqs
|
322
66
|
end
|
323
67
|
|
324
|
-
|
325
|
-
# which spec contained the Dependency.
|
326
|
-
#
|
327
|
-
class DependencyRequest
|
328
|
-
def initialize(dep, act)
|
329
|
-
@dependency = dep
|
330
|
-
@requester = act
|
331
|
-
end
|
68
|
+
@set.prefetch reqs
|
332
69
|
|
333
|
-
|
70
|
+
reqs
|
71
|
+
end
|
334
72
|
|
335
|
-
|
336
|
-
|
337
|
-
end
|
73
|
+
##
|
74
|
+
# Proceed with resolution! Returns an array of ActivationRequest objects.
|
338
75
|
|
339
|
-
|
340
|
-
|
341
|
-
end
|
76
|
+
def resolve
|
77
|
+
@conflicts = []
|
342
78
|
|
343
|
-
|
344
|
-
@dependency.to_s
|
345
|
-
end
|
79
|
+
needed = nil
|
346
80
|
|
347
|
-
|
348
|
-
|
349
|
-
when Dependency
|
350
|
-
@dependency == other
|
351
|
-
when DependencyRequest
|
352
|
-
@dependency == other.dependency && @requester == other.requester
|
353
|
-
else
|
354
|
-
false
|
355
|
-
end
|
356
|
-
end
|
81
|
+
@needed.reverse_each do |n|
|
82
|
+
needed = Gem::List.new(Gem::DependencyResolver::DependencyRequest.new(n, nil), needed)
|
357
83
|
end
|
358
84
|
|
359
|
-
|
360
|
-
# Also contains a dependency that was used to introduce this
|
361
|
-
# activation.
|
362
|
-
#
|
363
|
-
class ActivationRequest
|
364
|
-
def initialize(spec, req, others_possible=true)
|
365
|
-
@spec = spec
|
366
|
-
@request = req
|
367
|
-
@others_possible = others_possible
|
368
|
-
end
|
369
|
-
|
370
|
-
attr_reader :spec, :request
|
85
|
+
res = resolve_for needed, nil
|
371
86
|
|
372
|
-
|
373
|
-
|
374
|
-
#
|
375
|
-
def others_possible?
|
376
|
-
@others_possible
|
377
|
-
end
|
87
|
+
raise Gem::DependencyResolutionError, res if
|
88
|
+
res.kind_of? Gem::DependencyResolver::DependencyConflict
|
378
89
|
|
379
|
-
|
380
|
-
|
381
|
-
#
|
382
|
-
def parent
|
383
|
-
@request.requester
|
384
|
-
end
|
385
|
-
|
386
|
-
def name
|
387
|
-
@spec.name
|
388
|
-
end
|
389
|
-
|
390
|
-
def full_name
|
391
|
-
@spec.full_name
|
392
|
-
end
|
393
|
-
|
394
|
-
def version
|
395
|
-
@spec.version
|
396
|
-
end
|
397
|
-
|
398
|
-
def full_spec
|
399
|
-
Gem::Specification === @spec ? @spec : @spec.spec
|
400
|
-
end
|
90
|
+
res.to_a
|
91
|
+
end
|
401
92
|
|
402
|
-
|
403
|
-
|
404
|
-
|
93
|
+
##
|
94
|
+
# The meat of the algorithm. Given +needed+ DependencyRequest objects and
|
95
|
+
# +specs+ being a list to ActivationRequest, calculate a new list of
|
96
|
+
# ActivationRequest objects.
|
97
|
+
|
98
|
+
def resolve_for needed, specs
|
99
|
+
while needed
|
100
|
+
dep = needed.value
|
101
|
+
needed = needed.tail
|
102
|
+
|
103
|
+
# If there is already a spec activated for the requested name...
|
104
|
+
if specs && existing = specs.find { |s| dep.name == s.name }
|
105
|
+
|
106
|
+
# then we're done since this new dep matches the
|
107
|
+
# existing spec.
|
108
|
+
next if dep.matches_spec? existing
|
109
|
+
|
110
|
+
# There is a conflict! We return the conflict
|
111
|
+
# object which will be seen by the caller and be
|
112
|
+
# handled at the right level.
|
113
|
+
|
114
|
+
# If the existing activation indicates that there
|
115
|
+
# are other possibles for it, then issue the conflict
|
116
|
+
# on the dep for the activation itself. Otherwise, issue
|
117
|
+
# it on the requester's request itself.
|
118
|
+
#
|
119
|
+
if existing.others_possible?
|
120
|
+
conflict =
|
121
|
+
Gem::DependencyResolver::DependencyConflict.new dep, existing
|
405
122
|
else
|
406
|
-
|
123
|
+
depreq = existing.request.requester.request
|
124
|
+
conflict =
|
125
|
+
Gem::DependencyResolver::DependencyConflict.new depreq, existing, dep
|
407
126
|
end
|
127
|
+
@conflicts << conflict
|
408
128
|
|
409
|
-
|
410
|
-
|
411
|
-
source.download full_spec, path
|
412
|
-
end
|
413
|
-
|
414
|
-
def ==(other)
|
415
|
-
case other
|
416
|
-
when Gem::Specification
|
417
|
-
@spec == other
|
418
|
-
when ActivationRequest
|
419
|
-
@spec == other.spec && @request == other.request
|
420
|
-
else
|
421
|
-
false
|
422
|
-
end
|
129
|
+
return conflict
|
423
130
|
end
|
424
131
|
|
425
|
-
|
426
|
-
|
132
|
+
# Get a list of all specs that satisfy dep
|
133
|
+
possible = @set.find_all dep
|
427
134
|
|
428
|
-
|
429
|
-
|
135
|
+
case possible.size
|
136
|
+
when 0
|
137
|
+
@missing << dep
|
430
138
|
|
431
|
-
|
432
|
-
|
139
|
+
unless @soft_missing
|
140
|
+
# If there are none, then our work here is done.
|
141
|
+
raise Gem::UnsatisfiableDependencyError, dep
|
433
142
|
end
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
143
|
+
when 1
|
144
|
+
# If there is one, then we just add it to specs
|
145
|
+
# and process the specs dependencies by adding
|
146
|
+
# them to needed.
|
147
|
+
|
148
|
+
spec = possible.first
|
149
|
+
act = Gem::DependencyResolver::ActivationRequest.new spec, dep, false
|
150
|
+
|
151
|
+
specs = Gem::List.prepend specs, act
|
152
|
+
|
153
|
+
# Put the deps for at the beginning of needed
|
154
|
+
# rather than the end to match the depth first
|
155
|
+
# searching done by the multiple case code below.
|
156
|
+
#
|
157
|
+
# This keeps the error messages consistent.
|
158
|
+
needed = requests(spec, act, needed)
|
159
|
+
else
|
160
|
+
# There are multiple specs for this dep. This is
|
161
|
+
# the case that this class is built to handle.
|
162
|
+
|
163
|
+
# Sort them so that we try the highest versions
|
164
|
+
# first.
|
165
|
+
possible = possible.sort_by { |s| [s.source, s.version] }
|
166
|
+
|
167
|
+
# We track the conflicts seen so that we can report them
|
168
|
+
# to help the user figure out how to fix the situation.
|
169
|
+
conflicts = []
|
170
|
+
|
171
|
+
# To figure out which to pick, we keep resolving
|
172
|
+
# given each one being activated and if there isn't
|
173
|
+
# a conflict, we know we've found a full set.
|
174
|
+
#
|
175
|
+
# We use an until loop rather than #reverse_each
|
176
|
+
# to keep the stack short since we're using a recursive
|
177
|
+
# algorithm.
|
178
|
+
#
|
179
|
+
until possible.empty?
|
180
|
+
s = possible.pop
|
181
|
+
|
182
|
+
# Recursively call #resolve_for with this spec
|
183
|
+
# and add it's dependencies into the picture...
|
184
|
+
|
185
|
+
act = Gem::DependencyResolver::ActivationRequest.new s, dep
|
186
|
+
|
187
|
+
try = requests(s, act, needed)
|
188
|
+
|
189
|
+
res = resolve_for try, Gem::List.prepend(specs, act)
|
190
|
+
|
191
|
+
# While trying to resolve these dependencies, there may
|
192
|
+
# be a conflict!
|
193
|
+
|
194
|
+
if res.kind_of? Gem::DependencyResolver::DependencyConflict
|
195
|
+
# The conflict might be created not by this invocation
|
196
|
+
# but rather one up the stack, so if we can't attempt
|
197
|
+
# to resolve this conflict (conflict isn't with the spec +s+)
|
198
|
+
# then just return it so the caller can try to sort it out.
|
199
|
+
return res unless res.for_spec? s
|
200
|
+
|
201
|
+
# Otherwise, this is a conflict that we can attempt to fix
|
202
|
+
conflicts << [s, res]
|
203
|
+
|
204
|
+
# Optimization:
|
205
|
+
#
|
206
|
+
# Because the conflict indicates the dependency that trigger
|
207
|
+
# it, we can prune possible based on this new information.
|
208
|
+
#
|
209
|
+
# This cuts down on the number of iterations needed.
|
210
|
+
possible.delete_if { |x| !res.dependency.matches_spec? x }
|
475
211
|
else
|
476
|
-
|
477
|
-
|
212
|
+
# No conflict, return the specs
|
213
|
+
return res
|
478
214
|
end
|
479
|
-
@conflicts << conflict
|
480
|
-
|
481
|
-
return conflict
|
482
215
|
end
|
483
216
|
|
484
|
-
#
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
when 0
|
489
|
-
# If there are none, then our work here is done.
|
490
|
-
raise UnsatisfiableDepedencyError.new(dep)
|
491
|
-
when 1
|
492
|
-
# If there is one, then we just add it to specs
|
493
|
-
# and process the specs dependencies by adding
|
494
|
-
# them to needed.
|
495
|
-
|
496
|
-
spec = possible.first
|
497
|
-
act = ActivationRequest.new(spec, dep, false)
|
498
|
-
|
499
|
-
specs << act
|
500
|
-
|
501
|
-
# Put the deps for at the beginning of needed
|
502
|
-
# rather than the end to match the depth first
|
503
|
-
# searching done by the multiple case code below.
|
504
|
-
#
|
505
|
-
# This keeps the error messages consistent.
|
506
|
-
needed = requests(spec, act) + needed
|
507
|
-
else
|
508
|
-
# There are multiple specs for this dep. This is
|
509
|
-
# the case that this class is built to handle.
|
510
|
-
|
511
|
-
# Sort them so that we try the highest versions
|
512
|
-
# first.
|
513
|
-
possible = possible.sort_by { |s| s.version }
|
514
|
-
|
515
|
-
# We track the conflicts seen so that we can report them
|
516
|
-
# to help the user figure out how to fix the situation.
|
517
|
-
conflicts = []
|
518
|
-
|
519
|
-
# To figure out which to pick, we keep resolving
|
520
|
-
# given each one being activated and if there isn't
|
521
|
-
# a conflict, we know we've found a full set.
|
522
|
-
#
|
523
|
-
# We use an until loop rather than #reverse_each
|
524
|
-
# to keep the stack short since we're using a recursive
|
525
|
-
# algorithm.
|
526
|
-
#
|
527
|
-
until possible.empty?
|
528
|
-
s = possible.pop
|
529
|
-
|
530
|
-
# Recursively call #resolve_for with this spec
|
531
|
-
# and add it's dependencies into the picture...
|
532
|
-
|
533
|
-
act = ActivationRequest.new(s, dep)
|
534
|
-
|
535
|
-
try = requests(s, act) + needed
|
536
|
-
|
537
|
-
res = resolve_for(try, specs + [act])
|
538
|
-
|
539
|
-
# While trying to resolve these dependencies, there may
|
540
|
-
# be a conflict!
|
541
|
-
|
542
|
-
if res.kind_of? DependencyConflict
|
543
|
-
# The conflict might be created not by this invocation
|
544
|
-
# but rather one up the stack, so if we can't attempt
|
545
|
-
# to resolve this conflict (conflict isn't with the spec +s+)
|
546
|
-
# then just return it so the caller can try to sort it out.
|
547
|
-
return res unless res.for_spec? s
|
548
|
-
|
549
|
-
# Otherwise, this is a conflict that we can attempt to fix
|
550
|
-
conflicts << [s, res]
|
551
|
-
|
552
|
-
# Optimization:
|
553
|
-
#
|
554
|
-
# Because the conflict indicates the dependency that trigger
|
555
|
-
# it, we can prune possible based on this new information.
|
556
|
-
#
|
557
|
-
# This cuts down on the number of iterations needed.
|
558
|
-
possible.delete_if { |x| !res.dependency.matches_spec? x }
|
559
|
-
else
|
560
|
-
# No conflict, return the specs
|
561
|
-
return res
|
562
|
-
end
|
563
|
-
end
|
564
|
-
|
565
|
-
# We tried all possibles and nothing worked, so we let the user
|
566
|
-
# know and include as much information about the problem since
|
567
|
-
# the user is going to have to take action to fix this.
|
568
|
-
raise ImpossibleDependenciesError.new(dep, conflicts)
|
569
|
-
end
|
217
|
+
# We tried all possibles and nothing worked, so we let the user
|
218
|
+
# know and include as much information about the problem since
|
219
|
+
# the user is going to have to take action to fix this.
|
220
|
+
raise Gem::ImpossibleDependenciesError.new(dep, conflicts)
|
570
221
|
end
|
571
|
-
|
572
|
-
specs
|
573
222
|
end
|
223
|
+
|
224
|
+
specs
|
574
225
|
end
|
226
|
+
|
575
227
|
end
|
228
|
+
|
229
|
+
require 'rubygems/dependency_resolver/api_set'
|
230
|
+
require 'rubygems/dependency_resolver/api_specification'
|
231
|
+
require 'rubygems/dependency_resolver/activation_request'
|
232
|
+
require 'rubygems/dependency_resolver/composed_set'
|
233
|
+
require 'rubygems/dependency_resolver/current_set'
|
234
|
+
require 'rubygems/dependency_resolver/dependency_conflict'
|
235
|
+
require 'rubygems/dependency_resolver/dependency_request'
|
236
|
+
require 'rubygems/dependency_resolver/index_set'
|
237
|
+
require 'rubygems/dependency_resolver/index_specification'
|
238
|
+
require 'rubygems/dependency_resolver/installed_specification'
|
239
|
+
require 'rubygems/dependency_resolver/installer_set'
|
240
|
+
|