rubygems-update 1.0.1 → 1.1.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.

Files changed (172) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +248 -0
  3. data/README +2 -0
  4. data/Rakefile +47 -23
  5. data/bin/gem +9 -4
  6. data/bin/update_rubygems +15 -1
  7. data/examples/application/bin/myapp +0 -0
  8. data/lib/rubygems.rb +506 -373
  9. data/lib/rubygems/builder.rb +14 -7
  10. data/lib/rubygems/command.rb +9 -9
  11. data/lib/rubygems/command_manager.rb +1 -0
  12. data/lib/rubygems/commands/cleanup_command.rb +67 -69
  13. data/lib/rubygems/commands/environment_command.rb +16 -10
  14. data/lib/rubygems/commands/fetch_command.rb +7 -9
  15. data/lib/rubygems/commands/install_command.rb +9 -3
  16. data/lib/rubygems/commands/list_command.rb +2 -4
  17. data/lib/rubygems/commands/mirror_command.rb +1 -1
  18. data/lib/rubygems/commands/query_command.rb +52 -5
  19. data/lib/rubygems/commands/sources_command.rb +19 -10
  20. data/lib/rubygems/commands/specification_command.rb +10 -6
  21. data/lib/rubygems/commands/uninstall_command.rb +23 -6
  22. data/lib/rubygems/commands/unpack_command.rb +15 -3
  23. data/lib/rubygems/commands/update_command.rb +27 -25
  24. data/lib/rubygems/custom_require.rb +1 -1
  25. data/lib/rubygems/defaults.rb +8 -1
  26. data/lib/rubygems/dependency_installer.rb +72 -104
  27. data/lib/rubygems/digest/digest_adapter.rb +0 -0
  28. data/lib/rubygems/digest/md5.rb +0 -0
  29. data/lib/rubygems/digest/sha1.rb +0 -0
  30. data/lib/rubygems/digest/sha2.rb +0 -0
  31. data/lib/rubygems/exceptions.rb +22 -1
  32. data/lib/rubygems/format.rb +16 -10
  33. data/lib/rubygems/indexer.rb +46 -33
  34. data/lib/rubygems/indexer/abstract_index_builder.rb +10 -2
  35. data/lib/rubygems/indexer/latest_index_builder.rb +35 -0
  36. data/lib/rubygems/indexer/master_index_builder.rb +9 -8
  37. data/lib/rubygems/indexer/quick_index_builder.rb +5 -3
  38. data/lib/rubygems/install_update_options.rb +7 -1
  39. data/lib/rubygems/installer.rb +8 -5
  40. data/lib/rubygems/package.rb +17 -774
  41. data/lib/rubygems/package/f_sync_dir.rb +24 -0
  42. data/lib/rubygems/package/tar_header.rb +245 -0
  43. data/lib/rubygems/package/tar_input.rb +219 -0
  44. data/lib/rubygems/package/tar_output.rb +143 -0
  45. data/lib/rubygems/package/tar_reader.rb +86 -0
  46. data/lib/rubygems/package/tar_reader/entry.rb +99 -0
  47. data/lib/rubygems/package/tar_writer.rb +180 -0
  48. data/lib/rubygems/remote_fetcher.rb +131 -16
  49. data/lib/rubygems/requirement.rb +2 -0
  50. data/lib/rubygems/rubygems_version.rb +1 -1
  51. data/lib/rubygems/security.rb +1 -0
  52. data/lib/rubygems/server.rb +85 -104
  53. data/lib/rubygems/source_index.rb +412 -329
  54. data/lib/rubygems/source_info_cache.rb +232 -99
  55. data/lib/rubygems/source_info_cache_entry.rb +14 -4
  56. data/lib/rubygems/specification.rb +9 -10
  57. data/lib/rubygems/timer.rb +0 -0
  58. data/lib/rubygems/uninstaller.rb +56 -32
  59. data/lib/rubygems/user_interaction.rb +4 -10
  60. data/lib/rubygems/validator.rb +0 -0
  61. data/scripts/gemdoc.rb +0 -0
  62. data/scripts/specdoc.rb +0 -0
  63. data/setup.rb +56 -19
  64. data/test/gem_installer_test_case.rb +86 -0
  65. data/test/gem_installer_test_case.rbc +0 -0
  66. data/test/gem_package_tar_test_case.rb +146 -0
  67. data/test/gem_package_tar_test_case.rbc +0 -0
  68. data/test/gemutilities.rb +123 -38
  69. data/test/gemutilities.rbc +0 -0
  70. data/test/mockgemui.rb +5 -13
  71. data/test/mockgemui.rbc +0 -0
  72. data/test/private_key.pem +27 -0
  73. data/test/public_cert.pem +20 -0
  74. data/test/simple_gem.rbc +0 -0
  75. data/test/test_config.rbc +0 -0
  76. data/test/test_gem.rb +46 -4
  77. data/test/test_gem.rbc +0 -0
  78. data/test/test_gem_builder.rbc +0 -0
  79. data/test/test_gem_command.rbc +0 -0
  80. data/test/test_gem_command_manager.rb +4 -2
  81. data/test/test_gem_command_manager.rbc +0 -0
  82. data/test/test_gem_commands_build_command.rbc +0 -0
  83. data/test/test_gem_commands_cert_command.rb +5 -1
  84. data/test/test_gem_commands_cert_command.rbc +0 -0
  85. data/test/test_gem_commands_check_command.rbc +0 -0
  86. data/test/test_gem_commands_contents_command.rbc +0 -0
  87. data/test/test_gem_commands_dependency_command.rbc +0 -0
  88. data/test/test_gem_commands_environment_command.rb +17 -1
  89. data/test/test_gem_commands_environment_command.rbc +0 -0
  90. data/test/test_gem_commands_fetch_command.rb +6 -5
  91. data/test/test_gem_commands_fetch_command.rbc +0 -0
  92. data/test/test_gem_commands_generate_index_command.rbc +0 -0
  93. data/test/test_gem_commands_install_command.rb +36 -28
  94. data/test/test_gem_commands_install_command.rbc +0 -0
  95. data/test/test_gem_commands_mirror_command.rbc +0 -0
  96. data/test/test_gem_commands_pristine_command.rbc +0 -0
  97. data/test/test_gem_commands_query_command.rb +143 -19
  98. data/test/test_gem_commands_query_command.rbc +0 -0
  99. data/test/test_gem_commands_server_command.rb +1 -1
  100. data/test/test_gem_commands_server_command.rbc +0 -0
  101. data/test/test_gem_commands_sources_command.rb +67 -9
  102. data/test/test_gem_commands_sources_command.rbc +0 -0
  103. data/test/test_gem_commands_specification_command.rb +3 -2
  104. data/test/test_gem_commands_specification_command.rbc +0 -0
  105. data/test/test_gem_commands_unpack_command.rb +46 -4
  106. data/test/test_gem_commands_unpack_command.rbc +0 -0
  107. data/test/test_gem_commands_update_command.rb +174 -0
  108. data/test/test_gem_commands_update_command.rbc +0 -0
  109. data/test/test_gem_config_file.rbc +0 -0
  110. data/test/test_gem_dependency.rbc +0 -0
  111. data/test/test_gem_dependency_installer.rb +172 -187
  112. data/test/test_gem_dependency_installer.rbc +0 -0
  113. data/test/test_gem_dependency_list.rbc +0 -0
  114. data/test/test_gem_digest.rb +0 -0
  115. data/test/test_gem_digest.rbc +0 -0
  116. data/test/test_gem_doc_manager.rbc +0 -0
  117. data/test/test_gem_ext_configure_builder.rb +9 -6
  118. data/test/test_gem_ext_configure_builder.rbc +0 -0
  119. data/test/test_gem_ext_ext_conf_builder.rbc +0 -0
  120. data/test/test_gem_ext_rake_builder.rbc +0 -0
  121. data/test/test_gem_format.rb +1 -1
  122. data/test/test_gem_format.rbc +0 -0
  123. data/test/test_gem_gem_path_searcher.rbc +0 -0
  124. data/test/test_gem_gem_runner.rbc +0 -0
  125. data/test/test_gem_indexer.rb +7 -2
  126. data/test/test_gem_indexer.rbc +0 -0
  127. data/test/test_gem_install_update_options.rbc +0 -0
  128. data/test/test_gem_installer.rb +5 -84
  129. data/test/test_gem_installer.rbc +0 -0
  130. data/test/test_gem_local_remote_options.rbc +0 -0
  131. data/test/test_gem_outdated_command.rbc +0 -0
  132. data/test/test_gem_package_tar_header.rb +137 -0
  133. data/test/test_gem_package_tar_header.rbc +0 -0
  134. data/test/test_gem_package_tar_input.rb +119 -0
  135. data/test/test_gem_package_tar_input.rbc +0 -0
  136. data/test/test_gem_package_tar_output.rb +104 -0
  137. data/test/test_gem_package_tar_output.rbc +0 -0
  138. data/test/test_gem_package_tar_reader.rb +53 -0
  139. data/test/test_gem_package_tar_reader.rbc +0 -0
  140. data/test/test_gem_package_tar_reader_entry.rb +116 -0
  141. data/test/test_gem_package_tar_reader_entry.rbc +0 -0
  142. data/test/test_gem_package_tar_writer.rb +151 -0
  143. data/test/test_gem_package_tar_writer.rbc +0 -0
  144. data/test/test_gem_platform.rbc +0 -0
  145. data/test/test_gem_remote_fetcher.rb +189 -17
  146. data/test/test_gem_remote_fetcher.rbc +0 -0
  147. data/test/test_gem_requirement.rbc +0 -0
  148. data/test/test_gem_server.rb +13 -12
  149. data/test/test_gem_server.rbc +0 -0
  150. data/test/test_gem_source_index.rb +305 -56
  151. data/test/test_gem_source_index.rbc +0 -0
  152. data/test/test_gem_source_info_cache.rb +179 -53
  153. data/test/test_gem_source_info_cache.rbc +0 -0
  154. data/test/test_gem_source_info_cache_entry.rb +41 -10
  155. data/test/test_gem_source_info_cache_entry.rbc +0 -0
  156. data/test/test_gem_specification.rb +7 -7
  157. data/test/test_gem_specification.rbc +0 -0
  158. data/test/test_gem_stream_ui.rbc +0 -0
  159. data/test/test_gem_uninstaller.rb +43 -0
  160. data/test/test_gem_uninstaller.rbc +0 -0
  161. data/test/test_gem_validator.rbc +0 -0
  162. data/test/test_gem_version.rb +1 -1
  163. data/test/test_gem_version.rbc +0 -0
  164. data/test/test_gem_version_option.rbc +0 -0
  165. data/test/test_kernel.rb +1 -0
  166. data/test/test_kernel.rbc +0 -0
  167. metadata +85 -8
  168. metadata.gz.sig +0 -0
  169. data/lib/rubygems/gem_open_uri.rb +0 -7
  170. data/lib/rubygems/open-uri.rb +0 -773
  171. data/test/test_open_uri.rb +0 -13
  172. data/test/test_package.rb +0 -608
