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,92 @@
1
+ require 'rubygems/source'
2
+
3
+ class Gem::Source::Local < Gem::Source
4
+ def initialize
5
+ @uri = nil
6
+ end
7
+
8
+ def load_specs(type)
9
+ names = []
10
+
11
+ @specs = {}
12
+
13
+ Dir["*.gem"].each do |file|
14
+ begin
15
+ pkg = Gem::Package.new(file)
16
+ rescue SystemCallError, Gem::Package::FormatError
17
+ # ignore
18
+ else
19
+ tup = pkg.spec.name_tuple
20
+ @specs[tup] = [File.expand_path(file), pkg]
21
+
22
+ case type
23
+ when :released
24
+ unless pkg.spec.version.prerelease?
25
+ names << pkg.spec.name_tuple
26
+ end
27
+ when :prerelease
28
+ if pkg.spec.version.prerelease?
29
+ names << pkg.spec.name_tuple
30
+ end
31
+ when :latest
32
+ tup = pkg.spec.name_tuple
33
+
34
+ cur = names.find { |x| x.name == tup.name }
35
+ if !cur
36
+ names << tup
37
+ elsif cur.version < tup.version
38
+ names.delete cur
39
+ names << tup
40
+ end
41
+ else
42
+ names << pkg.spec.name_tuple
43
+ end
44
+ end
45
+ end
46
+
47
+ names
48
+ end
49
+
50
+ def find_gem(gem_name, version=Gem::Requirement.default,
51
+ prerelease=false)
52
+ load_specs :complete
53
+
54
+ found = []
55
+
56
+ @specs.each do |n, data|
57
+ if n.name == gem_name
58
+ s = data[1].spec
59
+
60
+ if version.satisfied_by?(s.version)
61
+ if prerelease
62
+ found << s
63
+ elsif !s.version.prerelease?
64
+ found << s
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ found.sort_by { |s| s.version }.last
71
+ end
72
+
73
+ def fetch_spec(name)
74
+ load_specs :complete
75
+
76
+ if data = @specs[name]
77
+ data.last.spec
78
+ else
79
+ raise Gem::Exception, "Unable to find spec for '#{name}'"
80
+ end
81
+ end
82
+
83
+ def download(spec, cache_dir=nil)
84
+ load_specs :complete
85
+
86
+ @specs.each do |name, data|
87
+ return data[0] if data[1].spec == spec
88
+ end
89
+
90
+ raise Gem::Exception, "Unable to find file for '#{spec.full_name}'"
91
+ end
92
+ end
@@ -0,0 +1,28 @@
1
+ class Gem::Source::SpecificFile < Gem::Source
2
+ def initialize(file)
3
+ @uri = nil
4
+ @path = ::File.expand_path(file)
5
+
6
+ @package = Gem::Package.new @path
7
+ @spec = @package.spec
8
+ @name = @spec.name_tuple
9
+ end
10
+
11
+ attr_reader :spec
12
+
13
+ def load_specs(*a)
14
+ [@name]
15
+ end
16
+
17
+ def fetch_spec(name)
18
+ return @spec if name == @name
19
+ raise Gem::Exception, "Unable to find '#{name}'"
20
+ @spec
21
+ end
22
+
23
+ def download(spec, dir=nil)
24
+ return @path if spec == @spec
25
+ raise Gem::Exception, "Unable to download '#{spec.full_name}'"
26
+ end
27
+
28
+ end
@@ -2,6 +2,7 @@ require 'rubygems/remote_fetcher'
2
2
  require 'rubygems/user_interaction'
3
3
  require 'rubygems/errors'
4
4
  require 'rubygems/text'
5
+ require 'rubygems/name_tuple'
5
6
 
6
7
  ##
7
8
  # SpecFetcher handles metadata updates from remote gem repositories.
@@ -11,17 +12,6 @@ class Gem::SpecFetcher
11
12
  include Gem::UserInteraction
12
13
  include Gem::Text
13
14
 
14
- FILES = {
15
- :all => 'specs',
16
- :latest => 'latest_specs',
17
- :prerelease => 'prerelease_specs',
18
- }
19
-
20
- ##
21
- # The SpecFetcher cache dir.
22
-
23
- attr_reader :dir # :nodoc:
24
-
25
15
  ##
