rubygems-update 1.8.30 → 2.0.0.preview2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (241) hide show
  1. checksums.yaml +6 -6
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -0
  4. data/.autotest +6 -3
  5. data/History.txt +137 -63
  6. data/LICENSE.txt +1 -5
  7. data/Manifest.txt +69 -32
  8. data/README.rdoc +11 -9
  9. data/Rakefile +24 -38
  10. data/bin/gem +0 -9
  11. data/bin/update_rubygems +1 -0
  12. data/lib/rubygems.rb +193 -405
  13. data/lib/rubygems/available_set.rb +95 -0
  14. data/lib/rubygems/command.rb +88 -45
  15. data/lib/rubygems/command_manager.rb +67 -40
  16. data/lib/rubygems/commands/build_command.rb +5 -23
  17. data/lib/rubygems/commands/cert_command.rb +199 -57
  18. data/lib/rubygems/commands/check_command.rb +14 -39
  19. data/lib/rubygems/commands/cleanup_command.rb +9 -1
  20. data/lib/rubygems/commands/contents_command.rb +30 -12
  21. data/lib/rubygems/commands/dependency_command.rb +3 -8
  22. data/lib/rubygems/commands/environment_command.rb +13 -8
  23. data/lib/rubygems/commands/fetch_command.rb +3 -16
  24. data/lib/rubygems/commands/generate_index_command.rb +7 -47
  25. data/lib/rubygems/commands/help_command.rb +1 -1
  26. data/lib/rubygems/commands/install_command.rb +69 -36
  27. data/lib/rubygems/commands/list_command.rb +6 -4
  28. data/lib/rubygems/commands/lock_command.rb +1 -1
  29. data/lib/rubygems/commands/mirror_command.rb +17 -0
  30. data/lib/rubygems/commands/outdated_command.rb +6 -3
  31. data/lib/rubygems/commands/owner_command.rb +13 -5
  32. data/lib/rubygems/commands/pristine_command.rb +19 -4
  33. data/lib/rubygems/commands/push_command.rb +12 -1
  34. data/lib/rubygems/commands/query_command.rb +43 -27
  35. data/lib/rubygems/commands/rdoc_command.rb +23 -28
  36. data/lib/rubygems/commands/search_command.rb +4 -18
  37. data/lib/rubygems/commands/server_command.rb +1 -1
  38. data/lib/rubygems/commands/setup_command.rb +124 -38
  39. data/lib/rubygems/commands/sources_command.rb +16 -16
  40. data/lib/rubygems/commands/specification_command.rb +11 -13
  41. data/lib/rubygems/commands/uninstall_command.rb +24 -7
  42. data/lib/rubygems/commands/unpack_command.rb +7 -3
  43. data/lib/rubygems/commands/update_command.rb +22 -36
  44. data/lib/rubygems/commands/yank_command.rb +98 -0
  45. data/lib/rubygems/compatibility.rb +51 -0
  46. data/lib/rubygems/config_file.rb +82 -54
  47. data/lib/rubygems/core_ext/kernel_gem.rb +53 -0
  48. data/lib/rubygems/core_ext/kernel_require.rb +119 -0
  49. data/lib/rubygems/defaults.rb +10 -21
  50. data/lib/rubygems/dependency.rb +61 -10
  51. data/lib/rubygems/dependency_installer.rb +157 -69
  52. data/lib/rubygems/dependency_list.rb +11 -19
  53. data/lib/rubygems/dependency_resolver.rb +562 -0
  54. data/lib/rubygems/deprecate.rb +40 -40
  55. data/lib/rubygems/errors.rb +77 -24
  56. data/lib/rubygems/exceptions.rb +25 -7
  57. data/lib/rubygems/ext/builder.rb +20 -23
  58. data/lib/rubygems/ext/configure_builder.rb +2 -2
  59. data/lib/rubygems/ext/ext_conf_builder.rb +5 -45
  60. data/lib/rubygems/ext/rake_builder.rb +2 -2
  61. data/lib/rubygems/gem_runner.rb +3 -16
  62. data/lib/rubygems/gemcutter_utilities.rb +22 -7
  63. data/lib/rubygems/indexer.rb +6 -159
  64. data/lib/rubygems/install_message.rb +12 -0
  65. data/lib/rubygems/install_update_options.rb +56 -18
  66. data/lib/rubygems/installer.rb +244 -134
  67. data/lib/rubygems/installer_test_case.rb +71 -19
  68. data/lib/rubygems/mock_gem_ui.rb +17 -0
  69. data/lib/rubygems/name_tuple.rb +110 -0
  70. data/lib/rubygems/package.rb +514 -43
  71. data/lib/rubygems/package/digest_io.rb +64 -0
  72. data/lib/rubygems/package/old.rb +147 -0
  73. data/lib/rubygems/package/tar_header.rb +18 -55
  74. data/lib/rubygems/package/tar_reader.rb +20 -3
  75. data/lib/rubygems/package/tar_writer.rb +63 -7
  76. data/lib/rubygems/package_task.rb +3 -4
  77. data/lib/rubygems/path_support.rb +14 -7
  78. data/lib/rubygems/platform.rb +19 -26
  79. data/lib/rubygems/rdoc.rb +316 -0
  80. data/lib/rubygems/remote_fetcher.rb +117 -54
  81. data/lib/rubygems/request_set.rb +182 -0
  82. data/lib/rubygems/requirement.rb +63 -26
  83. data/lib/rubygems/security.rb +295 -555
  84. data/lib/rubygems/security/policies.rb +115 -0
  85. data/lib/rubygems/security/policy.rb +227 -0
  86. data/lib/rubygems/security/signer.rb +136 -0
  87. data/lib/rubygems/security/trust_dir.rb +104 -0
  88. data/lib/rubygems/server.rb +45 -55
  89. data/lib/rubygems/source.rb +144 -0
  90. data/lib/rubygems/source_list.rb +87 -0
  91. data/lib/rubygems/source_local.rb +92 -0
  92. data/lib/rubygems/source_specific_file.rb +28 -0
  93. data/lib/rubygems/spec_fetcher.rb +116 -184
  94. data/lib/rubygems/specification.rb +731 -335
  95. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot.pem +88 -30
  96. data/lib/rubygems/ssl_certs/Entrust_net-Secure-Server-Certification-Authority.pem +90 -0
  97. data/lib/rubygems/ssl_certs/VerisignClass3PublicPrimaryCertificationAuthority-G2.pem +57 -0
  98. data/lib/rubygems/syck_hack.rb +2 -0
  99. data/lib/rubygems/test_case.rb +199 -109
  100. data/lib/rubygems/test_utilities.rb +25 -5
  101. data/lib/rubygems/uninstaller.rb +62 -20
  102. data/lib/rubygems/user_interaction.rb +10 -0
  103. data/lib/rubygems/validator.rb +33 -40
  104. data/lib/rubygems/version.rb +19 -8
  105. data/setup.rb +8 -1
  106. data/test/rubygems/alternate_cert.pem +9 -0
  107. data/test/rubygems/alternate_cert_32.pem +9 -0
  108. data/test/rubygems/alternate_key.pem +9 -0
  109. data/test/rubygems/bad_rake.rb +1 -0
  110. data/test/rubygems/child_cert.pem +9 -0
  111. data/test/rubygems/child_cert_32.pem +9 -0
  112. data/test/rubygems/child_key.pem +9 -0
  113. data/test/rubygems/data/null-type.gemspec.rz +0 -0
  114. data/test/rubygems/expired_cert.pem +9 -0
  115. data/test/rubygems/future_cert.pem +9 -0
  116. data/test/rubygems/future_cert_32.pem +9 -0
  117. data/test/rubygems/good_rake.rb +1 -0
  118. data/test/rubygems/grandchild_cert.pem +9 -0
  119. data/test/rubygems/grandchild_cert_32.pem +9 -0
  120. data/test/rubygems/grandchild_key.pem +9 -0
  121. data/test/rubygems/invalid_issuer_cert.pem +9 -0
  122. data/test/rubygems/invalid_issuer_cert_32.pem +9 -0
  123. data/test/rubygems/invalid_key.pem +9 -0
  124. data/test/rubygems/invalid_signer_cert.pem +9 -0
  125. data/test/rubygems/invalid_signer_cert_32.pem +9 -0
  126. data/test/rubygems/invalidchild_cert.pem +9 -0
  127. data/test/rubygems/invalidchild_cert_32.pem +9 -0
  128. data/test/rubygems/invalidchild_key.pem +9 -0
  129. data/test/rubygems/plugin/exception/rubygems_plugin.rb +1 -1
  130. data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +1 -1
  131. data/test/rubygems/private_key.pem +7 -25
  132. data/test/rubygems/public_cert.pem +8 -18
  133. data/test/rubygems/public_cert_32.pem +10 -0
  134. data/test/rubygems/public_key.pem +4 -0
  135. data/test/rubygems/rubygems/commands/crash_command.rb +1 -1
  136. data/test/rubygems/test_config.rb +4 -6
  137. data/test/rubygems/test_deprecate.rb +76 -0
  138. data/test/rubygems/test_gem.rb +318 -83
  139. data/test/rubygems/test_gem_available_set.rb +106 -0
  140. data/test/rubygems/test_gem_command.rb +10 -0
  141. data/test/rubygems/test_gem_command_manager.rb +55 -9
  142. data/test/rubygems/test_gem_commands_build_command.rb +11 -19
  143. data/test/rubygems/test_gem_commands_cert_command.rb +441 -42
  144. data/test/rubygems/test_gem_commands_cleanup_command.rb +29 -1
  145. data/test/rubygems/test_gem_commands_contents_command.rb +23 -0
  146. data/test/rubygems/test_gem_commands_dependency_command.rb +5 -0
  147. data/test/rubygems/test_gem_commands_fetch_command.rb +19 -20
  148. data/test/rubygems/test_gem_commands_generate_index_command.rb +2 -83
  149. data/test/rubygems/test_gem_commands_help_command.rb +2 -1
  150. data/test/rubygems/test_gem_commands_install_command.rb +647 -48
  151. data/test/rubygems/test_gem_commands_mirror.rb +32 -0
  152. data/test/rubygems/test_gem_commands_owner_command.rb +4 -8
  153. data/test/rubygems/test_gem_commands_pristine_command.rb +99 -4
  154. data/test/rubygems/test_gem_commands_push_command.rb +62 -8
  155. data/test/rubygems/test_gem_commands_query_command.rb +51 -0
  156. data/test/rubygems/test_gem_commands_search_command.rb +25 -0
  157. data/test/rubygems/test_gem_commands_setup_command.rb +45 -0
  158. data/test/rubygems/test_gem_commands_sources_command.rb +21 -6
  159. data/test/rubygems/test_gem_commands_specification_command.rb +33 -1
  160. data/test/rubygems/test_gem_commands_uninstall_command.rb +91 -31
  161. data/test/rubygems/test_gem_commands_unpack_command.rb +3 -3
  162. data/test/rubygems/test_gem_commands_update_command.rb +56 -38
  163. data/test/rubygems/test_gem_commands_which_command.rb +4 -4
  164. data/test/rubygems/test_gem_commands_yank_command.rb +97 -0
  165. data/test/rubygems/test_gem_config_file.rb +66 -21
  166. data/test/rubygems/test_gem_dependency.rb +46 -0
  167. data/test/rubygems/test_gem_dependency_installer.rb +228 -18
  168. data/test/rubygems/test_gem_dependency_list.rb +0 -9
  169. data/test/rubygems/test_gem_dependency_resolver.rb +327 -0
  170. data/test/rubygems/test_gem_ext_configure_builder.rb +4 -4
  171. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +21 -49
  172. data/test/rubygems/test_gem_ext_rake_builder.rb +13 -13
  173. data/test/rubygems/test_gem_gem_runner.rb +27 -5
  174. data/test/rubygems/test_gem_gemcutter_utilities.rb +19 -0
  175. data/test/rubygems/test_gem_indexer.rb +14 -227
  176. data/test/rubygems/test_gem_install_update_options.rb +83 -3
  177. data/test/rubygems/test_gem_installer.rb +211 -236
  178. data/test/rubygems/test_gem_local_remote_options.rb +8 -2
  179. data/test/rubygems/test_gem_name_tuple.rb +15 -0
  180. data/test/rubygems/test_gem_package.rb +547 -0
  181. data/test/rubygems/test_gem_package_old.rb +37 -0
  182. data/test/rubygems/test_gem_package_tar_reader.rb +32 -0
  183. data/test/rubygems/test_gem_package_tar_writer.rb +84 -1
  184. data/test/rubygems/test_gem_path_support.rb +4 -30
  185. data/test/rubygems/test_gem_platform.rb +3 -6
  186. data/test/rubygems/test_gem_rdoc.rb +245 -0
  187. data/test/rubygems/test_gem_remote_fetcher.rb +51 -5
  188. data/test/rubygems/test_gem_request_set.rb +70 -0
  189. data/test/rubygems/test_gem_requirement.rb +53 -24
  190. data/test/rubygems/test_gem_security.rb +189 -43
  191. data/test/rubygems/test_gem_security_policy.rb +376 -0
  192. data/test/rubygems/test_gem_security_signer.rb +184 -0
  193. data/test/rubygems/test_gem_security_trust_dir.rb +94 -0
  194. data/test/rubygems/test_gem_server.rb +31 -36
  195. data/test/rubygems/test_gem_silent_ui.rb +2 -2
  196. data/test/rubygems/test_gem_source.rb +188 -0
  197. data/test/rubygems/test_gem_source_list.rb +87 -0
  198. data/test/rubygems/test_gem_source_local.rb +83 -0
  199. data/test/rubygems/test_gem_source_specific_file.rb +33 -0
  200. data/test/rubygems/test_gem_spec_fetcher.rb +91 -255
  201. data/test/rubygems/test_gem_specification.rb +293 -39
  202. data/test/rubygems/test_gem_uninstaller.rb +136 -13
  203. data/test/rubygems/test_gem_validator.rb +14 -41
  204. data/test/rubygems/test_gem_version.rb +15 -21
  205. data/test/rubygems/test_require.rb +193 -0
  206. data/test/rubygems/wrong_key_cert.pem +9 -0
  207. data/test/rubygems/wrong_key_cert_32.pem +9 -0
  208. metadata +171 -83
  209. metadata.gz.sig +1 -0
  210. data/CVE-2013-4287.txt +0 -36
  211. data/CVE-2013-4363.txt +0 -45
  212. data/ci_build.sh +0 -27
  213. data/cruise_config.rb +0 -32
  214. data/lib/rbconfig/datadir.rb +0 -13
  215. data/lib/rubygems/builder.rb +0 -99
  216. data/lib/rubygems/custom_require.rb +0 -69
  217. data/lib/rubygems/doc_manager.rb +0 -243
  218. data/lib/rubygems/format.rb +0 -82
  219. data/lib/rubygems/gem_openssl.rb +0 -90
  220. data/lib/rubygems/gem_path_searcher.rb +0 -172
  221. data/lib/rubygems/old_format.rb +0 -153
  222. data/lib/rubygems/package/f_sync_dir.rb +0 -23
  223. data/lib/rubygems/package/tar_input.rb +0 -234
  224. data/lib/rubygems/package/tar_output.rb +0 -146
  225. data/lib/rubygems/require_paths_builder.rb +0 -18
  226. data/lib/rubygems/source_index.rb +0 -406
  227. data/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
  228. data/lib/rubygems/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
  229. data/lib/rubygems/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
  230. data/lib/rubygems/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
  231. data/lib/rubygems/ssl_certs/GeoTrustGlobalCA.pem +0 -20
  232. data/test/rubygems/test_bundled_ca.rb +0 -59
  233. data/test/rubygems/test_gem_builder.rb +0 -44
  234. data/test/rubygems/test_gem_doc_manager.rb +0 -32
  235. data/test/rubygems/test_gem_ext_builder.rb +0 -58
  236. data/test/rubygems/test_gem_format.rb +0 -88
  237. data/test/rubygems/test_gem_gem_path_searcher.rb +0 -94
  238. data/test/rubygems/test_gem_package_tar_input.rb +0 -129
  239. data/test/rubygems/test_gem_package_tar_output.rb +0 -101
  240. data/test/rubygems/test_gem_source_index.rb +0 -250
  241. data/util/update_bundled_ca_certificates.rb +0 -103