@@ -2,7 +2,6 @@ require 'net/http'
2
2
  require 'uri'
3
3
 
4
4
  require 'rubygems'
5
- require 'rubygems/gem_open_uri'
6
5
 
7
6
  ##
8
7
  # RemoteFetcher handles the details of fetching gems and gem information from
@@ -10,6 +9,8 @@ require 'rubygems/gem_open_uri'
10
9
 
11
10
  class Gem::RemoteFetcher
12
11
 
12
+ include Gem::UserInteraction
13
+
13
14
  class FetchError < Gem::Exception; end
14
15
 
15
16
  @fetcher = nil
@@ -29,6 +30,10 @@ class Gem::RemoteFetcher
29
30
  # HTTP_PROXY_PASS)
30
31
  # * <tt>:no_proxy</tt>: ignore environment variables and _don't_ use a proxy
31
32
  def initialize(proxy)
33
+ Socket.do_not_reverse_lookup = true
34
+
35
+ @connections = {}
36
+ @requests = Hash.new 0
32
37
  @proxy_uri =
33
38
  case proxy
34
39
  when :no_proxy then nil
@@ -38,6 +43,65 @@ class Gem::RemoteFetcher
38
43
  end
39
44
  end
40
45
 
46
+ ##
47
+ # Moves the gem +spec+ from +source_uri+ to the cache dir unless it is
48
+ # already there. If the source_uri is local the gem cache dir copy is
49
+ # always replaced.
50
+ def download(spec, source_uri, install_dir = Gem.dir)
51
+ gem_file_name = "#{spec.full_name}.gem"
52
+ local_gem_path = File.join install_dir, 'cache', gem_file_name
53
+
54
+ Gem.ensure_gem_subdirectories install_dir
55
+
56
+ source_uri = URI.parse source_uri unless URI::Generic === source_uri
57
+ scheme = source_uri.scheme
58
+
59
+ # URI.parse gets confused by MS Windows paths with forward slashes.
60
+ scheme = nil if scheme =~ /^[a-z]$/i
61
+
62
+ case scheme
63
+ when 'http' then
64
+ unless File.exist? local_gem_path then
65
+ begin
66
+ say "Downloading gem #{gem_file_name}" if
67
+ Gem.configuration.really_verbose
68
+
69
+ remote_gem_path = source_uri + "gems/#{gem_file_name}"
70
+
71
+ gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
72
+ rescue Gem::RemoteFetcher::FetchError
73
+ raise if spec.original_platform == spec.platform
74
+
75
+ alternate_name = "#{spec.original_name}.gem"
76
+
77
+ say "Failed, downloading gem #{alternate_name}" if
78
+ Gem.configuration.really_verbose
79
+
80
+ remote_gem_path = source_uri + "gems/#{alternate_name}"
81
+
82
+ gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
83
+ end
84
+
85
+ File.open local_gem_path, 'wb' do |fp|
86
+ fp.write gem
87
+ end
88
+ end
89
+ when nil, 'file' then # TODO test for local overriding cache
90
+ begin
91
+ FileUtils.cp source_uri.to_s, local_gem_path
92
+ rescue Errno::EACCES
93
+ local_gem_path = source_uri.to_s
94
+ end
95
+
96
+ say "Using local gem #{local_gem_path}" if
97
+ Gem.configuration.really_verbose
98
+ else
99
+ raise Gem::InstallError, "unsupported URI scheme #{source_uri.scheme}"
100
+ end
101
+
102
+ local_gem_path
103
+ end
104
+
41
105
  # Downloads +uri+.
