rubygems-update 4.0.21 → 4.1.0.beta1

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.
Files changed (496) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +590 -53
  3. data/CONTRIBUTING.md +66 -5
  4. data/MIT.txt +4 -3
  5. data/Manifest.txt +332 -375
  6. data/README.md +26 -6
  7. data/bundler.gemspec +63 -0
  8. data/doc/POLICIES.md +147 -0
  9. data/doc/UPGRADING.md +4 -4
  10. data/{bundler/lib → lib}/bundler/build_metadata.rb +2 -2
  11. data/{bundler/lib → lib}/bundler/checksum.rb +40 -25
  12. data/{bundler/lib → lib}/bundler/ci_detector.rb +1 -1
  13. data/{bundler/lib → lib}/bundler/cli/add.rb +3 -4
  14. data/{bundler/lib → lib}/bundler/cli/cache.rb +4 -0
  15. data/{bundler/lib → lib}/bundler/cli/clean.rb +5 -0
  16. data/{bundler/lib → lib}/bundler/cli/common.rb +37 -1
  17. data/{bundler/lib → lib}/bundler/cli/config.rb +4 -2
  18. data/{bundler/lib → lib}/bundler/cli/gem.rb +0 -17
  19. data/{bundler/lib → lib}/bundler/cli/install.rb +4 -5
  20. data/{bundler/lib → lib}/bundler/cli/lock.rb +1 -2
  21. data/{bundler/lib → lib}/bundler/cli/outdated.rb +8 -3
  22. data/{bundler/lib → lib}/bundler/cli/pristine.rb +2 -1
  23. data/{bundler/lib → lib}/bundler/cli/update.rb +21 -12
  24. data/{bundler/lib → lib}/bundler/cli.rb +14 -11
  25. data/{bundler/lib → lib}/bundler/definition.rb +61 -24
  26. data/{bundler/lib → lib}/bundler/dependency.rb +4 -0
  27. data/{bundler/lib → lib}/bundler/dsl.rb +77 -11
  28. data/{bundler/lib → lib}/bundler/endpoint_specification.rb +51 -14
  29. data/{bundler/lib → lib}/bundler/env.rb +7 -24
  30. data/{bundler/lib → lib}/bundler/errors.rb +34 -5
  31. data/{bundler/lib → lib}/bundler/fetcher/compact_index.rb +14 -5
  32. data/lib/bundler/fetcher/connection_pools.rb +150 -0
  33. data/{bundler/lib → lib}/bundler/fetcher/downloader.rb +31 -16
  34. data/{bundler/lib → lib}/bundler/fetcher.rb +8 -47
  35. data/{bundler/lib → lib}/bundler/injector.rb +3 -3
  36. data/{bundler/lib → lib}/bundler/inline.rb +44 -4
  37. data/{bundler/lib → lib}/bundler/installer/parallel_installer.rb +25 -30
  38. data/{bundler/lib → lib}/bundler/installer.rb +20 -6
  39. data/{bundler/lib → lib}/bundler/lazy_specification.rb +44 -17
  40. data/{bundler/lib → lib}/bundler/lockfile_generator.rb +24 -2
  41. data/{bundler/lib → lib}/bundler/lockfile_parser.rb +43 -5
  42. data/{bundler/lib → lib}/bundler/man/bundle-add.1 +7 -4
  43. data/{bundler/lib → lib}/bundler/man/bundle-add.1.ronn +8 -4
  44. data/{bundler/lib → lib}/bundler/man/bundle-binstubs.1 +1 -1
  45. data/{bundler/lib → lib}/bundler/man/bundle-cache.1 +2 -2
  46. data/{bundler/lib → lib}/bundler/man/bundle-cache.1.ronn +2 -2
  47. data/{bundler/lib → lib}/bundler/man/bundle-check.1 +1 -1
  48. data/{bundler/lib → lib}/bundler/man/bundle-clean.1 +1 -1
  49. data/{bundler/lib → lib}/bundler/man/bundle-config.1 +38 -6
  50. data/{bundler/lib → lib}/bundler/man/bundle-config.1.ronn +143 -10
  51. data/{bundler/lib → lib}/bundler/man/bundle-console.1 +1 -1
  52. data/{bundler/lib → lib}/bundler/man/bundle-doctor.1 +1 -1
  53. data/{bundler/lib → lib}/bundler/man/bundle-env.1 +1 -1
  54. data/{bundler/lib → lib}/bundler/man/bundle-exec.1 +1 -1
  55. data/{bundler/lib → lib}/bundler/man/bundle-fund.1 +1 -1
  56. data/{bundler/lib → lib}/bundler/man/bundle-gem.1 +1 -1
  57. data/{bundler/lib → lib}/bundler/man/bundle-help.1 +1 -1
  58. data/{bundler/lib → lib}/bundler/man/bundle-info.1 +1 -1
  59. data/{bundler/lib → lib}/bundler/man/bundle-init.1 +1 -1
  60. data/{bundler/lib → lib}/bundler/man/bundle-install.1 +2 -2
  61. data/{bundler/lib → lib}/bundler/man/bundle-install.1.ronn +4 -4
  62. data/{bundler/lib → lib}/bundler/man/bundle-issue.1 +1 -1
  63. data/{bundler/lib → lib}/bundler/man/bundle-licenses.1 +1 -1
  64. data/{bundler/lib → lib}/bundler/man/bundle-list.1 +1 -1
  65. data/{bundler/lib → lib}/bundler/man/bundle-lock.1 +3 -3
  66. data/{bundler/lib → lib}/bundler/man/bundle-lock.1.ronn +5 -5
  67. data/{bundler/lib → lib}/bundler/man/bundle-open.1 +1 -1
  68. data/{bundler/lib → lib}/bundler/man/bundle-outdated.1 +1 -1
  69. data/{bundler/lib → lib}/bundler/man/bundle-platform.1 +1 -1
  70. data/{bundler/lib → lib}/bundler/man/bundle-plugin.1 +1 -1
  71. data/{bundler/lib → lib}/bundler/man/bundle-pristine.1 +1 -1
  72. data/{bundler/lib → lib}/bundler/man/bundle-remove.1 +1 -1
  73. data/{bundler/lib → lib}/bundler/man/bundle-show.1 +1 -1
  74. data/{bundler/lib → lib}/bundler/man/bundle-update.1 +3 -3
  75. data/{bundler/lib → lib}/bundler/man/bundle-update.1.ronn +3 -5
  76. data/{bundler/lib → lib}/bundler/man/bundle-version.1 +1 -1
  77. data/{bundler/lib → lib}/bundler/man/bundle.1 +1 -1
  78. data/{bundler/lib → lib}/bundler/man/gemfile.5 +45 -1
  79. data/{bundler/lib → lib}/bundler/man/gemfile.5.ronn +53 -0
  80. data/lib/bundler/match_metadata.rb +50 -0
  81. data/{bundler/lib → lib}/bundler/match_platform.rb +25 -2
  82. data/lib/bundler/match_remote_metadata.rb +44 -0
  83. data/{bundler/lib → lib}/bundler/materialization.rb +2 -1
  84. data/lib/bundler/override.rb +69 -0
  85. data/{bundler/lib → lib}/bundler/plugin/dsl.rb +3 -5
  86. data/{bundler/lib → lib}/bundler/plugin/events.rb +55 -13
  87. data/{bundler/lib → lib}/bundler/plugin/index.rb +87 -11
  88. data/{bundler/lib → lib}/bundler/plugin/installer/path.rb +1 -1
  89. data/{bundler/lib → lib}/bundler/plugin/installer.rb +13 -5
  90. data/{bundler/lib → lib}/bundler/plugin.rb +58 -30
  91. data/{bundler/lib → lib}/bundler/remote_specification.rb +6 -3
  92. data/{bundler/lib → lib}/bundler/resolver/base.rb +2 -1
  93. data/{bundler/lib → lib}/bundler/resolver/incompatibility.rb +1 -1
  94. data/{bundler/lib → lib}/bundler/resolver.rb +73 -23
  95. data/{bundler/lib → lib}/bundler/ruby_version.rb +0 -2
  96. data/{bundler/lib → lib}/bundler/rubygems_ext.rb +71 -1
  97. data/{bundler/lib → lib}/bundler/rubygems_gem_installer.rb +41 -2
  98. data/{bundler/lib → lib}/bundler/rubygems_integration.rb +7 -2
  99. data/{bundler/lib → lib}/bundler/runtime.rb +69 -2
  100. data/{bundler/lib → lib}/bundler/self_manager.rb +9 -15
  101. data/{bundler/lib → lib}/bundler/settings.rb +373 -30
  102. data/{bundler/lib → lib}/bundler/shared_helpers.rb +2 -1
  103. data/{bundler/lib → lib}/bundler/source/git/git_proxy.rb +2 -10
  104. data/{bundler/lib → lib}/bundler/source/git.rb +15 -6
  105. data/{bundler/lib → lib}/bundler/source/path/installer.rb +1 -1
  106. data/{bundler/lib → lib}/bundler/source/rubygems/remote.rb +10 -5
  107. data/{bundler/lib → lib}/bundler/source/rubygems.rb +48 -12
  108. data/{bundler/lib → lib}/bundler/spec_set.rb +16 -4
  109. data/{bundler/lib → lib}/bundler/stub_specification.rb +2 -1
  110. data/{bundler/lib → lib}/bundler/templates/newgem/Gemfile.tt +4 -4
  111. data/{bundler/lib → lib}/bundler/templates/newgem/newgem.gemspec.tt +3 -3
  112. data/{bundler/lib → lib}/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
  113. data/{bundler/lib → lib}/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
  114. data/{bundler/lib → lib}/bundler/ui/shell.rb +0 -4
  115. data/{bundler/lib → lib}/bundler/ui/silent.rb +0 -4
  116. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
  117. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/base.rb +2 -1
  118. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
  119. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
  120. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/version.rb +1 -1
  121. data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor.rb +34 -1
  122. data/lib/bundler/vendored_pub_grub.rb +7 -0
  123. data/lib/bundler/vendored_securerandom.rb +15 -0
  124. data/lib/bundler/vendored_uri.rb +21 -0
  125. data/{bundler/lib → lib}/bundler/version.rb +1 -1
  126. data/{bundler/lib → lib}/bundler/worker.rb +3 -2
  127. data/{bundler/lib → lib}/bundler.rb +1 -1
  128. data/lib/rubygems/basic_specification.rb +15 -14
  129. data/lib/rubygems/bundler_settings.rb +137 -0
  130. data/lib/rubygems/bundler_version_finder.rb +13 -55
  131. data/lib/rubygems/ci_detector.rb +1 -1
  132. data/lib/rubygems/commands/build_command.rb +8 -1
  133. data/lib/rubygems/commands/cert_command.rb +9 -7
  134. data/lib/rubygems/commands/contents_command.rb +1 -1
  135. data/lib/rubygems/commands/dependency_command.rb +15 -3
  136. data/lib/rubygems/commands/environment_command.rb +1 -0
  137. data/lib/rubygems/commands/exec_command.rb +3 -0
  138. data/lib/rubygems/commands/fetch_command.rb +1 -1
  139. data/lib/rubygems/commands/help_command.rb +3 -1
  140. data/lib/rubygems/commands/install_command.rb +13 -3
  141. data/lib/rubygems/commands/lock_command.rb +2 -2
  142. data/lib/rubygems/commands/outdated_command.rb +77 -2
  143. data/lib/rubygems/commands/owner_command.rb +1 -1
  144. data/lib/rubygems/commands/push_command.rb +159 -21
  145. data/lib/rubygems/commands/setup_command.rb +20 -23
  146. data/lib/rubygems/commands/signin_command.rb +3 -1
  147. data/lib/rubygems/commands/signout_command.rb +26 -6
  148. data/lib/rubygems/commands/specification_command.rb +1 -1
  149. data/lib/rubygems/commands/uninstall_command.rb +1 -1
  150. data/lib/rubygems/commands/update_command.rb +84 -2
  151. data/lib/rubygems/commands/yank_command.rb +10 -7
  152. data/lib/rubygems/compact_index_client/cache.rb +122 -0
  153. data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
  154. data/lib/rubygems/compact_index_client/http_fetcher.rb +88 -0
  155. data/lib/rubygems/compact_index_client/parser.rb +90 -0
  156. data/lib/rubygems/compact_index_client/updater.rb +113 -0
  157. data/lib/rubygems/compact_index_client.rb +111 -0
  158. data/lib/rubygems/config_file.rb +304 -22
  159. data/lib/rubygems/content_address.rb +194 -0
  160. data/lib/rubygems/cooldown.rb +173 -0
  161. data/lib/rubygems/cooldown_option.rb +27 -0
  162. data/lib/rubygems/cooldown_settings.rb +57 -0
  163. data/lib/rubygems/credential_store/native/linux.rb +97 -0
  164. data/lib/rubygems/credential_store/native/macos.rb +88 -0
  165. data/lib/rubygems/credential_store/native/windows.rb +130 -0
  166. data/lib/rubygems/credential_store.rb +332 -0
  167. data/lib/rubygems/defaults.rb +9 -0
  168. data/lib/rubygems/dependency_installer.rb +15 -0
  169. data/lib/rubygems/doctor.rb +23 -6
  170. data/lib/rubygems/exceptions.rb +11 -43
  171. data/lib/rubygems/ext/builder.rb +70 -5
  172. data/lib/rubygems/ext/cargo_builder.rb +0 -9
  173. data/lib/rubygems/ext/ext_conf_builder.rb +8 -15
  174. data/lib/rubygems/gemcutter_utilities.rb +44 -2
  175. data/lib/rubygems/install_update_options.rb +16 -0
  176. data/lib/rubygems/installer.rb +90 -11
  177. data/lib/rubygems/installer_uninstaller_utils.rb +24 -3
  178. data/lib/rubygems/name_tuple.rb +55 -18
  179. data/lib/rubygems/package/old.rb +1 -1
  180. data/lib/rubygems/package.rb +200 -47
  181. data/lib/rubygems/package_task.rb +2 -2
  182. data/lib/rubygems/platform.rb +2 -2
  183. data/lib/rubygems/query_utils.rb +84 -24
  184. data/lib/rubygems/remote_fetcher.rb +65 -17
  185. data/lib/rubygems/request/connection_pools.rb +3 -0
  186. data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
  187. data/lib/rubygems/request_set/lockfile.rb +0 -2
  188. data/lib/rubygems/request_set.rb +105 -17
  189. data/lib/rubygems/resolver/api_set.rb +14 -26
  190. data/lib/rubygems/resolver/api_specification.rb +56 -15
  191. data/lib/rubygems/resolver/incompatibility.rb +10 -0
  192. data/lib/rubygems/resolver/index_specification.rb +6 -4
  193. data/lib/rubygems/resolver/installer_set.rb +2 -2
  194. data/lib/rubygems/resolver/lock_specification.rb +5 -1
  195. data/lib/rubygems/resolver/spec_specification.rb +4 -0
  196. data/lib/rubygems/resolver/specification.rb +16 -1
  197. data/lib/rubygems/resolver/strategy.rb +44 -0
  198. data/lib/rubygems/resolver.rb +471 -145
  199. data/lib/rubygems/safe_marshal.rb +2 -1
  200. data/lib/rubygems/safe_yaml.rb +20 -3
  201. data/lib/rubygems/security/policy.rb +11 -3
  202. data/lib/rubygems/security/signer.rb +15 -7
  203. data/lib/rubygems/security.rb +111 -17
  204. data/lib/rubygems/source/local.rb +7 -2
  205. data/lib/rubygems/source.rb +270 -23
  206. data/lib/rubygems/spec_fetcher.rb +47 -12
  207. data/lib/rubygems/specification.rb +76 -32
  208. data/lib/rubygems/specification_policy.rb +33 -6
  209. data/lib/rubygems/specification_record.rb +41 -2
  210. data/lib/rubygems/stub_specification.rb +39 -16
  211. data/lib/rubygems/uninstaller.rb +2 -0
  212. data/lib/rubygems/util/atomic_file_writer.rb +109 -0
  213. data/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb +2 -1
  214. data/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb +5 -6
  215. data/lib/rubygems/vendor/net-http/lib/net/http/header.rb +8 -4
  216. data/lib/rubygems/vendor/net-http/lib/net/http/requests.rb +15 -1
  217. data/lib/rubygems/vendor/net-http/lib/net/http/response.rb +2 -1
  218. data/lib/rubygems/vendor/net-http/lib/net/http/responses.rb +68 -0
  219. data/lib/rubygems/vendor/net-http/lib/net/http.rb +60 -49
  220. data/lib/rubygems/vendor/optparse/lib/optparse.rb +23 -30
  221. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
  222. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
  223. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
  224. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
  225. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
  226. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
  227. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
  228. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
  229. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
  230. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
  231. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
  232. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
  233. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
  234. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
  235. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
  236. data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
  237. data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
  238. data/lib/rubygems/vendor/resolv/lib/resolv.rb +3508 -0
  239. data/lib/rubygems/vendor/securerandom/lib/securerandom.rb +4 -0
  240. data/lib/rubygems/vendor/timeout/lib/timeout.rb +190 -77
  241. data/lib/rubygems/vendor/uri/lib/uri.rb +4 -0
  242. data/{bundler/lib/bundler → lib/rubygems}/vendored_pub_grub.rb +0 -1
  243. data/lib/rubygems/version.rb +129 -111
  244. data/lib/rubygems/version_option.rb +14 -0
  245. data/lib/rubygems/yaml_serializer.rb +853 -71
  246. data/lib/rubygems.rb +45 -11
  247. data/rubygems-update.gemspec +3 -4
  248. data/setup.rb +1 -0
  249. metadata +365 -410
  250. data/bundler/CHANGELOG.md +0 -5784
  251. data/bundler/LICENSE.md +0 -22
  252. data/bundler/README.md +0 -58
  253. data/bundler/bundler.gemspec +0 -46
  254. data/bundler/lib/bundler/compact_index_client/cache.rb +0 -107
  255. data/bundler/lib/bundler/compact_index_client/cache_file.rb +0 -148
  256. data/bundler/lib/bundler/compact_index_client/parser.rb +0 -87
  257. data/bundler/lib/bundler/compact_index_client/updater.rb +0 -105
  258. data/bundler/lib/bundler/compact_index_client.rb +0 -92
  259. data/bundler/lib/bundler/match_metadata.rb +0 -30
  260. data/bundler/lib/bundler/match_remote_metadata.rb +0 -29
  261. data/bundler/lib/bundler/vendor/connection_pool/LICENSE +0 -20
  262. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
  263. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
  264. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
  265. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
  266. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
  267. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
  268. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
  269. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
  270. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
  271. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
  272. data/bundler/lib/bundler/vendor/securerandom/lib/securerandom.rb +0 -102
  273. data/bundler/lib/bundler/vendor/uri/COPYING +0 -56
  274. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +0 -922
  275. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +0 -100
  276. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -267
  277. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +0 -1592
  278. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +0 -137
  279. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +0 -23
  280. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +0 -261
  281. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +0 -22
  282. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -293
  283. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +0 -547
  284. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +0 -206
  285. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +0 -6
  286. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +0 -83
  287. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +0 -23
  288. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +0 -104
  289. data/bundler/lib/bundler/vendored_persistent.rb +0 -11
  290. data/bundler/lib/bundler/vendored_securerandom.rb +0 -12
  291. data/bundler/lib/bundler/vendored_uri.rb +0 -21
  292. data/bundler/lib/bundler/yaml_serializer.rb +0 -98
  293. data/doc/rubygems/CONTRIBUTING.md +0 -231
  294. data/doc/rubygems/POLICIES.md +0 -60
  295. data/lib/rubygems/request_set/lockfile/parser.rb +0 -344
  296. data/lib/rubygems/request_set/lockfile/tokenizer.rb +0 -122
  297. data/lib/rubygems/resolver/conflict.rb +0 -146
  298. data/lib/rubygems/resolver/stats.rb +0 -46
  299. data/lib/rubygems/util/list.rb +0 -40
  300. data/lib/rubygems/vendor/molinillo/LICENSE +0 -9
  301. data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  302. data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  303. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  304. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  305. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  306. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  307. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  308. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  309. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  310. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  311. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  312. data/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  313. data/lib/rubygems/vendor/molinillo/lib/molinillo/errors.rb +0 -149
  314. data/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  315. data/lib/rubygems/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  316. data/lib/rubygems/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  317. data/lib/rubygems/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  318. data/lib/rubygems/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  319. data/lib/rubygems/vendor/molinillo/lib/molinillo/state.rb +0 -58
  320. data/lib/rubygems/vendor/molinillo/lib/molinillo.rb +0 -11
  321. data/lib/rubygems/vendored_molinillo.rb +0 -3
  322. /data/{bundler/exe → exe}/bundle +0 -0
  323. /data/{bundler/exe → exe}/bundler +0 -0
  324. /data/{bundler/lib → lib}/bundler/.document +0 -0
  325. /data/{bundler/lib → lib}/bundler/capistrano.rb +0 -0
  326. /data/{bundler/lib → lib}/bundler/cli/binstubs.rb +0 -0
  327. /data/{bundler/lib → lib}/bundler/cli/check.rb +0 -0
  328. /data/{bundler/lib → lib}/bundler/cli/console.rb +0 -0
  329. /data/{bundler/lib → lib}/bundler/cli/doctor/diagnose.rb +0 -0
  330. /data/{bundler/lib → lib}/bundler/cli/doctor/ssl.rb +0 -0
  331. /data/{bundler/lib → lib}/bundler/cli/doctor.rb +0 -0
  332. /data/{bundler/lib → lib}/bundler/cli/exec.rb +0 -0
  333. /data/{bundler/lib → lib}/bundler/cli/fund.rb +0 -0
  334. /data/{bundler/lib → lib}/bundler/cli/info.rb +0 -0
  335. /data/{bundler/lib → lib}/bundler/cli/init.rb +0 -0
  336. /data/{bundler/lib → lib}/bundler/cli/issue.rb +0 -0
  337. /data/{bundler/lib → lib}/bundler/cli/list.rb +0 -0
  338. /data/{bundler/lib → lib}/bundler/cli/open.rb +0 -0
  339. /data/{bundler/lib → lib}/bundler/cli/platform.rb +0 -0
  340. /data/{bundler/lib → lib}/bundler/cli/plugin.rb +0 -0
  341. /data/{bundler/lib → lib}/bundler/cli/remove.rb +0 -0
  342. /data/{bundler/lib → lib}/bundler/cli/show.rb +0 -0
  343. /data/{bundler/lib → lib}/bundler/constants.rb +0 -0
  344. /data/{bundler/lib → lib}/bundler/current_ruby.rb +0 -0
  345. /data/{bundler/lib → lib}/bundler/deployment.rb +0 -0
  346. /data/{bundler/lib → lib}/bundler/deprecate.rb +0 -0
  347. /data/{bundler/lib → lib}/bundler/digest.rb +0 -0
  348. /data/{bundler/lib → lib}/bundler/environment_preserver.rb +0 -0
  349. /data/{bundler/lib → lib}/bundler/feature_flag.rb +0 -0
  350. /data/{bundler/lib → lib}/bundler/fetcher/base.rb +0 -0
  351. /data/{bundler/lib → lib}/bundler/fetcher/dependency.rb +0 -0
  352. /data/{bundler/lib → lib}/bundler/fetcher/gem_remote_fetcher.rb +0 -0
  353. /data/{bundler/lib → lib}/bundler/fetcher/index.rb +0 -0
  354. /data/{bundler/lib → lib}/bundler/force_platform.rb +0 -0
  355. /data/{bundler/lib → lib}/bundler/friendly_errors.rb +0 -0
  356. /data/{bundler/lib → lib}/bundler/gem_helper.rb +0 -0
  357. /data/{bundler/lib → lib}/bundler/gem_tasks.rb +0 -0
  358. /data/{bundler/lib → lib}/bundler/gem_version_promoter.rb +0 -0
  359. /data/{bundler/lib → lib}/bundler/index.rb +0 -0
  360. /data/{bundler/lib → lib}/bundler/installer/gem_installer.rb +0 -0
  361. /data/{bundler/lib → lib}/bundler/installer/standalone.rb +0 -0
  362. /data/{bundler/lib → lib}/bundler/man/.document +0 -0
  363. /data/{bundler/lib → lib}/bundler/man/bundle-binstubs.1.ronn +0 -0
  364. /data/{bundler/lib → lib}/bundler/man/bundle-check.1.ronn +0 -0
  365. /data/{bundler/lib → lib}/bundler/man/bundle-clean.1.ronn +0 -0
  366. /data/{bundler/lib → lib}/bundler/man/bundle-console.1.ronn +0 -0
  367. /data/{bundler/lib → lib}/bundler/man/bundle-doctor.1.ronn +0 -0
  368. /data/{bundler/lib → lib}/bundler/man/bundle-env.1.ronn +0 -0
  369. /data/{bundler/lib → lib}/bundler/man/bundle-exec.1.ronn +0 -0
  370. /data/{bundler/lib → lib}/bundler/man/bundle-fund.1.ronn +0 -0
  371. /data/{bundler/lib → lib}/bundler/man/bundle-gem.1.ronn +0 -0
  372. /data/{bundler/lib → lib}/bundler/man/bundle-help.1.ronn +0 -0
  373. /data/{bundler/lib → lib}/bundler/man/bundle-info.1.ronn +0 -0
  374. /data/{bundler/lib → lib}/bundler/man/bundle-init.1.ronn +0 -0
  375. /data/{bundler/lib → lib}/bundler/man/bundle-issue.1.ronn +0 -0
  376. /data/{bundler/lib → lib}/bundler/man/bundle-licenses.1.ronn +0 -0
  377. /data/{bundler/lib → lib}/bundler/man/bundle-list.1.ronn +0 -0
  378. /data/{bundler/lib → lib}/bundler/man/bundle-open.1.ronn +0 -0
  379. /data/{bundler/lib → lib}/bundler/man/bundle-outdated.1.ronn +0 -0
  380. /data/{bundler/lib → lib}/bundler/man/bundle-platform.1.ronn +0 -0
  381. /data/{bundler/lib → lib}/bundler/man/bundle-plugin.1.ronn +0 -0
  382. /data/{bundler/lib → lib}/bundler/man/bundle-pristine.1.ronn +0 -0
  383. /data/{bundler/lib → lib}/bundler/man/bundle-remove.1.ronn +0 -0
  384. /data/{bundler/lib → lib}/bundler/man/bundle-show.1.ronn +0 -0
  385. /data/{bundler/lib → lib}/bundler/man/bundle-version.1.ronn +0 -0
  386. /data/{bundler/lib → lib}/bundler/man/bundle.1.ronn +0 -0
  387. /data/{bundler/lib → lib}/bundler/man/index.txt +0 -0
  388. /data/{bundler/lib → lib}/bundler/mirror.rb +0 -0
  389. /data/{bundler/lib → lib}/bundler/plugin/api/source.rb +0 -0
  390. /data/{bundler/lib → lib}/bundler/plugin/api.rb +0 -0
  391. /data/{bundler/lib → lib}/bundler/plugin/installer/git.rb +0 -0
  392. /data/{bundler/lib → lib}/bundler/plugin/installer/rubygems.rb +0 -0
  393. /data/{bundler/lib → lib}/bundler/plugin/source_list.rb +0 -0
  394. /data/{bundler/lib → lib}/bundler/plugin/unloaded_source.rb +0 -0
  395. /data/{bundler/lib → lib}/bundler/process_lock.rb +0 -0
  396. /data/{bundler/lib → lib}/bundler/resolver/candidate.rb +0 -0
  397. /data/{bundler/lib → lib}/bundler/resolver/package.rb +0 -0
  398. /data/{bundler/lib → lib}/bundler/resolver/root.rb +0 -0
  399. /data/{bundler/lib → lib}/bundler/resolver/spec_group.rb +0 -0
  400. /data/{bundler/lib → lib}/bundler/resolver/strategy.rb +0 -0
  401. /data/{bundler/lib → lib}/bundler/retry.rb +0 -0
  402. /data/{bundler/lib → lib}/bundler/ruby_dsl.rb +0 -0
  403. /data/{bundler/lib → lib}/bundler/safe_marshal.rb +0 -0
  404. /data/{bundler/lib → lib}/bundler/settings/validator.rb +0 -0
  405. /data/{bundler/lib → lib}/bundler/setup.rb +0 -0
  406. /data/{bundler/lib → lib}/bundler/source/gemspec.rb +0 -0
  407. /data/{bundler/lib → lib}/bundler/source/metadata.rb +0 -0
  408. /data/{bundler/lib → lib}/bundler/source/path.rb +0 -0
  409. /data/{bundler/lib → lib}/bundler/source/rubygems_aggregate.rb +0 -0
  410. /data/{bundler/lib → lib}/bundler/source.rb +0 -0
  411. /data/{bundler/lib → lib}/bundler/source_list.rb +0 -0
  412. /data/{bundler/lib → lib}/bundler/source_map.rb +0 -0
  413. /data/{bundler/lib → lib}/bundler/templates/.document +0 -0
  414. /data/{bundler/lib → lib}/bundler/templates/Executable +0 -0
  415. /data/{bundler/lib → lib}/bundler/templates/Executable.standalone +0 -0
  416. /data/{bundler/lib → lib}/bundler/templates/Gemfile +0 -0
  417. /data/{bundler/lib → lib}/bundler/templates/newgem/CHANGELOG.md.tt +0 -0
  418. /data/{bundler/lib → lib}/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +0 -0
  419. /data/{bundler/lib → lib}/bundler/templates/newgem/Cargo.toml.tt +0 -0
  420. /data/{bundler/lib → lib}/bundler/templates/newgem/LICENSE.txt.tt +0 -0
  421. /data/{bundler/lib → lib}/bundler/templates/newgem/README.md.tt +0 -0
  422. /data/{bundler/lib → lib}/bundler/templates/newgem/Rakefile.tt +0 -0
  423. /data/{bundler/lib → lib}/bundler/templates/newgem/bin/console.tt +0 -0
  424. /data/{bundler/lib → lib}/bundler/templates/newgem/bin/setup.tt +0 -0
  425. /data/{bundler/lib → lib}/bundler/templates/newgem/circleci/config.yml.tt +0 -0
  426. /data/{bundler/lib → lib}/bundler/templates/newgem/exe/newgem.tt +0 -0
  427. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +0 -0
  428. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/build.rs.tt +0 -0
  429. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +0 -0
  430. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt +0 -0
  431. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +0 -0
  432. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/go.mod.tt +0 -0
  433. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem-go.c.tt +0 -0
  434. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.c.tt +0 -0
  435. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.go.tt +0 -0
  436. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/newgem.h.tt +0 -0
  437. /data/{bundler/lib → lib}/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +0 -0
  438. /data/{bundler/lib → lib}/bundler/templates/newgem/github/workflows/build-gems.yml.tt +0 -0
  439. /data/{bundler/lib → lib}/bundler/templates/newgem/github/workflows/main.yml.tt +0 -0
  440. /data/{bundler/lib → lib}/bundler/templates/newgem/gitignore.tt +0 -0
  441. /data/{bundler/lib → lib}/bundler/templates/newgem/gitlab-ci.yml.tt +0 -0
  442. /data/{bundler/lib → lib}/bundler/templates/newgem/lib/newgem/version.rb.tt +0 -0
  443. /data/{bundler/lib → lib}/bundler/templates/newgem/lib/newgem.rb.tt +0 -0
  444. /data/{bundler/lib → lib}/bundler/templates/newgem/rspec.tt +0 -0
  445. /data/{bundler/lib → lib}/bundler/templates/newgem/rubocop.yml.tt +0 -0
  446. /data/{bundler/lib → lib}/bundler/templates/newgem/sig/newgem.rbs.tt +0 -0
  447. /data/{bundler/lib → lib}/bundler/templates/newgem/spec/spec_helper.rb.tt +0 -0
  448. /data/{bundler/lib → lib}/bundler/templates/newgem/standard.yml.tt +0 -0
  449. /data/{bundler/lib → lib}/bundler/templates/newgem/test/minitest/test_helper.rb.tt +0 -0
  450. /data/{bundler/lib → lib}/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +0 -0
  451. /data/{bundler/lib → lib}/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +0 -0
  452. /data/{bundler/lib → lib}/bundler/ui/rg_proxy.rb +0 -0
  453. /data/{bundler/lib → lib}/bundler/ui.rb +0 -0
  454. /data/{bundler/lib → lib}/bundler/uri_credentials_filter.rb +0 -0
  455. /data/{bundler/lib → lib}/bundler/uri_normalizer.rb +0 -0
  456. /data/{bundler/lib → lib}/bundler/vendor/.document +0 -0
  457. /data/{bundler/lib → lib}/bundler/vendor/fileutils/COPYING +0 -0
  458. /data/{bundler/lib → lib}/bundler/vendor/fileutils/lib/fileutils.rb +0 -0
  459. /data/{bundler/lib → lib}/bundler/vendor/thor/LICENSE.md +0 -0
  460. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/create_file.rb +0 -0
  461. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/create_link.rb +0 -0
  462. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/directory.rb +0 -0
  463. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +0 -0
  464. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +0 -0
  465. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/actions.rb +0 -0
  466. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/command.rb +0 -0
  467. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +0 -0
  468. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/error.rb +0 -0
  469. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/group.rb +0 -0
  470. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/invocation.rb +0 -0
  471. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor/basic.rb +0 -0
  472. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor/readline.rb +0 -0
  473. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/line_editor.rb +0 -0
  474. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/nested_context.rb +0 -0
  475. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/argument.rb +0 -0
  476. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/arguments.rb +0 -0
  477. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/option.rb +0 -0
  478. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser/options.rb +0 -0
  479. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/parser.rb +0 -0
  480. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/rake_compat.rb +0 -0
  481. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/runner.rb +0 -0
  482. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/column_printer.rb +0 -0
  483. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/html.rb +0 -0
  484. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/table_printer.rb +0 -0
  485. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/terminal.rb +0 -0
  486. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +0 -0
  487. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/shell.rb +0 -0
  488. /data/{bundler/lib → lib}/bundler/vendor/thor/lib/thor/util.rb +0 -0
  489. /data/{bundler/lib → lib}/bundler/vendored_fileutils.rb +0 -0
  490. /data/{bundler/lib → lib}/bundler/vendored_net_http.rb +0 -0
  491. /data/{bundler/lib → lib}/bundler/vendored_thor.rb +0 -0
  492. /data/{bundler/lib → lib}/bundler/vendored_timeout.rb +0 -0
  493. /data/{bundler/lib → lib}/bundler/vendored_tsort.rb +0 -0
  494. /data/{bundler/lib → lib}/bundler/vlad.rb +0 -0
  495. /data/{bundler/lib/bundler → lib/rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
  496. /data/{bundler/lib/bundler/vendor/securerandom → lib/rubygems/vendor/resolv}/COPYING +0 -0
@@ -27,12 +27,16 @@ require "rbconfig"
27
27
  #
28
28
  # +:backtrace+:: See #backtrace
29
29
  # +:bulk_threshold+:: See #bulk_threshold
30
+ # +:cooldown+:: See #cooldown
30
31
  # +:verbose+:: See #verbose
31
32
  # +:update_sources+:: See #update_sources
32
33
  # +:concurrent_downloads+:: See #concurrent_downloads
33
34
  # +:cert_expiration_length_days+:: See #cert_expiration_length_days
34
35
  # +:install_extension_in_lib+:: See #install_extension_in_lib
35
36
  # +:ipv4_fallback_enabled+:: See #ipv4_fallback_enabled
37
+ # +:global_gem_cache+:: See #global_gem_cache
38
+ # +:use_psych+:: See #use_psych
39
+ # +:credential_store+:: See #credential_store
36
40
  # +:gemhome+:: See #home
37
41
  # +:gempath+:: See #path
38
42
  # +:sources+:: Sets Gem::sources
@@ -53,13 +57,23 @@ class Gem::ConfigFile
53
57
 
54
58
  DEFAULT_BACKTRACE = true
55
59
  DEFAULT_BULK_THRESHOLD = 1000
60
+ DEFAULT_COOLDOWN = 0
56
61
  DEFAULT_VERBOSITY = true
57
62
  DEFAULT_UPDATE_SOURCES = true
58
63
  DEFAULT_CONCURRENT_DOWNLOADS = 8
59
64
  DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
60
65
  DEFAULT_IPV4_FALLBACK_ENABLED = false
61
- # TODO: Use false as default value for this option in RubyGems 4.0
62
66
  DEFAULT_INSTALL_EXTENSION_IN_LIB = true
67
+ DEFAULT_GLOBAL_GEM_CACHE = false
68
+ DEFAULT_USE_PSYCH = false
69
+ DEFAULT_CREDENTIAL_STORE = false
70
+
71
+ ##
72
+ # The account name under which the default RubyGems.org API key is
73
+ # stored in the credential store, mirroring the +:rubygems_api_key+
74
+ # symbol used by the plain text credentials file.
75
+
76
+ CREDENTIAL_STORE_DEFAULT_ACCOUNT = "rubygems_api_key"
63
77
 
64
78
  ##
65
79
  # For Ruby packagers to set configuration defaults. Set in
@@ -113,6 +127,20 @@ class Gem::ConfigFile
113
127
 
114
128
  attr_accessor :bulk_threshold
115
129
 
130
+ ##
131
+ # Number of days a newly published gem version must wait before it is
132
+ # considered for installation or update (the cooldown period). 0
133
+ # disables the cooldown, unless Bundler is configured with a longer one:
134
+ # this setting and Bundler's own +cooldown+ setting are both read, and the
135
+ # longer of the two applies, so a cooldown configured for only one of the
136
+ # two tools still covers both. <tt>--cooldown</tt> overrides both.
137
+ #
138
+ # A value that cannot be read as a non-negative integer warns and takes no
139
+ # part in that resolution, so a typo in the gemrc file does not make every
140
+ # command fail.
141
+
142
+ attr_accessor :cooldown
143
+
116
144
  ##
117
145
  # Verbose level of output:
118
146
  # * false -- No output
@@ -166,11 +194,38 @@ class Gem::ConfigFile
166
194
 
167
195
  attr_accessor :ipv4_fallback_enabled
168
196
 
197
+ ##
198
+ # Use a global cache for .gem files shared across all Ruby installations.
199
+ # When enabled, gems fetched from a remote source are cached to
200
+ # ~/.cache/gem/gems (or XDG_CACHE_HOME/gem/gems). Gems installed from a
201
+ # local path are not, since a cached copy is later reused without being
202
+ # verified again. <tt>gem fetch</tt> still writes to the working directory,
203
+ # and an unwritable cache directory falls back to the cache of the
204
+ # installation.
205
+
206
+ attr_accessor :global_gem_cache
207
+
208
+ ##
209
+ # Use Psych (C extension YAML parser) instead of the pure Ruby YAMLSerializer.
210
+
211
+ attr_accessor :use_psych
212
+
169
213
  ##
170
214
  # Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
171
215
 
172
216
  attr_reader :ssl_client_cert
173
217
 
218
+ ##
219
+ # == Experimental ==
220
+ # Store and read push/authentication credentials in a credential store
221
+ # instead of the plain text credentials file. +true+ selects the operating
222
+ # system's native store (macOS Keychain, Linux Secret Service, Windows
223
+ # Credential Manager) when one is available on this platform. A string
224
+ # selects a named backend registered by a third-party gem, such as
225
+ # +"1password"+. +false+ (the default) keeps using the credentials file.
226
+
227
+ attr_accessor :credential_store
228
+
174
229
  ##
175
230
  # Create the config file object. +args+ is the list of arguments
176
231
  # from the command line.
@@ -197,12 +252,16 @@ class Gem::ConfigFile
197
252
 
198
253
  @backtrace = DEFAULT_BACKTRACE
199
254
  @bulk_threshold = DEFAULT_BULK_THRESHOLD
255
+ @cooldown = DEFAULT_COOLDOWN
200
256
  @verbose = DEFAULT_VERBOSITY
201
257
  @update_sources = DEFAULT_UPDATE_SOURCES
202
258
  @concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
203
259
  @cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
204
260
  @install_extension_in_lib = DEFAULT_INSTALL_EXTENSION_IN_LIB
205
261
  @ipv4_fallback_enabled = ENV["IPV4_FALLBACK_ENABLED"] == "true" || DEFAULT_IPV4_FALLBACK_ENABLED
262
+ @global_gem_cache = ENV["RUBYGEMS_GLOBAL_GEM_CACHE"] == "true" || DEFAULT_GLOBAL_GEM_CACHE
263
+ @use_psych = ENV["RUBYGEMS_USE_PSYCH"] == "true" || DEFAULT_USE_PSYCH
264
+ @credential_store = normalize_credential_store(ENV["RUBYGEMS_CREDENTIAL_STORE"], DEFAULT_CREDENTIAL_STORE)
206
265
 
207
266
  operating_system_config = Gem::Util.deep_dup(OPERATING_SYSTEM_DEFAULTS)
208
267
  platform_config = Gem::Util.deep_dup(PLATFORM_DEFAULTS)
@@ -223,9 +282,10 @@ class Gem::ConfigFile
223
282
 
224
283
  @hash.transform_keys! do |k|
225
284
  # gemhome and gempath are not working with symbol keys
226
- if %w[backtrace bulk_threshold verbose update_sources cert_expiration_length_days
227
- install_extension_in_lib ipv4_fallback_enabled sources disable_default_gem_server
228
- ssl_verify_mode ssl_ca_cert ssl_client_cert].include?(k)
285
+ if %w[backtrace bulk_threshold cooldown verbose update_sources cert_expiration_length_days
286
+ concurrent_downloads install_extension_in_lib ipv4_fallback_enabled
287
+ global_gem_cache use_psych credential_store sources
288
+ disable_default_gem_server ssl_verify_mode ssl_ca_cert ssl_client_cert].include?(k)
229
289
  k.to_sym
230
290
  else
231
291
  k
@@ -235,12 +295,16 @@ class Gem::ConfigFile
235
295
  # HACK: these override command-line args, which is bad
236
296
  @backtrace = @hash[:backtrace] if @hash.key? :backtrace
237
297
  @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold
298
+ @cooldown = @hash[:cooldown] if @hash.key? :cooldown
238
299
  @verbose = @hash[:verbose] if @hash.key? :verbose
239
300
  @update_sources = @hash[:update_sources] if @hash.key? :update_sources
240
- # TODO: We should handle concurrent_downloads same as other options
301
+ @concurrent_downloads = @hash[:concurrent_downloads] if @hash.key? :concurrent_downloads
241
302
  @cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
242
303
  @install_extension_in_lib = @hash[:install_extension_in_lib] if @hash.key? :install_extension_in_lib
243
304
  @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
305
+ @global_gem_cache = @hash[:global_gem_cache] if @hash.key? :global_gem_cache
306
+ @use_psych = @hash[:use_psych] if @hash.key? :use_psych
307
+ @credential_store = normalize_credential_store(@hash[:credential_store], @credential_store) if @hash.key? :credential_store
244
308
 
245
309
  @home = @hash[:gemhome] if @hash.key? :gemhome
246
310
  @path = @hash[:gempath] if @hash.key? :gempath
@@ -257,7 +321,11 @@ class Gem::ConfigFile
257
321
  end
258
322
 
259
323
  ##
260
- # Hash of RubyGems.org and alternate API keys
324
+ # Hash of RubyGems.org and alternate API keys, as they appear in the
325
+ # credentials file. Keys held in the credential store are not included, so
326
+ # this is not the full set of keys a command can authenticate with. Use
327
+ # #credential_store_api_key_for or #credential_store_default_api_key to
328
+ # reach those.
261
329
 
262
330
  def api_keys
263
331
  load_api_keys unless @api_keys
@@ -332,45 +400,147 @@ if you believe they were disclosed to a third party.
332
400
  def rubygems_api_key
333
401
  load_api_keys unless @rubygems_api_key
334
402
 
335
- @rubygems_api_key
403
+ # #load_api_keys only reads the credentials file, which no longer holds the
404
+ # key once it is stored. A copy left there after the move is stale.
405
+ credential_store_default_api_key || @rubygems_api_key
336
406
  end
337
407
 
338
408
  ##
339
409
  # Sets the RubyGems.org API key to +api_key+
340
410
 
341
411
  def rubygems_api_key=(api_key)
412
+ if credential_store
413
+ store = active_credential_store
414
+
415
+ if api_key.to_s.empty?
416
+ warn_unremoved_credential(CREDENTIAL_STORE_DEFAULT_ACCOUNT) if store&.available? && !store.delete(CREDENTIAL_STORE_DEFAULT_ACCOUNT)
417
+ elsif store&.set(CREDENTIAL_STORE_DEFAULT_ACCOUNT, api_key)
418
+ remove_api_key_from_file(:rubygems_api_key)
419
+ @rubygems_api_key = api_key
420
+ return
421
+ else
422
+ warn_unremoved_credential(CREDENTIAL_STORE_DEFAULT_ACCOUNT) if store&.available? && !store.delete(CREDENTIAL_STORE_DEFAULT_ACCOUNT)
423
+ warn_credential_store_fallback
424
+ end
425
+ end
426
+
342
427
  set_api_key :rubygems_api_key, api_key
343
428
 
344
429
  @rubygems_api_key = api_key
345
430
  end
346
431
 
432
+ ##
433
+ # Looks up +host+'s own API key from the credential store, when the
434
+ # #credential_store setting is on. Only the host-specific account is
435
+ # consulted: falling back to the default account here would send the
436
+ # RubyGems.org key to whatever host was asked for, ahead of that host's own
437
+ # key in the credentials file. #credential_store_default_api_key covers the
438
+ # default account, at the precedence the credentials file uses for it.
439
+
440
+ def credential_store_api_key_for(host)
441
+ return nil if host.nil? || host.to_s.empty?
442
+ return nil unless credential_store
443
+ return nil unless store = active_credential_store
444
+
445
+ store.get(self.class.credential_store_account(host))
446
+ end
447
+
448
+ ##
449
+ # True when a read for +host+ failed rather than finding nothing. Whether
450
+ # the store holds a key for it is unknowable once the read fails, which is
451
+ # the point: a caller that would otherwise fall through to a key belonging
452
+ # to a different host has to treat "unknown" differently from "absent".
453
+
454
+ def credential_store_read_failed_for?(host)
455
+ return false unless credential_store
456
+ return false unless store = active_credential_store
457
+
458
+ # #rubygems_api_key reads the default account on the way to answering, and
459
+ # for the default host that is the only failure that can happen.
460
+ return true if store.read_failed?(CREDENTIAL_STORE_DEFAULT_ACCOUNT)
461
+ return false if host.nil? || host.to_s.empty?
462
+
463
+ store.read_failed?(self.class.credential_store_account(host))
464
+ end
465
+
466
+ ##
467
+ # The default RubyGems.org API key from the credential store, or +nil+.
468
+ # This is the stored counterpart of #rubygems_api_key, and belongs at the
469
+ # same point in the lookup order.
470
+
471
+ def credential_store_default_api_key
472
+ return nil unless credential_store
473
+ return nil unless store = active_credential_store
474
+
475
+ store.get(CREDENTIAL_STORE_DEFAULT_ACCOUNT)
476
+ end
477
+
347
478
  ##
348
479
  # Set a specific host's API key to +api_key+
349
480
 
350
481
  def set_api_key(host, api_key)
351
- check_credentials_permissions
482
+ if credential_store && host != :rubygems_api_key
483
+ store = active_credential_store
484
+
485
+ if api_key.to_s.empty?
486
+ delete_stored_key(store, host)
487
+ elsif store&.set(self.class.credential_store_account(host), api_key)
488
+ remove_api_key_from_file(host)
489
+ return
490
+ else
491
+ delete_stored_key(store, host)
492
+ warn_credential_store_fallback
493
+ end
494
+ end
352
495
 
353
- config = load_file(credentials_path).merge(host => api_key)
496
+ check_credentials_permissions
354
497
 
355
- dirname = File.dirname credentials_path
356
- require "fileutils"
357
- FileUtils.mkdir_p(dirname)
498
+ config = load_file(credentials_path).merge(self.class.normalize_credentials_key(host) => api_key)
358
499
 
359
- permissions = 0o600 & ~File.umask
360
- File.open(credentials_path, "w", permissions) do |f|
361
- f.write self.class.dump_with_rubygems_yaml(config)
362
- end
500
+ write_credentials(config)
363
501
 
364
502
  load_api_keys # reload
365
503
  end
366
504
 
367
505
  ##
368
- # Remove the +~/.gem/credentials+ file to clear all the current sessions.
506
+ # Remove the +~/.gem/credentials+ file to clear all the current sessions,
507
+ # and every RubyGems key from the credential store when the
508
+ # #credential_store setting is on, including keys saved for other hosts
509
+ # with <tt>gem signin --host</tt>.
369
510
 
370
511
  def unset_api_key!
371
- return false unless File.exist?(credentials_path)
512
+ store = active_credential_store
513
+ store_cleared =
514
+ if store.nil?
515
+ true
516
+ elsif store.available?
517
+ store.delete_all
518
+ else
519
+ # Failing here would make signout exit 1 on every platform without a
520
+ # native store, and plain success would claim a removal nobody made.
521
+ Gem::CredentialStore.warn_once "The credential store is enabled but unavailable, so any key it holds was left in place."
522
+ true
523
+ end
524
+
525
+ file_removed =
526
+ if File.exist?(credentials_path)
527
+ # POSIX deletes a read-only file whenever the directory is writable, so
528
+ # the marking has to be honored explicitly.
529
+ if File.writable?(credentials_path)
530
+ begin
531
+ File.delete(credentials_path)
532
+ true
533
+ rescue SystemCallError
534
+ false
535
+ end
536
+ else
537
+ false
538
+ end
539
+ else
540
+ false
541
+ end
372
542
 
373
- File.delete(credentials_path)
543
+ [store_cleared, file_removed]
374
544
  end
375
545
 
376
546
  def load_file(filename)
@@ -380,7 +550,9 @@ if you believe they were disclosed to a third party.
380
550
 
381
551
  begin
382
552
  config = self.class.load_with_rubygems_config_hash(File.read(filename))
383
- if config.keys.any? {|k| k.to_s.gsub(%r{https?:\/\/}, "").include?(": ") }
553
+ has_invalid_keys = config.keys.any? {|k| k.to_s.gsub(%r{https?:\/\/}, "").include?(": ") }
554
+ has_invalid_values = config.values.any? {|v| v.is_a?(String) && v.gsub(%r{https?:\/\/}, "").match?(/\A\S+: /) }
555
+ if has_invalid_keys || has_invalid_values
384
556
  warn "Failed to load #{filename} because it doesn't contain valid YAML hash"
385
557
  return {}
386
558
  else
@@ -565,12 +737,41 @@ if you believe they were disclosed to a third party.
565
737
  def self.load_with_rubygems_config_hash(yaml)
566
738
  require_relative "yaml_serializer"
567
739
 
568
- content = Gem::YAMLSerializer.load(yaml)
740
+ content = Gem::YAMLSerializer.load(yaml, permitted_classes: [])
741
+ return {} unless content.is_a?(Hash)
742
+
569
743
  deep_transform_config_keys!(content)
570
744
  end
571
745
 
572
746
  private
573
747
 
748
+ # Built on the same normalized form the credentials file uses, so the two
749
+ # never disagree about which host a spelling refers to. Userinfo is dropped
750
+ # because the account reaches the backend as a command argument, where any
751
+ # other user on the machine can read it.
752
+ def self.credential_store_account(host)
753
+ host = normalize_credentials_key(host).to_s
754
+ return host unless host.match?(%r{\Ahttps?://}i)
755
+
756
+ require_relative "vendor/uri/lib/uri"
757
+ uri = Gem::URI(host)
758
+ return host unless uri.userinfo
759
+
760
+ uri = uri.dup
761
+ uri.user = uri.password = nil
762
+ uri.to_s
763
+ rescue Gem::URI::Error
764
+ host
765
+ end
766
+
767
+ # A trailing slash, or the underscore pair standing in for a dot, comes back
768
+ # rewritten from #load_file, so a raw host would silently miss.
769
+ def self.normalize_credentials_key(host)
770
+ return host unless host.is_a?(String)
771
+
772
+ deep_transform_config_keys!(host => nil).keys.first
773
+ end
774
+
574
775
  def self.deep_transform_config_keys!(config)
575
776
  config.transform_keys! do |k|
576
777
  if k.match?(/\A:(.*)\z/)
@@ -599,7 +800,7 @@ if you believe they were disclosed to a third party.
599
800
  else
600
801
  v
601
802
  end
602
- elsif v.empty?
803
+ elsif v.respond_to?(:empty?) && v.empty?
603
804
  nil
604
805
  elsif v.is_a?(Hash)
605
806
  deep_transform_config_keys!(v)
@@ -611,6 +812,87 @@ if you believe they were disclosed to a third party.
611
812
  config
612
813
  end
613
814
 
815
+ def active_credential_store
816
+ return nil unless credential_store
817
+
818
+ require_relative "credential_store"
819
+ Gem::CredentialStore.for(credential_store)
820
+ end
821
+
822
+ def write_credentials(config)
823
+ dirname = File.dirname credentials_path
824
+ require "fileutils"
825
+ FileUtils.mkdir_p(dirname)
826
+
827
+ permissions = 0o600 & ~File.umask
828
+ File.open(credentials_path, "w", permissions) do |f|
829
+ f.write self.class.dump_with_rubygems_yaml(config)
830
+ end
831
+ end
832
+
833
+ def remove_api_key_from_file(host)
834
+ return unless File.exist?(credentials_path)
835
+
836
+ unless File.writable?(credentials_path)
837
+ alert_warning "The API key moved to the credential store but the plain text copy " \
838
+ "in #{credentials_path} could not be removed. Delete it yourself."
839
+ return
840
+ end
841
+
842
+ key = self.class.normalize_credentials_key(host)
843
+ config = load_file(credentials_path)
844
+ return unless config.key?(key)
845
+
846
+ config.delete(key)
847
+ write_credentials(config)
848
+ load_api_keys
849
+ end
850
+
851
+ def delete_stored_key(store, host)
852
+ account = self.class.credential_store_account(host)
853
+ warn_unremoved_credential(account) if store&.available? && !store.delete(account)
854
+ end
855
+
856
+ def warn_unremoved_credential(account)
857
+ alert_warning "Could not remove the API key for #{account} from the credential store. " \
858
+ "It is still there and will be used instead of the one just set. " \
859
+ "Remove it with your platform's credential manager."
860
+ end
861
+
862
+ def warn_credential_store_fallback
863
+ alert_warning "Could not write the API key to the credential store, so it was written to #{credentials_path} in plain text."
864
+ end
865
+
866
+ CREDENTIAL_STORE_OFF = %w[false 0 no off f n].freeze
867
+ private_constant :CREDENTIAL_STORE_OFF
868
+
869
+ CREDENTIAL_STORE_ON = %w[true 1 yes on t y].freeze
870
+ private_constant :CREDENTIAL_STORE_ON
871
+
872
+ #--
873
+ # Anything that reads as a boolean is one, so RUBYGEMS_CREDENTIAL_STORE=0
874
+ # turns the store off rather than naming a backend gem "0". Both lists are
875
+ # this setting's own. Nothing on the way here turns `off` into a boolean, so
876
+ # a gemrc saying `off` arrives as a String just as the environment variable
877
+ # does. Bundler leaves `off` out of its half because every one of its
878
+ # boolean settings shares a single vocabulary that has never had it. Nothing
879
+ # here shares that constraint.
880
+
881
+ def normalize_credential_store(value, default)
882
+ # An environment variable can carry bytes String#downcase would reject.
883
+ normalized = value.to_s.b.downcase
884
+
885
+ if normalized.empty?
886
+ default
887
+ elsif CREDENTIAL_STORE_OFF.include?(normalized)
888
+ false
889
+ elsif CREDENTIAL_STORE_ON.include?(normalized)
890
+ true
891
+ else
892
+ value
893
+ end
894
+ end
895
+
614
896
  def set_config_file_name(args)
615
897
  @config_file_name = ENV["GEMRC"]
616
898
  need_config_file_name = false
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Gem::ContentAddress is the single home for content-addressing semantics:
5
+ # what an address and a Ruby ABI look like, which specs are eligible, how
6
+ # addresses are generated and verified against gem files.
7
+ module Gem::ContentAddress
8
+ ##
9
+ # A content address is 8 to 64 lowercase hexadecimal characters -- a
10
+ # prefix of the SHA256 digest of the gem file contents.
11
+
12
+ PATTERN = /\A[0-9a-f]{8,64}\z/
13
+
14
+ ##
15
+ # A Ruby ABI is a major and minor version pair ("X.Y").
16
+
17
+ RUBY_ABI_PATTERN = /\A\d+\.\d+\z/
18
+
19
+ private_constant :PATTERN, :RUBY_ABI_PATTERN
20
+
21
+ ##
22
+ # Default number of hexadecimal characters in a generated content address.
23
+
24
+ DEFAULT_LENGTH = 8
25
+
26
+ ##
27
+ # Whether +value+ is a valid content address (a string of 8-64
28
+ # lowercase hexadecimal characters). This only checks the shape of a
29
+ # string: use content_addressed? to ask whether a spec is actually
30
+ # content addressed, and file_name_claim to ask whether a file name
31
+ # claims an address.
32
+
33
+ def self.match?(value)
34
+ value.is_a?(String) && PATTERN.match?(value)
35
+ end
36
+
37
+ ##
38
+ # Whether +value+ is a well-formed Ruby ABI ("X.Y").
39
+
40
+ def self.valid_ruby_abi?(value)
41
+ value.is_a?(String) && RUBY_ABI_PATTERN.match?(value)
42
+ end
43
+
44
+ ##
45
+ # Derives the Ruby ABI ("X.Y") from +required_ruby_version+. Only a
46
+ # single pessimistic requirement with three segments ending in zero
47
+ # ("~> X.Y.0") pins an ABI. Returns nil for any other shape.
48
+
49
+ def self.ruby_abi_for(required_ruby_version)
50
+ return nil if required_ruby_version.nil?
51
+
52
+ requirements = required_ruby_version.requirements
53
+ return nil if requirements.size != 1
54
+
55
+ op, version = requirements.first
56
+ segments = version.segments
57
+ return nil if op != "~>" || segments.size != 3 || segments[2] != 0
58
+ return nil unless segments[0].is_a?(Integer) && segments[1].is_a?(Integer)
59
+
60
+ segments[0..1].join(".")
61
+ end
62
+
63
+ ##
64
+ # The required_ruby_version that pins +ruby_abi+ ("X.Y" to "~> X.Y.0").
65
+ # Inverse of +ruby_abi_for+.
66
+
67
+ def self.ruby_abi_requirement(ruby_abi)
68
+ Gem::Requirement.new("~> #{ruby_abi}.0")
69
+ end
70
+
71
+ ##
72
+ # Whether +platform+ is eligible for content addressing: present and
73
+ # not the generic RUBY platform.
74
+
75
+ def self.platform_eligible?(platform)
76
+ !platform.nil? && platform != Gem::Platform::RUBY
77
+ end
78
+
79
+ ##
80
+ # Whether +spec+ is eligible for content addressing. A gem must pin
81
+ # its required_ruby_version to a single Ruby ABI ("~> X.Y.0") and
82
+ # declare a non-RUBY platform to be content addressed. This makes
83
+ # `content_addressed? implies ruby_abi present` structural: no spec
84
+ # can count as content addressed without an ABI to scope it by.
85
+
86
+ def self.eligible?(spec, validate_ruby_abi: true)
87
+ return false unless platform_eligible?(spec.platform)
88
+ return true unless validate_ruby_abi
89
+
90
+ !ruby_abi_for(spec.required_ruby_version).nil?
91
+ end
92
+
93
+ ##
94
+ # Whether +spec+ is content-addressed: it is eligible for content
95
+ # addressing and has a valid content address set. See eligible? for
96
+ # when to pass <tt>validate_ruby_abi: false</tt>.
97
+
98
+ def self.content_addressed?(spec, validate_ruby_abi: true)
99
+ eligible?(spec, validate_ruby_abi: validate_ruby_abi) && match?(spec.content_address)
100
+ end
101
+
102
+ ##
103
+ # Whether an index row describes a content-addressed gem: an
104
+ # address-shaped +suffix+, a pinned +platform+, and a
105
+ # +required_ruby_version+ pinning a single Ruby ABI. Rows missing any
106
+ # of these must not assign a content address, so specs cannot be
107
+ # constructed half content-addressed. See eligible? for when to pass
108
+ # <tt>validate_ruby_abi: false</tt>.
109
+
110
+ def self.content_addressed_row?(suffix, platform, required_ruby_version = nil, validate_ruby_abi: true)
111
+ return false unless match?(suffix) && platform_eligible?(platform)
112
+ return true unless validate_ruby_abi
113
+
114
+ !ruby_abi_for(required_ruby_version).nil?
115
+ end
116
+
117
+ ##
118
+ # Whether +spec+'s required_ruby_version permits building for +ruby_abi+:
119
+ # an unset or default requirement can still be pinned to the ABI, and
120
+ # anything else must already pin exactly that ABI. Used at build time,
121
+ # before the requirement is injected, where eligible? would be
122
+ # premature.
123
+
124
+ def self.ruby_abi_compatible?(spec, ruby_abi)
125
+ required_ruby_version = spec.required_ruby_version
126
+ return true if required_ruby_version.nil? || required_ruby_version.none?
127
+
128
+ ruby_abi_for(required_ruby_version) == ruby_abi
129
+ end
130
+
131
+ ##
132
+ # Generates the content address for +bytes+: the first +length+
133
+ # characters of the hexadecimal SHA256 digest of the contents.
134
+
135
+ def self.address_for(bytes, length: DEFAULT_LENGTH)
136
+ require "digest"
137
+ Digest::SHA256.hexdigest(bytes)[0, length]
138
+ end
139
+
140
+ ##
141
+ # The content address claimed by a gem file name, or nil when the name
142
+ # makes no claim. +filename+ is the file's base name without the ".gem"
143
+ # extension ("name-version[-suffix]"). A name claims an address when its
144
+ # suffix is address-shaped and is not just +spec+'s own platform: a
145
+ # platform string that happens to look like hexadecimal (both
146
+ # normalized and original spellings) is a platform name, not a claim.
147
+
148
+ def self.file_name_claim(filename, spec)
149
+ suffix = filename.delete_prefix("#{spec.name}-#{spec.version}-")
150
+ return nil if suffix == filename
151
+ return nil unless match?(suffix)
152
+ return nil if [spec.platform.to_s, spec.original_platform.to_s].include?(suffix)
153
+
154
+ suffix
155
+ end
156
+
157
+ ##
158
+ # Verifies the content address claimed by the gem file at +path+ against
159
+ # the SHA256 digest of its contents. Returns the verified address, or nil
160
+ # when the file name makes no claim. Raises Gem::InstallError when the
161
+ # contents do not match the claim, regardless of whether the packaged
162
+ # +spec+ is eligible, so swapped contents cannot hide behind an
163
+ # ineligible specification.
164
+
165
+ def self.verified_file_name_claim(path, spec)
166
+ basename = File.basename(path, ".gem")
167
+ address = file_name_claim(basename, spec)
168
+ return nil unless address
169
+
170
+ require "digest"
171
+ digest = Digest::SHA256.file(path).hexdigest
172
+ unless digest.start_with?(address)
173
+ raise Gem::InstallError, "content address mismatch for #{File.basename(path)}"
174
+ end
175
+
176
+ address
177
+ end
178
+
179
+ ##
180
+ # Ranks +spec+ for candidate selection against +ruby_version+: a
181
+ # content-addressed spec built for that Ruby ranks first (0), any
182
+ # non-content-addressed spec next (1), and a content-addressed spec built
183
+ # for another Ruby last (2), since its binary cannot load there.
184
+
185
+ def self.ruby_abi_specificity_match(spec, ruby_version = Gem.ruby_version)
186
+ return 1 unless match?(spec.content_address)
187
+
188
+ if spec.required_ruby_version.satisfied_by?(ruby_version)
189
+ 0
190
+ else
191
+ 2
192
+ end
193
+ end
194
+ end