@@ -0,0 +1,104 @@
1
+ class Gem::Security::TrustDir
2
+
3
+ DEFAULT_PERMISSIONS = {
4
+ :trust_dir => 0700,
5
+ :trusted_cert => 0600,
6
+ }
7
+
8
+ def initialize dir, permissions = DEFAULT_PERMISSIONS
9
+ @dir = dir
10
+ @permissions = permissions
11
+
12
+ @digester = Gem::Security::DIGEST_ALGORITHM
13
+ end
14
+
15
+ attr_reader :dir
16
+
17
+ ##
18
+ # Returns the path to the trusted +certificate+
19
+
20
+ def cert_path certificate
21
+ name_path certificate.subject
22
+ end
23
+
24
+ ##
25
+ # Enumerates trusted certificates.
26
+
27
+ def each_certificate
28
+ return enum_for __method__ unless block_given?
29
+
30
+ glob = File.join @dir, '*.pem'
31
+
32
+ Dir[glob].each do |certificate_file|
33
+ begin
34
+ certificate = load_certificate certificate_file
35
+
36
+ yield certificate, certificate_file
37
+ rescue OpenSSL::X509::CertificateError
38
+ next # HACK warn
39
+ end
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Returns the issuer certificate of the given +certificate+ if it exists in
45
+ # the trust directory.
46
+
47
+ def issuer_of certificate
48
+ path = name_path certificate.issuer
49
+
50
+ return unless File.exist? path
51
+
52
+ load_certificate path
53
+ end
54
+
55
+ ##
56
+ # Returns the path to the trusted certificate with the given ASN.1 +name+
57
+
58
+ def name_path name
59
+ digest = @digester.hexdigest name.to_s
60
+
61
+ File.join @dir, "cert-#{digest}.pem"
62
+ end
63
+
64
+ ##
65
+ # Loads the given +certificate_file+
66
+
67
+ def load_certificate certificate_file
68
+ pem = File.read certificate_file
69
+
70
+ OpenSSL::X509::Certificate.new pem
71
+ end
72
+
73
+ ##
74
+ # Add a certificate to trusted certificate list.
75
+
76
+ def trust_cert certificate
77
+ verify
78
+
79
+ destination = cert_path certificate
80
+
81
+ open destination, 'wb', @permissions[:trusted_cert] do |io|
82
+ io.write certificate.to_pem
83
+ end
84
+ end
85
+
86
+ ##
87
+ # Make sure the trust directory exists. If it does exist, make sure it's
88
+ # actually a directory. If not, then create it with the appropriate
89
+ # permissions.
90
+
91
+ def verify
92
+ if File.exist? @dir then
93
+ raise Gem::Security::Exception,
94
+ "trust directory #{@dir} is not a directory" unless
95
+ File.directory? @dir
96
+
97
+ FileUtils.chmod 0700, @dir
98
+ else
99
+ FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir]
100
+ end
101
+ end
102
+
103
+ end
104
+
@@ -3,7 +3,7 @@ require 'zlib'
3
3
  require 'erb'
