rubygems-update 0.9.4 → 0.9.5

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 (225) hide show
  1. data/ChangeLog +587 -0
  2. data/README +0 -1
  3. data/Rakefile +39 -12
  4. data/TODO +0 -5
  5. data/bin/gem +7 -7
  6. data/bin/update_rubygems +1 -1
  7. data/examples/application/an-app.gemspec +1 -1
  8. data/gemspecs/cgikit-1.1.0.gemspec +1 -2
  9. data/gemspecs/jabber4r.gemspec +1 -1
  10. data/gemspecs/linguistics.gemspec +1 -1
  11. data/gemspecs/ook.gemspec +1 -1
  12. data/gemspecs/progressbar.gemspec +1 -1
  13. data/gemspecs/redcloth.gemspec +1 -1
  14. data/gemspecs/rublog.gemspec +1 -1
  15. data/gemspecs/ruby-doom.gemspec +1 -1
  16. data/gemspecs/rubyjdwp.gemspec +1 -1
  17. data/gemspecs/statistics.gemspec +1 -1
  18. data/lib/rubygems.rb +167 -105
  19. data/lib/rubygems/builder.rb +12 -10
  20. data/lib/rubygems/command.rb +177 -60
  21. data/lib/rubygems/command_manager.rb +30 -38
  22. data/lib/rubygems/commands/build_command.rb +42 -46
  23. data/lib/rubygems/commands/cert_command.rb +72 -69
  24. data/lib/rubygems/commands/check_command.rb +63 -63
  25. data/lib/rubygems/commands/cleanup_command.rb +25 -7
  26. data/lib/rubygems/commands/contents_command.rb +70 -62
  27. data/lib/rubygems/commands/dependency_command.rb +131 -86
  28. data/lib/rubygems/commands/environment_command.rb +67 -46
  29. data/lib/rubygems/commands/fetch_command.rb +62 -0
  30. data/lib/rubygems/commands/generate_index_command.rb +57 -0
  31. data/lib/rubygems/commands/help_command.rb +163 -73
  32. data/lib/rubygems/commands/install_command.rb +114 -128
  33. data/lib/rubygems/commands/list_command.rb +10 -8
  34. data/lib/rubygems/commands/lock_command.rb +101 -0
  35. data/lib/rubygems/commands/mirror_command.rb +105 -0
  36. data/lib/rubygems/commands/outdated_command.rb +24 -15
  37. data/lib/rubygems/commands/pristine_command.rb +118 -88
  38. data/lib/rubygems/commands/query_command.rb +109 -77
  39. data/lib/rubygems/commands/rdoc_command.rb +13 -10
  40. data/lib/rubygems/commands/search_command.rb +10 -8
  41. data/lib/rubygems/commands/server_command.rb +48 -0
  42. data/lib/rubygems/commands/sources_command.rb +104 -83
  43. data/lib/rubygems/commands/specification_command.rb +65 -51
  44. data/lib/rubygems/commands/uninstall_command.rb +17 -12
  45. data/lib/rubygems/commands/unpack_command.rb +68 -68
  46. data/lib/rubygems/commands/update_command.rb +72 -25
  47. data/lib/rubygems/commands/which_command.rb +86 -0
  48. data/lib/rubygems/config_file.rb +202 -78
  49. data/lib/rubygems/custom_require.rb +7 -88
  50. data/lib/rubygems/dependency.rb +65 -0
  51. data/lib/rubygems/dependency_installer.rb +232 -0
  52. data/lib/rubygems/dependency_list.rb +133 -105
  53. data/lib/rubygems/digest/md5.rb +4 -1
  54. data/lib/rubygems/digest/sha2.rb +1 -1
  55. data/lib/rubygems/doc_manager.rb +41 -19
  56. data/lib/rubygems/exceptions.rb +63 -0
  57. data/lib/rubygems/ext.rb +18 -0
  58. data/lib/rubygems/ext/builder.rb +56 -0
  59. data/lib/rubygems/ext/configure_builder.rb +24 -0
  60. data/lib/rubygems/ext/ext_conf_builder.rb +23 -0
  61. data/lib/rubygems/ext/rake_builder.rb +27 -0
  62. data/lib/rubygems/format.rb +16 -6
  63. data/lib/rubygems/gem_openssl.rb +43 -6
  64. data/lib/rubygems/gem_path_searcher.rb +84 -0
  65. data/lib/rubygems/gem_runner.rb +20 -5
  66. data/lib/rubygems/indexer.rb +163 -0
  67. data/lib/rubygems/indexer/abstract_index_builder.rb +80 -0
  68. data/lib/rubygems/indexer/marshal_index_builder.rb +17 -0
  69. data/lib/rubygems/indexer/master_index_builder.rb +53 -0
  70. data/lib/rubygems/indexer/quick_index_builder.rb +48 -0
  71. data/lib/rubygems/install_update_options.rb +87 -0
  72. data/lib/rubygems/installer.rb +316 -562
  73. data/lib/rubygems/local_remote_options.rb +106 -0
  74. data/lib/rubygems/old_format.rb +5 -13
  75. data/lib/rubygems/open-uri.rb +2 -0
  76. data/lib/rubygems/package.rb +28 -32
  77. data/lib/rubygems/platform.rb +187 -0
  78. data/lib/rubygems/remote_fetcher.rb +46 -29
  79. data/lib/rubygems/remote_installer.rb +11 -18
  80. data/lib/rubygems/requirement.rb +157 -0
  81. data/lib/rubygems/rubygems_version.rb +1 -1
  82. data/lib/rubygems/security.rb +715 -457
  83. data/lib/rubygems/server.rb +77 -59
  84. data/lib/rubygems/source_index.rb +154 -83
  85. data/lib/rubygems/source_info_cache.rb +73 -30
  86. data/lib/rubygems/source_info_cache_entry.rb +12 -3
  87. data/lib/rubygems/specification.rb +378 -145
  88. data/lib/rubygems/uninstaller.rb +183 -0
  89. data/lib/rubygems/user_interaction.rb +38 -9
  90. data/lib/rubygems/validator.rb +53 -24
  91. data/lib/rubygems/version.rb +126 -289
  92. data/lib/rubygems/version_option.rb +49 -0
  93. data/pkgs/sources/lib/sources.rb +1 -4
  94. data/pkgs/sources/sources.gemspec +3 -3
  95. data/scripts/gemdoc.rb +0 -1
  96. data/setup.rb +166 -1505
  97. data/test/bogussources.rb +0 -1
  98. data/test/data/gem-private_key.pem +27 -0
  99. data/test/data/gem-public_cert.pem +20 -0
  100. data/test/functional.rb +3 -105
  101. data/test/gemutilities.rb +145 -24
  102. data/test/insure_session.rb +0 -1
  103. data/test/{test_datadir.rb → test_config.rb} +7 -13
  104. data/test/test_gem.rb +360 -9
  105. data/test/test_gem_builder.rb +34 -0
  106. data/test/{test_command.rb → test_gem_command.rb} +119 -62
  107. data/test/{test_parse_commands.rb → test_gem_command_manager.rb} +64 -40
  108. data/test/test_gem_commands_build_command.rb +75 -0
  109. data/test/test_gem_commands_cert_command.rb +122 -0
  110. data/test/test_gem_commands_check_command.rb +25 -0
  111. data/test/test_gem_commands_contents_command.rb +92 -0
  112. data/test/test_gem_commands_dependency_command.rb +108 -0
  113. data/test/test_gem_commands_environment_command.rb +117 -0
  114. data/test/test_gem_commands_fetch_command.rb +34 -0
  115. data/test/test_gem_commands_generate_index_command.rb +32 -0
  116. data/test/test_gem_commands_install_command.rb +160 -0
  117. data/test/test_gem_commands_mirror_command.rb +56 -0
  118. data/test/test_gem_commands_pristine_command.rb +100 -0
  119. data/test/test_gem_commands_query_command.rb +82 -0
  120. data/test/test_gem_commands_sources_command.rb +147 -0
  121. data/test/test_gem_commands_specification_command.rb +93 -0
  122. data/test/test_gem_commands_unpack_command.rb +55 -0
  123. data/test/test_gem_config_file.rb +210 -0
  124. data/test/test_gem_dependency.rb +89 -0
  125. data/test/test_gem_dependency_installer.rb +542 -0
  126. data/test/test_gem_dependency_list.rb +212 -0
  127. data/test/test_gem_doc_manager.rb +32 -0
  128. data/test/test_gem_ext_configure_builder.rb +13 -17
  129. data/test/test_gem_ext_ext_conf_builder.rb +9 -9
  130. data/test/test_gem_ext_rake_builder.rb +23 -11
  131. data/test/test_gem_format.rb +69 -0
  132. data/test/test_gem_gem_path_searcher.rb +57 -0
  133. data/test/test_gem_gem_runner.rb +35 -0
  134. data/test/test_gem_indexer.rb +119 -0
  135. data/test/test_gem_install_update_options.rb +40 -0
  136. data/test/test_gem_installer.rb +796 -0
  137. data/test/test_gem_local_remote_options.rb +84 -0
  138. data/test/test_gem_outdated_command.rb +11 -9
  139. data/test/test_gem_platform.rb +240 -0
  140. data/test/{test_remote_fetcher.rb → test_gem_remote_fetcher.rb} +124 -55
  141. data/test/{test_remote_installer.rb → test_gem_remote_installer.rb} +3 -4
  142. data/test/test_gem_requirement.rb +223 -0
  143. data/test/test_gem_server.rb +71 -0
  144. data/test/test_gem_source_index.rb +429 -0
  145. data/test/test_gem_source_info_cache.rb +79 -17
  146. data/test/test_gem_source_info_cache_entry.rb +11 -9
  147. data/test/test_gem_specification.rb +738 -0
  148. data/test/test_gem_stream_ui.rb +117 -0
  149. data/test/test_gem_validator.rb +70 -0
  150. data/test/test_gem_version.rb +191 -0
  151. data/test/test_gem_version_option.rb +77 -0
  152. data/test/{test_require_gem.rb → test_kernel.rb} +19 -12
  153. data/test/test_open_uri.rb +1 -2
  154. data/test/test_package.rb +45 -34
  155. metadata +116 -141
  156. data/Releases +0 -127
  157. data/bin/gem_mirror +0 -73
  158. data/bin/gem_server +0 -6
  159. data/bin/gemlock +0 -127
  160. data/bin/gemri +0 -24
  161. data/bin/gemwhich +0 -89
  162. data/bin/index_gem_repository.rb +0 -302
  163. data/lib/gemconfigure.rb +0 -24
  164. data/lib/rubygems/gem_commands.rb +0 -273
  165. data/pkgs/sources/sources-0.0.1.gem +0 -0
  166. data/post-install.rb +0 -121
  167. data/test/brokenbuildgem.rb +0 -35
  168. data/test/data/PostMessage-0.0.1.gem +0 -0
  169. data/test/data/a-0.0.1.gem +0 -0
  170. data/test/data/a-0.0.2.gem +0 -0
  171. data/test/data/b-0.0.2.gem +0 -0
  172. data/test/data/broken-1.0.0.gem +0 -0
  173. data/test/data/broken_build/broken-build.gemspec +0 -20
  174. data/test/data/broken_build/ext/extconf.rb +0 -3
  175. data/test/data/broken_build/ext/foo.c +0 -1
  176. data/test/data/c-1.2.gem +0 -0
  177. data/test/data/gemhome/cache/a-0.0.1.gem +0 -0
  178. data/test/data/gemhome/cache/a-0.0.2.gem +0 -0
  179. data/test/data/gemhome/cache/b-0.0.2.gem +0 -0
  180. data/test/data/gemhome/cache/c-1.2.gem +0 -0
  181. data/test/data/gemhome/gems/a-0.0.1/lib/code.rb +0 -1
  182. data/test/data/gemhome/gems/a-0.0.2/lib/code.rb +0 -1
  183. data/test/data/gemhome/gems/b-0.0.2/lib/code.rb +0 -1
  184. data/test/data/gemhome/gems/c-1.2/lib/code.rb +0 -1
  185. data/test/data/gemhome/specifications/a-0.0.1.gemspec +0 -8
  186. data/test/data/gemhome/specifications/a-0.0.2.gemspec +0 -8
  187. data/test/data/gemhome/specifications/b-0.0.2.gemspec +0 -8
  188. data/test/data/gemhome/specifications/c-1.2.gemspec +0 -8
  189. data/test/data/legacy/keyedlist-0.4.0.ruby +0 -11
  190. data/test/data/legacy/keyedlist-0.4.0.yaml +0 -16
  191. data/test/data/lib/code.rb +0 -1
  192. data/test/data/one/README.one +0 -1
  193. data/test/data/one/lib/one.rb +0 -9
  194. data/test/data/one/one-0.0.1.gem +0 -0
  195. data/test/data/one/one.gemspec +0 -17
  196. data/test/data/one/one.yaml +0 -40
  197. data/test/data/post_install.gemspec +0 -19
  198. data/test/functional_extension_gems.rb +0 -48
  199. data/test/functional_generate_yaml_index.rb +0 -104
  200. data/test/gemenvironment.rb +0 -59
  201. data/test/io_capture.rb +0 -33
  202. data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +0 -11
  203. data/test/mock/gems/specifications/sources-0.0.1.gemspec +0 -8
  204. data/test/onegem.rb +0 -35
  205. data/test/test_builder.rb +0 -34
  206. data/test/test_check_command.rb +0 -34
  207. data/test/test_configfile.rb +0 -42
  208. data/test/test_dependency_list.rb +0 -169
  209. data/test/test_file_list.rb +0 -101
  210. data/test/test_format.rb +0 -49
  211. data/test/test_gem_sources_command.rb +0 -135
  212. data/test/test_gemloadpaths.rb +0 -51
  213. data/test/test_gempaths.rb +0 -170
  214. data/test/test_installer.rb +0 -369
  215. data/test/test_loadmanager.rb +0 -48
  216. data/test/test_process_commands.rb +0 -52
  217. data/test/test_source_index.rb +0 -231
  218. data/test/test_specific_extras.rb +0 -46
  219. data/test/test_specification.rb +0 -565
  220. data/test/test_user_interaction.rb +0 -48
  221. data/test/test_validator.rb +0 -59
  222. data/test/test_version_comparison.rb +0 -321
  223. data/test/testgem.rc +0 -7
  224. data/test/user_capture.rb +0 -7
  225. data/test/yaml_data.rb +0 -63
