rubygems-update 0.8.11 → 0.9.0
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 +199 -1
- data/README +6 -4
- data/Rakefile +46 -14
- data/bin/gem +6 -0
- data/bin/gem_mirror +7 -1
- data/bin/gem_server +3 -5
- data/bin/gemlock +127 -0
- data/bin/gemri +24 -0
- data/bin/gemwhich +39 -11
- data/bin/index_gem_repository.rb +280 -0
- data/bin/update_rubygems +6 -0
- data/doc/makedoc.rb +7 -1
- data/examples/application/lib/somefunctionality.rb +6 -0
- data/lib/gemconfigure.rb +6 -0
- data/lib/rbconfig/datadir.rb +24 -0
- data/lib/rubygems.rb +90 -24
- data/lib/rubygems/builder.rb +6 -0
- data/lib/rubygems/cmd_manager.rb +36 -30
- data/lib/rubygems/command.rb +90 -29
- data/lib/rubygems/config_file.rb +45 -2
- data/lib/rubygems/custom_require.rb +12 -6
- data/lib/rubygems/dependency_list.rb +6 -0
- data/lib/rubygems/doc_manager.rb +79 -34
- data/lib/rubygems/format.rb +6 -0
- data/lib/rubygems/gem_commands.rb +209 -88
- data/lib/rubygems/gem_openssl.rb +12 -0
- data/lib/rubygems/gem_runner.rb +25 -10
- data/lib/rubygems/incremental_fetcher.rb +136 -0
- data/lib/rubygems/installer.rb +103 -28
- data/lib/rubygems/loadpath_manager.rb +6 -0
- data/lib/rubygems/old_format.rb +6 -0
- data/lib/rubygems/open-uri.rb +231 -79
- data/lib/rubygems/package.rb +5 -3
- data/lib/rubygems/remote_installer.rb +89 -52
- data/lib/rubygems/rubygems_version.rb +1 -1
- data/lib/rubygems/security.rb +6 -0
- data/lib/rubygems/source_index.rb +115 -52
- data/lib/rubygems/specification.rb +92 -76
- data/lib/rubygems/timer.rb +6 -0
- data/lib/rubygems/user_interaction.rb +88 -4
- data/lib/rubygems/validator.rb +6 -0
- data/lib/rubygems/version.rb +6 -0
- data/lib/ubygems.rb +6 -0
- data/post-install.rb +6 -0
- data/scripts/buildtests.rb +6 -0
- data/scripts/gemdoc.rb +6 -0
- data/scripts/runtest.rb +6 -0
- data/scripts/specdoc.rb +6 -0
- data/scripts/upload_gemdoc.rb +6 -0
- data/test/bogussources.rb +6 -2
- data/test/data/PostMessage-0.0.1.gem +0 -0
- data/test/data/a-0.0.1.gem +0 -0
- data/test/data/a-0.0.2.gem +0 -0
- data/test/data/b-0.0.2.gem +0 -0
- data/test/data/c-1.2.gem +0 -0
- data/test/data/gemhome/cache/a-0.0.1.gem +0 -0
- data/test/data/gemhome/cache/a-0.0.2.gem +0 -0
- data/test/data/gemhome/cache/b-0.0.2.gem +0 -0
- data/test/data/gemhome/cache/c-1.2.gem +0 -0
- data/test/data/gemhome/gems/a-0.0.1/lib/code.rb +6 -0
- data/test/data/gemhome/gems/a-0.0.2/lib/code.rb +6 -0
- data/test/data/gemhome/gems/b-0.0.2/lib/code.rb +6 -0
- data/test/data/gemhome/gems/c-1.2/lib/code.rb +6 -0
- data/test/data/gemhome/specifications/a-0.0.1.gemspec +1 -1
- data/test/data/gemhome/specifications/a-0.0.2.gemspec +1 -1
- data/test/data/gemhome/specifications/b-0.0.2.gemspec +1 -1
- data/test/data/gemhome/specifications/c-1.2.gemspec +1 -1
- data/test/data/lib/code.rb +6 -0
- data/test/data/one/lib/one.rb +6 -0
- data/test/data/one/one-0.0.1.gem +0 -0
- data/test/data/post_install.gemspec +19 -0
- data/test/fake_certlib/openssl.rb +6 -0
- data/test/functional.rb +15 -1
- data/test/functional_generate_yaml_index.rb +101 -0
- data/test/gemenvironment.rb +8 -0
- data/test/gemutilities.rb +18 -2
- data/test/insure_session.rb +6 -0
- data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +6 -0
- data/test/mockgemui.rb +6 -0
- data/test/onegem.rb +12 -0
- data/test/simple_gem.rb +6 -0
- data/test/test_builder.rb +6 -0
- data/test/test_cached_fetcher.rb +6 -0
- data/test/test_check_command.rb +6 -0
- data/test/test_command.rb +6 -0
- data/test/test_configfile.rb +6 -0
- data/test/test_datadir.rb +32 -0
- data/test/test_dependency_list.rb +6 -0
- data/test/test_file_list.rb +6 -0
- data/test/test_format.rb +6 -0
- data/test/test_gemloadpaths.rb +6 -0
- data/test/test_gempaths.rb +11 -1
- data/test/test_incremental_fetcher.rb +175 -0
- data/test/test_installer.rb +30 -3
- data/test/test_loadmanager.rb +6 -0
- data/test/test_local_cache.rb +8 -2
- data/test/test_package.rb +6 -0
- data/test/test_parse_commands.rb +8 -2
- data/test/test_process_commands.rb +31 -0
- data/test/test_remote_fetcher.rb +47 -5
- data/test/test_remote_installer.rb +6 -0
- data/test/test_require_gem.rb +6 -0
- data/test/test_source_index.rb +27 -0
- data/test/test_specific_extras.rb +6 -0
- data/test/test_specification.rb +30 -0
- data/test/test_validator.rb +6 -0
- data/test/test_version_comparison.rb +6 -0
- data/test/testgem.rc +1 -0
- data/test/user_capture.rb +6 -0
- data/test/yaml_data.rb +8 -4
- metadata +187 -173
- data/bin/generate_yaml_index.rb +0 -78
- data/lib/rubygems/deployment.rb +0 -267
- data/test/test_deployment.rb +0 -93
data/lib/rubygems/package.rb
CHANGED
@@ -506,10 +506,8 @@ class TarInput
|
|
506
506
|
gzis.close
|
507
507
|
end
|
508
508
|
when 'metadata.gz.sig'
|
509
|
-
Gem.ensure_ssl_available
|
510
509
|
meta_sig = entry.read
|
511
510
|
when 'data.tar.gz.sig'
|
512
|
-
Gem.ensure_ssl_available
|
513
511
|
data_sig = entry.read
|
514
512
|
when 'data.tar.gz'
|
515
513
|
if security_policy
|
@@ -703,7 +701,11 @@ class TarOutput
|
|
703
701
|
|
704
702
|
TarWriter.new(os) do |inner_tar_stream|
|
705
703
|
klass = class <<inner_tar_stream; self end
|
706
|
-
|
704
|
+
if RUBY_VERSION >= "1.9" then
|
705
|
+
klass.funcall(:define_method, :metadata=, &set_meta)
|
706
|
+
else
|
707
|
+
klass.send(:define_method, :metadata=, &set_meta)
|
708
|
+
end
|
707
709
|
block.call inner_tar_stream
|
708
710
|
end
|
709
711
|
ensure
|
@@ -1,3 +1,9 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
1
7
|
require 'rubygems'
|
2
8
|
require 'socket'
|
3
9
|
require 'fileutils'
|
@@ -8,18 +14,37 @@ module Gem
|
|
8
14
|
class GemNotFoundException < Gem::Exception; end
|
9
15
|
class RemoteInstallationCancelled < Gem::Exception; end
|
10
16
|
|
17
|
+
####################################################################
|
11
18
|
# RemoteSourceFetcher handles the details of fetching gems and gem
|
12
19
|
# information from a remote source.
|
13
20
|
class RemoteSourceFetcher
|
14
21
|
include UserInteraction
|
15
22
|
|
16
23
|
# Initialize a remote fetcher using the source URI (and possible
|
17
|
-
# proxy information).
|
24
|
+
# proxy information).
|
25
|
+
# +proxy+
|
26
|
+
# * [String]: explicit specification of proxy; overrides any
|
27
|
+
# environment variable setting
|
28
|
+
# * nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER, HTTP_PROXY_PASS)
|
29
|
+
# * <tt>:no_proxy</tt>: ignore environment variables and _don't_
|
30
|
+
# use a proxy
|
18
31
|
def initialize(source_uri, proxy)
|
19
32
|
@uri = normalize_uri(source_uri)
|
20
|
-
@
|
21
|
-
|
22
|
-
|
33
|
+
@proxy_uri =
|
34
|
+
case proxy
|
35
|
+
when :no_proxy
|
36
|
+
nil
|
37
|
+
when nil
|
38
|
+
env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
39
|
+
uri = env_proxy ? URI.parse(env_proxy) : nil
|
40
|
+
if uri and uri.user.nil? and uri.password.nil?
|
41
|
+
#Probably we have http_proxy_* variables?
|
42
|
+
uri.user = ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER']
|
43
|
+
uri.password = ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS']
|
44
|
+
end
|
45
|
+
uri
|
46
|
+
else
|
47
|
+
URI.parse(proxy.to_str)
|
23
48
|
end
|
24
49
|
end
|
25
50
|
|
@@ -43,7 +68,7 @@ module Gem
|
|
43
68
|
# and queries, but may have some information elided (hence
|
44
69
|
# "abbreviated").
|
45
70
|
def source_index
|
46
|
-
say "
|
71
|
+
say "Bulk updating Gem source index for: #{@uri}"
|
47
72
|
begin
|
48
73
|
require 'zlib'
|
49
74
|
yaml_spec = fetch_path("/yaml.Z")
|
@@ -53,7 +78,7 @@ module Gem
|
|
53
78
|
end
|
54
79
|
begin
|
55
80
|
yaml_spec = fetch_path("/yaml") unless yaml_spec
|
56
|
-
|
81
|
+
convert_spec(yaml_spec)
|
57
82
|
rescue SocketError => e
|
58
83
|
raise RemoteSourceException.new("Error fetching remote gem cache: #{e.to_s}")
|
59
84
|
end
|
@@ -68,9 +93,8 @@ module Gem
|
|
68
93
|
|
69
94
|
# Connect to the source host/port, using a proxy if needed.
|
70
95
|
def connect_to(host, port)
|
71
|
-
if @
|
72
|
-
|
73
|
-
Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new(host, port)
|
96
|
+
if @proxy_uri
|
97
|
+
Net::HTTP::Proxy(@proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password).new(host, port)
|
74
98
|
else
|
75
99
|
Net::HTTP.new(host, port)
|
76
100
|
end
|
@@ -86,7 +110,6 @@ module Gem
|
|
86
110
|
# command.
|
87
111
|
def read_size(uri)
|
88
112
|
return File.size(get_file_uri_path(uri)) if is_file_uri(uri)
|
89
|
-
|
90
113
|
require 'net/http'
|
91
114
|
require 'uri'
|
92
115
|
u = URI.parse(uri)
|
@@ -118,10 +141,13 @@ module Gem
|
|
118
141
|
if is_file_uri(uri)
|
119
142
|
open(get_file_uri_path(uri), &block)
|
120
143
|
else
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
144
|
+
connection_options = {"User-Agent" => "RubyGems/#{Gem::RubyGemsVersion}"}
|
145
|
+
if @proxy_uri
|
146
|
+
http_proxy_url = "#{@proxy_uri.scheme}://#{@proxy_uri.host}:#{@proxy_uri.port}"
|
147
|
+
connection_options[:proxy_http_basic_authentication] = [http_proxy_url, @proxy_uri.user||'', @proxy_uri.password||'']
|
148
|
+
end
|
149
|
+
|
150
|
+
open(uri, connection_options, &block)
|
125
151
|
end
|
126
152
|
end
|
127
153
|
|
@@ -139,7 +165,7 @@ module Gem
|
|
139
165
|
# these are hashes of specs.).
|
140
166
|
def convert_spec(yaml_spec)
|
141
167
|
YAML.load(reduce_spec(yaml_spec)) or
|
142
|
-
|
168
|
+
fail "Didn't get a valid YAML document"
|
143
169
|
end
|
144
170
|
|
145
171
|
# This reduces the source spec in size so that YAML bugs with
|
@@ -172,10 +198,33 @@ module Gem
|
|
172
198
|
end
|
173
199
|
end
|
174
200
|
|
175
|
-
|
176
|
-
#
|
177
|
-
|
178
|
-
|
201
|
+
####################################################################
|
202
|
+
# Entrys held by a SourceInfoCache.
|
203
|
+
class SourceInfoCacheEntry
|
204
|
+
# The source index for this cache entry.
|
205
|
+
attr_reader :source_index
|
206
|
+
|
207
|
+
# The size of the of the source entry. Used to determine if the
|
208
|
+
# source index has changed.
|
209
|
+
attr_reader :size
|
210
|
+
|
211
|
+
# Create a cache entry.
|
212
|
+
def initialize(si, size)
|
213
|
+
replace_source_index(si, size)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Replace the source index and the index size with given values.
|
217
|
+
def replace_source_index(si, size)
|
218
|
+
@source_index = si || SourceIndex.new({})
|
219
|
+
@size = size
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
####################################################################
|
224
|
+
# SourceInfoCache implements the cache management policy on where
|
225
|
+
# the source info is stored on local file system. There are two
|
226
|
+
# possible cache locations: (1) the system wide cache, and (2) the
|
227
|
+
# user specific cache.
|
179
228
|
#
|
180
229
|
# * The system cache is prefered if it is writable (or can be
|
181
230
|
# created).
|
@@ -185,7 +234,10 @@ module Gem
|
|
185
234
|
# Once a cache is selected, it will be used for all operations. It
|
186
235
|
# will not switch between cache files dynamically.
|
187
236
|
#
|
188
|
-
|
237
|
+
# Cache data is a simple hash indexed by the source URI. Retrieving
|
238
|
+
# and entry from the cache data will return a SourceInfoCacheEntry.
|
239
|
+
#
|
240
|
+
class SourceInfoCache
|
189
241
|
|
190
242
|
# The most recent cache data.
|
191
243
|
def cache_data
|
@@ -197,7 +249,7 @@ module Gem
|
|
197
249
|
def write_cache
|
198
250
|
data = cache_data
|
199
251
|
open(writable_file, "wb") do |f|
|
200
|
-
|
252
|
+
f.write Marshal.dump(data)
|
201
253
|
end
|
202
254
|
end
|
203
255
|
|
@@ -242,8 +294,6 @@ module Gem
|
|
242
294
|
|
243
295
|
def load_local_cache(f)
|
244
296
|
Marshal.load(f)
|
245
|
-
rescue StandardError => ex
|
246
|
-
{}
|
247
297
|
end
|
248
298
|
|
249
299
|
# Select a writable cache file
|
@@ -274,7 +324,7 @@ module Gem
|
|
274
324
|
end
|
275
325
|
end
|
276
326
|
|
277
|
-
|
327
|
+
####################################################################
|
278
328
|
# CachedFetcher is a decorator that adds local file caching to
|
279
329
|
# RemoteSourceFetcher objects.
|
280
330
|
class CachedFetcher
|
@@ -282,8 +332,10 @@ module Gem
|
|
282
332
|
# Create a cached fetcher (based on a RemoteSourceFetcher) for the
|
283
333
|
# source at +source_uri+ (through the proxy +proxy+).
|
284
334
|
def initialize(source_uri, proxy)
|
335
|
+
require 'rubygems/incremental_fetcher'
|
285
336
|
@source_uri = source_uri
|
286
|
-
|
337
|
+
rsf = RemoteSourceFetcher.new(source_uri, proxy)
|
338
|
+
@fetcher = IncrementalFetcher.new(source_uri, rsf, manager)
|
287
339
|
end
|
288
340
|
|
289
341
|
# The uncompressed +size+ of the source's directory (e.g. source
|
@@ -307,14 +359,11 @@ module Gem
|
|
307
359
|
# "abbreviated").
|
308
360
|
def source_index
|
309
361
|
cache = manager.cache_data[@source_uri]
|
310
|
-
if cache && cache
|
311
|
-
cache
|
362
|
+
if cache && cache.size == @fetcher.size
|
363
|
+
cache.source_index
|
312
364
|
else
|
313
365
|
result = @fetcher.source_index
|
314
|
-
manager.cache_data[@source_uri] =
|
315
|
-
'size' => @fetcher.size,
|
316
|
-
'cache' => result,
|
317
|
-
}
|
366
|
+
manager.cache_data[@source_uri] = SourceInfoCacheEntry.new(result, @fetcher.size)
|
318
367
|
manager.update
|
319
368
|
result
|
320
369
|
end
|
@@ -338,10 +387,9 @@ module Gem
|
|
338
387
|
|
339
388
|
# The Cache manager for all instances of this class.
|
340
389
|
def manager
|
341
|
-
@manager ||=
|
390
|
+
@manager ||= SourceInfoCache.new
|
342
391
|
end
|
343
392
|
|
344
|
-
|
345
393
|
# Sent by the client when it is done with all the sources,
|
346
394
|
# allowing any cleanup activity to take place.
|
347
395
|
def finish
|
@@ -354,25 +402,18 @@ module Gem
|
|
354
402
|
class RemoteInstaller
|
355
403
|
include UserInteraction
|
356
404
|
|
357
|
-
# <tt>http_proxy</tt>::
|
405
|
+
# <tt>options[:http_proxy]</tt>::
|
358
406
|
# * [String]: explicit specification of proxy; overrides any
|
359
407
|
# environment variable setting
|
360
|
-
# * nil: respect environment variables
|
408
|
+
# * nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER, HTTP_PROXY_PASS)
|
361
409
|
# * <tt>:no_proxy</tt>: ignore environment variables and _don't_
|
362
410
|
# use a proxy
|
363
411
|
#
|
364
412
|
def initialize(options={})
|
413
|
+
require 'uri'
|
414
|
+
|
365
415
|
# Ensure http_proxy env vars are used if no proxy explicitly supplied.
|
366
416
|
@options = options
|
367
|
-
@http_proxy =
|
368
|
-
case @options[:http_proxy]
|
369
|
-
when :no_proxy
|
370
|
-
false
|
371
|
-
when nil
|
372
|
-
true
|
373
|
-
else
|
374
|
-
@options[:http_proxy].to_str
|
375
|
-
end
|
376
417
|
@fetcher_class = CachedFetcher
|
377
418
|
end
|
378
419
|
|
@@ -387,11 +428,7 @@ module Gem
|
|
387
428
|
# Returns::
|
388
429
|
# an array of Gem::Specification objects, one for each gem installed.
|
389
430
|
#
|
390
|
-
def install(gem_name,
|
391
|
-
version_requirement = "> 0.0.0",
|
392
|
-
force=false,
|
393
|
-
install_dir=Gem.dir,
|
394
|
-
install_stub=true)
|
431
|
+
def install(gem_name, version_requirement = "> 0.0.0", force=false, install_dir=Gem.dir, install_stub=true)
|
395
432
|
unless version_requirement.respond_to?(:satisfied_by?)
|
396
433
|
version_requirement = Version::Requirement.new(version_requirement)
|
397
434
|
end
|
@@ -422,7 +459,7 @@ module Gem
|
|
422
459
|
# Return a list of the sources that we can download gems from
|
423
460
|
def sources
|
424
461
|
unless @sources
|
425
|
-
|
462
|
+
require 'sources'
|
426
463
|
@sources = Gem.sources
|
427
464
|
end
|
428
465
|
@sources
|
@@ -441,7 +478,7 @@ module Gem
|
|
441
478
|
|
442
479
|
# Return the source info for the given source. The
|
443
480
|
def fetch_source(source)
|
444
|
-
rsf = @fetcher_class.new(source, @http_proxy)
|
481
|
+
rsf = @fetcher_class.new(source, @options[:http_proxy])
|
445
482
|
rsf.source_index
|
446
483
|
end
|
447
484
|
|
@@ -524,7 +561,7 @@ module Gem
|
|
524
561
|
end
|
525
562
|
|
526
563
|
def download_gem(destination_file, source, spec)
|
527
|
-
rsf = @fetcher_class.new(source, @
|
564
|
+
rsf = @fetcher_class.new(source, @proxy_uri)
|
528
565
|
path = "/gems/#{spec.full_name}.gem"
|
529
566
|
response = rsf.fetch_path(path)
|
530
567
|
write_gem_to_file(response, destination_file)
|
data/lib/rubygems/security.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
1
7
|
require 'rubygems/user_interaction'
|
2
8
|
|
3
9
|
require 'forwardable'
|
10
|
+
require 'digest/sha2'
|
11
|
+
require 'time'
|
4
12
|
|
5
13
|
module Gem
|
6
14
|
|
@@ -10,18 +18,91 @@ module Gem
|
|
10
18
|
# specification.
|
11
19
|
#
|
12
20
|
# NOTE:: The class used to be named Cache, but that became
|
13
|
-
# confusing when cached source fetchers where introduced.
|
14
|
-
#
|
15
|
-
#
|
21
|
+
# confusing when cached source fetchers where introduced. The
|
22
|
+
# constant Gem::Cache is an alias for this class to allow old
|
23
|
+
# YAMLized source index objects to load properly.
|
16
24
|
#
|
17
25
|
class SourceIndex
|
18
26
|
extend Forwardable
|
19
27
|
include Enumerable
|
20
28
|
|
29
|
+
# Class Methods. -------------------------------------------------
|
21
30
|
class << self
|
22
31
|
include Gem::UserInteraction
|
23
|
-
end
|
24
32
|
|
33
|
+
# Factory method to construct a source index instance for a given
|
34
|
+
# path.
|
35
|
+
#
|
36
|
+
# deprecated::
|
37
|
+
# If supplied, from_installed_gems will act just like
|
38
|
+
# +from_gems_in+. This argument is deprecated and is provided
|
39
|
+
# just for backwards compatibility, and should not generally
|
40
|
+
# be used.
|
41
|
+
#
|
42
|
+
# return::
|
43
|
+
# SourceIndex instance
|
44
|
+
#
|
45
|
+
def from_installed_gems(*deprecated)
|
46
|
+
if deprecated.empty?
|
47
|
+
from_gems_in(*installed_spec_directories)
|
48
|
+
else
|
49
|
+
from_gems_in(*deprecated)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return a list of directories in the current gem path that
|
54
|
+
# contain specifications.
|
55
|
+
#
|
56
|
+
# return::
|
57
|
+
# List of directory paths (all ending in "../specifications").
|
58
|
+
#
|
59
|
+
def installed_spec_directories
|
60
|
+
Gem.path.collect { |dir| File.join(dir, "specifications") }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Factory method to construct a source index instance for a
|
64
|
+
# given path.
|
65
|
+
#
|
66
|
+
# spec_dirs::
|
67
|
+
# List of directories to search for specifications. Each
|
68
|
+
# directory should have a "specifications" subdirectory
|
69
|
+
# containing the gem specifications.
|
70
|
+
#
|
71
|
+
# return::
|
72
|
+
# SourceIndex instance
|
73
|
+
#
|
74
|
+
def from_gems_in(*spec_dirs)
|
75
|
+
self.new.load_gems_in(*spec_dirs)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Load a specification from a file (eval'd Ruby code)
|
79
|
+
#
|
80
|
+
# file_name:: [String] The .gemspec file
|
81
|
+
# return:: Specification instance or nil if an error occurs
|
82
|
+
#
|
83
|
+
def load_specification(file_name)
|
84
|
+
begin
|
85
|
+
spec_code = File.read(file_name).untaint
|
86
|
+
gemspec = eval(spec_code)
|
87
|
+
if gemspec.is_a?(Gem::Specification)
|
88
|
+
gemspec.loaded_from = file_name
|
89
|
+
return gemspec
|
90
|
+
end
|
91
|
+
alert_warning "File '#{file_name}' does not evaluate to a gem specification"
|
92
|
+
rescue SyntaxError => e
|
93
|
+
alert_warning e
|
94
|
+
alert_warning spec_code
|
95
|
+
rescue Exception => e
|
96
|
+
alert_warning(e.inspect.to_s + "\n" + spec_code)
|
97
|
+
alert_warning "Invalid .gemspec format in '#{file_name}'"
|
98
|
+
end
|
99
|
+
return nil
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
# Instance Methods -----------------------------------------------
|
105
|
+
|
25
106
|
# Constructs a source index instance from the provided
|
26
107
|
# specifications
|
27
108
|
#
|
@@ -32,69 +113,51 @@ module Gem
|
|
32
113
|
@gems = specifications
|
33
114
|
end
|
34
115
|
|
35
|
-
# Reconstruct
|
36
|
-
# directories.
|
37
|
-
|
38
|
-
#
|
39
|
-
def from_installed_gems(*spec_dirs)
|
116
|
+
# Reconstruct the source index from the list of source
|
117
|
+
# directories.
|
118
|
+
def load_gems_in(*spec_dirs)
|
40
119
|
@gems.clear
|
41
|
-
if spec_dirs.empty?
|
42
|
-
spec_dirs = Gem.path.collect { |dir| File.join(dir, "specifications") }
|
43
|
-
end
|
44
120
|
Dir.glob("{#{spec_dirs.join(',')}}/*.gemspec").each do |file_name|
|
45
|
-
gemspec = self.class.load_specification(file_name)
|
46
|
-
|
121
|
+
gemspec = self.class.load_specification(file_name.untaint)
|
122
|
+
add_spec(gemspec) if gemspec
|
47
123
|
end
|
48
124
|
self
|
49
125
|
end
|
50
126
|
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
# source_dirs::
|
55
|
-
# List of gem directories to search for specifications. The
|
56
|
-
# default is the "specification" directories under each
|
57
|
-
# directory in Gem.path.
|
58
|
-
#
|
59
|
-
# return::
|
60
|
-
# SourceIndex instance
|
61
|
-
#
|
62
|
-
def self.from_installed_gems(*spec_dirs)
|
63
|
-
self.new.from_installed_gems(*spec_dirs)
|
127
|
+
# Add a gem specification to the source index.
|
128
|
+
def add_spec(gem_spec)
|
129
|
+
@gems[gem_spec.full_name] = gem_spec
|
64
130
|
end
|
65
131
|
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
# return:: Specification instance or nil if an error occurs
|
70
|
-
#
|
71
|
-
def self.load_specification(file_name)
|
72
|
-
begin
|
73
|
-
spec_code = File.read(file_name)
|
74
|
-
gemspec = eval(spec_code)
|
75
|
-
if gemspec.is_a?(Gem::Specification)
|
76
|
-
gemspec.loaded_from = file_name
|
77
|
-
return gemspec
|
78
|
-
end
|
79
|
-
alert_warning "File '#{file_name}' does not evaluate to a gem specification"
|
80
|
-
rescue SyntaxError => e
|
81
|
-
alert_warning e
|
82
|
-
alert_warning spec_code
|
83
|
-
rescue Exception => e
|
84
|
-
alert_warning(e.inspect.to_s + "\n" + spec_code)
|
85
|
-
alert_warning "Invalid .gemspec format in '#{file_name}'"
|
86
|
-
end
|
87
|
-
return nil
|
132
|
+
# Remove a gem specification named +full_name+.
|
133
|
+
def remove_spec(full_name)
|
134
|
+
@gems.delete(full_name)
|
88
135
|
end
|
89
|
-
|
136
|
+
|
90
137
|
# Iterate over the specifications in the source index.
|
91
138
|
#
|
92
|
-
# &block:: [yields gem.
|
139
|
+
# &block:: [yields gem.full_name, Gem::Specification]
|
93
140
|
#
|
94
141
|
def each(&block)
|
95
142
|
@gems.each(&block)
|
96
143
|
end
|
97
144
|
|
145
|
+
# The gem specification given a full gem spec name.
|
146
|
+
def specification(full_name)
|
147
|
+
@gems[full_name]
|
148
|
+
end
|
149
|
+
|
150
|
+
# The signature for the source index. Changes in the signature
|
151
|
+
# indicate a change in the index.
|
152
|
+
def index_signature
|
153
|
+
Digest::SHA256.new(@gems.keys.sort.join(',')).to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
# The signature for the given gem specification.
|
157
|
+
def gem_signature(gem_full_name)
|
158
|
+
Digest::SHA256.new(@gems[gem_full_name].to_yaml).to_s
|
159
|
+
end
|
160
|
+
|
98
161
|
def_delegators :@gems, :size, :length
|
99
162
|
|
100
163
|
# Find a gem by an exact match on the short name.
|
@@ -132,7 +195,7 @@ module Gem
|
|
132
195
|
# return:: Returns a pointer to itself.
|
133
196
|
#
|
134
197
|
def refresh!
|
135
|
-
|
198
|
+
load_gems_in(self.class.installed_spec_directories)
|
136
199
|
end
|
137
200
|
|
138
201
|
end
|