rubygems-update 0.8.10 → 0.8.11
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.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- data/ChangeLog +66 -0
- data/README +17 -3
- data/Rakefile +29 -11
- data/bin/gem_mirror +67 -0
- data/examples/application/an-app.gemspec +2 -0
- data/lib/rubygems.rb +18 -3
- data/lib/rubygems/builder.rb +14 -1
- data/lib/rubygems/cmd_manager.rb +2 -0
- data/lib/rubygems/command.rb +26 -2
- data/lib/rubygems/custom_require.rb +30 -21
- data/lib/rubygems/format.rb +4 -4
- data/lib/rubygems/gem_commands.rb +161 -9
- data/lib/rubygems/gem_openssl.rb +34 -0
- data/lib/rubygems/gem_runner.rb +5 -1
- data/lib/rubygems/installer.rb +117 -38
- data/lib/rubygems/package.rb +135 -25
- data/lib/rubygems/remote_installer.rb +59 -29
- data/lib/rubygems/rubygems_version.rb +1 -1
- data/lib/rubygems/security.rb +478 -0
- data/lib/rubygems/specification.rb +48 -28
- data/post-install.rb +2 -1
- data/scripts/gemdoc.rb +2 -2
- data/scripts/specdoc.rb +25 -24
- data/scripts/upload_gemdoc.rb +134 -0
- data/setup.rb +1 -1
- 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/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/one/one-0.0.1.gem +0 -0
- data/test/fake_certlib/openssl.rb +1 -0
- data/test/functional.rb +49 -14
- data/test/gemutilities.rb +69 -5
- data/test/test_cached_fetcher.rb +5 -7
- data/test/test_file_list.rb +96 -0
- data/test/test_gempaths.rb +36 -34
- data/test/test_installer.rb +214 -0
- data/test/test_local_cache.rb +45 -102
- data/test/test_parse_commands.rb +3 -1
- data/test/test_remote_installer.rb +24 -5
- data/test/test_specific_extras.rb +40 -0
- data/test/test_specification.rb +106 -16
- metadata +14 -3
@@ -1,7 +1,13 @@
|
|
1
|
-
require '
|
1
|
+
require 'time'
|
2
2
|
require 'rubygems'
|
3
3
|
require 'rubygems/version'
|
4
4
|
|
5
|
+
class Time
|
6
|
+
def self.today
|
7
|
+
Time.parse Time.now.strftime("%Y-%m-%d")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
module Gem
|
6
12
|
|
7
13
|
##
|
@@ -74,6 +80,9 @@ module Gem
|
|
74
80
|
# List of _all_ attributes and default values: [[:name, nil], [:bindir, 'bin'], ...]
|
75
81
|
@@attributes = []
|
76
82
|
|
83
|
+
# List of array attributes
|
84
|
+
@@array_attributes = []
|
85
|
+
|
77
86
|
# Map of attribute names to default values.
|
78
87
|
@@default_value = {}
|
79
88
|
|
@@ -99,6 +108,10 @@ module Gem
|
|
99
108
|
@@required_attributes.include? name.to_sym
|
100
109
|
end
|
101
110
|
|
111
|
+
def self.array_attributes
|
112
|
+
@@array_attributes.dup
|
113
|
+
end
|
114
|
+
|
102
115
|
# ------------------------- Infrastructure class methods.
|
103
116
|
|
104
117
|
# A list of Specification instances that have been defined in this Ruby instance.
|
@@ -130,6 +143,7 @@ module Gem
|
|
130
143
|
# Same as :attribute, but ensures that values assigned to the
|
131
144
|
# attribute are array values by applying :to_a to the value.
|
132
145
|
def self.array_attribute(name)
|
146
|
+
@@array_attributes << name
|
133
147
|
@@attributes << [name, []]
|
134
148
|
@@default_value[name] = []
|
135
149
|
module_eval %{
|
@@ -222,6 +236,10 @@ module Gem
|
|
222
236
|
attribute :has_rdoc, false
|
223
237
|
attribute :required_ruby_version, Gem::Version::Requirement.default
|
224
238
|
attribute :platform, Gem::Platform::RUBY
|
239
|
+
|
240
|
+
attribute :signing_key, nil
|
241
|
+
attribute :cert_chain, nil
|
242
|
+
|
225
243
|
array_attribute :authors
|
226
244
|
array_attribute :files
|
227
245
|
array_attribute :test_files
|
@@ -276,23 +294,22 @@ module Gem
|
|
276
294
|
end
|
277
295
|
|
278
296
|
overwrite_accessor :date= do |date|
|
279
|
-
# We want to end up with a
|
280
|
-
#
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
297
|
+
# We want to end up with a Time object with one-day resolution. This is
|
298
|
+
# the cleanest, most-readable, faster-than-using-Date way to do it.
|
299
|
+
case date
|
300
|
+
when String then
|
301
|
+
@date = Time.parse date
|
302
|
+
when Time then
|
303
|
+
@date = Time.parse date.strftime("%Y-%m-%d")
|
304
|
+
when Date then
|
305
|
+
@date = Time.parse date.to_s
|
285
306
|
else
|
286
|
-
date =
|
307
|
+
@date = Time.today
|
287
308
|
end
|
288
|
-
@date = date || Date.today
|
289
309
|
end
|
290
310
|
|
291
311
|
overwrite_accessor :date do
|
292
|
-
|
293
|
-
unless @date.is_a? Date
|
294
|
-
self.date = @date
|
295
|
-
end
|
312
|
+
self.date = nil if @date.nil? # HACK Sets the default value for date
|
296
313
|
@date
|
297
314
|
end
|
298
315
|
|
@@ -352,15 +369,16 @@ module Gem
|
|
352
369
|
# ------------------------- Constructors.
|
353
370
|
|
354
371
|
##
|
355
|
-
# Specification constructor. Assigns the default values to the
|
356
|
-
# spec to the list of loaded specs (see
|
357
|
-
# further initialization.
|
372
|
+
# Specification constructor. Assigns the default values to the
|
373
|
+
# attributes, adds this spec to the list of loaded specs (see
|
374
|
+
# Specification.list), and yields itself for further initialization.
|
358
375
|
#
|
359
376
|
def initialize
|
360
|
-
# Each attribute has a default value (possibly nil). Here, we
|
361
|
-
# attributes to their default value. This is done
|
362
|
-
# methods, so special behaviours will be honored.
|
363
|
-
# _copy_ of the default so each specification
|
377
|
+
# Each attribute has a default value (possibly nil). Here, we
|
378
|
+
# initialize all attributes to their default value. This is done
|
379
|
+
# through the accessor methods, so special behaviours will be honored.
|
380
|
+
# Furthermore, we take a _copy_ of the default so each specification
|
381
|
+
# instance has its own empty
|
364
382
|
# arrays, etc.
|
365
383
|
@@attributes.each do |name, default|
|
366
384
|
self.send "#{name}=", copy_of(default)
|
@@ -430,11 +448,12 @@ module Gem
|
|
430
448
|
end
|
431
449
|
|
432
450
|
##
|
433
|
-
# Returns the full name (name-version) of this Gem. Platform information
|
434
|
-
# (name-version-platform) if it is specified (and not the
|
451
|
+
# Returns the full name (name-version) of this Gem. Platform information
|
452
|
+
# is included (name-version-platform) if it is specified (and not the
|
453
|
+
# default Ruby platform).
|
435
454
|
#
|
436
455
|
def full_name
|
437
|
-
if platform == Gem::Platform::RUBY
|
456
|
+
if platform == Gem::Platform::RUBY || platform.nil?
|
438
457
|
"#{@name}-#{@version}"
|
439
458
|
else
|
440
459
|
"#{@name}-#{@version}-#{platform}"
|
@@ -490,16 +509,17 @@ module Gem
|
|
490
509
|
|
491
510
|
# ------------------------- Export methods (YAML and Ruby code).
|
492
511
|
|
493
|
-
# Returns an array of attribute names to be used when generating a YAML
|
494
|
-
# of this object. If an attribute still has its default
|
512
|
+
# Returns an array of attribute names to be used when generating a YAML
|
513
|
+
# representation of this object. If an attribute still has its default
|
514
|
+
# value, it is omitted.
|
495
515
|
def to_yaml_properties
|
496
516
|
mark_version
|
497
517
|
@@attributes.map { |name, default| "@#{name}" }
|
498
518
|
end
|
499
519
|
|
500
|
-
# Returns a Ruby code representation of this specification, such that it
|
501
|
-
# eval'ed and reconstruct the same specification later. Attributes
|
502
|
-
# their default values are omitted.
|
520
|
+
# Returns a Ruby code representation of this specification, such that it
|
521
|
+
# can be eval'ed and reconstruct the same specification later. Attributes
|
522
|
+
# that still have their default values are omitted.
|
503
523
|
def to_ruby
|
504
524
|
mark_version
|
505
525
|
result = "Gem::Specification.new do |s|\n"
|
data/post-install.rb
CHANGED
@@ -51,7 +51,8 @@ def install_windows_batch_files
|
|
51
51
|
target = File.join(bindir, File.basename(f))
|
52
52
|
if is_windows_platform
|
53
53
|
File.open(target+".cmd", "w") do |file|
|
54
|
-
|
54
|
+
ruby_cmd = Gem.ruby rescue 'ruby'
|
55
|
+
file.puts %{@"#{ruby_cmd}" "#{target}" %1 %2 %3 %4 %5 %6 %7 %8 %9}
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
data/scripts/gemdoc.rb
CHANGED
@@ -35,7 +35,7 @@ def table_of_contents
|
|
35
35
|
out.gsub(/^\s+(\w+)/) {
|
36
36
|
cmd_name = $1
|
37
37
|
" [http://rubygems.rubyforge.org/wiki/wiki.pl?GemReference##{cmd_name} -] #{cmd_name}"
|
38
|
-
}
|
38
|
+
}
|
39
39
|
end
|
40
40
|
|
41
41
|
while line = gets
|
@@ -52,7 +52,7 @@ while line = gets
|
|
52
52
|
when "!toc"
|
53
53
|
puts table_of_contents()
|
54
54
|
when "!toc-link"
|
55
|
-
puts "
|
55
|
+
puts "\"Table of Contents\":http://docs.rubygems.org/read/chapter/10#toc"
|
56
56
|
when "!version"
|
57
57
|
puts Gem::RubyGemsPackageVersion
|
58
58
|
end
|
data/scripts/specdoc.rb
CHANGED
@@ -18,14 +18,14 @@ end
|
|
18
18
|
|
19
19
|
# Returns a link to the given anchor on the page.
|
20
20
|
def _link(attribute, text=nil)
|
21
|
-
link = "
|
22
|
-
"
|
21
|
+
link = "##{attribute}"
|
22
|
+
%{<a href="#{link}">#{text || attribute}</a>}
|
23
23
|
end
|
24
24
|
|
25
25
|
def _themed_toc_more_vspace
|
26
26
|
SECTIONS.each do |s|
|
27
|
-
puts "\n
|
28
|
-
puts s['attributes'].
|
27
|
+
puts "\n* *#{s['name']}*"
|
28
|
+
puts s['attributes'].collect { |a|
|
29
29
|
": #{_link(a, '#')} #{a}"
|
30
30
|
}
|
31
31
|
end
|
@@ -33,14 +33,13 @@ end
|
|
33
33
|
|
34
34
|
def _themed_toc_less_vspace
|
35
35
|
SECTIONS.each do |s|
|
36
|
-
puts "\n
|
37
|
-
|
38
|
-
puts s['attributes'].map { |a| _link(a) }.join(SEPSTRING)
|
36
|
+
puts "\n* *#{s['name']}:* "
|
37
|
+
puts s['attributes'].collect { |a| _link(a) }.join(SEPSTRING)
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
41
|
def timestamp
|
43
|
-
puts "
|
42
|
+
puts "p(((. <em>Last generated: #{Time.now.strftime '%Y-%m-%d %H:%M:%S %Z (%A)'}</em>"
|
44
43
|
end
|
45
44
|
|
46
45
|
# Prints a thematic table of contents, drawing from the structure in the YAML file.
|
@@ -51,24 +50,24 @@ end
|
|
51
50
|
# Prints an alphabetical table of contents in a fairly compact yet readable way, with all
|
52
51
|
# Wiki formatting included.
|
53
52
|
def alpha_toc
|
54
|
-
attributes = SECTIONS.
|
53
|
+
attributes = SECTIONS.collect { |s| s['attributes'] }.flatten
|
55
54
|
# -> ['author', 'autorequire', ...]
|
56
55
|
attr_map = attributes.partition_by { |a| a[0,1] }
|
57
56
|
# -> { 'a' => ['author', ...], 'b' => ... }
|
58
|
-
attributes = attr_map.
|
57
|
+
attributes = attr_map.collect { |letter, attrs|
|
59
58
|
[letter.upcase, attrs.sort]
|
60
59
|
}.sort_by { |l, _| l }
|
61
60
|
# -> [ ['A', ['author', ...], ...]
|
62
|
-
attributes = attributes.
|
63
|
-
"
|
61
|
+
attributes = attributes.collect { |letter, attrs|
|
62
|
+
"* *#{letter}* " << attrs.collect { |a| _link(a) }.join(SEPSTRING)
|
64
63
|
} # -> [ 'A author | autorequire', 'B bindir', ...]
|
65
|
-
puts attributes.join(
|
64
|
+
puts attributes.join("\n")
|
66
65
|
end
|
67
66
|
|
68
67
|
# Print the "important" table of contents, which consists of the attributes given as
|
69
68
|
# arguments.
|
70
69
|
def important_toc(*attributes)
|
71
|
-
puts attributes.
|
70
|
+
puts attributes.collect { |a| _link(a) }.join(SEPSTRING)
|
72
71
|
end
|
73
72
|
|
74
73
|
# Returns text like "Optional; default = 'bin'", with Wiki formatting.
|
@@ -76,9 +75,10 @@ def _metadata(attribute)
|
|
76
75
|
type = attribute.klass || "Unknown"
|
77
76
|
required =
|
78
77
|
case attribute.mandatory
|
79
|
-
when nil, false
|
80
|
-
|
81
|
-
else
|
78
|
+
when nil, false
|
79
|
+
'<em>Optional</em>'
|
80
|
+
else
|
81
|
+
'<em>Required</em>'
|
82
82
|
end
|
83
83
|
default_str =
|
84
84
|
case attribute.default
|
@@ -88,8 +88,8 @@ def _metadata(attribute)
|
|
88
88
|
else attribute.default.inspect
|
89
89
|
end
|
90
90
|
default_str = "; default = #{default_str}" unless default_str.empty?
|
91
|
-
result = sprintf "
|
92
|
-
result.gsub(/ /, ' ')
|
91
|
+
result = sprintf "<em>Type: %s; %s%s</em>", type, required, default_str
|
92
|
+
# result.gsub(/ /, ' ')
|
93
93
|
end
|
94
94
|
|
95
95
|
# Turns 'L(section)' into a link to that section.
|
@@ -103,13 +103,14 @@ end
|
|
103
103
|
# * the description, usage, and notes for that attribute
|
104
104
|
# * a link to the table of contents
|
105
105
|
def attribute_survey
|
106
|
-
heading = proc { |str|
|
107
|
-
subheading = proc { |str| "\n
|
106
|
+
heading = proc { |str| %{\n\nh3. <a name="#{str}">#{str}</a>\n\n} }
|
107
|
+
subheading = proc { |str| "\n\nh4. #{str}\n\n" }
|
108
108
|
pre = proc { |str| "<pre>\n#{str}\n</pre>\n" }
|
109
109
|
para = proc { |str| str.gsub(/\n/, "\n\n") }
|
110
|
-
toclink = "\n
|
110
|
+
toclink = "\n<em>Goto #{_link('toc', 'Table of Contents')}</em>"
|
111
111
|
ATTRIBUTES.sort_by { |a| a['name'] }.each do |a|
|
112
112
|
a = OpenStruct.new(a)
|
113
|
+
puts "\n----\n"
|
113
114
|
puts heading[a.name]
|
114
115
|
puts _metadata(a)
|
115
116
|
puts subheading['Description']
|
@@ -127,9 +128,9 @@ end
|
|
127
128
|
# Checks to see that all the attributes are documented. Warn on STDERR of any
|
128
129
|
# discrepencies.
|
129
130
|
def _check_attribute_completeness
|
130
|
-
documented_attributes = ATTRIBUTES.
|
131
|
+
documented_attributes = ATTRIBUTES.collect { |a| a['name'].to_s }
|
131
132
|
# ^ The attributes documented in specdoc.yaml.
|
132
|
-
coded_attributes = Gem::Specification.attribute_names.
|
133
|
+
coded_attributes = Gem::Specification.attribute_names.collect { |a| a.to_s }
|
133
134
|
# ^ The attributes defined in specification.rb.
|
134
135
|
missing = coded_attributes - documented_attributes
|
135
136
|
unless missing.empty?
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mechanize'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
DOC = {}
|
7
|
+
UPDATED = {}
|
8
|
+
MISSING = []
|
9
|
+
|
10
|
+
$page_count = 0
|
11
|
+
|
12
|
+
def save_page(page)
|
13
|
+
$page_count += 1
|
14
|
+
page_name = "logs/page_%03d.html" % $page_count
|
15
|
+
open(page_name, "w") do |f| f.puts page.body end
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_document
|
19
|
+
open("scripts/gemdoc.hieraki") do |f|
|
20
|
+
name = nil
|
21
|
+
f.each do |line|
|
22
|
+
if line =~ /^==/
|
23
|
+
line =~ /gem\s+(\S+)/ or fail "Illformatted Document Line [#{line.chomp}]"
|
24
|
+
name = $1
|
25
|
+
DOC[name] = ''
|
26
|
+
else
|
27
|
+
next if name.nil?
|
28
|
+
DOC[name] << line
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_credentials
|
35
|
+
unless File.exist?(".hieraki_author.rb")
|
36
|
+
print "Hieraki Author Name: "
|
37
|
+
author = gets.chomp
|
38
|
+
print "Hieraki Password: "
|
39
|
+
password = gets.chomp
|
40
|
+
open(".hieraki_author.rb", "w") do |f|
|
41
|
+
f.puts "module Hieraki"
|
42
|
+
f.puts " Author = '#{author}'"
|
43
|
+
f.puts " Password = '#{password}'"
|
44
|
+
f.puts "end"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
load "./.hieraki_author.rb"
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_agent
|
52
|
+
FileUtils.mkdir "logs" unless File.exist?("logs")
|
53
|
+
logfile = open("logs/update_hieraki.log", "w")
|
54
|
+
$agent = WWW::Mechanize.new { |a| a.log = Logger.new(logfile) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def login_to_hieraki
|
58
|
+
puts "*** Getting Start Page"
|
59
|
+
start_page = $agent.get("http://docs.rubygems.org")
|
60
|
+
save_page(start_page)
|
61
|
+
|
62
|
+
puts "*** Going to Login Page"
|
63
|
+
login_link = start_page.links.find { |l| l.node.text =~ /login/i }
|
64
|
+
login_page = $agent.click(login_link)
|
65
|
+
save_page(login_page)
|
66
|
+
|
67
|
+
puts "*** Attempting to Log In"
|
68
|
+
login_form = login_page.forms.first
|
69
|
+
login_form.fields.find { |f| f.name == 'login' }.value = Hieraki::Author
|
70
|
+
login_form.fields.find { |f| f.name == 'password' }.value = Hieraki::Password
|
71
|
+
author_page = $agent.submit(login_form)
|
72
|
+
fail "Unsuccessful Login -- check .hieraki_author.rb file" if author_page.body =~ /unsuccessful/
|
73
|
+
save_page(author_page)
|
74
|
+
author_page
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def goto_command_reference_page(page)
|
79
|
+
puts "*** Going to Command Reference Book"
|
80
|
+
link = page.links.find { |l| l.node.text =~ /command reference/i }
|
81
|
+
ref_page = $agent.click(link)
|
82
|
+
save_page(ref_page)
|
83
|
+
|
84
|
+
puts "*** Going to Command Reference Chapter"
|
85
|
+
link = ref_page.links.find { |l| l.node.text =~ /command reference/i && l.href =~ /chapter/ }
|
86
|
+
cmdref_page = $agent.click(link)
|
87
|
+
save_page(cmdref_page)
|
88
|
+
cmdref_page
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_command_docs(cmdref_page)
|
92
|
+
cmdref_page.links.select { |l| l.node.text == "edit" }.each do |l|
|
93
|
+
edit_page = $agent.click(l)
|
94
|
+
save_page(edit_page)
|
95
|
+
edit_form = edit_page.forms.first
|
96
|
+
title = edit_form.fields.find { |f| f.name = 'page_title'}.value
|
97
|
+
if title =~ /gem\s([a-z]+)/
|
98
|
+
name = $1
|
99
|
+
if DOC[name]
|
100
|
+
body_field = edit_form.fields.find { |f| f.name == 'page[body]'}
|
101
|
+
body_field.value = DOC[name]
|
102
|
+
puts "*** Updating gem #{name} page"
|
103
|
+
$agent.submit(edit_form)
|
104
|
+
UPDATED[name] = true
|
105
|
+
else
|
106
|
+
MISSING << name
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def check_missing
|
114
|
+
(DOC.keys - UPDATED.keys).sort.each do |name|
|
115
|
+
puts "No page found for 'gem #{name}'"
|
116
|
+
end
|
117
|
+
MISSING.each do |name|
|
118
|
+
puts "No data found for 'gem #{name}' page"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def upload_gemdoc_main(args)
|
123
|
+
create_agent
|
124
|
+
get_credentials
|
125
|
+
read_document
|
126
|
+
page = login_to_hieraki
|
127
|
+
cmdref_page = goto_command_reference_page(page)
|
128
|
+
update_command_docs(cmdref_page)
|
129
|
+
check_missing
|
130
|
+
end
|
131
|
+
|
132
|
+
if __FILE__ == $0 then
|
133
|
+
upload_gemdoc_main(ARGV)
|
134
|
+
end
|
data/setup.rb
CHANGED
@@ -1142,8 +1142,8 @@ class Installer
|
|
1142
1142
|
w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
|
1143
1143
|
w.write r.read
|
1144
1144
|
}
|
1145
|
-
move_file tmpfile, File.basename(path)
|
1146
1145
|
}
|
1146
|
+
move_file tmpfile, File.basename(path)
|
1147
1147
|
ensure
|
1148
1148
|
File.unlink tmpfile if File.exist?(tmpfile)
|
1149
1149
|
end
|
data/test/data/a-0.0.1.gem
CHANGED
Binary file
|
data/test/data/a-0.0.2.gem
CHANGED
Binary file
|
data/test/data/b-0.0.2.gem
CHANGED
Binary file
|