@@ -1,21 +1,23 @@
1
- require 'rubygems'
2
- Gem.manage_gems
3
1
  require 'webrick'
4
- require 'yaml'
5
- require 'optparse'
6
2
  require 'rdoc/template'
3
+ require 'yaml'
4
+ require 'zlib'
5
+
6
+ require 'rubygems'
7
7
 
8
+ ##
8
9
  # Gem::Server and allows users to serve gems for consumption by
9
10
  # `gem --remote-install`.
10
- #
11
+ #
11
12
  # gem_server starts an HTTP server on the given port and serves the folowing:
12
13
  # * "/" - Browsing of gem spec files for installed gems
13
- # * "/yaml" - Full yaml dump of metadata for installed gems
14
+ # * "/Marshal" - Full SourceIndex dump of metadata for installed gems
15
+ # * "/yaml" - YAML dump of metadata for installed gems - deprecated
14
16
  # * "/gems" - Direct access to download the installable gems
15
17
  #
16
18
  # == Usage
17
19
  #
18
- # gem_server [-p portnum] [-d gem_path]
20
+ # gem server [-p portnum] [-d gem_path]
19
21
  #
20
22
  # port_num:: The TCP port the HTTP server will bind to
21
23
  # gem_path::
@@ -23,6 +25,8 @@ require 'rdoc/template'
23
25
  # subdirectories.