26
16
  # Cache of latest specs
27
17
 
@@ -48,8 +38,6 @@ class Gem::SpecFetcher
48
38
  end
49
39
 
50
40
  def initialize
51
- require 'fileutils'
52
-
53
41
  @dir = File.join Gem.user_home, '.gem', 'specs'
54
42
  @update_cache = File.stat(Gem.user_home).uid == Process.uid
55
43
 
@@ -60,144 +48,124 @@ class Gem::SpecFetcher
60
48
  @caches = {
61
49
  :latest => @latest_specs,
62
50
  :prerelease => @prerelease_specs,
63
- :all => @specs
51
+ :released => @specs,
64
52
  }
65
53
 
66
54
  @fetcher = Gem::RemoteFetcher.fetcher
67
55
  end
68
56
 
69
57
  ##
70
- # Returns the local directory to write +uri+ to.
58
+ #
59
+ # Find and fetch gem name tuples that match +dependency+.
60
+ #
61
+ # If +matching_platform+ is false, gems for all platforms are returned.
71
62
 
72
- def cache_dir(uri)
73
- # Correct for windows paths
74
- escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
75
- File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
76
- end
63
+ def search_for_dependency(dependency, matching_platform=true)
64
+ found = {}
77
65
 
78
- ##
79
- # Fetch specs matching +dependency+. If +all+ is true, all matching
80
- # (released) versions are returned. If +matching_platform+ is
81
- # false, all platforms are returned. If +prerelease+ is true,
82
- # prerelease versions are included.
83
-
84
- def fetch_with_errors(dependency,
85
- all = false,
86
- matching_platform = true,
87
- prerelease = false)
88
-
89
- specs_and_sources, errors = find_matching_with_errors(dependency,
90
- all,
91
- matching_platform,
92
- prerelease)
93
-
94
- ss = specs_and_sources.map do |spec_tuple, source_uri|
95
- [fetch_spec(spec_tuple, URI.parse(source_uri)), source_uri]
66
+ rejected_specs = {}
67
+
68
+ if dependency.prerelease?
69
+ type = :complete
70
+ elsif dependency.latest_version?
71
+ type = :latest
72
+ else
73
+ type = :released
96
74
  end
97
75
 
98
- return [ss, errors]
99
- end
76
+ list, errors = available_specs(type)
77
+ list.each do |source, specs|
78
+ found[source] = specs.select do |tup|
79
+ if dependency.match?(tup)
80
+ if matching_platform and !Gem::Platform.match(tup.platform)
81
+ pm = (
82
+ rejected_specs[dependency] ||= \
83
+ Gem::PlatformMismatch.new(tup.name, tup.version))
84
+ pm.add_platform tup.platform
85
+ false
86
+ else
87
+ true
88
+ end
89
+ end
90
+ end
91
+ end
100
92
 
101
- def fetch(*args)
102
- fetch_with_errors(*args).first
103
- end
93
+ errors += rejected_specs.values
104
94
 
105
- def fetch_spec(spec, source_uri)
106
- source_uri = URI.parse source_uri if String === source_uri
107
- spec = spec - [nil, 'ruby', '']
108
- spec_file_name = "#{spec.join '-'}.gemspec"
95
+ tuples = []
109
96
 
110
- uri = source_uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
97
+ found.each do |source, specs|
98
+ specs.each do |s|
99
+ tuples << [s, source]
100
+ end
101
+ end
111
102
 
112
- cache_dir = cache_dir uri
103
+ tuples = tuples.sort_by { |x| x[0] }
113
104
 
114
- local_spec = File.join cache_dir, spec_file_name
105
+ return [tuples, errors]
106
+ end
115
107
 
116
- if File.exist? local_spec then
117
- spec = Gem.read_binary local_spec
118
- else
119
- uri.path << '.rz'
120
108
 
121
- spec = @fetcher.fetch_path uri
122
- spec = Gem.inflate spec
109
+ ##
110
+ # Return all gem name tuples who's names match +obj+
123
111
 