42
106
  def fetch_path(uri)
43
107
  open_uri_or_path(uri) do |input|
@@ -47,9 +111,8 @@ class Gem::RemoteFetcher
47
111
  raise FetchError, "timed out fetching #{uri}"
48
112
  rescue IOError, SocketError, SystemCallError => e
49
113
  raise FetchError, "#{e.class}: #{e} reading #{uri}"
50
- rescue OpenURI::HTTPError => e
51
- body = e.io.readlines.join "\n\t"
52
- message = "#{e.class}: #{e} reading #{uri}\n\t#{body}"
114
+ rescue => e
115
+ message = "#{e.class}: #{e} reading #{uri}"
53
116
  raise FetchError, message
54
117
  end
55
118
 
@@ -83,7 +146,8 @@ class Gem::RemoteFetcher
83
146
  end
84
147
 
85
148
  rescue SocketError, SystemCallError, Timeout::Error => e
86
- raise FetchError, "#{e.message} (#{e.class})\n\tgetting size of #{uri}"
149
+ raise Gem::RemoteFetcher::FetchError,
150
+ "#{e.message} (#{e.class})\n\tgetting size of #{uri}"
87
151
  end
88
152
 
89
153
  private
@@ -131,26 +195,77 @@ class Gem::RemoteFetcher
131
195
 
132
196
  # Read the data from the (source based) URI, but if it is a file:// URI,
133
197
  # read from the filesystem instead.
134
- def open_uri_or_path(uri, &block)
198
+ def open_uri_or_path(uri, depth = 0, &block)
135
199
  if file_uri?(uri)
136
200
  open(get_file_uri_path(uri), &block)
137
201
  else
138
- connection_options = {
139
- "User-Agent" => "RubyGems/#{Gem::RubyGemsVersion} #{Gem::Platform.local}"
140
- }
202
+ uri = URI.parse uri unless URI::Generic === uri
203
+ net_http_args = [uri.host, uri.port]
204
+
205
+ if @proxy_uri then
206
+ net_http_args += [ @proxy_uri.host,
207
+ @proxy_uri.port,
208
+ @proxy_uri.user,
209
+ @proxy_uri.password
210
+ ]
211
+ end
212
+
213
+ connection_id = net_http_args.join ':'
214
+ @connections[connection_id] ||= Net::HTTP.new(*net_http_args)
215
+ connection = @connections[connection_id]
141
216
 
142
- if @proxy_uri
143
- http_proxy_url = "#{@proxy_uri.scheme}://#{@proxy_uri.host}:#{@proxy_uri.port}"
144
- connection_options[:proxy_http_basic_authentication] = [http_proxy_url, unescape(@proxy_uri.user)||'', unescape(@proxy_uri.password)||'']
217
+ if uri.scheme == 'https' && ! connection.started?
218
+ http_obj.use_ssl = true
219
+ http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
145
220
  end
146
221
 
147
- uri = URI.parse uri unless URI::Generic === uri
222
+ connection.start unless connection.started?
223
+
224
+ request = Net::HTTP::Get.new(uri.request_uri)
148
225
  unless uri.nil? || uri.user.nil? || uri.user.empty? then
149
- connection_options[:http_basic_authentication] =
150
- [unescape(uri.user), unescape(uri.password)]
226
+ request.basic_auth(uri.user, uri.password)
151
227
  end
152
228
 
153
- open(uri, connection_options, &block)
229
+ ua = "RubyGems/#{Gem::RubyGemsVersion} #{Gem::Platform.local}"
230
+ ua << " Ruby/#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
231
+ ua << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
232
+ ua << ")"
233
+
234
+ request.add_field 'User-Agent', ua
235
+ request.add_field 'Connection', 'keep-alive'
236
+ request.add_field 'Keep-Alive', '30'
237
+
238
+ # HACK work around EOFError bug in Net::HTTP
239
+ retried = false
240
+ begin
241
+ @requests[connection_id] += 1
242
+ response = connection.request(request)
243
+ rescue EOFError
244
+ requests = @requests[connection_id]
245
+ say "connection reset after #{requests} requests, retrying" if
246
+ Gem.configuration.really_verbose
247
+
248
+ raise Gem::RemoteFetcher::FetchError, 'too many connection resets' if
249
+ retried
250
+
251
+ @requests[connection_id] = 0
252
+
253
+ connection.finish
254
+ connection.start
255
+ retried = true
256
+ retry
257
+ end
258
+
259
+ case response
260
+ when Net::HTTPOK then
261
+ block.call(StringIO.new(response.body)) if block
262
+ when Net::HTTPRedirection then
263
+ raise Gem::RemoteFetcher::FetchError, "too many redirects" if depth > 10
264
+ open_uri_or_path(response['Location'], depth + 1, &block)
265
+ else
266
+ raise Gem::RemoteFetcher::FetchError,
267
+ "bad response #{response.message} #{response.code}"
268
+ end
154
269
  end
155
270
  end
156
271
 
@@ -16,6 +16,8 @@ class Gem::Requirement
16
16
 
17
17
  include Comparable
18
18
 