4
4
 
5
5
  require 'rubygems'
6
- require 'rubygems/doc_manager'
6
+ require 'rubygems/rdoc'
7
7
 
8
8
  ##
9
9
  # Gem::Server and allows users to serve gems for consumption by
@@ -17,9 +17,6 @@ require 'rubygems/doc_manager'
17
17
  # * "/quick/" - Individual gemspecs
18
18
  # * "/gems" - Direct access to download the installable gems
19
19
  # * "/rdoc?q=" - Search for installed rdoc documentation
20
- # * legacy indexes:
21
- # * "/Marshal.#{Gem.marshal_version}" - Full SourceIndex dump of metadata
22
- # for installed gems
23
20
  #
24
21
  # == Usage
25
22
  #
@@ -430,53 +427,25 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
430
427
  options[:launch], options[:addresses]).run
431
428
  end
432
429
 
433
- ##
434
- # Only the first directory in gem_dirs is used for serving gems
435
-
436
430
  def initialize(gem_dirs, port, daemon, launch = nil, addresses = nil)
431
+ Gem::RDoc.load_rdoc
437
432
  Socket.do_not_reverse_lookup = true
438
433
 
439
- @gem_dirs = Array gem_dirs
440
- @port = port
441
- @daemon = daemon
442
- @launch = launch
434
+ @gem_dirs = Array gem_dirs
435
+ @port = port
436
+ @daemon = daemon
437
+ @launch = launch
443
438
  @addresses = addresses
