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
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cooldown_settings"
4
+ require_relative "user_interaction"
5
+
6
+ ##
7
+ # Applies a cooldown period to remote gem versions as a supply chain attack
8
+ # mitigation. When a cooldown of N days is configured, gem versions
9
+ # published within the last N days are not considered for installation or
10
+ # update. Versions whose publish time is unknown are never excluded, so
11
+ # sources that do not provide publish times keep working.
12
+ #
13
+ # The cooldown period comes from the <tt>--cooldown DAYS</tt> option when
14
+ # given, and 0 there disables the cooldown. Without the option the
15
+ # <tt>:cooldown:</tt> setting in the gemrc file and Bundler's own cooldown
16
+ # setting both apply and the longer of the two wins, so a 0 in either of them
17
+ # disables nothing while the other names a period.
18
+
19
+ class Gem::Cooldown
20
+ ##
21
+ # The cooldown period in days.
22
+
23
+ attr_reader :days
24
+
25
+ ##
26
+ # Creates a Cooldown from the command line +options+. The --cooldown
27
+ # option wins outright, so <tt>--cooldown 0</tt> bypasses the cooldown
28
+ # however the two tools are configured. Without it the :cooldown: gemrc
29
+ # setting and Bundler's cooldown setting are both read and the longer of
30
+ # the two applies, so a cooldown configured for only one of them still
31
+ # covers gem commands.
32
+
33
+ def self.from_options(options)
34
+ days = options[:cooldown]
35
+ return new(days) unless days.nil?
36
+
37
+ require_relative "bundler_settings"
38
+
39
+ new Gem::CooldownSettings.combine(warn_unless_valid(Gem.configuration.cooldown, "the gemrc file"),
40
+ warn_unless_valid(Gem::BundlerSettings["cooldown"], "Bundler's configuration"))
41
+ end
42
+
43
+ def initialize(days, now: Time.now)
44
+ invalid = Gem::CooldownSettings.invalid?(days)
45
+
46
+ @days = Gem::CooldownSettings.days(days) || 0
47
+ @now = now
48
+
49
+ Gem::Cooldown.warn_invalid_days(days, "the cooldown setting") if invalid
50
+ end
51
+
52
+ ##
53
+ # True when a cooldown period is configured.
54
+
55
+ def active?
56
+ @days > 0
57
+ end
58
+
59
+ ##
60
+ # True when a gem version published at +created_at+ must not be
61
+ # considered. Versions with an unknown publish time (+nil+) are kept.
62
+
63
+ def skip?(created_at)
64
+ return false unless active?
65
+ return false unless created_at
66
+
67
+ (@now - created_at) < @days * 86_400
68
+ end
69
+
70
+ ##
71
+ # Number of days until a gem version published at +created_at+ leaves
72
+ # the cooldown period, rounded up and at least 1.
73
+
74
+ def remaining_days(created_at)
75
+ remaining = @days * 86_400 - (@now - created_at)
76
+
77
+ [(remaining / 86_400.0).ceil, 1].max
78
+ end
79
+
80
+ ##
81
+ # Reports, per gem, the newest version the cooldown kept out of a
82
+ # completed installation or update. +entries+ are hashes with :name,
83
+ # :version, :resolved and :available_in_days keys; when several entries
84
+ # name the same gem only the newest version is shown.
85
+
86
+ def self.output_skipped_summary(entries)
87
+ return if entries.nil? || entries.empty?
88
+
89
+ newest = {}
90
+ entries.each do |entry|
91
+ current = newest[entry[:name]]
92
+ newest[entry[:name]] = entry if current.nil? || entry[:version] > current[:version]
93
+ end
94
+
95
+ ui = Gem::DefaultUserInteraction.ui
96
+ ui.say "The following gem versions were skipped by the cooldown setting:"
97
+ newest.values.sort_by {|entry| entry[:name] }.each do |entry|
98
+ days = entry[:available_in_days]
99
+ ui.say " * #{entry[:name]} #{entry[:version]} (available in #{days} #{days == 1 ? "day" : "days"}), resolved #{entry[:resolved]} instead"
100
+ end
101
+ end
102
+
103
+ # Matches an ISO 8601 time zone designator at the end of a timestamp.
104
+ TIME_ZONE_SUFFIX = /(?:Z|z|[+-]\d{2}(?::?\d{2})?)\z/ # :nodoc:
105
+ private_constant :TIME_ZONE_SUFFIX
106
+
107
+ # Matches the four-digit year an ISO 8601 timestamp starts with.
108
+ # Time.iso8601 also accepts a year of any length, and one far enough
109
+ # away overflows the Float arithmetic behind #remaining_days.
110
+ FOUR_DIGIT_YEAR = /\A\d{4}-/ # :nodoc:
111
+ private_constant :FOUR_DIGIT_YEAR
112
+
113
+ ##
114
+ # Parses a +created_at+ timestamp from the compact index. A timestamp
115
+ # without a time zone offset is read as UTC, because reading it as local
116
+ # time would shift the cooldown window by the environment's offset.
117
+ # Returns nil for anything unparsable, including a year outside four
118
+ # digits, so the cooldown fails open.
119
+
120
+ def self.parse_created_at(value)
121
+ return unless value.is_a?(String) && value.match?(FOUR_DIGIT_YEAR)
122
+
123
+ require "time"
124
+ begin
125
+ Time.iso8601(value.match?(TIME_ZONE_SUFFIX) ? value : "#{value}Z")
126
+ rescue ArgumentError
127
+ nil
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Warns once per process that +source+ did not provide publish times, so
133
+ # the cooldown cannot be applied to gems from it.
134
+
135
+ def self.warn_missing_created_at(source)
136
+ return if @warned
137
+ @warned = true
138
+
139
+ Gem::DefaultUserInteraction.ui.alert_warning \
140
+ "#{source.uri} does not provide gem publish times, the cooldown period does not apply to gems from this source"
141
+ end
142
+
143
+ def self.reset_warned_missing_created_at # :nodoc:
144
+ @warned = nil
145
+ end
146
+
147
+ # Returns +value+, warning first when it is configured but cannot be read
148
+ # as a number of days.
149
+
150
+ def self.warn_unless_valid(value, source) # :nodoc:
151
+ warn_invalid_days(value, source) if Gem::CooldownSettings.invalid?(value)
152
+
153
+ value
154
+ end
155
+
156
+ # Warns that a configured cooldown value cannot be read as a non-negative
157
+ # integer, so it does not apply. The --cooldown option is validated by the
158
+ # option parser; this catches the config file paths. Both the gemrc and
159
+ # Bundler settings feed one resolution, so each source gets its own warning
160
+ # rather than the first one silencing the other.
161
+
162
+ def self.warn_invalid_days(value, source) # :nodoc:
163
+ @warned_invalid_days ||= []
164
+ return if @warned_invalid_days.include?(source)
165
+ @warned_invalid_days << source
166
+
167
+ Gem::DefaultUserInteraction.ui.alert_warning Gem::CooldownSettings.invalid_message(value, source)
168
+ end
169
+
170
+ def self.reset_warned_invalid_days # :nodoc:
171
+ @warned_invalid_days = nil
172
+ end
173
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cooldown"
4
+
5
+ ##
6
+ # Mixin methods for the cooldown option for Gem::Commands.
7
+
8
+ module Gem::CooldownOption
9
+ ##
10
+ # Add the --cooldown option to the option parser.
11
+
12
+ def add_cooldown_option(group = nil)
13
+ args = [group, "--cooldown DAYS", Integer,
14
+ "Do not use gem versions published within",
15
+ "the last DAYS days (0 disables the cooldown,",
16
+ "overriding the gemrc and Bundler settings)"].compact
17
+
18
+ add_option(*args) do |value, options|
19
+ if value.negative?
20
+ raise Gem::OptionParser::InvalidArgument,
21
+ "#{value} (expected a non-negative integer number of days; use 0 to disable the cooldown)"
22
+ end
23
+
24
+ options[:cooldown] = value
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Skip reloading when an identical copy (e.g. the one shipped inside the Bundler
4
+ # gem) was already required from a different path, to avoid redefinition warnings.
5
+ return if defined?(Gem::CooldownSettings)
6
+
7
+ ##
8
+ # The rules RubyGems and Bundler share for reading a configured cooldown
9
+ # period. Bundler ships a copy of this file, so it deliberately has no
10
+ # requires: none of the rest of RubyGems is guaranteed to be around it.
11
+
12
+ module Gem::CooldownSettings
13
+ ##
14
+ # +value+ read as a number of days, or nil when it is absent or cannot be
15
+ # read as a non-negative integer. A gemrc entry and a Bundler config entry
16
+ # are both arbitrary YAML, so either can be any type at all.
17
+
18
+ def self.days(value)
19
+ return if value.nil?
20
+
21
+ # Base 10 explicitly: a leading zero is how a user writes a small number
22
+ # of days, not a request for octal.
23
+ days = Integer(value.to_s, 10, exception: false)
24
+
25
+ days if days && !days.negative?
26
+ end
27
+
28
+ ##
29
+ # True when +value+ is configured but cannot be read as a number of days.
30
+
31
+ def self.invalid?(value)
32
+ !value.nil? && days(value).nil?
33
+ end
34
+
35
+ ##
36
+ # The cooldown that applies when RubyGems and Bundler are configured
37
+ # separately: the longest of +values+, so a cooldown configured for only
38
+ # one of the two tools protects both. Returns nil when none of them is
39
+ # usable.
40
+ #
41
+ # A configured 0 takes part like any other value rather than switching the
42
+ # cooldown off, which leaves <tt>--cooldown 0</tt> as the way to bypass a
43
+ # cooldown that the other tool configures.
44
+
45
+ def self.combine(*values)
46
+ values.filter_map {|value| days(value) }.max
47
+ end
48
+
49
+ # +source+ names where the value came from, since RubyGems and Bundler now
50
+ # each read the other's setting and the same complaint from either of them
51
+ # is otherwise impossible to trace back to a file.
52
+
53
+ def self.invalid_message(value, source) # :nodoc:
54
+ "Invalid cooldown value #{value.inspect} in #{source}, so it is ignored. " \
55
+ "Expected a non-negative integer number of days."
56
+ end
57
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
6
+
7
+ ##
8
+ # Stores credentials in the Secret Service API (GNOME Keyring, KWallet,
9
+ # ...) via the +secret-tool+ command line tool from libsecret.
10
+
11
+ class Gem::CredentialStore::LinuxBackend
12
+ # secret-tool prints an item's attributes to stderr, one per line.
13
+ ACCOUNT_ATTRIBUTE = /^attribute\.account = (.*)$/
14
+ def self.available?
15
+ return @available if defined?(@available)
16
+
17
+ @available = ENV["PATH"].to_s.split(File::PATH_SEPARATOR).any? do |dir|
18
+ File.executable?(File.join(dir, "secret-tool"))
19
+ end
20
+ end
21
+
22
+ ##
23
+ # Clears the memoized #available? result. Intended for tests only.
24
+
25
+ def self.reset!
26
+ remove_instance_variable(:@available) if defined?(@available)
27
+ end
28
+
29
+ def self.get(service, account)
30
+ out, err, status = Open3.capture3(
31
+ "secret-tool", "lookup", "service", service, "account", account
32
+ )
33
+ # secret-tool exits 1 with nothing on stderr when the entry is simply
34
+ # absent. Anything else is a real failure.
35
+ unless status.success?
36
+ return nil if status.exitstatus == 1 && err.to_s.strip.empty?
37
+
38
+ raise "secret-tool exited with #{status.exitstatus}: #{err.strip}"
39
+ end
40
+
41
+ secret = out.chomp
42
+ secret.empty? ? nil : secret
43
+ end
44
+
45
+ def self.set(service, account, secret)
46
+ _out, status = Open3.capture2(
47
+ "secret-tool", "store", "--label=RubyGems", "service", service, "account", account,
48
+ stdin_data: secret
49
+ )
50
+ status.success?
51
+ end
52
+
53
+ # secret-tool writes attributes to stderr and secrets to stdout, so accounts
54
+ # are read from stderr. Discarding stdout also keeps a secret containing a
55
+ # newline from being mistaken for an attribute line.
56
+ def self.list(service)
57
+ _out, err, status = Open3.capture3(
58
+ "secret-tool", "search", "--all", "service", service
59
+ )
60
+ return [] unless status.success?
61
+
62
+ err.scan(ACCOUNT_ATTRIBUTE).flatten.uniq
63
+ end
64
+
65
+ def self.delete(service, account)
66
+ _out, err, status = Open3.capture3(
67
+ "secret-tool", "clear", "service", service, "account", account
68
+ )
69
+ return cleared?(service, account) if status.success?
70
+
71
+ # secret-tool clear exits 1 with no stderr when nothing matched.
72
+ status.exitstatus == 1 && err.to_s.strip.empty?
73
+ end
74
+
75
+ def self.delete_all(service)
76
+ _out, err, status = Open3.capture3(
77
+ "secret-tool", "clear", "service", service
78
+ )
79
+ return cleared?(service) if status.success?
80
+
81
+ status.exitstatus == 1 && err.to_s.strip.empty?
82
+ end
83
+
84
+ # libsecret clears only unlocked items and reports no error for the ones it
85
+ # skipped, so a locked keyring answers a clear with success while keeping
86
+ # every secret. search exits zero either way, so its output is the answer.
87
+ def self.cleared?(service, account = nil)
88
+ _out, err, status = Open3.capture3(
89
+ "secret-tool", "search", "--all", "service", service
90
+ )
91
+ return false unless status.success?
92
+
93
+ remaining = err.scan(ACCOUNT_ATTRIBUTE).flatten
94
+ account ? !remaining.include?(account) : remaining.empty?
95
+ end
96
+ private_class_method :cleared?
97
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
6
+
7
+ ##
8
+ # Stores credentials in the macOS Keychain via the +security+ command line
9
+ # tool. +security+ has no way to read a password from stdin as raw bytes
10
+ # for +add-generic-password+, so #set uses +security -i+ (batch/interactive
11
+ # mode, one tokenized command per stdin line) to keep the secret off argv
12
+ # and out of +ps+ output.
13
+ #
14
+ # A newline would start a second command in the +security -i+ batch, and
15
+ # +security find-generic-password -w+ prints any non-printable byte back as a
16
+ # hex string rather than the original value, so a non-ASCII secret would
17
+ # round-trip corrupted. Those are the limits Gem::CredentialStore#set enforces
18
+ # for every backend, so the caller falls back to file storage rather than
19
+ # storing something that cannot be read back.
20
+
21
+ class Gem::CredentialStore::MacOSBackend
22
+ NOT_FOUND_STATUS = 44
23
+
24
+ def self.get(service, account)
25
+ out, err, status = Open3.capture3(
26
+ "security", "find-generic-password", "-a", account, "-s", service, "-w"
27
+ )
28
+ # A locked keychain and an absent entry both yield no secret, but only the
29
+ # second one is ordinary.
30
+ unless status.success?
31
+ return nil if status.exitstatus == NOT_FOUND_STATUS
32
+
33
+ raise "security exited with #{status.exitstatus}: #{err.strip}"
34
+ end
35
+
36
+ secret = out.chomp
37
+ secret.empty? ? nil : secret
38
+ end
39
+
40
+ def self.set(service, account, secret)
41
+ command = "add-generic-password -U -a #{quote(account)} -s #{quote(service)} -w #{quote(secret)}\n"
42
+ _out, err, status = Open3.capture3("security", "-i", stdin_data: command)
43
+ return true if status.success?
44
+
45
+ # Raise rather than return false so the reason reaches the user. The
46
+ # wrapper turns it back into false after reporting it.
47
+ raise "security exited with #{status.exitstatus}: #{err.strip}"
48
+ end
49
+
50
+ # security has no "list by service" subcommand, so this reads the dump, which
51
+ # never reports the secrets.
52
+ def self.list(service)
53
+ out, status = Open3.capture2("security", "dump-keychain", err: File::NULL)
54
+ return [] unless status.success?
55
+
56
+ out.split(/^keychain: /).filter_map do |entry|
57
+ next unless entry[/^\s*"svce"<blob>="(.*)"$/, 1] == service
58
+
59
+ entry[/^\s*"acct"<blob>="(.*)"$/, 1]
60
+ end.uniq
61
+ end
62
+
63
+ def self.delete(service, account)
64
+ _out, status = Open3.capture2(
65
+ "security", "delete-generic-password", "-a", account, "-s", service,
66
+ err: File::NULL
67
+ )
68
+ status.success? || status.exitstatus == NOT_FOUND_STATUS
69
+ end
70
+
71
+ # security deletes one entry per call, so keep going until it reports there
72
+ # is nothing left (exit 44). Other services are untouched.
73
+ def self.delete_all(service)
74
+ loop do
75
+ _out, status = Open3.capture2(
76
+ "security", "delete-generic-password", "-s", service,
77
+ err: File::NULL
78
+ )
79
+ return true if status.exitstatus == NOT_FOUND_STATUS
80
+ return false unless status.success?
81
+ end
82
+ end
83
+
84
+ def self.quote(value)
85
+ %("#{value.gsub("\\", "\\\\\\\\").gsub('"', '\\"')}")
86
+ end
87
+ private_class_method :quote
88
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ class Gem::CredentialStore; end unless defined?(Gem::CredentialStore)
6
+
7
+ ##
8
+ # Stores credentials in the Windows Credential Manager via the
9
+ # +Windows.Security.Credentials.PasswordVault+ WinRT API, driven from
10
+ # PowerShell. Account/service/secret values are passed as environment
11
+ # variables rather than interpolated into the script text, so no quoting
12
+ # scheme is needed and values cannot break out of the script.
13
+ #
14
+ # Windows PowerShell is used rather than PowerShell 7 (+pwsh+) because the
15
+ # WinRT projection used here is not reliably available under pwsh. It is
16
+ # spawned as +powershell+ rather than +powershell.exe+, the way this codebase
17
+ # spawns +git+, so PATHEXT resolves it. That also lets the tests put a shim
18
+ # ahead of it on Windows, where a file with a shebang is not executable.
19
+
20
+ class Gem::CredentialStore::WindowsBackend
21
+ LOAD_VAULT_TYPE = <<~POWERSHELL
22
+ $ErrorActionPreference = 'Stop'
23
+ [void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
24
+ POWERSHELL
25
+ private_constant :LOAD_VAULT_TYPE
26
+
27
+ def self.get(service, account)
28
+ script = <<~POWERSHELL
29
+ #{LOAD_VAULT_TYPE}
30
+ $vault = New-Object Windows.Security.Credentials.PasswordVault
31
+ $credential = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
32
+ # Emitting into the pipeline would send the string through PowerShell's
33
+ # formatter, which wraps at the host width and would corrupt a secret.
34
+ [Console]::Out.Write($credential.Password)
35
+ POWERSHELL
36
+
37
+ out, err, status = run(script, service, account)
38
+ # An absent credential is ordinary. Any other failure is not, so raise and
39
+ # let the wrapper report why rather than authenticating without one.
40
+ unless status.success?
41
+ return nil if missing_credential?(err)
42
+
43
+ raise "powershell exited with #{status.exitstatus}: #{err.strip}"
44
+ end
45
+
46
+ secret = out.chomp
47
+ secret.empty? ? nil : secret
48
+ end
49
+
50
+ def self.set(service, account, secret)
51
+ script = <<~POWERSHELL
52
+ #{LOAD_VAULT_TYPE}
53
+ $vault = New-Object Windows.Security.Credentials.PasswordVault
54
+ try {
55
+ $existing = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
56
+ $vault.Remove($existing)
57
+ } catch {}
58
+ $credential = New-Object Windows.Security.Credentials.PasswordCredential($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT, $env:RUBYGEMS_CRED_SECRET)
59
+ $vault.Add($credential)
60
+ POWERSHELL
61
+
62
+ _out, err, status = run(script, service, account, secret)
63
+ return true if status.success?
64
+
65
+ # Raise so the reason reaches the user; see MacOSBackend.set.
66
+ raise "powershell exited with #{status.exitstatus}: #{err.strip}"
67
+ end
68
+
69
+ def self.delete(service, account)
70
+ script = <<~POWERSHELL
71
+ #{LOAD_VAULT_TYPE}
72
+ $vault = New-Object Windows.Security.Credentials.PasswordVault
73
+ $credential = $vault.Retrieve($env:RUBYGEMS_CRED_SERVICE, $env:RUBYGEMS_CRED_ACCOUNT)
74
+ $vault.Remove($credential)
75
+ POWERSHELL
76
+
77
+ _out, err, status = run(script, service, account)
78
+ status.success? || missing_credential?(err)
79
+ end
80
+
81
+ # FindAllByResource raises when the resource has no entries, which is an
82
+ # empty list rather than an error.
83
+ def self.list(service)
84
+ script = <<~POWERSHELL
85
+ #{LOAD_VAULT_TYPE}
86
+ $vault = New-Object Windows.Security.Credentials.PasswordVault
87
+ try {
88
+ $vault.FindAllByResource($env:RUBYGEMS_CRED_SERVICE) | ForEach-Object {
89
+ [Console]::Out.WriteLine($_.UserName)
90
+ }
91
+ } catch {
92
+ if (-not ($_.Exception.Message -match 'not found|0x80070490')) { throw }
93
+ }
94
+ POWERSHELL
95
+
96
+ out, _err, status = run(script, service, nil)
97
+ return [] unless status.success?
98
+
99
+ out.split("\n").map(&:chomp).reject(&:empty?).uniq
100
+ end
101
+
102
+ def self.delete_all(service)
103
+ script = <<~POWERSHELL
104
+ #{LOAD_VAULT_TYPE}
105
+ $vault = New-Object Windows.Security.Credentials.PasswordVault
106
+ try {
107
+ $vault.FindAllByResource($env:RUBYGEMS_CRED_SERVICE) | ForEach-Object { $vault.Remove($_) }
108
+ } catch {
109
+ if (-not ($_.Exception.Message -match 'not found|0x80070490')) { throw }
110
+ }
111
+ POWERSHELL
112
+
113
+ _out, err, status = run(script, service, nil)
114
+ status.success? || missing_credential?(err)
115
+ end
116
+
117
+ def self.run(script, service, account, secret = nil)
118
+ env = { "RUBYGEMS_CRED_SERVICE" => service, "RUBYGEMS_CRED_ACCOUNT" => account }
119
+ env["RUBYGEMS_CRED_SECRET"] = secret if secret
120
+
121
+ Open3.capture3(env, "powershell", "-NoProfile", "-NonInteractive", "-Command", "-", stdin_data: script)
122
+ end
123
+ private_class_method :run
124
+
125
+ def self.missing_credential?(message)
126
+ text = message.to_s.downcase
127
+ text.include?("element not found") || text.include?("0x80070490") || text.include?("could not be found")
128
+ end
129
+ private_class_method :missing_credential?
130
+ end