rubygems-update 1.3.1 → 1.3.2

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.

Files changed (128) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +24 -0
  3. data/.document +4 -3
  4. data/ChangeLog +382 -1
  5. data/Manifest.txt +214 -0
  6. data/README +1 -49
  7. data/Rakefile +124 -191
  8. data/bin/gem +1 -4
  9. data/cruise_config.rb +22 -0
  10. data/doc/release_notes/rel_1_3_1.rdoc +3 -3
  11. data/doc/release_notes/rel_1_3_2.rdoc +119 -0
  12. data/lib/gauntlet_rubygems.rb +50 -0
  13. data/lib/rubygems.rb +250 -25
  14. data/lib/rubygems/builder.rb +62 -60
  15. data/lib/rubygems/command.rb +421 -319
  16. data/lib/rubygems/command_manager.rb +153 -125
  17. data/lib/rubygems/commands/check_command.rb +12 -7
  18. data/lib/rubygems/commands/cleanup_command.rb +11 -2
  19. data/lib/rubygems/commands/contents_command.rb +42 -18
  20. data/lib/rubygems/commands/generate_index_command.rb +91 -15
  21. data/lib/rubygems/commands/install_command.rb +33 -47
  22. data/lib/rubygems/commands/query_command.rb +36 -20
  23. data/lib/rubygems/commands/rdoc_command.rb +62 -68
  24. data/lib/rubygems/commands/search_command.rb +26 -32
  25. data/lib/rubygems/commands/setup_command.rb +353 -0
  26. data/lib/rubygems/commands/sources_command.rb +5 -0
  27. data/lib/rubygems/commands/specification_command.rb +23 -3
  28. data/lib/rubygems/commands/uninstall_command.rb +71 -61
  29. data/lib/rubygems/commands/unpack_command.rb +14 -12
  30. data/lib/rubygems/commands/update_command.rb +26 -5
  31. data/lib/rubygems/defaults.rb +16 -3
  32. data/lib/rubygems/dependency.rb +38 -7
  33. data/lib/rubygems/dependency_installer.rb +7 -4
  34. data/lib/rubygems/digest/digest_adapter.rb +42 -33
  35. data/lib/rubygems/digest/sha1.rb +6 -1
  36. data/lib/rubygems/digest/sha2.rb +5 -0
  37. data/lib/rubygems/doc_manager.rb +31 -11
  38. data/lib/rubygems/ext/ext_conf_builder.rb +2 -1
  39. data/lib/rubygems/ext/rake_builder.rb +6 -2
  40. data/lib/rubygems/format.rb +63 -63
  41. data/lib/rubygems/gem_openssl.rb +14 -2
  42. data/lib/rubygems/gem_path_searcher.rb +7 -3
  43. data/lib/rubygems/gem_runner.rb +59 -39
  44. data/lib/rubygems/indexer.rb +450 -109
  45. data/lib/rubygems/install_update_options.rb +13 -1
  46. data/lib/rubygems/installer.rb +25 -22
  47. data/lib/rubygems/local_remote_options.rb +5 -3
  48. data/lib/rubygems/old_format.rb +124 -120
  49. data/lib/rubygems/package/tar_header.rb +25 -3
  50. data/lib/rubygems/package/tar_input.rb +5 -5
  51. data/lib/rubygems/package/tar_output.rb +2 -0
  52. data/lib/rubygems/package/tar_reader.rb +19 -0
  53. data/lib/rubygems/package/tar_reader/entry.rb +43 -0
  54. data/lib/rubygems/package/tar_writer.rb +65 -3
  55. data/lib/rubygems/package_task.rb +117 -0
  56. data/lib/rubygems/platform.rb +12 -8
  57. data/lib/rubygems/remote_fetcher.rb +43 -24
  58. data/lib/rubygems/require_paths_builder.rb +14 -12
  59. data/lib/rubygems/requirement.rb +15 -6
  60. data/lib/rubygems/rubygems_version.rb +14 -1
  61. data/lib/rubygems/source_index.rb +38 -16
  62. data/lib/rubygems/source_info_cache_entry.rb +2 -2
  63. data/lib/rubygems/spec_fetcher.rb +43 -20
  64. data/lib/rubygems/specification.rb +1122 -947
  65. data/lib/rubygems/text.rb +30 -0
  66. data/lib/rubygems/timer.rb +14 -11
  67. data/lib/rubygems/uninstaller.rb +25 -5
  68. data/lib/rubygems/user_interaction.rb +294 -264
  69. data/lib/rubygems/validator.rb +70 -36
  70. data/lib/rubygems/version.rb +97 -33
  71. data/lib/rubygems/version_option.rb +1 -0
  72. data/setup.rb +11 -306
  73. data/test/foo/discover.rb +0 -0
  74. data/test/gem_installer_test_case.rb +22 -11
  75. data/test/gem_package_tar_test_case.rb +0 -14
  76. data/test/gemutilities.rb +89 -8
  77. data/test/mockgemui.rb +2 -1
  78. data/test/rubygems_plugin.rb +16 -0
  79. data/test/test_gem.rb +107 -36
  80. data/test/test_gem_command.rb +3 -13
  81. data/test/test_gem_command_manager.rb +1 -14
  82. data/test/test_gem_commands_cert_command.rb +1 -1
  83. data/test/test_gem_commands_contents_command.rb +63 -0
  84. data/test/test_gem_commands_environment_command.rb +1 -1
  85. data/test/test_gem_commands_generate_index_command.rb +104 -1
  86. data/test/test_gem_commands_install_command.rb +95 -0
  87. data/test/test_gem_commands_pristine_command.rb +3 -3
  88. data/test/test_gem_commands_query_command.rb +46 -0
  89. data/test/test_gem_commands_sources_command.rb +9 -5
  90. data/test/test_gem_commands_specification_command.rb +31 -0
  91. data/test/test_gem_commands_uninstall_command.rb +3 -2
  92. data/test/test_gem_commands_unpack_command.rb +3 -2
  93. data/test/test_gem_commands_update_command.rb +12 -7
  94. data/test/test_gem_dependency.rb +62 -11
  95. data/test/test_gem_dependency_installer.rb +18 -5
  96. data/test/test_gem_dependency_list.rb +6 -6
  97. data/test/test_gem_doc_manager.rb +7 -1
  98. data/test/test_gem_ext_configure_builder.rb +8 -10
  99. data/test/test_gem_ext_ext_conf_builder.rb +14 -8
  100. data/test/test_gem_gem_path_searcher.rb +1 -1
  101. data/test/test_gem_gem_runner.rb +11 -0
  102. data/test/test_gem_indexer.rb +398 -21
  103. data/test/test_gem_install_update_options.rb +20 -6
  104. data/test/test_gem_installer.rb +22 -14
  105. data/test/test_gem_local_remote_options.rb +2 -1
  106. data/test/test_gem_package_tar_header.rb +3 -3
  107. data/test/test_gem_package_tar_input.rb +3 -3
  108. data/test/test_gem_package_tar_output.rb +2 -2
  109. data/test/test_gem_package_task.rb +70 -0
  110. data/test/test_gem_platform.rb +12 -6
  111. data/test/test_gem_remote_fetcher.rb +23 -1
  112. data/test/test_gem_source_index.rb +32 -21
  113. data/test/test_gem_spec_fetcher.rb +77 -5
  114. data/test/test_gem_specification.rb +274 -1
  115. data/test/test_gem_uninstaller.rb +34 -4
  116. data/test/test_gem_version.rb +94 -4
  117. data/test/test_gem_version_option.rb +13 -0
  118. data/test/test_kernel.rb +4 -4
  119. data/util/CL2notes +56 -0
  120. data/util/gem_prelude.rb.template +251 -0
  121. metadata +30 -20
  122. metadata.gz.sig +3 -4
  123. data/TODO +0 -1
  124. data/scripts/buildtests.rb +0 -31
  125. data/scripts/gemdoc.rb +0 -67
  126. data/scripts/runtest.rb +0 -40
  127. data/scripts/specdoc.rb +0 -171
  128. data/scripts/upload_gemdoc.rb +0 -140