24
26
  class Gem::Server
25
27
 
28
+ include Gem::UserInteraction
29
+
26
30
  DOC_TEMPLATE = <<-WEBPAGE
27
31
  <?xml version="1.0" encoding="iso-8859-1"?>
28
32
  <!DOCTYPE html
@@ -33,7 +37,7 @@ class Gem::Server
33
37
  <head>
34
38
  <title>RubyGems Documentation Index</title>
35
39
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
36
- <link rel="stylesheet" href="rdoc-style.css" type="text/css" media="screen" />
40
+ <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
37
41
  </head>
38
42
  <body>
39
43
  <div id="fileHeader">
@@ -71,13 +75,13 @@ IFNOT:rdoc_installed
71
75
  <span title="rdoc not installed">[rdoc]</span>
72
76
  ENDIF:rdoc_installed
73
77
  IF:homepage
74
- <a href="%homepage%" target="_blank" title="%homepage%">[www]</a>
78
+ <a href="%homepage%" title="%homepage%">[www]</a>
75
79
  ENDIF:homepage
76
80
  IFNOT:homepage
77
81
  <span title="no homepage available">[www]</span>
78
82
  ENDIF:homepage
79
83
  IF:has_deps
80
- - depends on
84
+ - depends on
81
85
  START:dependencies