19
+ attr_reader :requirements
20
+
19
21
  OPS = {
20
22
  "=" => lambda { |v, r| v == r },
21
23
  "!=" => lambda { |v, r| v != r },
@@ -2,5 +2,5 @@
2
2
  # This file is auto-generated by build scripts.
3
3
  # See: rake update_version
4
4
  module Gem
5
- RubyGemsVersion = '1.0.1'
5
+ RubyGemsVersion = '1.1.0'
6
6
  end
@@ -4,6 +4,7 @@
4
4
  # See LICENSE.txt for permissions.
5
5
  #++
6
6
 
7
+ require 'rubygems'
7
8
  require 'rubygems/gem_openssl'
8
9
 
9
10
  # = Signed Gems README
@@ -1,7 +1,7 @@
1
1
  require 'webrick'
2
- require 'rdoc/template'
3
2
  require 'yaml'
4
3
  require 'zlib'
4
+ require 'erb'
5
5
 
6
6
  require 'rubygems'
7
7
 
@@ -27,107 +27,87 @@ class Gem::Server
27
27
 
28
28
  include Gem::UserInteraction
29
29
 
30
- DOC_TEMPLATE = <<-WEBPAGE
31
- <?xml version="1.0" encoding="iso-8859-1"?>
32
- <!DOCTYPE html
33
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
34
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
35
-
36
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
37
- <head>
38
- <title>RubyGems Documentation Index</title>
39
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
40
- <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
41
- </head>
42
- <body>
43
- <div id="fileHeader">
44
- <h1>RubyGems Documentation Index</h1>
45
- </div>
46
- <!-- banner header -->
47
-
48
- <div id="bodyContent">
49
- <div id="contextContent">
50
- <div id="description">
51
- <h1>Summary</h1>
52
- <p>There are %gem_count% gems installed:</p>
53
- <p>
54
- START:specs
55
- IFNOT:is_last
56
- <a href="#%name%">%name%</a>,
57
- ENDIF:is_last
58
- IF:is_last
59
- <a href="#%name%">%name%</a>.
60
- ENDIF:is_last
61
- END:specs
62
- <h1>Gems</h1>
63
-
64
- <dl>
65
- START:specs
66
- <dt>
67
- IF:first_name_entry
68
- <a name="%name%"></a>
69
- ENDIF:first_name_entry
70
- <b>%name% %version%</b>
71
- IF:rdoc_installed
72
- <a href="%doc_path%">[rdoc]</a>
73
- ENDIF:rdoc_installed
74
- IFNOT:rdoc_installed
75
- <span title="rdoc not installed">[rdoc]</span>
76
- ENDIF:rdoc_installed
77
- IF:homepage
78
- <a href="%homepage%" title="%homepage%">[www]</a>
79
- ENDIF:homepage
80
- IFNOT:homepage
81
- <span title="no homepage available">[www]</span>
82
- ENDIF:homepage
83
- IF:has_deps
84
- - depends on
85
- START:dependencies
86
- IFNOT:is_last
87
- <a href="#%name%" title="%version%">%name%</a>,
88
- ENDIF:is_last
89
- IF:is_last
90
- <a href="#%name%" title="%version%">%name%</a>.
91
- ENDIF:is_last
92
- END:dependencies
93
- ENDIF:has_deps
94
- </dt>
95
- <dd>
96
- %summary%
97
- IF:executables
98
- <br/>
99
-
100
- IF:only_one_executable
101
- Executable is
102
- ENDIF:only_one_executable
103
-
104
- IFNOT:only_one_executable
105
- Executables are
106
- ENDIF:only_one_executable
107
-
108
- START:executables
109
- IFNOT:is_last
110
- <span class="context-item-name">%executable%</span>,
111
- ENDIF:is_last
112
- IF:is_last
113
- <span class="context-item-name">%executable%</span>.
114
- ENDIF:is_last
115
- END:executables
116
- ENDIF:executables
117
- <br/>
118
- <br/>
119
- </dd>
120
- END:specs
121
- </dl>
122
-
30
+ DOC_TEMPLATE = <<-'WEBPAGE'
31
+ <?xml version="1.0" encoding="iso-8859-1"?>
32
+ <!DOCTYPE html
33
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
34
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
35
+
36
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
37
+ <head>
38
+ <title>RubyGems Documentation Index</title>
39
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
40
+ <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
41
+ </head>
42
+ <body>
43
+ <div id="fileHeader">
44
+ <h1>RubyGems Documentation Index</h1>
45
+ </div>
46
+ <!-- banner header -->
47
+
48
+ <div id="bodyContent">
49
+ <div id="contextContent">
50
+ <div id="description">
51
+ <h1>Summary</h1>
52
+ <p>There are <%=values["gem_count"]%> gems installed:</p>
53
+ <p>
54
+ <%= values["specs"].map { |v| "<a href=\"#{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
55
+ <h1>Gems</h1>
56
+
57
+ <dl>
58
+ <% values["specs"].each do |spec| %>
59
+ <dt>
60
+ <% if spec["first_name_entry"] then %>
61
+ <a name="<%=spec["name"]%>"></a>
62
+ <% end %>
63
+
64
+ <b><%=spec["name"]%> <%=spec["version"]%></b>
65
+
66
+ <% if spec["rdoc_installed"] then %>
67
+ <a href="<%=spec["doc_path"]%>">[rdoc]</a>
68
+ <% else %>
69
+ <span title="rdoc not installed">[rdoc]</span>
70
+ <% end %>
71
+
72
+ <% if spec["homepage"] then %>
73
+ <a href="<%=spec["homepage"]%>" title="<%=spec["homepage"]%>">[www]</a>
74
+ <% else %>
75
+ <span title="no homepage available">[www]</span>
76
+ <% end %>
77
+
78
+ <% if spec["has_deps"] then %>
79
+ - depends on
80
+ <%= spec["dependencies"].map { |v| "<a href=\"#{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
81
+ <% end %>
82
+ </dt>
83
+ <dd>
84
+ <%=spec["summary"]%>
85
+ <% if spec["executables"] then %>
86
+ <br/>
87
+
88
+ <% if spec["only_one_executable"] then %>
89
+ Executable is
90
+ <% else %>
91
+ Executables are
92
+ <%end%>
93
+
94
+ <%= spec["executables"].map { |v| "<span class=\"context-item-name\">#{v["executable"]}</span>"}.join ', ' %>.
95
+
96
+ <%end%>
97
+ <br/>
98
+ <br/>
99
+ </dd>
100
+ <% end %>
101
+ </dl>
102
+
103
+ </div>
104
+ </div>
123
105
  </div>
124
- </div>
106
+ <div id="validator-badges">
107
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
125
108
  </div>
126
- <div id="validator-badges">
127
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
128
- </div>
129
- </body>
130
- </html>
109
+ </body>
110
+ </html>
131
111
  WEBPAGE
132
112
 
133
113
  # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
@@ -496,11 +476,12 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
496
476
  end
497
477
 
498
478
  # create page from template
499
- template = TemplatePage.new(DOC_TEMPLATE)
479
+ template = ERB.new(DOC_TEMPLATE)
500
480
  res['content-type'] = 'text/html'
501
- template.write_html_on res.body,
502
- "gem_count" => specs.size.to_s, "specs" => specs,
503
- "total_file_count" => total_file_count.to_s
481
+ values = { "gem_count" => specs.size.to_s, "specs" => specs,
482
+ "total_file_count" => total_file_count.to_s }
483
+ result = template.result binding
484
+ res.body = result
504
485
  end
505
486
 
506
487
  paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
@@ -8,436 +8,519 @@ require 'rubygems'
8
8
  require 'rubygems/user_interaction'
9
9
  require 'rubygems/specification'
10
10
 
11
- module Gem
11
+ ##
12
+ # The SourceIndex object indexes all the gems available from a
13
+ # particular source (e.g. a list of gem directories, or a remote
14
+ # source). A SourceIndex maps a gem full name to a gem
15
+ # specification.
16
+ #
17
+ # NOTE:: The class used to be named Cache, but that became
18
+ # confusing when cached source fetchers where introduced. The
19
+ # constant Gem::Cache is an alias for this class to allow old
20
+ # YAMLized source index objects to load properly.
12
21
 
13
- # The SourceIndex object indexes all the gems available from a
14
- # particular source (e.g. a list of gem directories, or a remote
15
- # source). A SourceIndex maps a gem full name to a gem
16
- # specification.
17
- #
18
- # NOTE:: The class used to be named Cache, but that became
19
- # confusing when cached source fetchers where introduced. The
20
- # constant Gem::Cache is an alias for this class to allow old
21
- # YAMLized source index objects to load properly.
22
- #
23
- class SourceIndex
22
+ class Gem::SourceIndex
24
23
 
25
- include Enumerable
24
+ include Enumerable
26
25
 
26
+ include Gem::UserInteraction
27
+
28
+ class << self
27
29
  include Gem::UserInteraction
28
30
 
29
- # Class Methods. -------------------------------------------------
30
- class << self
31
- include Gem::UserInteraction
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") }
31
+ ##
32
+ # Factory method to construct a source index instance for a given
33
+ # path.
34
+ #
35
+ # deprecated::
36
+ # If supplied, from_installed_gems will act just like
37
+ # +from_gems_in+. This argument is deprecated and is provided
38
+ # just for backwards compatibility, and should not generally
39
+ # be used.
40
+ #
41
+ # return::
42
+ # SourceIndex instance
43
+
44
+ def from_installed_gems(*deprecated)
45
+ if deprecated.empty?
46
+ from_gems_in(*installed_spec_directories)
47
+ else
48
+ from_gems_in(*deprecated) # HACK warn
61
49
  end
50
+ end
62
51
 
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, binding, file_name
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}'"
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
+ ##
64
+ # Creates a new SourceIndex from the ruby format gem specifications in
65
+ # +spec_dirs+.
66
+
67
+ def from_gems_in(*spec_dirs)
68
+ self.new.load_gems_in(*spec_dirs)
69
+ end
70
+
71
+ ##
72
+ # Loads a ruby-format specification from +file_name+ and returns the
73
+ # loaded spec.
74
+
75
+ def load_specification(file_name)
76
+ begin
77
+ spec_code = File.read(file_name).untaint
78
+ gemspec = eval spec_code, binding, file_name
79
+ if gemspec.is_a?(Gem::Specification)
80
+ gemspec.loaded_from = file_name
81
+ return gemspec
98
82
  end
99
- return nil
83
+ alert_warning "File '#{file_name}' does not evaluate to a gem specification"
84
+ rescue SyntaxError => e
85
+ alert_warning e
86
+ alert_warning spec_code
87
+ rescue Exception => e
88
+ alert_warning(e.inspect.to_s + "\n" + spec_code)
89
+ alert_warning "Invalid .gemspec format in '#{file_name}'"
100
90
  end
101
-
91
+ return nil
102
92
  end
103
93
 
104
- # Instance Methods -----------------------------------------------
94
+ end
105
95
 
106
- # Constructs a source index instance from the provided
107
- # specifications
108
- #
109
- # specifications::
110
- # [Hash] hash of [Gem name, Gem::Specification] pairs
111
- #
112
- def initialize(specifications={})
113
- @gems = specifications
114
- end
115
-
116
- # Reconstruct the source index from the list of source
117
- # directories.
118
- def load_gems_in(*spec_dirs)
119
- @gems.clear
120
- specs = Dir.glob File.join("{#{spec_dirs.join(',')}}", "*.gemspec")
121
- specs.each do |file_name|
122
- gemspec = self.class.load_specification(file_name.untaint)
123
- add_spec(gemspec) if gemspec
96
+ ##
97
+ # Constructs a source index instance from the provided
98
+ # specifications
99
+ #
100
+ # specifications::
101
+ # [Hash] hash of [Gem name, Gem::Specification] pairs
102
+
103
+ def initialize(specifications={})
104
+ @gems = specifications
105
+ end
106
+
107
+ ##
108
+ # Reconstruct the source index from the specifications in +spec_dirs+.
109
+
110
+ def load_gems_in(*spec_dirs)
111
+ @gems.clear
112
+
113
+ spec_dirs.reverse_each do |spec_dir|
114
+ spec_files = Dir.glob File.join(spec_dir, '*.gemspec')
115
+
116
+ spec_files.each do |spec_file|
117
+ gemspec = self.class.load_specification spec_file.untaint
118
+ add_spec gemspec if gemspec
124
119
  end
125
- self
126
120
  end
127
121
 
128
- # Returns a Hash of name => Specification of the latest versions of each
129
- # gem in this index.
130
- def latest_specs
131
- result, latest = Hash.new { |h,k| h[k] = [] }, {}
122
+ self
123
+ end
132
124
 
133
- self.each do |_, spec| # SourceIndex is not a hash, so we're stuck with each
134
- name = spec.name
135
- curr_ver = spec.version
136
- prev_ver = latest[name]
125
+ ##
126
+ # Returns a Hash of name => Specification of the latest versions of each
127
+ # gem in this index.
137
128
 
138
- next unless prev_ver.nil? or curr_ver >= prev_ver
129
+ def latest_specs
130
+ result = Hash.new { |h,k| h[k] = [] }
131
+ latest = {}
139
132
 
140
- if prev_ver.nil? or curr_ver > prev_ver then
141
- result[name].clear
142
- latest[name] = curr_ver
143
- end
133
+ sort.each do |_, spec|
134
+ name = spec.name
135
+ curr_ver = spec.version
136
+ prev_ver = latest.key?(name) ? latest[name].version : nil
137
+
138
+ next unless prev_ver.nil? or curr_ver >= prev_ver or
139
+ latest[name].platform != Gem::Platform::RUBY
144
140
 
145
- result[name] << spec
141
+ if prev_ver.nil? or
142
+ (curr_ver > prev_ver and spec.platform == Gem::Platform::RUBY) then
143
+ result[name].clear
144
+ latest[name] = spec
146
145
  end
147
146
 
148
- result.values.flatten
149
- end
147
+ if spec.platform != Gem::Platform::RUBY then
148
+ result[name].delete_if do |result_spec|
149
+ result_spec.platform == spec.platform
150
+ end
151
+ end
150
152
 
151
- # Add a gem specification to the source index.
152
- def add_spec(gem_spec)
153
- @gems[gem_spec.full_name] = gem_spec
153
+ result[name] << spec
154
154
  end
155
155
 
156
- # Remove a gem specification named +full_name+.
157
- def remove_spec(full_name)
158
- @gems.delete(full_name)
159
- end
156
+ result.values.flatten
157
+ end
160
158
 
161
- # Iterate over the specifications in the source index.
162
- def each(&block) # :yields: gem.full_name, gem
163
- @gems.each(&block)
164
- end
159
+ ##
160
+ # Add a gem specification to the source index.
165
161
 
166
- # The gem specification given a full gem spec name.
167
- def specification(full_name)
168
- @gems[full_name]
169
- end
162
+ def add_spec(gem_spec)
163
+ @gems[gem_spec.full_name] = gem_spec
164
+ end
170
165
 
171
- # The signature for the source index. Changes in the signature
172
- # indicate a change in the index.
173
- def index_signature
174
- require 'rubygems/digest/sha2'
166
+ ##
167
+ # Add gem specifications to the source index.
175
168
 
176
- Gem::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
169
+ def add_specs(*gem_specs)
170
+ gem_specs.each do |spec|
171
+ add_spec spec
177
172
  end
173
+ end
178
174
 
179
- # The signature for the given gem specification.
180
- def gem_signature(gem_full_name)
181
- require 'rubygems/digest/sha2'
175
+ ##
176
+ # Remove a gem specification named +full_name+.
182
177
 
183
- Gem::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
184
- end
178
+ def remove_spec(full_name)
179
+ @gems.delete(full_name)
180
+ end
181
+
182
+ ##
183
+ # Iterate over the specifications in the source index.
184
+
185
+ def each(&block) # :yields: gem.full_name, gem
186
+ @gems.each(&block)
187
+ end
188
+
189
+ ##
190
+ # The gem specification given a full gem spec name.
191
+
192
+ def specification(full_name)
193
+ @gems[full_name]
194
+ end
195
+
196
+ ##
197
+ # The signature for the source index. Changes in the signature indicate a
198
+ # change in the index.
199
+
200
+ def index_signature
201
+ require 'rubygems/digest/sha2'
202
+
203
+ Gem::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
204
+ end
205
+
206
+ ##
207
+ # The signature for the given gem specification.
185
208
 
186
- def size
187
- @gems.size
209
+ def gem_signature(gem_full_name)
210
+ require 'rubygems/digest/sha2'
211
+
212
+ Gem::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
213
+ end
214
+
215
+ def size
216
+ @gems.size
217
+ end
218
+ alias length size
219
+
220
+ ##
221
+ # Find a gem by an exact match on the short name.
222
+
223
+ def find_name(gem_name, version_requirement = Gem::Requirement.default)
224
+ search(/^#{gem_name}$/, version_requirement)
225
+ end
226
+
227
+ ##
228
+ # Search for a gem by Gem::Dependency +gem_pattern+. If +only_platform+
229
+ # is true, only gems matching Gem::Platform.local will be returned. An
230
+ # Array of matching Gem::Specification objects is returned.
231
+ #
232
+ # For backwards compatibility, a String or Regexp pattern may be passed as
233
+ # +gem_pattern+, and a Gem::Requirement for +platform_only+. This
234
+ # behavior is deprecated and will be removed.
235
+
236
+ def search(gem_pattern, platform_only = false)
237
+ version_requirement = nil
238
+ only_platform = false
239
+
240
+ case gem_pattern # TODO warn after 2008/03, remove three months after
241
+ when Regexp then
242
+ version_requirement = platform_only || Gem::Requirement.default
243
+ when Gem::Dependency then
244
+ only_platform = platform_only
245
+ version_requirement = gem_pattern.version_requirements
246
+ gem_pattern = if gem_pattern.name.empty? then
247
+ //
248
+ else
249
+ /^#{Regexp.escape gem_pattern.name}$/
250
+ end
251
+ else
252
+ version_requirement = platform_only || Gem::Requirement.default
253
+ gem_pattern = /#{gem_pattern}/i
188
254
  end
189
- alias length size
190
255
 
191
- # Find a gem by an exact match on the short name.
192
- def find_name(gem_name, version_requirement = Gem::Requirement.default)
193
- search(/^#{gem_name}$/, version_requirement)
256
+ unless Gem::Requirement === version_requirement then
257
+ version_requirement = Gem::Requirement.create version_requirement
194
258
  end
195
259
 
196
- # Search for a gem by Gem::Dependency +gem_pattern+. If +only_platform+
197
- # is true, only gems matching Gem::Platform.local will be returned. An
198
- # Array of matching Gem::Specification objects is returned.
199
- #
200
- # For backwards compatibility, a String or Regexp pattern may be passed as
201
- # +gem_pattern+, and a Gem::Requirement for +platform_only+. This
202
- # behavior is deprecated and will be removed.
203
- def search(gem_pattern, platform_only = false)
204
- version_requirement = nil
205
- only_platform = false
206
-
207
- case gem_pattern # TODO warn after 2008/03, remove three months after
208
- when Regexp then
209
- version_requirement = platform_only || Gem::Requirement.default
210
- when Gem::Dependency then
211
- only_platform = platform_only
212
- version_requirement = gem_pattern.version_requirements
213
- gem_pattern = if gem_pattern.name.empty? then
214
- //
215
- else
216
- /^#{Regexp.escape gem_pattern.name}$/
217
- end
218
- else
219
- version_requirement = platform_only || Gem::Requirement.default
220
- gem_pattern = /#{gem_pattern}/i
221
- end
260
+ specs = @gems.values.select do |spec|
261
+ spec.name =~ gem_pattern and
262
+ version_requirement.satisfied_by? spec.version
263
+ end
222
264
 
223
- unless Gem::Requirement === version_requirement then
224
- version_requirement = Gem::Requirement.create version_requirement
265
+ if only_platform then
266
+ specs = specs.select do |spec|
267
+ Gem::Platform.match spec.platform
225
268
  end
269
+ end
226
270
 
227
- specs = @gems.values.select do |spec|
228
- spec.name =~ gem_pattern and
229
- version_requirement.satisfied_by? spec.version
230
- end
271
+ specs.sort_by { |s| s.sort_obj }
272
+ end
231
273
 
232
- if only_platform then
233
- specs = specs.select do |spec|
234
- Gem::Platform.match spec.platform
235
- end
236
- end
274
+ ##
275
+ # Refresh the source index from the local file system.
276
+ #
277
+ # return:: Returns a pointer to itself.
237
278
 
238
- specs.sort_by { |s| s.sort_obj }
239
- end
279
+ def refresh!
280
+ load_gems_in(self.class.installed_spec_directories)
281
+ end
240
282
 
241
- # Refresh the source index from the local file system.
242
- #
243
- # return:: Returns a pointer to itself.
244
- #
245
- def refresh!
246
- load_gems_in(self.class.installed_spec_directories)
247
- end
283
+ ##
284
+ # Returns an Array of Gem::Specifications that are not up to date.
248
285
 
249
- # Returns an Array of Gem::Specifications that are not up to date.
250
- #
251
- def outdated
252
- dep = Gem::Dependency.new '', Gem::Requirement.default
286
+ def outdated
287
+ dep = Gem::Dependency.new '', Gem::Requirement.default
253
288
 
254
- remotes = Gem::SourceInfoCache.search dep, true
289
+ remotes = Gem::SourceInfoCache.search dep, true
255
290
 
256
- outdateds = []
291
+ outdateds = []
257
292
 
258
- latest_specs.each do |local|
259
- name = local.name
260
- remote = remotes.select { |spec| spec.name == name }.
261
- sort_by { |spec| spec.version.to_ints }.
262
- last
263
- outdateds << name if remote and local.version < remote.version
264
- end
293
+ latest_specs.each do |local|
294
+ name = local.name
295
+ remote = remotes.select { |spec| spec.name == name }.
296
+ sort_by { |spec| spec.version.to_ints }.
297
+ last
265
298
 
266
- outdateds
299
+ outdateds << name if remote and local.version < remote.version
267
300
  end
268
301
 
269
- def update(source_uri)
270
- use_incremental = false
302
+ outdateds
303
+ end
271
304
 
272
- begin
273
- gem_names = fetch_quick_index source_uri
274
- remove_extra gem_names
275
- missing_gems = find_missing gem_names
305
+ ##
306
+ # Updates this SourceIndex from +source_uri+. If +all+ is false, only the
307
+ # latest gems are fetched.
276
308
 
277
- return false if missing_gems.size.zero?
309
+ def update(source_uri, all)
310
+ source_uri = URI.parse source_uri unless URI::Generic === source_uri
311
+ source_uri.path += '/' unless source_uri.path =~ /\/$/
278
312
 
279
- say "missing #{missing_gems.size} gems" if
280
- missing_gems.size > 0 and Gem.configuration.really_verbose
313
+ use_incremental = false
281
314
 
282
- use_incremental = missing_gems.size <= Gem.configuration.bulk_threshold
283
- rescue Gem::OperationNotSupportedError => ex
284
- alert_error "Falling back to bulk fetch: #{ex.message}" if
285
- Gem.configuration.really_verbose
286
- use_incremental = false
287
- end
315
+ begin
316
+ gem_names = fetch_quick_index source_uri, all
317
+ remove_extra gem_names
318
+ missing_gems = find_missing gem_names
288
319
 
289
- if use_incremental then
290
- update_with_missing(source_uri, missing_gems)
291
- else
292
- new_index = fetch_bulk_index(source_uri)
293
- @gems.replace(new_index.gems)
294
- end
320
+ return false if missing_gems.size.zero?
295
321
 
296
- true
297
- end
322
+ say "Missing metadata for #{missing_gems.size} gems" if
323
+ missing_gems.size > 0 and Gem.configuration.really_verbose
298
324
 
299
- def ==(other) # :nodoc:
300
- self.class === other and @gems == other.gems
325
+ use_incremental = missing_gems.size <= Gem.configuration.bulk_threshold
326
+ rescue Gem::OperationNotSupportedError => ex
327
+ alert_error "Falling back to bulk fetch: #{ex.message}" if
328
+ Gem.configuration.really_verbose
329
+ use_incremental = false
301
330
  end
302
331
 
303
- def dump
304
- Marshal.dump(self)
332
+ if use_incremental then
333
+ update_with_missing(source_uri, missing_gems)
334
+ else
335
+ new_index = fetch_bulk_index(source_uri)
336
+ @gems.replace(new_index.gems)
305
337
  end
306
338
 
307
- protected
339
+ true
340
+ end
308
341
 
309
- attr_reader :gems
342
+ def ==(other) # :nodoc:
343
+ self.class === other and @gems == other.gems
344
+ end
310
345
 
311
- private
346
+ def dump
347
+ Marshal.dump(self)
348
+ end
312
349
 
313
- def fetcher
314
- require 'rubygems/remote_fetcher'
350
+ protected
315
351
 
316
- Gem::RemoteFetcher.fetcher
317
- end
352
+ attr_reader :gems
318
353
 
319
- def fetch_index_from(source_uri)
320
- @fetch_error = nil
354
+ private
355
+
356
+ def fetcher
357
+ require 'rubygems/remote_fetcher'
358
+
359
+ Gem::RemoteFetcher.fetcher
360
+ end
321
361
 
322
- indexes = %W[
362
+ def fetch_index_from(source_uri)
363
+ @fetch_error = nil
364
+
365
+ indexes = %W[
323
366
  Marshal.#{Gem.marshal_version}.Z
324
367
  Marshal.#{Gem.marshal_version}
325
368
  yaml.Z
326
369
  yaml
327
370
  ]
328
371
 
329
- indexes.each do |name|
330
- spec_data = nil
331
- begin
332
- spec_data = fetcher.fetch_path("#{source_uri}/#{name}")
333
- spec_data = unzip(spec_data) if name =~ /\.Z$/
334
- if name =~ /Marshal/ then
335
- return Marshal.load(spec_data)
336
- else
337
- return YAML.load(spec_data)
338
- end
339
- rescue => e
340
- if Gem.configuration.really_verbose then
341
- alert_error "Unable to fetch #{name}: #{e.message}"
342
- end
343
- @fetch_error = e
372
+ indexes.each do |name|
373
+ spec_data = nil
374
+ index = source_uri + name
375
+ begin
376
+ spec_data = fetcher.fetch_path index
377
+ spec_data = unzip(spec_data) if name =~ /\.Z$/
378
+
379
+ if name =~ /Marshal/ then
380
+ return Marshal.load(spec_data)
381
+ else
382
+ return YAML.load(spec_data)
344
383
  end
384
+ rescue => e
385
+ if Gem.configuration.really_verbose then
386
+ alert_error "Unable to fetch #{name}: #{e.message}"
387
+ end
388
+
389
+ @fetch_error = e
345
390
  end
346
- nil
347
391
  end
348
392
 
349
- def fetch_bulk_index(source_uri)
350
- say "Bulk updating Gem source index for: #{source_uri}"
393
+ nil
394
+ end
395
+
396
+ def fetch_bulk_index(source_uri)
397
+ say "Bulk updating Gem source index for: #{source_uri}"
351
398
 
352
- index = fetch_index_from(source_uri)
353
- if index.nil? then
354
- raise Gem::RemoteSourceException,
399
+ index = fetch_index_from(source_uri)
400
+ if index.nil? then
401
+ raise Gem::RemoteSourceException,
355
402
  "Error fetching remote gem cache: #{@fetch_error}"
356
- end
357
- @fetch_error = nil
358
- index
359
403
  end
404
+ @fetch_error = nil
405
+ index
406
+ end
407
+
408
+ ##
409
+ # Get the quick index needed for incremental updates.
360
410
 
361
- # Get the quick index needed for incremental updates.
362
- def fetch_quick_index(source_uri)
363
- zipped_index = fetcher.fetch_path source_uri + '/quick/index.rz'
364
- unzip(zipped_index).split("\n")
365
- rescue ::Exception => ex
411
+ def fetch_quick_index(source_uri, all)
412
+ index = all ? 'index' : 'latest_index'
413
+
414
+ zipped_index = fetcher.fetch_path source_uri + "quick/#{index}.rz"
415
+
416
+ unzip(zipped_index).split("\n")
417
+ rescue ::Exception => e
418
+ unless all then
419
+ say "Latest index not found, using quick index" if
420
+ Gem.configuration.really_verbose
421
+
422
+ fetch_quick_index source_uri, true
423
+ else
366
424
  raise Gem::OperationNotSupportedError,
367
- "No quick index found: " + ex.message
425
+ "No quick index found: #{e.message}"
368
426
  end
427
+ end
369
428
 
370
- # Make a list of full names for all the missing gemspecs.
371
- def find_missing(spec_names)
372
- spec_names.find_all { |full_name|
373
- specification(full_name).nil?
374
- }
375
- end
429
+ ##
430
+ # Make a list of full names for all the missing gemspecs.
376
431
 
377
- def remove_extra(spec_names)
378
- dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
379
- each do |name, spec|
380
- remove_spec name unless dictionary.include? name
432
+ def find_missing(spec_names)
433
+ unless defined? @originals then
434
+ @originals = {}
435
+ each do |full_name, spec|
436
+ @originals[spec.original_name] = spec
381
437
  end
382
438
  end
383
439
 
384
- # Unzip the given string.
385
- def unzip(string)
386
- require 'zlib'
387
- Zlib::Inflate.inflate(string)
440
+ spec_names.find_all { |full_name|
441
+ @originals[full_name].nil?
442
+ }
443
+ end
444
+
445
+ def remove_extra(spec_names)
446
+ dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
447
+ each do |name, spec|
448
+ remove_spec name unless dictionary.include? spec.original_name
388
449
  end
450
+ end
389
451
 
390
- # Tries to fetch Marshal representation first, then YAML
391
- def fetch_single_spec(source_uri, spec_name)
392
- @fetch_error = nil
393
- begin
394
- marshal_uri = source_uri + "/quick/Marshal.#{Gem.marshal_version}/#{spec_name}.gemspec.rz"
395
- zipped = fetcher.fetch_path marshal_uri
396
- return Marshal.load(unzip(zipped))
397
- rescue => ex
398
- @fetch_error = ex
399
- if Gem.configuration.really_verbose then
400
- say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}"
401
- end
452
+ ##
453
+ # Unzip the given string.
454
+
455
+ def unzip(string)
456
+ require 'zlib'
457
+ Zlib::Inflate.inflate(string)
458
+ end
459
+
460
+ ##
461
+ # Tries to fetch Marshal representation first, then YAML
462
+
463
+ def fetch_single_spec(source_uri, spec_name)
464
+ @fetch_error = nil
465
+
466
+ begin
467
+ marshal_uri = source_uri + "quick/Marshal.#{Gem.marshal_version}/#{spec_name}.gemspec.rz"
468
+ zipped = fetcher.fetch_path marshal_uri
469
+ return Marshal.load(unzip(zipped))
470
+ rescue => ex
471
+ @fetch_error = ex
472
+
473
+ if Gem.configuration.really_verbose then
474
+ say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}"
402
475
  end
476
+ end
403
477
 
404
- begin
405
- yaml_uri = source_uri + "/quick/#{spec_name}.gemspec.rz"
406
- zipped = fetcher.fetch_path yaml_uri
407
- return YAML.load(unzip(zipped))
408
- rescue => ex
409
- @fetch_error = ex
410
- if Gem.configuration.really_verbose then
411
- say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}"
412
- end
478
+ begin
479
+ yaml_uri = source_uri + "quick/#{spec_name}.gemspec.rz"
480
+ zipped = fetcher.fetch_path yaml_uri
481
+ return YAML.load(unzip(zipped))
482
+ rescue => ex
483
+ @fetch_error = ex
484
+ if Gem.configuration.really_verbose then
485
+ say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}"
413
486
  end
414
- nil
415
487
  end
416
488
 
417
- # Update the cached source index with the missing names.
418
- def update_with_missing(source_uri, missing_names)
419
- progress = ui.progress_reporter(missing_names.size,
489
+ nil
490
+ end
491
+
492
+ ##
493
+ # Update the cached source index with the missing names.
494
+
495
+ def update_with_missing(source_uri, missing_names)
496
+ progress = ui.progress_reporter(missing_names.size,
420
497
  "Updating metadata for #{missing_names.size} gems from #{source_uri}")
421
- missing_names.each do |spec_name|
422
- gemspec = fetch_single_spec(source_uri, spec_name)
423
- if gemspec.nil? then
424
- ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \
498
+ missing_names.each do |spec_name|
499
+ gemspec = fetch_single_spec(source_uri, spec_name)
500
+ if gemspec.nil? then
501
+ ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \
425
502
  "\t#{@fetch_error.message}"
426
- else
427
- add_spec gemspec
428
- progress.updated spec_name
429
- end
430
- @fetch_error = nil
503
+ else
504
+ add_spec gemspec
505
+ progress.updated spec_name
431
506
  end
432
- progress.done
433
- progress.count
507
+ @fetch_error = nil
434
508
  end
435
-
509
+ progress.done
510
+ progress.count
436
511
  end
437
512
 
438
- # Cache is an alias for SourceIndex to allow older YAMLized source
439
- # index objects to load properly.
513
+ end
514
+
515
+ module Gem
516
+
517
+ # :stopdoc:
518
+
519
+ # Cache is an alias for SourceIndex to allow older YAMLized source index
520
+ # objects to load properly.
440
521
  Cache = SourceIndex
441
522
 
523
+ # :starddoc:
524
+
442
525
  end
443
526