@@ -105,6 +105,10 @@ class Gem::Platform
105
105
  def to_s
106
106
  to_a.compact.join '-'
107
107
  end
108
+
109
+ def empty?
110
+ to_s.empty?
111
+ end
108
112
 
109
113
  ##
110
114
  # Is +other+ equal to this platform? Two platforms are equal if they have
@@ -143,14 +147,14 @@ class Gem::Platform
143
147
  when String then
144
148
  # This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007
145
149
  other = case other
146
- when /^i686-darwin(\d)/ then ['x86', 'darwin', $1]
147
- when /^i\d86-linux/ then ['x86', 'linux', nil]
148
- when 'java', 'jruby' then [nil, 'java', nil]
149
- when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2]
150
- when 'powerpc-darwin' then ['powerpc', 'darwin', nil]
151
- when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1]
152
- when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8']
153
- when /universal-darwin(\d)/ then ['universal', 'darwin', $1]
150
+ when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ]
151
+ when /^i\d86-linux/ then ['x86', 'linux', nil ]
152
+ when 'java', 'jruby' then [nil, 'java', nil ]
153
+ when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
154
+ when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
155
+ when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
156
+ when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ]
157
+ when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ]
154
158
  else other
155
159
  end
156
160
 
@@ -55,7 +55,7 @@ class Gem::RemoteFetcher
55
55
  # HTTP_PROXY_PASS)