444
- logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
445
- @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
446
439
 
447
- @spec_dirs = @gem_dirs.map do |gem_dir|
448
- spec_dir = File.join gem_dir, 'specifications'
449
-
450
- unless File.directory? spec_dir then
451
- raise ArgumentError, "#{gem_dir} does not appear to be a gem repository"
452
- end
440
+ logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
441
+ @server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
453
442
 
454
- spec_dir
455
- end
443
+ @spec_dirs = @gem_dirs.map { |gem_dir| File.join gem_dir, 'specifications' }
444
+ @spec_dirs.reject! { |spec_dir| !File.directory? spec_dir }
456
445
 
457
446
  Gem::Specification.dirs = @gem_dirs
458
- end
459
447
 
460
- def Marshal(req, res)
461
- Gem::Specification.reset
462
-
463
- add_date res
464
-
465
- index = Gem::Deprecate.skip_during { Marshal.dump Gem.source_index }
466
-
467
- if req.request_method == 'HEAD' then
468
- res['content-length'] = index.length
469
- return
470
- end
471
-
472
- if req.path =~ /Z$/ then
473
- res['content-type'] = 'application/x-deflate'
474
- index = Gem.deflate index
475
- else
476
- res['content-type'] = 'application/octet-stream'
477
- end
478
-
479
- res.body << index
448
+ @have_rdoc_4_plus = nil
480
449
  end