82
86
  IFNOT:is_last
83
87
  <a href="#%name%" title="%version%">%name%</a>,
@@ -337,75 +341,89 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
337
341
  .ruby-value { color: #7fffd4; background: transparent; }
338
342
  RDOCCSS
339
343
 
340
- def self.process_args(args)
341
- options = {}
342
- options[:port] = 8808
343
- options[:gemdir] = Gem.dir
344
- options[:daemon] = false
345
-
346
- opts = OptionParser.new do |opts|
347
- opts.on_tail("--help", "show this message") do
348
- puts opts
349
- exit
350
- end
351
-
352
- opts.on('-p', '--port=PORT', "Specify the port to listen on") do |port|
353
- options[:port] = port
354
- end
355
-
356
- opts.on('-d', '--dir=GEMDIR',
357
- "Specify the directory from which to serve Gems") do |gemdir|
358
- options[:gemdir] = gemdir
359
- end
360
-
361
- opts.on( '--daemon', "Run as a daemon") do |daemon|
362
- options[:daemon] = daemon
363
- end
364
-
365
- end
366
-
367
- opts.parse! args
368
-
369
- options
370
- end
371
-
372
- def self.run(args = ARGV)
373
- options = process_args args
344
+ def self.run(options)
374
345
  new(options[:gemdir], options[:port], options[:daemon]).run
375
346
  end
376
347
 
377
348
  def initialize(gemdir, port, daemon)
378
- Socket.do_not_reverse_lookup=true
349
+ Socket.do_not_reverse_lookup = true
379
350
 
380
351
  @gemdir = gemdir
381
352
  @port = port
382
353
  @daemon = daemon
354
+ logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
355
+ @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
356
+
357
+ @spec_dir = File.join @gemdir, "specifications"
358
+ @source_index = Gem::SourceIndex.from_gems_in @spec_dir
359
+ end
360
+
361
+ def quick(req, res)
362
+ res['content-type'] = 'text/plain'
363
+ res['date'] = File.stat(@spec_dir).mtime
364
+
365
+ case req.request_uri.request_uri
366
+ when '/quick/index' then
367
+ res.body << @source_index.map { |name,_| name }.join("\n")
368
+ when '/quick/index.rz' then
369
+ index = @source_index.map { |name,_| name }.join("\n")
370
+ res.body << Zlib::Deflate.deflate(index)
371
+ when %r|^/quick/(.*)-([0-9.]+)\.gemspec(\.marshal)?\.rz$| then
372
+ specs = @source_index.search $1, $2
373
+ if specs.empty? then
374
+ res.status = 404
375
+ elsif specs.length > 1 then
376
+ res.status = 500
377
+ elsif $3 # marshal quickindex instead of YAML
378
+ res.body << Zlib::Deflate.deflate(Marshal.dump(specs.first))
379
+ else # deprecated YAML format
380
+ res.body << Zlib::Deflate.deflate(specs.first.to_yaml)
381
+ end
382
+ else
383
+ res.status = 404
384
+ end
383
385
  end
384
386
 
385
387
  def run
386
- WEBrick::Daemon.start if @daemon
388
+ @server.listen nil, @port
389
+
390
+ say "Starting gem server on http://localhost:#{@port}/"
387
391
 
388
- spec_dir = File.join @gemdir, "specifications"
392
+ WEBrick::Daemon.start if @daemon
389
393
 
390
- s = WEBrick::HTTPServer.new :Port => @port
394
+ @server.mount_proc("/yaml") do |req, res|
395
+ res['content-type'] = 'text/plain'
396
+ res['date'] = File.stat(@spec_dir).mtime
397
+ if req.request_method == 'HEAD' then
398
+ res['content-length'] = @source_index.to_yaml.length
399
+ else
400
+ res.body << @source_index.to_yaml
401
+ end
402
+ end
391
403
 
392
- s.mount_proc("/yaml") do |req, res|
404
+ @server.mount_proc("/Marshal") do |req, res|
393
405
  res['content-type'] = 'text/plain'
394
- res['date'] = File.stat(spec_dir).mtime
395
- res.body << Gem::SourceIndex.from_gems_in(spec_dir).to_yaml
406
+ res['date'] = File.stat(@spec_dir).mtime
407
+ if req.request_method == 'HEAD' then
408
+ res['content-length'] = Marshal.dump(@source_index).length
409
+ else
410
+ res.body << Marshal.dump(@source_index)
411
+ end
396
412
  end
397
413
 
398
- s.mount_proc("/rdoc-style.css") do |req, res|
414
+ @server.mount_proc("/quick/", &method(:quick))
415
+
416
+ @server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
399
417
  res['content-type'] = 'text/css'
400
- res['date'] = File.stat(spec_dir).mtime
418
+ res['date'] = File.stat(@spec_dir).mtime
401
419
  res.body << RDOC_CSS
402
420
  end
403
421
 
404
- s.mount_proc("/") do |req, res|
422
+ @server.mount_proc("/") do |req, res|
405
423
  specs = []
406
424
  total_file_count = 0
407
425
 
408
- Gem::SourceIndex.from_gems_in(spec_dir).each do |path, spec|
426
+ @source_index.each do |path, spec|
409
427
  total_file_count += spec.files.size
410
428
  deps = spec.dependencies.collect { |dep|
411
429
  { "name" => dep.name,
@@ -472,14 +490,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
472
490
 
473
491
  paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
474
492
  paths.each do |mount_point, mount_dir|
475
- s.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
493
+ @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
476
494
  File.join(@gemdir, mount_dir), true)
477
495
  end
478
496
 
479
- trap("INT") { s.shutdown; exit! }
480
- trap("TERM") { s.shutdown; exit! }
497
+ trap("INT") { @server.shutdown; exit! }
498
+ trap("TERM") { @server.shutdown; exit! }
481
499
 
482
- s.start
500
+ @server.start
483
501
  end
484
502
 
485
503
  end
@@ -4,12 +4,11 @@
4
4
  # See LICENSE.txt for permissions.
5
5
  #++
6
6
 
7
- require 'rubygems/user_interaction'
8
- require 'rubygems/remote_fetcher'
9
- require 'rubygems/digest/sha2'
10
-
11
7
  require 'forwardable'
12
- require 'time'
8
+
9
+ require 'rubygems'
10
+ require 'rubygems/user_interaction'
11
+ require 'rubygems/specification'
13
12
 
14
13
  module Gem
15
14
 
@@ -30,8 +29,6 @@ module Gem
30
29
 
31
30
  include Gem::UserInteraction
32
31
 
33
- INCREMENTAL_THRESHHOLD = 50
34
-
35
32
  # Class Methods. -------------------------------------------------
36
33
  class << self
37
34
  include Gem::UserInteraction
@@ -89,7 +86,7 @@ module Gem
89
86
  def load_specification(file_name)
90
87
  begin
91
88
  spec_code = File.read(file_name).untaint
92
- gemspec = eval(spec_code)
89
+ gemspec = eval spec_code, binding, file_name
93
90
  if gemspec.is_a?(Gem::Specification)
94
91
  gemspec.loaded_from = file_name
95
92
  return gemspec
@@ -134,18 +131,24 @@ module Gem
134
131
  # Returns a Hash of name => Specification of the latest versions of each
135
132
  # gem in this index.
136
133
  def latest_specs
137
- thin = {}
134
+ result, latest = Hash.new { |h,k| h[k] = [] }, {}
138
135
 
139
- each do |full_name, spec|
136
+ self.each do |_, spec| # SourceIndex is not a hash, so we're stuck with each
140
137
  name = spec.name
141
- if thin.has_key? name then
142
- thin[name] = spec if spec.version > thin[name].version
143
- else
144
- thin[name] = spec
138
+ curr_ver = spec.version
139
+ prev_ver = latest[name]
140
+
141
+ next unless prev_ver.nil? or curr_ver >= prev_ver
142
+
143
+ if prev_ver.nil? or curr_ver > prev_ver then
144
+ result[name].clear
145
+ latest[name] = curr_ver
145
146
  end
147
+
148
+ result[name] << spec
146
149
  end
147
150
 
148
- thin
151
+ result.values.flatten
149
152
  end
150
153
 
151
154
  # Add a gem specification to the source index.
@@ -159,10 +162,7 @@ module Gem
159
162
  end
160
163
 
161
164
  # Iterate over the specifications in the source index.
162
- #
163
- # &block:: [yields gem.full_name, Gem::Specification]
164
- #
165
- def each(&block)
165
+ def each(&block) # :yields: gem.full_name, gem
166
166
  @gems.each(&block)
167
167
  end
168
168
 
@@ -174,18 +174,22 @@ module Gem
174
174
  # The signature for the source index. Changes in the signature
175
175
  # indicate a change in the index.
176
176
  def index_signature
177
+ require 'rubygems/digest/sha2'
178
+
177
179
  Gem::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
178
180
  end
179
181
 
180
182
  # The signature for the given gem specification.
181
183
  def gem_signature(gem_full_name)
184
+ require 'rubygems/digest/sha2'
185
+
182
186
  Gem::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
183
187
  end
184
188
 
185
189
  def_delegators :@gems, :size, :length
186
190
 
187
191
  # Find a gem by an exact match on the short name.
188
- def find_name(gem_name, version_requirement=Version::Requirement.new(">= 0"))
192
+ def find_name(gem_name, version_requirement = Gem::Requirement.default)
189
193
  search(/^#{gem_name}$/, version_requirement)
190
194
  end
191
195
 
@@ -195,22 +199,46 @@ module Gem
195
199
  # [String] a partial for the (short) name of the gem, or
196
200
  # [Regex] a pattern to match against the short name
197
201
  # version_requirement::
198
- # [String | default=Version::Requirement.new(">= 0")] version to
202
+ # [String | default=Gem::Requirement.default] version to
199
203
  # find
200
204
  # return::
201
205
  # [Array] list of Gem::Specification objects in sorted (version)
202
206
  # order. Empty if not found.
203
207
  #
204
- def search(gem_pattern, version_requirement=Version::Requirement.new(">= 0"))
205
- gem_pattern = /#{ gem_pattern }/i if String === gem_pattern
206
- version_requirement = Gem::Version::Requirement.create(version_requirement)
207
- result = []
208
- @gems.each do |full_spec_name, spec|
209
- next unless spec.name =~ gem_pattern
210
- result << spec if version_requirement.satisfied_by?(spec.version)
208
+ def search(gem_pattern, platform_only_or_version_req = false)
209
+ version_requirement = nil
210
+ only_platform = false
211
+
212
+ case gem_pattern
213
+ when Regexp then
214
+ version_requirement = platform_only_or_version_req ||
215
+ Gem::Requirement.default
216
+ when Gem::Dependency then
217
+ only_platform = platform_only_or_version_req
218
+ version_requirement = gem_pattern.version_requirements
219
+ gem_pattern = gem_pattern.name.empty? ? // : /^#{gem_pattern.name}$/
220
+ else
221
+ version_requirement = platform_only_or_version_req ||
222
+ Gem::Requirement.default
223
+ gem_pattern = /#{gem_pattern}/i
224
+ end
225
+
226
+ unless Gem::Requirement === version_requirement then
227
+ version_requirement = Gem::Requirement.create version_requirement
211
228
  end
212
- result = result.sort
213
- result
229
+
230
+ specs = @gems.values.select do |spec|
231
+ spec.name =~ gem_pattern and
232
+ version_requirement.satisfied_by? spec.version
233
+ end
234
+
235
+ if only_platform then
236
+ specs = specs.select do |spec|
237
+ Gem::Platform.match spec.platform
238
+ end
239
+ end
240
+
241
+ specs.sort_by { |s| s.sort_obj }
214
242
  end
215
243
 
216
244
  # Refresh the source index from the local file system.
@@ -224,15 +252,20 @@ module Gem
224
252
  # Returns an Array of Gem::Specifications that are not up to date.
225
253
  #
226
254
  def outdated
227
- remotes = Gem::SourceInfoCache.search(//)
255
+ dep = Gem::Dependency.new '', Gem::Requirement.default
256
+
257
+ remotes = Gem::SourceInfoCache.search dep, true
258
+
228
259
  outdateds = []
229
- latest_specs.each do |_, local|
260
+
261
+ latest_specs.each do |local|
230
262
  name = local.name
231
263
  remote = remotes.select { |spec| spec.name == name }.
232
- sort_by { |spec| spec.version }.
264
+ sort_by { |spec| spec.version.to_ints }.
233
265
  last
234
266
  outdateds << name if remote and local.version < remote.version
235
267
  end
268
+
236
269
  outdateds
237
270
  end
238
271
 
@@ -243,58 +276,89 @@ module Gem
243
276
  gem_names = fetch_quick_index source_uri
244
277
  remove_extra gem_names
245
278
  missing_gems = find_missing gem_names
246
- use_incremental = missing_gems.size <= INCREMENTAL_THRESHHOLD
279
+
280
+ return false if missing_gems.size.zero?
281
+
282
+ say "missing #{missing_gems.size} gems" if
283
+ missing_gems.size > 0 and Gem.configuration.really_verbose
284
+
285
+ use_incremental = missing_gems.size <= Gem.configuration.bulk_threshold
247
286
  rescue Gem::OperationNotSupportedError => ex
287
+ alert_error "Falling back to bulk fetch: #{ex.message}" if
288
+ Gem.configuration.really_verbose
248
289
  use_incremental = false
249
290
  end
250
291
 
251
292
  if use_incremental then
252
- update_with_missing source_uri, missing_gems
293
+ update_with_missing(source_uri, missing_gems)
253
294
  else
254
- new_index = fetch_bulk_index source_uri
255
- @gems.replace new_index.gems
295
+ new_index = fetch_bulk_index(source_uri)
296
+ @gems.replace(new_index.gems)
256
297
  end
257
298
 
258
- self
299
+ true
259
300
  end
260
-
301
+
261
302
  def ==(other) # :nodoc:
262
303
  self.class === other and @gems == other.gems
263
304
  end
264
305
 
306
+ def dump
307
+ Marshal.dump(self)
308
+ end
309
+
265
310
  protected
266
311
 
267
312
  attr_reader :gems
268
313
 
269
314
  private
270
315
 
271
- # Convert the yamlized string spec into a real spec (actually, these are
272
- # hashes of specs.).
273
- def convert_specs(yaml_spec)
274
- YAML.load(reduce_specs(yaml_spec)) or
275
- raise "Didn't get a valid YAML document"
276
- end
277
-
278
316
  def fetcher
317
+ require 'rubygems/remote_fetcher'
318
+
279
319
  Gem::RemoteFetcher.fetcher
280
320
  end
281
321
 
282
- def fetch_bulk_index(source_uri)
283
- say "Bulk updating Gem source index for: #{source_uri}"
322
+ def fetch_index_from(source_uri)
323
+ @fetch_error = nil
284
324
 
285
- begin
286
- yaml_spec = fetcher.fetch_path source_uri + '/yaml.Z'
287
- yaml_spec = unzip yaml_spec
288
- rescue
325
+ indexes = %W[
326
+ Marshal.#{Gem.marshal_version}.Z
327
+ Marshal.#{Gem.marshal_version}
328
+ yaml.Z
329
+ yaml
330
+ ]
331
+
332
+ indexes.each do |name|
333
+ spec_data = nil
289
334
  begin
290
- yaml_spec = fetcher.fetch_path source_uri + '/yaml'
335
+ spec_data = fetcher.fetch_path("#{source_uri}/#{name}")
336
+ spec_data = unzip(spec_data) if name =~ /\.Z$/
337
+ if name =~ /Marshal/ then
338
+ return Marshal.load(spec_data)
339
+ else
340
+ return YAML.load(spec_data)
341
+ end
291
342
  rescue => e
292
- raise Gem::RemoteSourceException,
293
- "Error fetching remote gem cache: #{e}"
343
+ if Gem.configuration.really_verbose then
344
+ alert_error "Unable to fetch #{name}: #{e.message}"
345
+ end
346
+ @fetch_error = e
294
347
  end
295
348
  end
349
+ nil
350
+ end
296
351
 
297
- convert_specs yaml_spec
352
+ def fetch_bulk_index(source_uri)
353
+ say "Bulk updating Gem source index for: #{source_uri}"
354
+
355
+ index = fetch_index_from(source_uri)
356
+ if index.nil? then
357
+ raise Gem::RemoteSourceException,
358
+ "Error fetching remote gem cache: #{@fetch_error}"
359
+ end
360
+ @fetch_error = nil
361
+ index
298
362
  end
299
363
 
300
364
  # Get the quick index needed for incremental updates.
@@ -313,26 +377,6 @@ module Gem
313
377
  }
314
378
  end
315
379
 
316
- # This reduces the source spec in size so that YAML bugs with large data
317
- # sets will be dodged. Obviously this is a workaround, but it allows Gems
318
- # to continue to work until the YAML bug is fixed.
319
- def reduce_specs(yaml_spec)
320
- result = ""
321
- state = :copy
322
- yaml_spec.each do |line|
323
- if state == :copy && line =~ /^\s+files:\s*$/
324
- state = :skip
325
- result << line.sub(/$/, " []")
326
- elsif state == :skip
327
- if line !~ /^\s+-/
328
- state = :copy
329
- end
330
- end
331
- result << line if state == :copy
332
- end
333
- result
334
- end
335
-
336
380
  def remove_extra(spec_names)
337
381
  dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
338
382
  each do |name, spec|
@@ -346,20 +390,47 @@ module Gem
346
390
  Zlib::Inflate.inflate(string)
347
391
  end
348
392
 
393
+ # Tries to fetch Marshal representation first, then YAML
394
+ def fetch_single_spec(source_uri, spec_name)
395
+ @fetch_error = nil
396
+ begin
397
+ marshal_uri = source_uri + "/quick/Marshal.#{Gem.marshal_version}/#{spec_name}.gemspec.rz"
398
+ zipped = fetcher.fetch_path marshal_uri
399
+ return Marshal.load(unzip(zipped))
400
+ rescue => ex
401
+ @fetch_error = ex
402
+ if Gem.configuration.really_verbose then
403
+ say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}"
404
+ end
405
+ end
406
+
407
+ begin
408
+ yaml_uri = source_uri + "/quick/#{spec_name}.gemspec.rz"
409
+ zipped = fetcher.fetch_path yaml_uri
410
+ return YAML.load(unzip(zipped))
411
+ rescue => ex
412
+ @fetch_error = ex
413
+ if Gem.configuration.really_verbose then
414
+ say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}"
415
+ end
416
+ end
417
+ nil
418
+ end
419
+
349
420
  # Update the cached source index with the missing names.
350
421
  def update_with_missing(source_uri, missing_names)
351
422
  progress = ui.progress_reporter(missing_names.size,
352
- "Need to update #{missing_names.size} gems from #{source_uri}")
423
+ "Updating metadata for #{missing_names.size} gems from #{source_uri}")
353
424
  missing_names.each do |spec_name|
354
- begin
355
- spec_uri = source_uri + "/quick/#{spec_name}.gemspec.rz"
356
- zipped_yaml = fetcher.fetch_path spec_uri
357
- gemspec = YAML.load unzip(zipped_yaml)
425
+ gemspec = fetch_single_spec(source_uri, spec_name)
426
+ if gemspec.nil? then
427
+ ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \
428
+ "\t#{@fetch_error.message}"
429
+ else
358
430
  add_spec gemspec
359
431
  progress.updated spec_name
360
- rescue RuntimeError => ex
361
- ui.say "Failed to download spec for #{spec_name} from #{source_uri}"
362
432
  end
433
+ @fetch_error = nil
363
434
  end
364
435
  progress.done
365
436
  progress.count