56
56
  # * <tt>:no_proxy</tt>: ignore environment variables and _don't_ use a proxy
57
57
 
58
- def initialize(proxy)
58
+ def initialize(proxy = nil)
59
59
  Socket.do_not_reverse_lookup = true
60
60
 
61
61
  @connections = {}
@@ -86,7 +86,11 @@ class Gem::RemoteFetcher
86
86
 
87
87
  FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
88
88
 
89
- source_uri = URI.parse source_uri unless URI::Generic === source_uri
89
+ # Always escape URI's to deal with potential spaces and such
90
+ unless URI::Generic === source_uri
91
+ source_uri = URI.parse(URI.escape(source_uri))
92
+ end
93
+
90
94
  scheme = source_uri.scheme
91
95
 
92
96
  # URI.parse gets confused by MS Windows paths with forward slashes.
@@ -101,7 +105,7 @@ class Gem::RemoteFetcher
101
105
 
102
106
  remote_gem_path = source_uri + "gems/#{gem_file_name}"
103
107
 
104
- gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
108
+ gem = self.fetch_path remote_gem_path
105
109
  rescue Gem::RemoteFetcher::FetchError
106
110
  raise if spec.original_platform == spec.platform
107
111
 
@@ -112,16 +116,30 @@ class Gem::RemoteFetcher
112
116
 
113
117
  remote_gem_path = source_uri + "gems/#{alternate_name}"
114
118
 
115
- gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
119
+ gem = self.fetch_path remote_gem_path
116
120
  end
117
121
 
118
122
  File.open local_gem_path, 'wb' do |fp|
119
123
  fp.write gem
120
124
  end
121
125
  end
122
- when nil, 'file' then # TODO test for local overriding cache
126
+ when 'file' then
127
+ begin
128
+ path = source_uri.path
129
+ path = File.dirname(path) if File.extname(path) == '.gem'
130
+
131
+ remote_gem_path = File.join(path, 'gems', gem_file_name)
132
+
133
+ FileUtils.cp(remote_gem_path, local_gem_path)
134
+ rescue Errno::EACCES
135
+ local_gem_path = source_uri.to_s
136
+ end
137
+
138
+ say "Using local gem #{local_gem_path}" if
139
+ Gem.configuration.really_verbose
140
+ when nil then # TODO test for local overriding cache
123
141
  begin
124
- FileUtils.cp source_uri.to_s, local_gem_path
142
+ FileUtils.cp URI.unescape(source_uri.path), local_gem_path
125
143
  rescue Errno::EACCES