481
450
 
482
451
  def add_date res
@@ -485,6 +454,19 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
485
454
  end.max
486
455
  end
487
456
 
457
+ def doc_root gem_name
458
+ if have_rdoc_4_plus? then
459
+ "/doc_root/#{gem_name}/"
460
+ else
461
+ "/doc_root/#{gem_name}/rdoc/index.html"
462
+ end
463
+ end
464
+
465
+ def have_rdoc_4_plus?
466
+ @have_rdoc_4_plus ||=
467
+ Gem::Requirement.new('>= 4').satisfied_by? Gem::RDoc.rdoc_version
468
+ end
469
+
488
470
  def latest_specs(req, res)
489
471
  Gem::Specification.reset
490
472
 
@@ -614,14 +596,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
614
596
  "authors" => spec.authors.sort.join(", "),
615
597
  "date" => spec.date.to_s,
616
598
  "dependencies" => deps,
617
- "doc_path" => "/doc_root/#{spec.full_name}/rdoc/index.html",
599
+ "doc_path" => doc_root(spec.full_name),
618
600
  "executables" => executables,
619
601
  "only_one_executable" => (executables && executables.size == 1),
620
602
  "full_name" => spec.full_name,
621
603
  "has_deps" => !deps.empty?,
622
604
  "homepage" => spec.homepage,