124
- if @update_cache then
125
- FileUtils.mkdir_p cache_dir
112
+ def detect(type=:complete)
113
+ tuples = []
126
114
 
127
- open local_spec, 'wb' do |io|
128
- io.write spec
115
+ list, _ = available_specs(type)
116
+ list.each do |source, specs|
117
+ specs.each do |tup|
118
+ if yield(tup)
119
+ tuples << [tup, source]
129
120
  end
130
121
  end
131
122
  end
132
123
 
133
- # TODO: Investigate setting Gem::Specification#loaded_from to a URI
134
- Marshal.load spec
124
+ tuples
135
125
  end
136
126
 
127
+
137
128
  ##
138
- # Find spec names that match +dependency+. If +all+ is true, all
139
- # matching released versions are returned. If +matching_platform+
140
- # is false, gems for all platforms are returned.
141
-
142
- def find_matching_with_errors(dependency,
143
- all = false,
144
- matching_platform = true,
145
- prerelease = false)
146
- found = {}
129
+ # Find and fetch specs that match +dependency+.
130
+ #
131
+ # If +matching_platform+ is false, gems for all platforms are returned.
147
132
 
148
- rejected_specs = {}
133
+ def spec_for_dependency(dependency, matching_platform=true)
134
+ tuples, errors = search_for_dependency(dependency, matching_platform)
149
135
 
150
- list(all, prerelease).each do |source_uri, specs|
151
- found[source_uri] = specs.select do |spec_name, version, spec_platform|
152
- if dependency.match?(spec_name, version)
153
- if matching_platform and !Gem::Platform.match(spec_platform)
154
- pm = (rejected_specs[dependency] ||= Gem::PlatformMismatch.new(spec_name, version))
155
- pm.add_platform spec_platform
156
- false
157
- else
158
- true
159
- end
160
- end
136
+ specs = []
137
+ tuples.each do |tup, source|
138
+ begin
139
+ spec = source.fetch_spec(tup)
140
+ rescue Gem::RemoteFetcher::FetchError => e
141
+ errors << Gem::SourceFetchProblem.new(source, e)
142
+ else
143
+ specs << [spec, source]
161
144
  end
162
145
  end
163
146
 
164
- errors = rejected_specs.values
165
-
166
- specs_and_sources = []
167
-
168
- found.each do |source_uri, specs|
169
- uri_str = source_uri.to_s
170
- specs_and_sources.concat(specs.map { |spec| [spec, uri_str] })
171
- end
172
-
173
- [specs_and_sources, errors]
174
- end
175
-
176
- def find_matching(*args)
177
- find_matching_with_errors(*args).first
147
+ return [specs, errors]
178
148
  end
179
149
 
180
150
  ##
181
- # Suggests a gem based on the supplied +gem_name+. Returns a string
182
- # of the gem name if an approximate match can be found or nil
183
- # otherwise. NOTE: for performance reasons only gems which exactly
184
- # match the first character of +gem_name+ are considered.
151
+ # Suggests gems based on the supplied +gem_name+. Returns an array of
152
+ # alternative gem names.
185
153
 
186
154
  def suggest_gems_from_name gem_name
187
- gem_name = gem_name.downcase
155
+ gem_name = gem_name.downcase.tr('_-', '')
188
156
  max = gem_name.size / 2
189
- specs = list.values.flatten 1
157
+ names = available_specs(:complete).first.values.flatten(1)
190
158
 
191
- matches = specs.map { |name, version, platform|
192
- next unless Gem::Platform.match platform
159
+ matches = names.map { |n|
160
+ next unless n.match_platform?
193
161
 
194
- distance = levenshtein_distance gem_name, name.downcase
162
+ distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '')
195
163
 
196
164
  next if distance >= max
197
165
 
198
- return [name] if distance == 0
166
+ return [n.name] if distance == 0
199
167
 
200
- [name, distance]
168
+ [n.name, distance]
201
169
  }.compact
202
170
 
203
171
  matches = matches.uniq.sort_by { |name, dist| dist }
@@ -206,92 +174,56 @@ class Gem::SpecFetcher
206
174
  end