126
144
  local_gem_path = source_uri.to_s
127
145
  end
@@ -177,7 +195,7 @@ class Gem::RemoteFetcher
177
195
 
178
196
  return nil if env_proxy.nil? or env_proxy.empty?
179
197
 
180
- uri = URI.parse env_proxy
198
+ uri = URI.parse(normalize_uri(env_proxy))
181
199
 
182
200
  if uri and uri.user.nil? and uri.password.nil? then
183
201
  # Probably we have http_proxy_* variables?
@@ -233,10 +251,25 @@ class Gem::RemoteFetcher
233
251
  def open_uri_or_path(uri, last_modified = nil, head = false, depth = 0)
234
252
  raise "block is dead" if block_given?
235
253
 
236
- return open(get_file_uri_path(uri)) if file_uri? uri
237
-
238
254
  uri = URI.parse uri unless URI::Generic === uri
239
- raise ArgumentError, 'uri is not an HTTP URI' unless URI::HTTP === uri
255
+
256
+ # This check is redundant unless Gem::RemoteFetcher is likely
257
+ # to be used directly, since the scheme is checked elsewhere.
258
+ # - Daniel Berger
259
+ unless ['http', 'https', 'file'].include?(uri.scheme)
260
+ raise ArgumentError, 'uri scheme is invalid'
261
+ end
262
+
263
+ if uri.scheme == 'file'
264
+ path = uri.path
265
+
266
+ # Deal with leading slash on Windows paths
267
+ if path[0].chr == '/' && path[1].chr =~ /[a-zA-Z]/ && path[2].chr == ':'
268
+ path = path[1..-1]
269
+ end
270
+
271
+ return Gem.read_binary(path)
272
+ end
240
273
 
241
274
  fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
242
275
  response = request uri, fetch_type, last_modified
@@ -326,19 +359,5 @@ class Gem::RemoteFetcher
326
359
  connection.start
327
360
  end
328
361
 