623
605
  "name" => spec.name,
624
- "rdoc_installed" => Gem::DocManager.new(spec).rdoc_installed?,
606
+ "rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?,
625
607
  "summary" => spec.summary,
626
608
  "version" => spec.version.to_s,
627
609
  }
@@ -630,7 +612,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
630
612
  specs << {
631
613
  "authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others",
632
614
  "dependencies" => [],
633
- "doc_path" => "/doc_root/rubygems-#{Gem::VERSION}/rdoc/index.html",
615
+ "doc_path" => doc_root("rubygems-#{Gem::VERSION}"),
634
616
  "executables" => [{"executable" => 'gem', "is_last" => true}],
635
617
  "only_one_executable" => true,
636
618
  "full_name" => "rubygems-#{Gem::VERSION}",
@@ -730,15 +712,15 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
730
712
  when 1
731
713
  new_path = File.basename(found_gems[0])
732
714
  res.status = 302
733
- res['Location'] = "/doc_root/#{new_path}/rdoc/index.html"
715
+ res['Location'] = doc_root new_path
734
716
  return true
735
717
  else
736
718
  doc_items = []
737
719
  found_gems.each do |file_name|
738
720
  base_name = File.basename(file_name)
739
721
  doc_items << {
740
- :name => base_name,
741
- :url => "/doc_root/#{base_name}/rdoc/index.html",
722
+ :name => base_name,
723
+ :url => doc_root(new_path),
742
724
  :summary => ''
743
725
  }
744
726
  end
@@ -756,9 +738,6 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
756
738
 
757
739
  WEBrick::Daemon.start if @daemon
758
740
 
759
- @server.mount_proc "/Marshal.#{Gem.marshal_version}", method(:Marshal)
760
- @server.mount_proc "/Marshal.#{Gem.marshal_version}.Z", method(:Marshal)
761
-
762
741
  @server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs)