207
175
 
208
176
  ##
209
- # Returns a list of gems available for each source in Gem::sources. If
210
- # +all+ is true, all released versions are returned instead of only latest
211
- # versions. If +prerelease+ is true, include prerelease versions.
212
-
213
- def list(all = false, prerelease = false)
214
- # TODO: make type the only argument
215
- type = if all
216
- :all
217
- elsif prerelease
218
- :prerelease
219
- else
220
- :latest
221
- end
222
-
223
- list = {}
224
- file = FILES[type]
225
- cache = @caches[type]
226
-
227
- Gem.sources.each do |source_uri|
228
- source_uri = URI.parse source_uri
229
-
230
- unless cache.include? source_uri
231
- cache[source_uri] = load_specs source_uri, file
232
- end
233
-
234
- list[source_uri] = cache[source_uri]
235
- end
236
-
237
- if type == :all
238
- list.values.map do |gems|
239
- gems.reject! { |g| !g[1] || g[1].prerelease? }
240
- end
241
- end
242
-
243
- list
244
- end
245
-
246
- ##
247
- # Loads specs in +file+, fetching from +source_uri+ if the on-disk cache is
248
- # out of date.
249
-
250
- def load_specs(source_uri, file)
251
- file_name = "#{file}.#{Gem.marshal_version}"
252
- spec_path = source_uri + "#{file_name}.gz"
253
- cache_dir = cache_dir spec_path
254
- local_file = File.join(cache_dir, file_name)
255
- loaded = false
256
-
257
- if File.exist? local_file then
177
+ # Returns a list of gems available for each source in Gem::sources.
178
+ #
179
+ # +type+ can be one of 3 values:
180
+ # :released => Return the list of all released specs
181
+ # :complete => Return the list of all specs
182
+ # :latest => Return the list of only the highest version of each gem
183
+ # :prerelease => Return the list of all prerelease only specs
184
+ #
185
+
186
+ def available_specs(type)
187
+ errors = []
188
+ list = {}
189
+
190
+ Gem.sources.each_source do |source|
258
191
  begin
259
- spec_dump =
260
- @fetcher.fetch_path(spec_path, File.mtime(local_file))
192
+ names = case type
193
+ when :latest
194
+ tuples_for source, :latest
195
+ when :released
196
+ tuples_for source, :released
197
+ when :complete
198
+ tuples_for(source, :prerelease, true) +
199
+ tuples_for(source, :released)
200
+ when :prerelease
201
+ tuples_for(source, :prerelease)
202
+ else
203
+ raise Gem::Exception, "Unknown type - :#{type}"
204
+ end
261
205
  rescue Gem::RemoteFetcher::FetchError => e
262
- alert_warning "Error fetching data: #{e.message}"
206
+ errors << Gem::SourceFetchProblem.new(source, e)
207
+ else
208
+ list[source] = names
263
209
  end
264
-
265
- loaded = true if spec_dump
266
-
267
- spec_dump ||= Gem.read_binary local_file
268
- else
269
- spec_dump = @fetcher.fetch_path spec_path
270
- loaded = true
271
210
  end
272
211
 
273
- specs = begin
274
- Marshal.load spec_dump
275
- rescue ArgumentError
276
- spec_dump = @fetcher.fetch_path spec_path
277
- loaded = true
212
+ [list, errors]
213
+ end
278
214
 
279
- Marshal.load spec_dump
280
- end
215
+ def tuples_for(source, type, gracefully_ignore=false)
216
+ cache = @caches[type]
281
217
 
282
- if loaded and @update_cache then
218
+ if gracefully_ignore
283
219
  begin
284
- FileUtils.mkdir_p cache_dir
285
-
286
- open local_file, 'wb' do |io|
287
- io << spec_dump
288
- end
289
- rescue
220
+ cache[source.uri] ||= source.load_specs(type)
221
+ rescue Gem::RemoteFetcher::FetchError
222
+ []
290
223
  end
224
+ else
225
+ cache[source.uri] ||= source.load_specs(type)
291
226
  end
292
-
293
- specs
294
227
  end
295
-
296
228
  end
297
229