rubygems-update 0.8.3
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.
- data/ChangeLog +2335 -0
- data/README +54 -0
- data/Rakefile +293 -0
- data/Releases +98 -0
- data/TODO +7 -0
- data/bin/gem +11 -0
- data/bin/gem_server +111 -0
- data/bin/generate_yaml_index.rb +58 -0
- data/bin/update_rubygems +18 -0
- data/doc/doc.css +73 -0
- data/doc/makedoc.rb +4 -0
- data/examples/application/an-app.gemspec +26 -0
- data/examples/application/bin/myapp +3 -0
- data/examples/application/lib/somefunctionality.rb +3 -0
- data/gemspecs/README +4 -0
- data/gemspecs/cgikit-1.1.0.gemspec +18 -0
- data/gemspecs/jabber4r.gemspec +26 -0
- data/gemspecs/linguistics.gemspec +22 -0
- data/gemspecs/ook.gemspec +21 -0
- data/gemspecs/progressbar.gemspec +22 -0
- data/gemspecs/redcloth.gemspec +22 -0
- data/gemspecs/rublog.gemspec +23 -0
- data/gemspecs/ruby-doom.gemspec +21 -0
- data/gemspecs/rubyjdwp.gemspec +21 -0
- data/gemspecs/statistics.gemspec +21 -0
- data/lib/rubygems.rb +353 -0
- data/lib/rubygems/builder.rb +54 -0
- data/lib/rubygems/cmd_manager.rb +127 -0
- data/lib/rubygems/command.rb +191 -0
- data/lib/rubygems/config_file.rb +57 -0
- data/lib/rubygems/doc_manager.rb +94 -0
- data/lib/rubygems/format.rb +65 -0
- data/lib/rubygems/gem_commands.rb +925 -0
- data/lib/rubygems/gem_runner.rb +23 -0
- data/lib/rubygems/installer.rb +621 -0
- data/lib/rubygems/loadpath_manager.rb +108 -0
- data/lib/rubygems/old_format.rb +150 -0
- data/lib/rubygems/open-uri.rb +604 -0
- data/lib/rubygems/package.rb +740 -0
- data/lib/rubygems/remote_installer.rb +499 -0
- data/lib/rubygems/rubygems_version.rb +6 -0
- data/lib/rubygems/source_index.rb +130 -0
- data/lib/rubygems/specification.rb +613 -0
- data/lib/rubygems/user_interaction.rb +176 -0
- data/lib/rubygems/validator.rb +148 -0
- data/lib/rubygems/version.rb +279 -0
- data/lib/ubygems.rb +4 -0
- data/pkgs/sources/lib/sources.rb +6 -0
- data/pkgs/sources/sources.gemspec +14 -0
- data/post-install.rb +75 -0
- data/redist/session.gem +433 -0
- data/scripts/buildtests.rb +25 -0
- data/scripts/gemdoc.rb +62 -0
- data/scripts/runtest.rb +17 -0
- data/scripts/specdoc.rb +164 -0
- data/setup.rb +1360 -0
- data/test/bogussources.rb +5 -0
- data/test/data/legacy/keyedlist-0.4.0.ruby +11 -0
- data/test/data/legacy/keyedlist-0.4.0.yaml +16 -0
- data/test/data/lib/code.rb +1 -0
- data/test/data/one/README.one +1 -0
- data/test/data/one/lib/one.rb +3 -0
- data/test/data/one/one.gemspec +17 -0
- data/test/data/one/one.yaml +40 -0
- data/test/functional.rb +145 -0
- data/test/gemenvironment.rb +45 -0
- data/test/gemutilities.rb +18 -0
- data/test/insure_session.rb +46 -0
- data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +5 -0
- data/test/mock/gems/specifications/sources-0.0.1.gemspec +8 -0
- data/test/mockgemui.rb +45 -0
- data/test/onegem.rb +23 -0
- data/test/simple_gem.rb +66 -0
- data/test/test_builder.rb +13 -0
- data/test/test_cached_fetcher.rb +60 -0
- data/test/test_check_command.rb +28 -0
- data/test/test_command.rb +130 -0
- data/test/test_configfile.rb +36 -0
- data/test/test_format.rb +70 -0
- data/test/test_gemloadpaths.rb +45 -0
- data/test/test_gempaths.rb +115 -0
- data/test/test_loadmanager.rb +40 -0
- data/test/test_local_cache.rb +157 -0
- data/test/test_package.rb +600 -0
- data/test/test_parse_commands.rb +179 -0
- data/test/test_process_commands.rb +21 -0
- data/test/test_remote_fetcher.rb +162 -0
- data/test/test_remote_installer.rb +154 -0
- data/test/test_source_index.rb +58 -0
- data/test/test_specification.rb +286 -0
- data/test/test_validator.rb +53 -0
- data/test/test_version_comparison.rb +204 -0
- data/test/testgem.rc +6 -0
- data/test/user_capture.rb +1 -0
- data/test/yaml_data.rb +59 -0
- metadata +151 -0
@@ -0,0 +1,499 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'socket'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Gem
|
6
|
+
class DependencyError < Gem::Exception; end
|
7
|
+
class RemoteSourceException < Gem::Exception; end
|
8
|
+
class GemNotFoundException < Gem::Exception; end
|
9
|
+
class RemoteInstallationCancelled < Gem::Exception; end
|
10
|
+
|
11
|
+
# RemoteSourceFetcher handles the details of fetching gems and gem
|
12
|
+
# information from a remote source.
|
13
|
+
class RemoteSourceFetcher
|
14
|
+
include UserInteraction
|
15
|
+
|
16
|
+
# Initialize a remote fetcher using the source URI (and possible
|
17
|
+
# proxy information).
|
18
|
+
def initialize(source_uri, proxy)
|
19
|
+
@uri = source_uri
|
20
|
+
@http_proxy = proxy
|
21
|
+
if @http_proxy == true
|
22
|
+
@http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# The uncompressed +size+ of the source's directory (e.g. source
|
27
|
+
# info).
|
28
|
+
def size
|
29
|
+
@size ||= get_size("/yaml")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Fetch the data from the source at the given path.
|
33
|
+
def fetch_path(path="")
|
34
|
+
read_data(@uri + path)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get the source index from the gem source. The source index is a
|
38
|
+
# directory of the gems available on the source, formatted as a
|
39
|
+
# Gem::Cache object. The cache object allows easy searching for
|
40
|
+
# gems by name and version requirement.
|
41
|
+
#
|
42
|
+
# Notice that the gem specs in the cache are adequate for searches
|
43
|
+
# and queries, but may have some information elided (hence
|
44
|
+
# "abbreviated").
|
45
|
+
def source_index
|
46
|
+
say "Updating Gem source index for: #{@uri}"
|
47
|
+
begin
|
48
|
+
require 'zlib'
|
49
|
+
yaml_spec = fetch_path("/yaml.Z")
|
50
|
+
yaml_spec = Zlib::Inflate.inflate(yaml_spec)
|
51
|
+
rescue
|
52
|
+
yaml_spec = nil
|
53
|
+
end
|
54
|
+
begin
|
55
|
+
yaml_spec = fetch_path("/yaml") unless yaml_spec
|
56
|
+
r = convert_spec(yaml_spec)
|
57
|
+
rescue SocketError => e
|
58
|
+
raise RemoteSourceException.new("Error fetching remote gem cache: #{e.to_s}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Connect to the source host/port, using a proxy if needed.
|
65
|
+
def connect_to(host, port)
|
66
|
+
if @http_proxy
|
67
|
+
proxy_uri = URI.parse(@http_proxy)
|
68
|
+
Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(host, port)
|
69
|
+
else
|
70
|
+
Net::HTTP.new(host, port)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Get the size of the (non-compressed) data from the source at the
|
75
|
+
# given path.
|
76
|
+
def get_size(path)
|
77
|
+
read_size(@uri + path)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Read the size of the (source based) URI using an HTTP HEAD
|
81
|
+
# command.
|
82
|
+
def read_size(uri)
|
83
|
+
require 'net/http'
|
84
|
+
require 'uri'
|
85
|
+
u = URI.parse(uri)
|
86
|
+
http = connect_to(u.host, u.port)
|
87
|
+
path = (u.path == "") ? "/" : u.path
|
88
|
+
resp = http.head(path)
|
89
|
+
fail RemoteSourceException, "HTTP Response #{resp.code}" if resp.code !~ /^2/
|
90
|
+
resp['content-length'].to_i
|
91
|
+
end
|
92
|
+
|
93
|
+
# Read the data from the (source based) URI.
|
94
|
+
def read_data(uri)
|
95
|
+
require 'rubygems/open-uri'
|
96
|
+
open(uri,
|
97
|
+
"User-Agent" => "RubyGems/#{Gem::RubyGemsVersion}",
|
98
|
+
:proxy => @http_proxy
|
99
|
+
) do |input|
|
100
|
+
input.read
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Convert the yamlized string spec into a real spec (actually,
|
105
|
+
# these are hashes of specs.).
|
106
|
+
def convert_spec(yaml_spec)
|
107
|
+
YAML.load(reduce_spec(yaml_spec)) or
|
108
|
+
raise "Didn't get a valid YAML document"
|
109
|
+
end
|
110
|
+
|
111
|
+
# This reduces the source spec in size so that YAML bugs with
|
112
|
+
# large data sets will be dodged. Obviously this is a workaround,
|
113
|
+
# but it allows Gems to continue to work until the YAML bug is
|
114
|
+
# fixed.
|
115
|
+
def reduce_spec(yaml_spec)
|
116
|
+
result = ""
|
117
|
+
state = :copy
|
118
|
+
yaml_spec.each do |line|
|
119
|
+
if state == :copy && line =~ /^\s+files:\s*$/
|
120
|
+
state = :skip
|
121
|
+
result << line.sub(/$/, " []")
|
122
|
+
elsif state == :skip
|
123
|
+
if line !~ /^\s+-/
|
124
|
+
state = :copy
|
125
|
+
end
|
126
|
+
end
|
127
|
+
result << line if state == :copy
|
128
|
+
end
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
class << self
|
133
|
+
# Sent by the client when it is done with all the sources,
|
134
|
+
# allowing any cleanup activity to take place.
|
135
|
+
def finish
|
136
|
+
# Nothing to do
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# LocalSourceInfoCache implements the cache management policy on
|
142
|
+
# where the source info is stored on local file system. There are
|
143
|
+
# two possible cache locations: (1) the system wide cache, and (2)
|
144
|
+
# the user specific cache.
|
145
|
+
#
|
146
|
+
# * The system cache is prefered if it is writable (or can be
|
147
|
+
# created).
|
148
|
+
# * The user cache is used if the system cache is not writable (or
|
149
|
+
# can not be created).
|
150
|
+
#
|
151
|
+
# Once a cache is selected, it will be used for all operations. It
|
152
|
+
# will not switch between cache files dynamically.
|
153
|
+
#
|
154
|
+
class LocalSourceInfoCache
|
155
|
+
|
156
|
+
# The most recent cache data.
|
157
|
+
def cache_data
|
158
|
+
@dirty = false
|
159
|
+
@cache_data ||= read_cache
|
160
|
+
end
|
161
|
+
|
162
|
+
# Write data to the proper cache.
|
163
|
+
def write_cache
|
164
|
+
data = cache_data
|
165
|
+
open(writable_file, "w") do |f|
|
166
|
+
f.puts data.to_yaml
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# The name of the system cache file.
|
171
|
+
def system_cache_file
|
172
|
+
@sysetm_cache ||= File.join(Gem.dir, "source_cache")
|
173
|
+
end
|
174
|
+
|
175
|
+
# The name of the user cache file.
|
176
|
+
def user_cache_file
|
177
|
+
@user_cache ||=
|
178
|
+
ENV['GEMCACHE'] || File.join(Gem.user_home, ".gem/source_cache")
|
179
|
+
end
|
180
|
+
|
181
|
+
# Mark the cache as updated (i.e. dirty).
|
182
|
+
def update
|
183
|
+
@dirty = true
|
184
|
+
end
|
185
|
+
|
186
|
+
# Write the cache to a local file (if it is dirty).
|
187
|
+
def flush
|
188
|
+
write_cache if @dirty
|
189
|
+
@dirty = false
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
# Find a writable cache file.
|
195
|
+
def writable_file
|
196
|
+
@cache_file
|
197
|
+
end
|
198
|
+
|
199
|
+
# Read the most current cache data.
|
200
|
+
def read_cache
|
201
|
+
@cache_file = select_cache_file
|
202
|
+
open(@cache_file) { |f| YAML.load(f) } || {}
|
203
|
+
end
|
204
|
+
|
205
|
+
# Select a writable cache file
|
206
|
+
def select_cache_file
|
207
|
+
try_file(system_cache_file) or
|
208
|
+
try_file(user_cache_file) or
|
209
|
+
fail "Unable to locate a writable cache file."
|
210
|
+
end
|
211
|
+
|
212
|
+
# Determine if +fn+ is a candidate for a cache file. Return fn if
|
213
|
+
# it is. Return nil if it is not.
|
214
|
+
def try_file(fn)
|
215
|
+
return fn if File.writable?(fn)
|
216
|
+
return nil if File.exist?(fn)
|
217
|
+
dir = File.dirname(fn)
|
218
|
+
if ! File.exist? dir
|
219
|
+
begin
|
220
|
+
FileUtils.mkdir_p(dir)
|
221
|
+
rescue RuntimeError
|
222
|
+
return nil
|
223
|
+
end
|
224
|
+
end
|
225
|
+
if File.writable?(dir)
|
226
|
+
FileUtils.touch fn
|
227
|
+
return fn
|
228
|
+
end
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
# CachedFetcher is a decorator that adds local file caching to
|
235
|
+
# RemoteSourceFetcher objects.
|
236
|
+
class CachedFetcher
|
237
|
+
|
238
|
+
# Create a cached fetcher (based on a RemoteSourceFetcher) for the
|
239
|
+
# source at +source_uri+ (through the proxy +proxy+).
|
240
|
+
def initialize(source_uri, proxy)
|
241
|
+
@source_uri = source_uri
|
242
|
+
@fetcher = RemoteSourceFetcher.new(source_uri, proxy)
|
243
|
+
end
|
244
|
+
|
245
|
+
# The uncompressed +size+ of the source's directory (e.g. source
|
246
|
+
# info).
|
247
|
+
def size
|
248
|
+
@fetcher.size
|
249
|
+
end
|
250
|
+
|
251
|
+
# Fetch the data from the source at the given path.
|
252
|
+
def fetch_path(path="")
|
253
|
+
@fetcher.fetch_path(path)
|
254
|
+
end
|
255
|
+
|
256
|
+
# Get the source index from the gem source. The source index is a
|
257
|
+
# directory of the gems available on the source, formatted as a
|
258
|
+
# Gem::Cache object. The cache object allows easy searching for
|
259
|
+
# gems by name and version requirement.
|
260
|
+
#
|
261
|
+
# Notice that the gem specs in the cache are adequate for searches
|
262
|
+
# and queries, but may have some information elided (hence
|
263
|
+
# "abbreviated").
|
264
|
+
def source_index
|
265
|
+
cache = manager.cache_data[@source_uri]
|
266
|
+
if cache && cache['size'] == @fetcher.size
|
267
|
+
cache['cache']
|
268
|
+
else
|
269
|
+
result = @fetcher.source_index
|
270
|
+
manager.cache_data[@source_uri] = {
|
271
|
+
'size' => @fetcher.size,
|
272
|
+
'cache' => result,
|
273
|
+
}
|
274
|
+
manager.update
|
275
|
+
result
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Flush the cache to a local file, if needed.
|
280
|
+
def flush
|
281
|
+
manager.flush
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
# The cache manager for this cached source.
|
287
|
+
def manager
|
288
|
+
self.class.manager
|
289
|
+
end
|
290
|
+
|
291
|
+
# The cache is shared between all caching fetchers, so the cache
|
292
|
+
# is put in the class object.
|
293
|
+
class << self
|
294
|
+
|
295
|
+
# The Cache manager for all instances of this class.
|
296
|
+
def manager
|
297
|
+
@manager ||= LocalSourceInfoCache.new
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
# Sent by the client when it is done with all the sources,
|
302
|
+
# allowing any cleanup activity to take place.
|
303
|
+
def finish
|
304
|
+
manager.flush
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
class RemoteInstaller
|
311
|
+
include UserInteraction
|
312
|
+
|
313
|
+
# <tt>http_proxy</tt>::
|
314
|
+
# * [String]: explicit specification of proxy; overrides any
|
315
|
+
# environment variable setting
|
316
|
+
# * nil: respect environment variables
|
317
|
+
# * <tt>:no_proxy</tt>: ignore environment variables and _don't_
|
318
|
+
# use a proxy
|
319
|
+
#
|
320
|
+
def initialize(http_proxy=nil)
|
321
|
+
# Ensure http_proxy env vars are used if no proxy explicitly supplied.
|
322
|
+
@http_proxy =
|
323
|
+
case http_proxy
|
324
|
+
when :no_proxy
|
325
|
+
false
|
326
|
+
when nil
|
327
|
+
true
|
328
|
+
else
|
329
|
+
http_proxy.to_str
|
330
|
+
end
|
331
|
+
@fetcher_class = CachedFetcher
|
332
|
+
end
|
333
|
+
|
334
|
+
# This method will install package_name onto the local system.
|
335
|
+
#
|
336
|
+
# gem_name::
|
337
|
+
# [String] Name of the Gem to install
|
338
|
+
#
|
339
|
+
# version_requirement::
|
340
|
+
# [default = "> 0.0.0"] Gem version requirement to install
|
341
|
+
#
|
342
|
+
# Returns::
|
343
|
+
# an array of Gem::Specification objects, one for each gem installed.
|
344
|
+
#
|
345
|
+
def install(gem_name,
|
346
|
+
version_requirement = "> 0.0.0",
|
347
|
+
force=false,
|
348
|
+
install_dir=Gem.dir,
|
349
|
+
install_stub=true)
|
350
|
+
unless version_requirement.respond_to?(:satisfied_by?)
|
351
|
+
version_requirement = Version::Requirement.new(version_requirement)
|
352
|
+
end
|
353
|
+
installed_gems = []
|
354
|
+
caches = source_index_hash
|
355
|
+
spec, source = find_gem_to_install(gem_name, version_requirement, caches)
|
356
|
+
dependencies = find_dependencies_not_installed(spec.dependencies)
|
357
|
+
installed_gems << install_dependencies(dependencies, force, install_dir)
|
358
|
+
cache_dir = File.join(install_dir, "cache")
|
359
|
+
destination_file = File.join(cache_dir, spec.full_name + ".gem")
|
360
|
+
download_gem(destination_file, source, spec)
|
361
|
+
installer = new_installer(destination_file)
|
362
|
+
installed_gems.unshift installer.install(force, install_dir, install_stub)
|
363
|
+
installed_gems.flatten
|
364
|
+
end
|
365
|
+
|
366
|
+
# Search Gem repository for a gem by specifying all or part of
|
367
|
+
# the Gem's name
|
368
|
+
def search(pattern_to_match)
|
369
|
+
results = []
|
370
|
+
caches = source_index_hash
|
371
|
+
caches.each do |cache|
|
372
|
+
results << cache[1].search(pattern_to_match)
|
373
|
+
end
|
374
|
+
results
|
375
|
+
end
|
376
|
+
|
377
|
+
# Return a list of the sources that we can download gems from
|
378
|
+
def sources
|
379
|
+
unless @sources
|
380
|
+
require_gem("sources")
|
381
|
+
@sources = Gem.sources
|
382
|
+
end
|
383
|
+
@sources
|
384
|
+
end
|
385
|
+
|
386
|
+
# Return a hash mapping the available source names to the source
|
387
|
+
# index of that source.
|
388
|
+
def source_index_hash
|
389
|
+
result = {}
|
390
|
+
sources.each do |source|
|
391
|
+
result[source] = fetch_source(source)
|
392
|
+
end
|
393
|
+
@fetcher_class.finish
|
394
|
+
result
|
395
|
+
end
|
396
|
+
|
397
|
+
# Return the source info for the given source. The
|
398
|
+
def fetch_source(source)
|
399
|
+
rsf = @fetcher_class.new(source, @http_proxy)
|
400
|
+
rsf.source_index
|
401
|
+
end
|
402
|
+
|
403
|
+
# Find a gem to be installed by interacting with the user.
|
404
|
+
def find_gem_to_install(gem_name, version_requirement, caches)
|
405
|
+
max_version = Version.new("0.0.0")
|
406
|
+
specs_n_sources = []
|
407
|
+
caches.each do |source, cache|
|
408
|
+
cache.each do |name, spec|
|
409
|
+
if (/#{gem_name}/i === name &&
|
410
|
+
version_requirement.satisfied_by?(spec.version))
|
411
|
+
specs_n_sources << [spec, source]
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
if specs_n_sources.size == 0
|
416
|
+
raise GemNotFoundException.new(
|
417
|
+
"Could not find #{gem_name} (#{version_requirement}) in the repository")
|
418
|
+
end
|
419
|
+
specs_n_sources = specs_n_sources.sort_by { |x| x[0].version }.reverse
|
420
|
+
if specs_n_sources.reject { |item|
|
421
|
+
item[0].platform.nil? || item[0].platform==Platform::RUBY
|
422
|
+
}.size == 0
|
423
|
+
# only non-binary gems...return latest
|
424
|
+
return specs_n_sources.first
|
425
|
+
end
|
426
|
+
list = specs_n_sources.collect {|item|
|
427
|
+
"#{item[0].name} #{item[0].version} (#{item[0].platform.to_s})"
|
428
|
+
}
|
429
|
+
list << "Cancel installation"
|
430
|
+
string, index = choose_from_list(
|
431
|
+
"Select which gem to install for your platform (#{RUBY_PLATFORM})",
|
432
|
+
list)
|
433
|
+
raise RemoteInstallationCancelled.new("Installation of #{gem_name} cancelled.") if
|
434
|
+
index == (list.size - 1)
|
435
|
+
specs_n_sources[index]
|
436
|
+
end
|
437
|
+
|
438
|
+
def find_dependencies_not_installed(dependencies)
|
439
|
+
to_install = []
|
440
|
+
dependencies.each do |dependency|
|
441
|
+
begin
|
442
|
+
require_gem(dependency.name, *dependency.requirement_list)
|
443
|
+
rescue LoadError => e
|
444
|
+
to_install.push dependency
|
445
|
+
end
|
446
|
+
end
|
447
|
+
to_install
|
448
|
+
end
|
449
|
+
|
450
|
+
# Install all the given dependencies. Returns an array of
|
451
|
+
# Gem::Specification objects, one for each dependency installed.
|
452
|
+
#
|
453
|
+
# TODO: For now, we recursively install, but this is not the right
|
454
|
+
# way to do things (e.g. if a package fails to download, we
|
455
|
+
# shouldn't install anything).
|
456
|
+
def install_dependencies(dependencies, force, install_dir)
|
457
|
+
installed_gems = []
|
458
|
+
dependencies.each do |dependency|
|
459
|
+
if ask_yes_no("Install required dependency #{dependency.name}?", true)
|
460
|
+
remote_installer = RemoteInstaller.new(
|
461
|
+
if @http_proxy == false
|
462
|
+
:no_proxy
|
463
|
+
elsif @http_proxy == true
|
464
|
+
else
|
465
|
+
@http_proxy
|
466
|
+
end
|
467
|
+
)
|
468
|
+
installed_gems << remote_installer.install(
|
469
|
+
dependency.name,
|
470
|
+
dependency.version_requirements,
|
471
|
+
force,
|
472
|
+
install_dir)
|
473
|
+
else
|
474
|
+
raise DependencyError.new("Required dependency #{dependency.name} not installed")
|
475
|
+
end
|
476
|
+
end
|
477
|
+
installed_gems
|
478
|
+
end
|
479
|
+
|
480
|
+
def download_gem(destination_file, source, spec)
|
481
|
+
rsf = @fetcher_class.new(source, @http_proxy)
|
482
|
+
path = "/gems/#{spec.full_name}.gem"
|
483
|
+
response = rsf.fetch_path(path)
|
484
|
+
write_gem_to_file(response, destination_file)
|
485
|
+
end
|
486
|
+
|
487
|
+
def write_gem_to_file(body, destination_file)
|
488
|
+
FileUtils.mkdir_p(File.dirname(destination_file)) unless File.exist?(destination_file)
|
489
|
+
File.open(destination_file, 'wb') do |out|
|
490
|
+
out.write(body)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def new_installer(gem)
|
495
|
+
return Installer.new(gem)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|