329
- ##
330
- # Checks if the provided string is a file:// URI.
331
-
332
- def file_uri?(uri)
333
- uri =~ %r{\Afile://}
334
- end
335
-
336
- ##
337
- # Given a file:// URI, returns its local path.
338
-
339
- def get_file_uri_path(uri)
340
- uri.sub(%r{\Afile://}, '')
341
- end
342
-
343
362
  end
344
363
 
@@ -1,15 +1,17 @@
1
- module Gem
2
- module RequirePathsBuilder
3
- def write_require_paths_file_if_needed(spec = @spec, gem_home = @gem_home)
4
- return if spec.require_paths == ["lib"] && (spec.bindir.nil? || spec.bindir == "bin")
5
- file_name = File.join(gem_home, 'gems', "#{@spec.full_name}", ".require_paths")
6
- file_name.untaint
7
- File.open(file_name, "w") do |file|
8
- spec.require_paths.each do |path|
9
- file.puts path
10
- end
11
- file.puts spec.bindir if spec.bindir
1
+ require 'rubygems'
2
+
3
+ module Gem::RequirePathsBuilder
4
+ def write_require_paths_file_if_needed(spec = @spec, gem_home = @gem_home)
5
+ return if spec.require_paths == ["lib"] &&
6
+ (spec.bindir.nil? || spec.bindir == "bin")
7
+ file_name = File.join(gem_home, 'gems', "#{@spec.full_name}", ".require_paths")
8
+ file_name.untaint
9
+ File.open(file_name, "w") do |file|
10
+ spec.require_paths.each do |path|
11
+ file.puts path
12
12
  end
13
+ file.puts spec.bindir if spec.bindir
13
14
  end
14
15
  end
15
- end
16
+ end
17
+
@@ -29,7 +29,7 @@ class Gem::Requirement
29
29
  "~>" => lambda { |v, r| v >= r && v < r.bump }
30
30
  }
31
31
 
32
- OP_RE = /#{OPS.keys.map{ |k| Regexp.quote k }.join '|'}/o
32
+ OP_RE = OPS.keys.map{ |k| Regexp.quote k }.join '|'
33
33
 
34
34
  ##
35
35
  # Factory method to create a Gem::Requirement object. Input may be a
@@ -99,11 +99,15 @@ class Gem::Requirement
99
99
  as_list.join(", ")
100
100
  end
101
101
 
102
+ def pretty_print(q) # :nodoc:
103
+ q.group 1, 'Gem::Requirement.new(', ')' do
104
+ q.pp as_list
105
+ end
106
+ end
107
+
102
108
  def as_list
103
109
  normalize
104
- @requirements.collect { |req|
105
- "#{req[0]} #{req[1]}"
106
- }
110
+ @requirements.map do |op, version| "#{op} #{version}" end
107
111
  end
108
112
 
109
113
  def normalize
@@ -129,6 +133,11 @@ class Gem::Requirement
129
133
  OPS[op].call(version, required_version)
130
134
  end
131
135
 
136
+ def prerelease?
137
+ # TODO: why is @requirements a nested array?
138
+ @requirements.any?{ |r| r[1].prerelease? }
139
+ end
140
+
132
141
  ##
133
142
  # Parse the version requirement obj returning the operator and version.
134
143
  #
@@ -138,9 +147,9 @@ class Gem::Requirement
138
147
 
139
148
  def parse(obj)
140
149
  case obj
141
- when /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/o then
150
+ when /^\s*(#{OP_RE})\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
142
151
  [$1, Gem::Version.new($2)]
143
- when /^\s*([0-9.]+)\s*$/ then
152
+ when /^\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
144
153
  ['=', Gem::Version.new($1)]
145
154
  when /^\s*(#{OP_RE})\s*$/o then
146
155
  [$1, Gem::Version.new('0')]
@@ -1,6 +1,19 @@
1
+ #--
1
2
  # DO NOT EDIT
2
3
  # This file is auto-generated by build scripts.
3
4
  # See: rake update_version
5
+ #++
6
+
4
7
  module Gem
5
- RubyGemsVersion = '1.3.1'
8
+
9
+ ##
10
+ # The version of RubyGems you are using
11
+
12
+ RubyGemsVersion = '1.3.2'
13
+
14
+ ##
15
+ # The version of RubyGems you are using (duplicated for familiarity)
16
+
17
+ VERSION = RubyGemsVersion
18
+
6
19
  end
@@ -7,9 +7,12 @@
7
7
  require 'rubygems'
8
8
  require 'rubygems/user_interaction'
9
9
  require 'rubygems/specification'
10
+
11
+ # :stopdoc:
10
12
  module Gem
11
- autoload(:SpecFetcher, 'rubygems/spec_fetcher')
13
+ autoload :SpecFetcher, 'rubygems/spec_fetcher'
12
14
  end
15
+ # :startdoc:
13
16
 
14
17
  ##
15
18
  # The SourceIndex object indexes all the gems available from a
@@ -28,7 +31,7 @@ class Gem::SourceIndex
28
31
 
29
32
  include Gem::UserInteraction
30
33
 
31
- attr_reader :gems # :nodoc:
34
+ attr_reader :gems, :prerelease_gems # :nodoc:
32
35
 
33
36
  ##
34
37
  # Directories to use to refresh this SourceIndex when calling refresh!
@@ -81,13 +84,15 @@ class Gem::SourceIndex
81
84
  # loaded spec.
82
85
 
83
86
  def load_specification(file_name)
84
- begin
85
- spec_code = if RUBY_VERSION < '1.9' then
86
- File.read file_name
87
- else
88
- File.read file_name, :encoding => 'UTF-8'
89
- end.untaint
87
+ return nil unless file_name and File.exist? file_name
88
+
89
+ spec_code = if RUBY_VERSION < '1.9' then
90
+ File.read file_name
91
+ else
92
+ File.read file_name, :encoding => 'UTF-8'
93
+ end.untaint
90
94
 
95
+ begin
91
96
  gemspec = eval spec_code, binding, file_name
92
97
 
93
98
  if gemspec.is_a?(Gem::Specification)
@@ -104,6 +109,7 @@ class Gem::SourceIndex
104
109
  alert_warning "#{e.inspect}\n#{spec_code}"
105
110
  alert_warning "Invalid .gemspec format in '#{file_name}'"
106
111
  end
112
+
107
113
  return nil
108
114
  end
109
115
 
@@ -117,7 +123,8 @@ class Gem::SourceIndex
117
123
  # [Hash] hash of [Gem name, Gem::Specification] pairs
118
124
 
119
125
  def initialize(specifications={})
120
- @gems = specifications
126
+ @gems, @prerelease_gems = [{}, {}]
127
+ specifications.each{ |full_name, spec| add_spec spec }
121
128
  @spec_dirs = nil
122
129
  end
123
130
 
@@ -170,14 +177,29 @@ class Gem::SourceIndex
170
177
  result[name] << spec
171
178
  end
172
179
 
180
+ # TODO: why is this a hash while @gems is an array? Seems like
181
+ # structural similarity would be good.
173
182
  result.values.flatten
174
183
  end
175
184
 
185
+ ##
186
+ # An array including only the prerelease gemspecs
187
+
188
+ def prerelease_specs
189
+ @prerelease_gems.values
190
+ end
191
+
176
192
  ##
177
193
  # Add a gem specification to the source index.
178
194
 
179
- def add_spec(gem_spec)
180
- @gems[gem_spec.full_name] = gem_spec
195
+ def add_spec(gem_spec, name = gem_spec.full_name)
196
+ # No idea why, but the Indexer wants to insert them using original_name
197
+ # instead of full_name. So we make it an optional arg.
198
+ if gem_spec.version.prerelease?
199
+ @prerelease_gems[name] = gem_spec
200
+ else
201
+ @gems[name] = gem_spec
202
+ end
181
203
  end
182
204
 
183
205
  ##
@@ -238,7 +260,7 @@ class Gem::SourceIndex
238
260
  # Find a gem by an exact match on the short name.
239
261
 
240
262
  def find_name(gem_name, version_requirement = Gem::Requirement.default)
241
- dep = Gem::Dependency.new(/^#{gem_name}$/, version_requirement)
263
+ dep = Gem::Dependency.new gem_name, version_requirement
242
264
  search dep
243
265
  end
244
266
 
@@ -545,15 +567,15 @@ class Gem::SourceIndex
545
567
 
546
568
  end
547
569
 
570
+ # :stopdoc:
548
571
  module Gem
549
572
 
550
- # :stopdoc:
551
-
573
+ ##
552
574
  # Cache is an alias for SourceIndex to allow older YAMLized source index
553
575
  # objects to load properly.
554
- Cache = SourceIndex
555
576
 
556
- # :startdoc:
577
+ Cache = SourceIndex
557
578
 
558
579
  end
580
+ # :startdoc:
559
581
 
@@ -13,8 +13,8 @@ class Gem::SourceInfoCacheEntry
13
13
  attr_reader :source_index
14
14
 
15
15
  ##
16
- # The size of the of the source entry. Used to determine if the
17
- # source index has changed.
16
+ # The size of the source entry. Used to determine if the source index has
17
+ # changed.
18
18
 
19
19
  attr_reader :size
20
20
 
@@ -1,4 +1,5 @@
1
1
  require 'zlib'
2
+ require 'fileutils'
2
3
 
3
4
  require 'rubygems'
4
5
  require 'rubygems/remote_fetcher'
@@ -26,6 +27,11 @@ class Gem::SpecFetcher
26
27
 
27
28
  attr_reader :specs # :nodoc:
28
29
 
30
+ ##
31
+ # Cache of prerelease specs
32
+
33
+ attr_reader :prerelease_specs # :nodoc:
34
+
29
35
  @fetcher = nil
30
36
 
31
37
  def self.fetcher
@@ -42,6 +48,7 @@ class Gem::SpecFetcher
42
48
 
43
49
  @specs = {}
44
50
  @latest_specs = {}
51
+ @prerelease_specs = {}
45
52
 
46
53
  @fetcher = Gem::RemoteFetcher.fetcher
47
54
  end
@@ -56,10 +63,10 @@ class Gem::SpecFetcher
56
63
  ##
57
64
  # Fetch specs matching +dependency+. If +all+ is true, all matching
58
65
  # versions are returned. If +matching_platform+ is false, all platforms are
59
- # returned.
66
+ # returned. If +prerelease+ is true, prerelease versions are included.
60
67
 
61
- def fetch(dependency, all = false, matching_platform = true)
62
- specs_and_sources = find_matching dependency, all, matching_platform
68
+ def fetch(dependency, all = false, matching_platform = true, prerelease = false)
69
+ specs_and_sources = find_matching dependency, all, matching_platform, prerelease
63
70
 
64
71
  specs_and_sources.map do |spec_tuple, source_uri|
65
72
  [fetch_spec(spec_tuple, URI.parse(source_uri)), source_uri]
@@ -110,10 +117,10 @@ class Gem::SpecFetcher
110
117
  # versions are returned. If +matching_platform+ is false, gems for all
111
118
  # platforms are returned.
112
119
 
113
- def find_matching(dependency, all = false, matching_platform = true)
120
+ def find_matching(dependency, all = false, matching_platform = true, prerelease = false)
114
121
  found = {}
115
122
 
116
- list(all).each do |source_uri, specs|
123
+ list(all, prerelease).each do |source_uri, specs|
117
124
  found[source_uri] = specs.select do |spec_name, version, spec_platform|
118
125
  dependency =~ Gem::Dependency.new(spec_name, version) and
119
126
  (not matching_platform or Gem::Platform.match(spec_platform))
@@ -155,28 +162,37 @@ class Gem::SpecFetcher
155
162
 
156
163
  ##
157
164
  # Returns a list of gems available for each source in Gem::sources. If
158
- # +all+ is true, all versions are returned instead of only latest versions.
165
+ # +all+ is true, all versions are returned instead of only latest
166
+ # versions. If +prerelease+ is true, include prerelease versions.
167
+
168
+ def list(all = false, prerelease = false)
169
+ # TODO: make type the only argument
170
+ type = if all
171
+ :all
172
+ elsif prerelease
173
+ :prerelease
174
+ else
175
+ :latest
176
+ end
159
177
 
160
- def list(all = false)
161
178
  list = {}
162
179
 
163
- file = all ? 'specs' : 'latest_specs'
180
+ file = { :latest => 'latest_specs',
181
+ :prerelease => 'prerelease_specs',
182
+ :all => 'specs' }[type]
164
183
 
184
+ cache = { :latest => @latest_specs,
185
+ :prerelease => @prerelease_specs,
186
+ :all => @specs }[type]
187
+
165
188
  Gem.sources.each do |source_uri|
166
189
  source_uri = URI.parse source_uri
167
190
 
168
- if all and @specs.include? source_uri then
169
- list[source_uri] = @specs[source_uri]
170
- elsif not all and @latest_specs.include? source_uri then
171
- list[source_uri] = @latest_specs[source_uri]
172
- else
173
- specs = load_specs source_uri, file
174
-
175
- cache = all ? @specs : @latest_specs
176
-
177
- cache[source_uri] = specs
178
- list[source_uri] = specs
191
+ unless cache.include? source_uri
192
+ cache[source_uri] = load_specs source_uri, file
179
193
  end
194
+
195
+ list[source_uri] = cache[source_uri]
180
196
  end
181
197
 
182
198
  list
@@ -206,7 +222,14 @@ class Gem::SpecFetcher
206
222
  loaded = true
207
223
  end
208
224
 
209
- specs = Marshal.load spec_dump
225
+ specs = begin
226
+ Marshal.load spec_dump
227
+ rescue ArgumentError
228
+ spec_dump = @fetcher.fetch_path spec_path
229
+ loaded = true
230
+
231
+ Marshal.load spec_dump
232
+ end
210
233
 
211
234
  if loaded and @update_cache then
212
235
  begin