763
742
  @server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs)
764
743
 
@@ -779,10 +758,21 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
779
758
 
780
759
  @server.mount_proc "/rdoc", method(:rdoc)
781
760
 
782
- paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
783
- paths.each do |mount_point, mount_dir|
784
- @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
785
- File.join(@gem_dirs.first, mount_dir), true)
761
+ file_handlers = {
762
+ '/gems' => '/cache/',
763
+ }
764
+
765
+ if have_rdoc_4_plus? then
766
+ @server.mount '/doc_root', RDoc::Servlet, '/doc_root'
767
+ else
768
+ file_handlers['/doc_root'] = '/doc/'
769
+ end
770
+
771
+ @gem_dirs.each do |gem_dir|
772
+ file_handlers.each do |mount_point, mount_dir|
773
+ @server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
774
+ File.join(gem_dir, mount_dir), true)
775
+ end
786
776
  end
787
777
 
788
778
  trap("INT") { @server.shutdown; exit! }
@@ -0,0 +1,144 @@
1
+ require 'uri'
2
+ require 'fileutils'
3
+
4
+ class Gem::Source
5
+ FILES = {
6
+ :released => 'specs',
7
+ :latest => 'latest_specs',
8
+ :prerelease => 'prerelease_specs',
9
+ }
10
+
11
+ def initialize(uri)
12
+ unless uri.kind_of? URI
13
+ uri = URI.parse(uri.to_s)
14
+ end
15
+
16
+ @uri = uri
17
+ @api_uri = nil
18
+ end
19
+
20
+ attr_reader :uri
21
+
22
+ def api_uri
23
+ require 'rubygems/remote_fetcher'
24
+ @api_uri ||= Gem::RemoteFetcher.fetcher.api_endpoint uri
25
+ end
26
+
27
+ def <=>(other)
28
+ if !@uri
29
+ return 0 unless other.uri
30
+ return -1
31
+ end
32
+
33
+ return 1 if !other.uri
34
+
35
+ @uri.to_s <=> other.uri.to_s
36
+ end
37
+
38
+ include Comparable
39
+
40
+ def ==(other)
41
+ case other
42
+ when self.class
43
+ @uri == other.uri
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ alias_method :eql?, :==
50
+
51
+ def hash
52
+ @uri.hash
53
+ end
54
+
55
+ ##
56
+ # Returns the local directory to write +uri+ to.
57
+
58
+ def cache_dir(uri)
59
+ # Correct for windows paths
60
+ escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
61
+ root = File.join Gem.user_home, '.gem', 'specs'
62
+ File.join root, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
63
+ end
64
+
65
+ def update_cache?
66
+ @update_cache ||= File.stat(Gem.user_home).uid == Process.uid
67
+ end
68
+
69
+ def fetch_spec(name)
70
+ fetcher = Gem::RemoteFetcher.fetcher
71
+
72
+ spec_file_name = name.spec_name
73
+
74
+ uri = @uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
75
+
76
+ cache_dir = cache_dir uri
77
+
78
+ local_spec = File.join cache_dir, spec_file_name
79
+
80
+ if File.exist? local_spec then
81
+ spec = Gem.read_binary local_spec
82
+ spec = Marshal.load(spec) rescue nil
83
+ return spec if spec
84
+ end
85
+
86
+ uri.path << '.rz'
87
+
88
+ spec = fetcher.fetch_path uri
89
+ spec = Gem.inflate spec
90
+
91
+ if update_cache? then
92
+ FileUtils.mkdir_p cache_dir
93
+
94
+ open local_spec, 'wb' do |io|
95
+ io.write spec
96
+ end
97
+ end
98
+
99
+ # TODO: Investigate setting Gem::Specification#loaded_from to a URI
100
+ Marshal.load spec
101
+ end
102
+
103
+ ##
104
+ # Loads +type+ kind of specs fetching from +@uri+ if the on-disk cache is
105
+ # out of date.
106
+ #
107
+ # +type+ is one of the following:
108
+ #
109
+ # :released => Return the list of all released specs
110
+ # :latest => Return the list of only the highest version of each gem
111
+ # :prerelease => Return the list of all prerelease only specs
112
+ #
113
+
114
+ def load_specs(type)
115
+ file = FILES[type]
116
+ fetcher = Gem::RemoteFetcher.fetcher
117
+ file_name = "#{file}.#{Gem.marshal_version}"
118
+ spec_path = @uri + "#{file_name}.gz"
119
+ cache_dir = cache_dir spec_path
120
+ local_file = File.join(cache_dir, file_name)
121
+ retried = false
122
+
123
+ FileUtils.mkdir_p cache_dir if update_cache?
124
+
125
+ spec_dump = fetcher.cache_update_path(spec_path, local_file)
126
+
127
+ begin
128
+ Gem::NameTuple.from_list Marshal.load(spec_dump)
129
+ rescue ArgumentError
130
+ if update_cache? && !retried
131
+ FileUtils.rm local_file
132
+ retried = true
133
+ retry
134
+ else
135
+ raise Gem::Exception.new("Invalid spec cache file in #{local_file}")
136
+ end
137
+ end
138
+ end
139
+
140
+ def download(spec, dir=Dir.pwd)
141
+ fetcher = Gem::RemoteFetcher.fetcher
142
+ fetcher.download spec, @uri.to_s, dir
143
+ end
144
+ end
@@ -0,0 +1,87 @@
1
+ require 'rubygems/source'
2
+
3
+ class Gem::SourceList
4
+ def initialize
5
+ @sources = []
6
+ end
7
+
8
+ attr_reader :sources
9
+
10
+ def self.from(ary)
11
+ list = new
12
+
13
+ if ary
14
+ ary.each do |x|
15
+ list << x
16
+ end
17
+ end
18
+
19
+ return list
20
+ end
21
+
22
+ def initialize_copy(other)
23
+ @sources = @sources.dup
24
+ end
25
+
26
+ def <<(obj)
27
+ src = case obj
28
+ when URI
29
+ Gem::Source.new(obj)
30
+ when Gem::Source
31
+ obj
32
+ else
33
+ Gem::Source.new(URI.parse(obj))
34
+ end
35
+
36
+ @sources << src
37
+ src
38
+ end
39
+
40
+ def replace(other)
41
+ @sources.clear
42
+
43
+ other.each do |x|
44
+ self << x
45
+ end
46
+
47
+ self
48
+ end
49
+
50
+ def each
51
+ @sources.each { |s| yield s.uri.to_s }
52
+ end
53
+
54
+ def each_source(&b)
55
+ @sources.each(&b)
56
+ end
57
+
58
+ def ==(other)
59
+ to_a == other
60
+ end
61
+
62
+ def to_a
63
+ @sources.map { |x| x.uri.to_s }
64
+ end
65
+
66
+ alias_method :to_ary, :to_a
67
+
68
+ def first
69
+ @sources.first
70
+ end
71
+
72
+ def include?(other)
73
+ if other.kind_of? Gem::Source
74
+ @sources.include? other
75
+ else
76
+ @sources.find { |x| x.uri.to_s == other.to_s }
77
+ end
78
+ end
79
+
80
+ def delete(uri)
81
+ if uri.kind_of? Gem::Source
82
+ @sources.delete uri
83
+ else
84
+ @sources.delete_if { |x| x.uri.to_s == uri.to_s }
85
+ end
86
+ end
87
+ end