rubygems-update 3.3.18 → 3.4.19

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 (615) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1429 -1064
  3. data/CONTRIBUTING.md +31 -8
  4. data/Manifest.txt +61 -36
  5. data/POLICIES.md +55 -20
  6. data/README.md +19 -6
  7. data/bundler/CHANGELOG.md +457 -1
  8. data/bundler/README.md +3 -6
  9. data/bundler/UPGRADING.md +11 -4
  10. data/bundler/bundler.gemspec +8 -10
  11. data/bundler/exe/bundle +5 -16
  12. data/bundler/lib/bundler/build_metadata.rb +2 -2
  13. data/bundler/lib/bundler/cli/add.rb +1 -1
  14. data/bundler/lib/bundler/cli/binstubs.rb +6 -2
  15. data/bundler/lib/bundler/cli/check.rb +1 -1
  16. data/bundler/lib/bundler/cli/common.rb +2 -0
  17. data/bundler/lib/bundler/cli/console.rb +2 -2
  18. data/bundler/lib/bundler/cli/doctor.rb +4 -6
  19. data/bundler/lib/bundler/cli/gem.rb +62 -40
  20. data/bundler/lib/bundler/cli/info.rb +1 -1
  21. data/bundler/lib/bundler/cli/init.rb +6 -2
  22. data/bundler/lib/bundler/cli/install.rb +8 -6
  23. data/bundler/lib/bundler/cli/lock.rb +8 -5
  24. data/bundler/lib/bundler/cli/open.rb +6 -4
  25. data/bundler/lib/bundler/cli/outdated.rb +14 -7
  26. data/bundler/lib/bundler/cli/platform.rb +7 -5
  27. data/bundler/lib/bundler/cli/viz.rb +1 -1
  28. data/bundler/lib/bundler/cli.rb +53 -7
  29. data/bundler/lib/bundler/compact_index_client/cache.rb +1 -1
  30. data/bundler/lib/bundler/compact_index_client/updater.rb +40 -39
  31. data/bundler/lib/bundler/constants.rb +1 -1
  32. data/bundler/lib/bundler/current_ruby.rb +16 -5
  33. data/bundler/lib/bundler/definition.rb +262 -133
  34. data/bundler/lib/bundler/dependency.rb +20 -86
  35. data/bundler/lib/bundler/digest.rb +1 -1
  36. data/bundler/lib/bundler/dsl.rb +6 -7
  37. data/bundler/lib/bundler/endpoint_specification.rb +2 -13
  38. data/bundler/lib/bundler/env.rb +2 -2
  39. data/bundler/lib/bundler/environment_preserver.rb +3 -2
  40. data/bundler/lib/bundler/errors.rb +1 -11
  41. data/bundler/lib/bundler/feature_flag.rb +0 -2
  42. data/bundler/lib/bundler/fetcher/compact_index.rb +11 -13
  43. data/bundler/lib/bundler/fetcher/dependency.rb +2 -6
  44. data/bundler/lib/bundler/fetcher/downloader.rb +4 -5
  45. data/bundler/lib/bundler/fetcher/index.rb +1 -2
  46. data/bundler/lib/bundler/fetcher.rb +21 -15
  47. data/bundler/lib/bundler/force_platform.rb +18 -0
  48. data/bundler/lib/bundler/friendly_errors.rb +1 -4
  49. data/bundler/lib/bundler/gem_helper.rb +3 -4
  50. data/bundler/lib/bundler/gem_helpers.rb +7 -2
  51. data/bundler/lib/bundler/gem_version_promoter.rb +53 -98
  52. data/bundler/lib/bundler/graph.rb +3 -3
  53. data/bundler/lib/bundler/index.rb +13 -47
  54. data/bundler/lib/bundler/injector.rb +5 -4
  55. data/bundler/lib/bundler/inline.rb +9 -11
  56. data/bundler/lib/bundler/installer/parallel_installer.rb +4 -34
  57. data/bundler/lib/bundler/installer/standalone.rb +13 -9
  58. data/bundler/lib/bundler/installer.rb +17 -29
  59. data/bundler/lib/bundler/lazy_specification.rb +54 -53
  60. data/bundler/lib/bundler/lockfile_generator.rb +3 -3
  61. data/bundler/lib/bundler/lockfile_parser.rb +17 -16
  62. data/bundler/lib/bundler/man/bundle-add.1 +6 -2
  63. data/bundler/lib/bundler/man/bundle-add.1.ronn +4 -1
  64. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  65. data/bundler/lib/bundler/man/bundle-cache.1 +9 -3
  66. data/bundler/lib/bundler/man/bundle-cache.1.ronn +9 -2
  67. data/bundler/lib/bundler/man/bundle-check.1 +1 -1
  68. data/bundler/lib/bundler/man/bundle-clean.1 +2 -2
  69. data/bundler/lib/bundler/man/bundle-clean.1.ronn +1 -1
  70. data/bundler/lib/bundler/man/bundle-config.1 +26 -10
  71. data/bundler/lib/bundler/man/bundle-config.1.ronn +17 -10
  72. data/bundler/lib/bundler/man/bundle-console.1 +53 -0
  73. data/bundler/lib/bundler/man/bundle-console.1.ronn +44 -0
  74. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  75. data/bundler/lib/bundler/man/bundle-exec.1 +6 -6
  76. data/bundler/lib/bundler/man/bundle-exec.1.ronn +6 -6
  77. data/bundler/lib/bundler/man/bundle-gem.1 +27 -37
  78. data/bundler/lib/bundler/man/bundle-gem.1.ronn +5 -5
  79. data/bundler/lib/bundler/man/bundle-help.1 +13 -0
  80. data/bundler/lib/bundler/man/bundle-help.1.ronn +12 -0
  81. data/bundler/lib/bundler/man/bundle-info.1 +3 -3
  82. data/bundler/lib/bundler/man/bundle-info.1.ronn +3 -3
  83. data/bundler/lib/bundler/man/bundle-init.1 +5 -1
  84. data/bundler/lib/bundler/man/bundle-init.1.ronn +2 -0
  85. data/bundler/lib/bundler/man/bundle-inject.1 +5 -2
  86. data/bundler/lib/bundler/man/bundle-inject.1.ronn +3 -1
  87. data/bundler/lib/bundler/man/bundle-install.1 +5 -30
  88. data/bundler/lib/bundler/man/bundle-install.1.ronn +6 -29
  89. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  90. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  91. data/bundler/lib/bundler/man/bundle-open.1 +22 -2
  92. data/bundler/lib/bundler/man/bundle-open.1.ronn +9 -1
  93. data/bundler/lib/bundler/man/bundle-outdated.1 +13 -9
  94. data/bundler/lib/bundler/man/bundle-outdated.1.ronn +12 -9
  95. data/bundler/lib/bundler/man/bundle-platform.1 +16 -6
  96. data/bundler/lib/bundler/man/bundle-platform.1.ronn +14 -7
  97. data/bundler/lib/bundler/man/bundle-plugin.1 +81 -0
  98. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +59 -0
  99. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  100. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  101. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  102. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  103. data/bundler/lib/bundler/man/bundle-version.1 +35 -0
  104. data/bundler/lib/bundler/man/bundle-version.1.ronn +24 -0
  105. data/bundler/lib/bundler/man/bundle-viz.1 +4 -1
  106. data/bundler/lib/bundler/man/bundle-viz.1.ronn +2 -0
  107. data/bundler/lib/bundler/man/bundle.1 +15 -10
  108. data/bundler/lib/bundler/man/bundle.1.ronn +12 -7
  109. data/bundler/lib/bundler/man/gemfile.5 +55 -55
  110. data/bundler/lib/bundler/man/gemfile.5.ronn +57 -53
  111. data/bundler/lib/bundler/man/index.txt +4 -0
  112. data/bundler/lib/bundler/match_metadata.rb +13 -0
  113. data/bundler/lib/bundler/match_remote_metadata.rb +29 -0
  114. data/bundler/lib/bundler/mirror.rb +5 -7
  115. data/bundler/lib/bundler/plugin/index.rb +5 -5
  116. data/bundler/lib/bundler/plugin/installer/rubygems.rb +0 -4
  117. data/bundler/lib/bundler/plugin/installer.rb +5 -2
  118. data/bundler/lib/bundler/plugin.rb +3 -1
  119. data/bundler/lib/bundler/remote_specification.rb +7 -12
  120. data/bundler/lib/bundler/resolver/base.rb +107 -0
  121. data/bundler/lib/bundler/resolver/candidate.rb +94 -0
  122. data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
  123. data/bundler/lib/bundler/resolver/package.rb +72 -0
  124. data/bundler/lib/bundler/resolver/root.rb +25 -0
  125. data/bundler/lib/bundler/resolver/spec_group.rb +42 -71
  126. data/bundler/lib/bundler/resolver.rb +335 -328
  127. data/bundler/lib/bundler/ruby_dsl.rb +7 -1
  128. data/bundler/lib/bundler/ruby_version.rb +8 -8
  129. data/bundler/lib/bundler/rubygems_ext.rb +100 -9
  130. data/bundler/lib/bundler/rubygems_gem_installer.rb +23 -14
  131. data/bundler/lib/bundler/rubygems_integration.rb +11 -15
  132. data/bundler/lib/bundler/runtime.rb +2 -6
  133. data/bundler/lib/bundler/safe_marshal.rb +31 -0
  134. data/bundler/lib/bundler/settings.rb +5 -11
  135. data/bundler/lib/bundler/setup.rb +4 -1
  136. data/bundler/lib/bundler/shared_helpers.rb +3 -3
  137. data/bundler/lib/bundler/source/git/git_proxy.rb +237 -74
  138. data/bundler/lib/bundler/source/git.rb +55 -30
  139. data/bundler/lib/bundler/source/metadata.rb +1 -2
  140. data/bundler/lib/bundler/source/path/installer.rb +1 -22
  141. data/bundler/lib/bundler/source/path.rb +6 -6
  142. data/bundler/lib/bundler/source/rubygems.rb +26 -81
  143. data/bundler/lib/bundler/source.rb +1 -1
  144. data/bundler/lib/bundler/source_list.rb +8 -2
  145. data/bundler/lib/bundler/spec_set.rb +60 -37
  146. data/bundler/lib/bundler/templates/Executable +1 -1
  147. data/bundler/lib/bundler/templates/Executable.bundler +5 -10
  148. data/bundler/lib/bundler/templates/Executable.standalone +2 -0
  149. data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  150. data/bundler/lib/bundler/templates/newgem/Gemfile.tt +3 -0
  151. data/bundler/lib/bundler/templates/newgem/README.md.tt +6 -4
  152. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +12 -1
  153. data/bundler/lib/bundler/templates/newgem/bin/console.tt +0 -4
  154. data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  155. data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  156. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt +10 -0
  157. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  158. data/bundler/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +1 -1
  159. data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  160. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +10 -0
  161. data/bundler/lib/bundler/templates/newgem/gitignore.tt +3 -0
  162. data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +13 -4
  163. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +9 -2
  164. data/bundler/lib/bundler/ui/rg_proxy.rb +1 -1
  165. data/bundler/lib/bundler/ui/shell.rb +35 -12
  166. data/bundler/lib/bundler/ui/silent.rb +21 -5
  167. data/bundler/lib/bundler/uri_normalizer.rb +23 -0
  168. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
  169. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
  170. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +3 -1
  171. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1351 -409
  172. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  173. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  174. data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  175. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  176. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  177. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  178. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +150 -0
  179. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  180. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  181. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  182. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  183. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +60 -0
  184. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  185. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  186. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +129 -0
  187. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +411 -0
  188. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +248 -0
  189. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  190. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  191. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +1 -1
  192. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +64 -16
  193. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
  194. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -1
  195. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +27 -7
  196. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
  197. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
  198. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  199. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  200. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
  201. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +15 -9
  202. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +11 -6
  203. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  204. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
  205. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
  206. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +3 -2
  207. data/bundler/lib/bundler/vendored_persistent.rb +1 -33
  208. data/bundler/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
  209. data/bundler/lib/bundler/version.rb +5 -1
  210. data/bundler/lib/bundler/worker.rb +5 -7
  211. data/bundler/lib/bundler.rb +25 -77
  212. data/{bin → exe}/gem +4 -5
  213. data/{bin → exe}/update_rubygems +12 -10
  214. data/lib/rubygems/available_set.rb +4 -3
  215. data/lib/rubygems/basic_specification.rb +5 -4
  216. data/lib/rubygems/bundler_version_finder.rb +2 -2
  217. data/lib/rubygems/command.rb +41 -32
  218. data/lib/rubygems/command_manager.rb +30 -15
  219. data/lib/rubygems/commands/build_command.rb +12 -8
  220. data/lib/rubygems/commands/cert_command.rb +34 -33
  221. data/lib/rubygems/commands/check_command.rb +21 -20
  222. data/lib/rubygems/commands/cleanup_command.rb +18 -17
  223. data/lib/rubygems/commands/contents_command.rb +14 -13
  224. data/lib/rubygems/commands/dependency_command.rb +17 -16
  225. data/lib/rubygems/commands/environment_command.rb +6 -5
  226. data/lib/rubygems/commands/exec_command.rb +249 -0
  227. data/lib/rubygems/commands/fetch_command.rb +10 -9
  228. data/lib/rubygems/commands/generate_index_command.rb +18 -17
  229. data/lib/rubygems/commands/help_command.rb +7 -6
  230. data/lib/rubygems/commands/info_command.rb +3 -3
  231. data/lib/rubygems/commands/install_command.rb +28 -23
  232. data/lib/rubygems/commands/list_command.rb +4 -3
  233. data/lib/rubygems/commands/lock_command.rb +5 -4
  234. data/lib/rubygems/commands/mirror_command.rb +4 -3
  235. data/lib/rubygems/commands/open_command.rb +10 -9
  236. data/lib/rubygems/commands/outdated_command.rb +6 -5
  237. data/lib/rubygems/commands/owner_command.rb +17 -14
  238. data/lib/rubygems/commands/pristine_command.rb +46 -36
  239. data/lib/rubygems/commands/push_command.rb +9 -8
  240. data/lib/rubygems/commands/query_command.rb +9 -8
  241. data/lib/rubygems/commands/rdoc_command.rb +21 -19
  242. data/lib/rubygems/commands/search_command.rb +4 -3
  243. data/lib/rubygems/commands/server_command.rb +4 -3
  244. data/lib/rubygems/commands/setup_command.rb +97 -106
  245. data/lib/rubygems/commands/signin_command.rb +10 -9
  246. data/lib/rubygems/commands/signout_command.rb +8 -7
  247. data/lib/rubygems/commands/sources_command.rb +22 -21
  248. data/lib/rubygems/commands/specification_command.rb +14 -13
  249. data/lib/rubygems/commands/stale_command.rb +3 -2
  250. data/lib/rubygems/commands/uninstall_command.rb +44 -40
  251. data/lib/rubygems/commands/unpack_command.rb +14 -13
  252. data/lib/rubygems/commands/update_command.rb +42 -63
  253. data/lib/rubygems/commands/which_command.rb +8 -7
  254. data/lib/rubygems/commands/yank_command.rb +12 -11
  255. data/lib/rubygems/config_file.rb +55 -21
  256. data/lib/rubygems/core_ext/kernel_gem.rb +1 -6
  257. data/lib/rubygems/core_ext/kernel_require.rb +109 -115
  258. data/lib/rubygems/core_ext/kernel_warn.rb +33 -37
  259. data/lib/rubygems/core_ext/tcpsocket_init.rb +3 -1
  260. data/lib/rubygems/defaults.rb +33 -18
  261. data/lib/rubygems/dependency.rb +15 -11
  262. data/lib/rubygems/dependency_installer.rb +38 -37
  263. data/lib/rubygems/dependency_list.rb +7 -6
  264. data/lib/rubygems/deprecate.rb +3 -2
  265. data/lib/rubygems/doctor.rb +19 -18
  266. data/lib/rubygems/errors.rb +3 -2
  267. data/lib/rubygems/exceptions.rb +16 -8
  268. data/lib/rubygems/ext/build_error.rb +2 -1
  269. data/lib/rubygems/ext/builder.rb +37 -21
  270. data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +9 -5
  271. data/lib/rubygems/ext/cargo_builder.rb +150 -111
  272. data/lib/rubygems/ext/cmake_builder.rb +2 -2
  273. data/lib/rubygems/ext/configure_builder.rb +2 -1
  274. data/lib/rubygems/ext/ext_conf_builder.rb +11 -9
  275. data/lib/rubygems/ext/rake_builder.rb +7 -5
  276. data/lib/rubygems/ext.rb +8 -7
  277. data/lib/rubygems/gem_runner.rb +6 -5
  278. data/lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb +163 -0
  279. data/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +105 -0
  280. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +78 -0
  281. data/lib/rubygems/gemcutter_utilities.rb +90 -34
  282. data/lib/rubygems/indexer.rb +29 -28
  283. data/lib/rubygems/install_default_message.rb +3 -2
  284. data/lib/rubygems/install_message.rb +3 -2
  285. data/lib/rubygems/install_update_options.rb +56 -55
  286. data/lib/rubygems/installer.rb +54 -46
  287. data/lib/rubygems/installer_uninstaller_utils.rb +2 -2
  288. data/lib/rubygems/local_remote_options.rb +19 -20
  289. data/lib/rubygems/mock_gem_ui.rb +3 -2
  290. data/lib/rubygems/name_tuple.rb +5 -4
  291. data/lib/rubygems/optparse/lib/optparse.rb +20 -15
  292. data/lib/rubygems/optparse.rb +1 -1
  293. data/lib/rubygems/package/digest_io.rb +1 -0
  294. data/lib/rubygems/package/file_source.rb +3 -2
  295. data/lib/rubygems/package/io_source.rb +1 -0
  296. data/lib/rubygems/package/old.rb +9 -8
  297. data/lib/rubygems/package/source.rb +1 -0
  298. data/lib/rubygems/package/tar_header.rb +63 -62
  299. data/lib/rubygems/package/tar_reader/entry.rb +91 -9
  300. data/lib/rubygems/package/tar_reader.rb +2 -29
  301. data/lib/rubygems/package/tar_writer.rb +8 -7
  302. data/lib/rubygems/package.rb +64 -48
  303. data/lib/rubygems/package_task.rb +5 -4
  304. data/lib/rubygems/path_support.rb +1 -0
  305. data/lib/rubygems/platform.rb +79 -53
  306. data/lib/rubygems/psych_tree.rb +2 -1
  307. data/lib/rubygems/query_utils.rb +35 -35
  308. data/lib/rubygems/rdoc.rb +3 -2
  309. data/lib/rubygems/remote_fetcher.rb +23 -22
  310. data/lib/rubygems/request/connection_pools.rb +4 -4
  311. data/lib/rubygems/request/http_pool.rb +2 -1
  312. data/lib/rubygems/request/https_pool.rb +1 -0
  313. data/lib/rubygems/request.rb +23 -22
  314. data/lib/rubygems/request_set/gem_dependency_api.rb +123 -123
  315. data/lib/rubygems/request_set/lockfile/parser.rb +28 -27
  316. data/lib/rubygems/request_set/lockfile/tokenizer.rb +5 -3
  317. data/lib/rubygems/request_set/lockfile.rb +6 -5
  318. data/lib/rubygems/request_set.rb +20 -19
  319. data/lib/rubygems/requirement.rb +15 -14
  320. data/lib/rubygems/resolver/activation_request.rb +4 -3
  321. data/lib/rubygems/resolver/api_set.rb +5 -4
  322. data/lib/rubygems/resolver/api_specification.rb +7 -6
  323. data/lib/rubygems/resolver/best_set.rb +6 -5
  324. data/lib/rubygems/resolver/composed_set.rb +1 -0
  325. data/lib/rubygems/resolver/conflict.rb +11 -10
  326. data/lib/rubygems/resolver/current_set.rb +1 -0
  327. data/lib/rubygems/resolver/dependency_request.rb +3 -2
  328. data/lib/rubygems/resolver/git_set.rb +3 -2
  329. data/lib/rubygems/resolver/git_specification.rb +7 -6
  330. data/lib/rubygems/resolver/index_set.rb +4 -3
  331. data/lib/rubygems/resolver/index_specification.rb +7 -5
  332. data/lib/rubygems/resolver/installed_specification.rb +5 -4
  333. data/lib/rubygems/resolver/installer_set.rb +15 -17
  334. data/lib/rubygems/resolver/local_specification.rb +3 -2
  335. data/lib/rubygems/resolver/lock_set.rb +5 -4
  336. data/lib/rubygems/resolver/lock_specification.rb +5 -4
  337. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +1 -1
  338. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +32 -26
  339. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  340. data/lib/rubygems/resolver/molinillo.rb +2 -1
  341. data/lib/rubygems/resolver/requirement_list.rb +1 -0
  342. data/lib/rubygems/resolver/set.rb +1 -0
  343. data/lib/rubygems/resolver/source_set.rb +2 -0
  344. data/lib/rubygems/resolver/spec_specification.rb +1 -0
  345. data/lib/rubygems/resolver/specification.rb +2 -1
  346. data/lib/rubygems/resolver/stats.rb +2 -1
  347. data/lib/rubygems/resolver/vendor_set.rb +2 -1
  348. data/lib/rubygems/resolver/vendor_specification.rb +4 -3
  349. data/lib/rubygems/resolver.rb +41 -40
  350. data/lib/rubygems/s3_uri_signer.rb +10 -8
  351. data/lib/rubygems/safe_yaml.rb +4 -2
  352. data/lib/rubygems/security/policies.rb +48 -47
  353. data/lib/rubygems/security/policy.rb +19 -18
  354. data/lib/rubygems/security/signer.rb +6 -5
  355. data/lib/rubygems/security/trust_dir.rb +5 -4
  356. data/lib/rubygems/security.rb +30 -42
  357. data/lib/rubygems/security_option.rb +6 -5
  358. data/lib/rubygems/shellwords.rb +3 -0
  359. data/lib/rubygems/source/git.rb +22 -22
  360. data/lib/rubygems/source/installed.rb +2 -1
  361. data/lib/rubygems/source/local.rb +3 -2
  362. data/lib/rubygems/source/lock.rb +1 -0
  363. data/lib/rubygems/source/specific_file.rb +2 -1
  364. data/lib/rubygems/source/vendor.rb +1 -0
  365. data/lib/rubygems/source.rb +16 -16
  366. data/lib/rubygems/spec_fetcher.rb +10 -9
  367. data/lib/rubygems/specification.rb +121 -114
  368. data/lib/rubygems/specification_policy.rb +36 -15
  369. data/lib/rubygems/stub_specification.rb +11 -9
  370. data/lib/rubygems/text.rb +2 -2
  371. data/lib/rubygems/tsort/lib/tsort.rb +308 -310
  372. data/lib/rubygems/tsort.rb +1 -1
  373. data/lib/rubygems/uninstaller.rb +19 -18
  374. data/lib/rubygems/update_suggestion.rb +69 -0
  375. data/lib/rubygems/uri.rb +4 -4
  376. data/lib/rubygems/uri_formatter.rb +1 -1
  377. data/lib/rubygems/user_interaction.rb +37 -21
  378. data/lib/rubygems/util/licenses.rb +4 -3
  379. data/lib/rubygems/util/list.rb +1 -0
  380. data/lib/rubygems/util.rb +12 -15
  381. data/lib/rubygems/validator.rb +7 -6
  382. data/lib/rubygems/version.rb +17 -11
  383. data/lib/rubygems/version_option.rb +4 -3
  384. data/lib/rubygems.rb +89 -68
  385. data/rubygems-update.gemspec +10 -8
  386. data/setup.rb +10 -9
  387. data/test/rubygems/alternate_cert.pem +14 -14
  388. data/test/rubygems/alternate_cert_32.pem +15 -15
  389. data/test/rubygems/alternate_key.pem +25 -25
  390. data/test/rubygems/bad_rake.rb +1 -0
  391. data/test/rubygems/bundler_test_gem.rb +421 -0
  392. data/test/rubygems/child_cert.pem +15 -16
  393. data/test/rubygems/child_cert_32.pem +15 -16
  394. data/test/rubygems/child_key.pem +25 -25
  395. data/test/rubygems/encrypted_private_key.pem +26 -26
  396. data/test/rubygems/expired_cert.pem +15 -15
  397. data/test/rubygems/fake_certlib/openssl.rb +1 -0
  398. data/test/rubygems/future_cert.pem +15 -15
  399. data/test/rubygems/future_cert_32.pem +15 -15
  400. data/test/rubygems/good_rake.rb +1 -0
  401. data/test/rubygems/grandchild_cert.pem +15 -16
  402. data/test/rubygems/grandchild_cert_32.pem +15 -16
  403. data/test/rubygems/grandchild_key.pem +25 -25
  404. data/test/rubygems/helper.rb +172 -151
  405. data/test/rubygems/installer_test_case.rb +14 -13
  406. data/test/rubygems/invalid_issuer_cert.pem +16 -16
  407. data/test/rubygems/invalid_issuer_cert_32.pem +16 -16
  408. data/test/rubygems/invalid_key.pem +25 -25
  409. data/test/rubygems/invalid_signer_cert.pem +15 -15
  410. data/test/rubygems/invalid_signer_cert_32.pem +15 -15
  411. data/test/rubygems/invalidchild_cert.pem +15 -16
  412. data/test/rubygems/invalidchild_cert_32.pem +15 -16
  413. data/test/rubygems/invalidchild_key.pem +25 -25
  414. data/test/rubygems/multifactor_auth_utilities.rb +111 -0
  415. data/test/rubygems/package/tar_test_case.rb +53 -17
  416. data/test/rubygems/packages/Bluebie-legs-0.6.2.gem +0 -0
  417. data/test/rubygems/plugin/exception/rubygems_plugin.rb +2 -1
  418. data/test/rubygems/plugin/load/rubygems_plugin.rb +1 -0
  419. data/test/rubygems/plugin/standarderror/rubygems_plugin.rb +2 -1
  420. data/test/rubygems/private_key.pem +25 -25
  421. data/test/rubygems/public_cert.pem +16 -16
  422. data/test/rubygems/public_cert_32.pem +15 -15
  423. data/test/rubygems/public_key.pem +7 -7
  424. data/test/rubygems/rubygems/commands/crash_command.rb +1 -0
  425. data/test/rubygems/rubygems_plugin.rb +3 -2
  426. data/test/rubygems/simple_gem.rb +2 -1
  427. data/test/rubygems/specifications/bar-0.0.2.gemspec +2 -0
  428. data/test/rubygems/specifications/rubyforge-0.0.1.gemspec +6 -4
  429. data/test/rubygems/test_bundled_ca.rb +13 -12
  430. data/test/rubygems/test_config.rb +5 -4
  431. data/test/rubygems/test_deprecate.rb +5 -4
  432. data/test/rubygems/test_exit.rb +9 -3
  433. data/test/rubygems/test_gem.rb +339 -677
  434. data/test/rubygems/test_gem_available_set.rb +22 -21
  435. data/test/rubygems/test_gem_bundler_version_finder.rb +6 -4
  436. data/test/rubygems/test_gem_command.rb +45 -44
  437. data/test/rubygems/test_gem_command_manager.rb +96 -30
  438. data/test/rubygems/test_gem_commands_build_command.rb +74 -63
  439. data/test/rubygems/test_gem_commands_cert_command.rb +98 -99
  440. data/test/rubygems/test_gem_commands_check_command.rb +5 -4
  441. data/test/rubygems/test_gem_commands_cleanup_command.rb +41 -40
  442. data/test/rubygems/test_gem_commands_contents_command.rb +28 -27
  443. data/test/rubygems/test_gem_commands_dependency_command.rb +37 -36
  444. data/test/rubygems/test_gem_commands_environment_command.rb +17 -16
  445. data/test/rubygems/test_gem_commands_exec_command.rb +853 -0
  446. data/test/rubygems/test_gem_commands_fetch_command.rb +38 -37
  447. data/test/rubygems/test_gem_commands_generate_index_command.rb +8 -7
  448. data/test/rubygems/test_gem_commands_help_command.rb +14 -13
  449. data/test/rubygems/test_gem_commands_info_command.rb +29 -2
  450. data/test/rubygems/test_gem_commands_install_command.rb +152 -132
  451. data/test/rubygems/test_gem_commands_list_command.rb +5 -4
  452. data/test/rubygems/test_gem_commands_lock_command.rb +11 -10
  453. data/test/rubygems/test_gem_commands_mirror.rb +3 -2
  454. data/test/rubygems/test_gem_commands_open_command.rb +5 -4
  455. data/test/rubygems/test_gem_commands_outdated_command.rb +10 -9
  456. data/test/rubygems/test_gem_commands_owner_command.rb +227 -50
  457. data/test/rubygems/test_gem_commands_pristine_command.rb +142 -93
  458. data/test/rubygems/test_gem_commands_push_command.rb +189 -64
  459. data/test/rubygems/test_gem_commands_query_command.rb +74 -73
  460. data/test/rubygems/test_gem_commands_search_command.rb +3 -2
  461. data/test/rubygems/test_gem_commands_server_command.rb +3 -2
  462. data/test/rubygems/test_gem_commands_setup_command.rb +123 -96
  463. data/test/rubygems/test_gem_commands_signin_command.rb +71 -31
  464. data/test/rubygems/test_gem_commands_signout_command.rb +3 -3
  465. data/test/rubygems/test_gem_commands_sources_command.rb +29 -29
  466. data/test/rubygems/test_gem_commands_specification_command.rb +33 -32
  467. data/test/rubygems/test_gem_commands_stale_command.rb +5 -4
  468. data/test/rubygems/test_gem_commands_uninstall_command.rb +99 -81
  469. data/test/rubygems/test_gem_commands_unpack_command.rb +32 -31
  470. data/test/rubygems/test_gem_commands_update_command.rb +96 -95
  471. data/test/rubygems/test_gem_commands_which_command.rb +7 -6
  472. data/test/rubygems/test_gem_commands_yank_command.rb +162 -43
  473. data/test/rubygems/test_gem_config_file.rb +94 -81
  474. data/test/rubygems/test_gem_dependency.rb +76 -73
  475. data/test/rubygems/test_gem_dependency_installer.rb +200 -165
  476. data/test/rubygems/test_gem_dependency_list.rb +48 -47
  477. data/test/rubygems/test_gem_dependency_resolution_error.rb +5 -4
  478. data/test/rubygems/test_gem_doctor.rb +27 -26
  479. data/test/rubygems/test_gem_ext_builder.rb +60 -61
  480. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +4 -4
  481. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{Cargo.lock → ext/custom_name_lib/Cargo.lock} +23 -33
  482. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{Cargo.toml → ext/custom_name_lib/Cargo.toml} +1 -1
  483. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/{src → ext/custom_name_lib/src}/lib.rs +1 -1
  484. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb +3 -0
  485. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +37 -33
  486. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
  487. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec +2 -0
  488. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +12 -0
  489. data/test/rubygems/test_gem_ext_cargo_builder.rb +48 -59
  490. data/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +20 -19
  491. data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +21 -36
  492. data/test/rubygems/test_gem_ext_cmake_builder.rb +16 -15
  493. data/test/rubygems/test_gem_ext_configure_builder.rb +14 -13
  494. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +51 -52
  495. data/test/rubygems/test_gem_ext_rake_builder.rb +16 -15
  496. data/test/rubygems/test_gem_gem_runner.rb +15 -9
  497. data/test/rubygems/test_gem_gemcutter_utilities.rb +170 -84
  498. data/test/rubygems/test_gem_impossible_dependencies_error.rb +5 -4
  499. data/test/rubygems/test_gem_indexer.rb +87 -67
  500. data/test/rubygems/test_gem_install_update_options.rb +17 -16
  501. data/test/rubygems/test_gem_installer.rb +422 -304
  502. data/test/rubygems/test_gem_local_remote_options.rb +11 -10
  503. data/test/rubygems/test_gem_name_tuple.rb +5 -4
  504. data/test/rubygems/test_gem_package.rb +243 -231
  505. data/test/rubygems/test_gem_package_old.rb +14 -13
  506. data/test/rubygems/test_gem_package_tar_header.rb +48 -47
  507. data/test/rubygems/test_gem_package_tar_reader.rb +56 -8
  508. data/test/rubygems/test_gem_package_tar_reader_entry.rb +162 -16
  509. data/test/rubygems/test_gem_package_tar_writer.rb +77 -76
  510. data/test/rubygems/test_gem_package_task.rb +19 -18
  511. data/test/rubygems/test_gem_path_support.rb +15 -14
  512. data/test/rubygems/test_gem_platform.rb +333 -227
  513. data/test/rubygems/test_gem_rdoc.rb +15 -14
  514. data/test/rubygems/test_gem_remote_fetcher.rb +155 -154
  515. data/test/rubygems/test_gem_request.rb +64 -58
  516. data/test/rubygems/test_gem_request_connection_pools.rb +30 -29
  517. data/test/rubygems/test_gem_request_set.rb +101 -100
  518. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +210 -211
  519. data/test/rubygems/test_gem_request_set_lockfile.rb +87 -86
  520. data/test/rubygems/test_gem_request_set_lockfile_parser.rb +58 -57
  521. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +63 -62
  522. data/test/rubygems/test_gem_requirement.rb +48 -41
  523. data/test/rubygems/test_gem_resolver.rb +167 -99
  524. data/test/rubygems/test_gem_resolver_activation_request.rb +7 -6
  525. data/test/rubygems/test_gem_resolver_api_set.rb +34 -33
  526. data/test/rubygems/test_gem_resolver_api_specification.rb +48 -47
  527. data/test/rubygems/test_gem_resolver_best_set.rb +23 -22
  528. data/test/rubygems/test_gem_resolver_composed_set.rb +2 -1
  529. data/test/rubygems/test_gem_resolver_conflict.rb +13 -12
  530. data/test/rubygems/test_gem_resolver_dependency_request.rb +16 -15
  531. data/test/rubygems/test_gem_resolver_git_set.rb +22 -21
  532. data/test/rubygems/test_gem_resolver_git_specification.rb +22 -21
  533. data/test/rubygems/test_gem_resolver_index_set.rb +13 -12
  534. data/test/rubygems/test_gem_resolver_index_specification.rb +17 -16
  535. data/test/rubygems/test_gem_resolver_installed_specification.rb +6 -5
  536. data/test/rubygems/test_gem_resolver_installer_set.rb +79 -34
  537. data/test/rubygems/test_gem_resolver_local_specification.rb +8 -7
  538. data/test/rubygems/test_gem_resolver_lock_set.rb +13 -12
  539. data/test/rubygems/test_gem_resolver_lock_specification.rb +18 -17
  540. data/test/rubygems/test_gem_resolver_requirement_list.rb +2 -1
  541. data/test/rubygems/test_gem_resolver_specification.rb +9 -8
  542. data/test/rubygems/test_gem_resolver_vendor_set.rb +7 -6
  543. data/test/rubygems/test_gem_resolver_vendor_specification.rb +11 -10
  544. data/test/rubygems/test_gem_security.rb +69 -68
  545. data/test/rubygems/test_gem_security_policy.rb +72 -72
  546. data/test/rubygems/test_gem_security_signer.rb +35 -34
  547. data/test/rubygems/test_gem_security_trust_dir.rb +7 -6
  548. data/test/rubygems/test_gem_silent_ui.rb +39 -32
  549. data/test/rubygems/test_gem_source.rb +45 -44
  550. data/test/rubygems/test_gem_source_fetch_problem.rb +10 -9
  551. data/test/rubygems/test_gem_source_git.rb +69 -62
  552. data/test/rubygems/test_gem_source_installed.rb +17 -16
  553. data/test/rubygems/test_gem_source_list.rb +6 -5
  554. data/test/rubygems/test_gem_source_local.rb +15 -14
  555. data/test/rubygems/test_gem_source_lock.rb +32 -31
  556. data/test/rubygems/test_gem_source_specific_file.rb +18 -17
  557. data/test/rubygems/test_gem_source_subpath_problem.rb +8 -7
  558. data/test/rubygems/test_gem_source_vendor.rb +14 -13
  559. data/test/rubygems/test_gem_spec_fetcher.rb +73 -72
  560. data/test/rubygems/test_gem_specification.rb +533 -469
  561. data/test/rubygems/test_gem_stream_ui.rb +53 -22
  562. data/test/rubygems/test_gem_stub_specification.rb +33 -32
  563. data/test/rubygems/test_gem_text.rb +2 -1
  564. data/test/rubygems/test_gem_uninstaller.rb +118 -117
  565. data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +4 -3
  566. data/test/rubygems/test_gem_update_suggestion.rb +209 -0
  567. data/test/rubygems/test_gem_uri.rb +6 -4
  568. data/test/rubygems/test_gem_uri_formatter.rb +15 -14
  569. data/test/rubygems/test_gem_util.rb +24 -23
  570. data/test/rubygems/test_gem_validator.rb +8 -8
  571. data/test/rubygems/test_gem_version.rb +24 -16
  572. data/test/rubygems/test_gem_version_option.rb +16 -15
  573. data/test/rubygems/test_kernel.rb +43 -48
  574. data/test/rubygems/test_project_sanity.rb +32 -3
  575. data/test/rubygems/test_remote_fetch_error.rb +8 -7
  576. data/test/rubygems/test_require.rb +118 -103
  577. data/test/rubygems/test_rubygems.rb +10 -8
  578. data/test/rubygems/test_webauthn_listener.rb +143 -0
  579. data/test/rubygems/test_webauthn_listener_response.rb +93 -0
  580. data/test/rubygems/test_webauthn_poller.rb +124 -0
  581. data/test/rubygems/utilities.rb +98 -34
  582. data/test/rubygems/wrong_key_cert.pem +15 -15
  583. data/test/rubygems/wrong_key_cert_32.pem +15 -15
  584. data/test/test_changelog_generator.rb +1 -1
  585. metadata +99 -46
  586. data/bundler/lib/bundler/dep_proxy.rb +0 -55
  587. data/bundler/lib/bundler/templates/gems.rb +0 -5
  588. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +0 -5
  589. data/bundler/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  590. data/bundler/lib/bundler/vendor/molinillo/LICENSE +0 -9
  591. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  592. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  593. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  594. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  595. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  596. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  597. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  598. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  599. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  600. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  601. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  602. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  603. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -149
  604. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  605. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  606. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  607. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  608. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  609. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
  610. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
  611. data/bundler/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  612. data/bundler/lib/bundler/vendored_molinillo.rb +0 -4
  613. data/bundler/lib/bundler/version_ranges.rb +0 -122
  614. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +0 -21
  615. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +0 -21
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/list_command'
2
+
3
+ require_relative "helper"
4
+ require "rubygems/commands/list_command"
4
5
 
5
6
  class TestGemCommandsListCommand < Gem::TestCase
6
7
  def setup
@@ -9,7 +10,7 @@ class TestGemCommandsListCommand < Gem::TestCase
9
10
  @cmd = Gem::Commands::ListCommand.new
10
11
 
11
12
  spec_fetcher do |fetcher|
12
- fetcher.spec 'c', 1
13
+ fetcher.spec "c", 1
13
14
  end
14
15
 
15
16
  @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
@@ -27,6 +28,6 @@ class TestGemCommandsListCommand < Gem::TestCase
27
28
  end
28
29
 
29
30
  assert_equal "true\n", @ui.output
30
- assert_equal '', @ui.error
31
+ assert_equal "", @ui.error
31
32
  end
32
33
  end
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/lock_command'
2
+
3
+ require_relative "helper"
4
+ require "rubygems/commands/lock_command"
4
5
 
5
6
  class TestGemCommandsLockCommand < Gem::TestCase
6
7
  def setup
7
8
  super
8
9
 
9
- @a1 = quick_gem 'a', '1'
10
- @b1 = quick_gem 'b', '1' do |s|
11
- s.add_runtime_dependency 'a'
10
+ @a1 = quick_gem "a", "1"
11
+ @b1 = quick_gem "b", "1" do |s|
12
+ s.add_runtime_dependency "a"
12
13
  end
13
14
 
14
- @d1 = quick_gem 'd', '1' do |s|
15
- s.add_runtime_dependency 'z'
15
+ @d1 = quick_gem "d", "1" do |s|
16
+ s.add_runtime_dependency "z"
16
17
  end
17
18
 
18
19
  @cmd = Gem::Commands::LockCommand.new
@@ -32,7 +33,7 @@ gem 'a', '= 1'
32
33
  EXPECTED
33
34
 
34
35
  assert_equal expected, @ui.output
35
- assert_equal '', @ui.error
36
+ assert_equal "", @ui.error
36
37
  end
37
38
 
38
39
  def test_execute_missing_dependency
@@ -49,7 +50,7 @@ gem 'd', '= 1'
49
50
  EXPECTED
50
51
 
51
52
  assert_equal expected, @ui.output
52
- assert_equal '', @ui.error
53
+ assert_equal "", @ui.error
53
54
  end
54
55
 
55
56
  def test_execute_strict
@@ -61,6 +62,6 @@ gem 'd', '= 1'
61
62
  end
62
63
  end
63
64
 
64
- assert_equal 'Could not find gem c-1, try using the full name', e.message
65
+ assert_equal "Could not find gem c-1, try using the full name", e.message
65
66
  end
66
67
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/mirror_command'
2
+
3
+ require_relative "helper"
4
+ require "rubygems/commands/mirror_command"
4
5
 
5
6
  class TestGemCommandsMirrorCommand < Gem::TestCase
6
7
  def setup
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/open_command'
2
+
3
+ require_relative "helper"
4
+ require "rubygems/commands/open_command"
4
5
 
5
6
  class TestGemCommandsOpenCommand < Gem::TestCase
6
7
  def setup
@@ -23,8 +24,8 @@ class TestGemCommandsOpenCommand < Gem::TestCase
23
24
  @cmd.options[:args] = %w[foo]
24
25
  @cmd.options[:editor] = "#{ruby_with_rubygems_in_load_path} -eexit --"
25
26
 
26
- gem 'foo', '1.0.0'
27
- spec = gem 'foo', '1.0.1'
27
+ gem "foo", "1.0.0"
28
+ spec = gem "foo", "1.0.1"
28
29
 
29
30
  assert_nothing_raised Gem::MockGemUi::TermError do
30
31
  Dir.stub(:chdir, spec.full_gem_path) do
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/outdated_command'
2
+
3
+ require_relative "helper"
4
+ require "rubygems/commands/outdated_command"
4
5
 
5
6
  class TestGemCommandsOutdatedCommand < Gem::TestCase
6
7
  def setup
@@ -15,10 +16,10 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
15
16
 
16
17
  def test_execute
17
18
  spec_fetcher do |fetcher|
18
- fetcher.download 'foo', '1.0'
19
- fetcher.download 'foo', '2.0'
20
- fetcher.gem 'foo', '0.1'
21
- fetcher.gem 'foo', '0.2'
19
+ fetcher.download "foo", "1.0"
20
+ fetcher.download "foo", "2.0"
21
+ fetcher.gem "foo", "0.1"
22
+ fetcher.gem "foo", "0.2"
22
23
  end
23
24
 
24
25
  use_ui @ui do
@@ -31,10 +32,10 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
31
32
 
32
33
  def test_execute_with_up_to_date_platform_specific_gem
33
34
  spec_fetcher do |fetcher|
34
- fetcher.download 'foo', '2.0'
35
+ fetcher.download "foo", "2.0"
35
36
 
36
- fetcher.gem 'foo', '1.0'
37
- fetcher.gem 'foo', '2.0' do |s|
37
+ fetcher.gem "foo", "1.0"
38
+ fetcher.gem "foo", "2.0" do |s|
38
39
  s.platform = Gem::Platform.local
39
40
  end
40
41
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'rubygems/commands/owner_command'
2
+
3
+ require_relative "helper"
4
+ require_relative "multifactor_auth_utilities"
5
+ require "rubygems/commands/owner_command"
4
6
 
5
7
  class TestGemCommandsOwnerCommand < Gem::TestCase
6
8
  def setup
@@ -10,7 +12,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase
10
12
 
11
13
  ENV["RUBYGEMS_HOST"] = nil
12
14
  @stub_ui = Gem::MockGemUi.new
13
- @stub_fetcher = Gem::FakeFetcher.new
15
+ @stub_fetcher = Gem::MultifactorAuthFetcher.new
14
16
  Gem::RemoteFetcher.fetcher = @stub_fetcher
15
17
  Gem.configuration = nil
16
18
  Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250"
@@ -36,7 +38,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase
36
38
  - id: 4
37
39
  EOF
38
40
 
39
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
41
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
40
42
 
41
43
  use_ui @stub_ui do
42
44
  @cmd.show_owners("freewill")
@@ -66,7 +68,7 @@ EOF
66
68
  - id: 4
67
69
  EOF
68
70
 
69
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
71
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
70
72
 
71
73
  assert_raise Psych::DisallowedClass do
72
74
  use_ui @ui do
@@ -80,7 +82,7 @@ EOF
80
82
  host = "http://rubygems.example"
81
83
  ENV["RUBYGEMS_HOST"] = host
82
84
 
83
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
85
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
84
86
 
85
87
  use_ui @stub_ui do
86
88
  @cmd.show_owners("freewill")
@@ -95,7 +97,7 @@ EOF
95
97
  host = "http://rubygems.example"
96
98
  @cmd.host = host
97
99
 
98
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
100
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
99
101
 
100
102
  use_ui @stub_ui do
101
103
  @cmd.show_owners("freewill")
@@ -107,7 +109,7 @@ EOF
107
109
 
108
110
  def test_show_owners_denied
109
111
  response = "You don't have permission to push to this gem"
110
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, 'Forbidden']
112
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
111
113
 
112
114
  assert_raise Gem::MockGemUi::TermError do
113
115
  use_ui @stub_ui do
@@ -118,23 +120,46 @@ EOF
118
120
  assert_match response, @stub_ui.output
119
121
  end
120
122
 
123
+ def test_show_owners_permanent_redirect
124
+ host = "http://rubygems.example"
125
+ ENV["RUBYGEMS_HOST"] = host
126
+ path = "/api/v1/gems/freewill/owners.yaml"
127
+ redirected_uri = "https://rubygems.example#{path}"
128
+
129
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
130
+ body: "",
131
+ code: "301",
132
+ msg: "Moved Permanently",
133
+ headers: { "location" => redirected_uri }
134
+ )
135
+
136
+ assert_raise Gem::MockGemUi::TermError do
137
+ use_ui @stub_ui do
138
+ @cmd.show_owners("freewill")
139
+ end
140
+ end
141
+
142
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
143
+ assert_match response, @stub_ui.output
144
+ end
145
+
121
146
  def test_show_owners_key
122
147
  response = "- email: user1@example.com\n"
123
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
124
- File.open Gem.configuration.credentials_path, 'a' do |f|
125
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
148
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
149
+ File.open Gem.configuration.credentials_path, "a" do |f|
150
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
126
151
  end
127
152
  Gem.configuration.load_api_keys
128
153
 
129
154
  @cmd.handle_options %w[-k other]
130
- @cmd.show_owners('freewill')
155
+ @cmd.show_owners("freewill")
131
156
 
132
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
157
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
133
158
  end
134
159
 
135
160
  def test_add_owners
136
161
  response = "Owner added successfully."
137
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
162
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
138
163
 
139
164
  use_ui @stub_ui do
140
165
  @cmd.add_owners("freewill", ["user-new1@example.com"])
@@ -149,7 +174,7 @@ EOF
149
174
 
150
175
  def test_add_owners_denied
151
176
  response = "You don't have permission to push to this gem"
152
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden']
177
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
153
178
 
154
179
  use_ui @stub_ui do
155
180
  @cmd.add_owners("freewill", ["user-new1@example.com"])
@@ -158,12 +183,33 @@ EOF
158
183
  assert_match response, @stub_ui.output
159
184
  end
160
185
 
186
+ def test_add_owners_permanent_redirect
187
+ host = "http://rubygems.example"
188
+ ENV["RUBYGEMS_HOST"] = host
189
+ path = "/api/v1/gems/freewill/owners"
190
+ redirected_uri = "https://rubygems.example#{path}"
191
+
192
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
193
+ body: "",
194
+ code: "308",
195
+ msg: "Permanent Redirect",
196
+ headers: { "location" => redirected_uri }
197
+ )
198
+
199
+ use_ui @stub_ui do
200
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
201
+ end
202
+
203
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
204
+ assert_match response, @stub_ui.output
205
+ end
206
+
161
207
  def test_add_owner_with_host_option_through_execute
162
208
  host = "http://rubygems.example"
163
209
  add_owner_response = "Owner added successfully."
164
210
  show_owners_response = "- email: user1@example.com\n"
165
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, 'OK']
166
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, 'OK']
211
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: add_owner_response, code: 200, msg: "OK")
212
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: show_owners_response, code: 200, msg: "OK")
167
213
 
168
214
  @cmd.handle_options %W[--host #{host} --add user-new1@example.com freewill]
169
215
 
@@ -178,21 +224,21 @@ EOF
178
224
 
179
225
  def test_add_owners_key
180
226
  response = "Owner added successfully."
181
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
182
- File.open Gem.configuration.credentials_path, 'a' do |f|
183
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
227
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
228
+ File.open Gem.configuration.credentials_path, "a" do |f|
229
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
184
230
  end
185
231
  Gem.configuration.load_api_keys
186
232
 
187
233
  @cmd.handle_options %w[-k other]
188
- @cmd.add_owners('freewill', ['user-new1@example.com'])
234
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
189
235
 
190
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
236
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
191
237
  end
192
238
 
193
239
  def test_remove_owners
194
240
  response = "Owner removed successfully."
195
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
241
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
196
242
 
197
243
  use_ui @stub_ui do
198
244
  @cmd.remove_owners("freewill", ["user-remove1@example.com"])
@@ -207,32 +253,69 @@ EOF
207
253
 
208
254
  def test_remove_owners_denied
209
255
  response = "You don't have permission to push to this gem"
210
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden']
256
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
257
+
258
+ use_ui @stub_ui do
259
+ @cmd.remove_owners("freewill", ["user-remove1@example.com"])
260
+ end
261
+
262
+ assert_match response, @stub_ui.output
263
+ end
264
+
265
+ def test_remove_owners_permanent_redirect
266
+ host = "http://rubygems.example"
267
+ ENV["RUBYGEMS_HOST"] = host
268
+ path = "/api/v1/gems/freewill/owners"
269
+ redirected_uri = "https://rubygems.example#{path}"
270
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
271
+ body: "",
272
+ code: "308",
273
+ msg: "Permanent Redirect",
274
+ headers: { "location" => redirected_uri }
275
+ )
211
276
 
212
277
  use_ui @stub_ui do
213
278
  @cmd.remove_owners("freewill", ["user-remove1@example.com"])
214
279
  end
215
280
 
281
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
282
+ assert_match response, @stub_ui.output
283
+
284
+ path = "/api/v1/gems/freewill/owners"
285
+ redirected_uri = "https://rubygems.example#{path}"
286
+
287
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
288
+ body: "",
289
+ code: "308",
290
+ msg: "Permanent Redirect",
291
+ headers: { "location" => redirected_uri }
292
+ )
293
+
294
+ use_ui @stub_ui do
295
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
296
+ end
297
+
298
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
216
299
  assert_match response, @stub_ui.output
217
300
  end
218
301
 
219
302
  def test_remove_owners_key
220
303
  response = "Owner removed successfully."
221
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
222
- File.open Gem.configuration.credentials_path, 'a' do |f|
223
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
304
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
305
+ File.open Gem.configuration.credentials_path, "a" do |f|
306
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
224
307
  end
225
308
  Gem.configuration.load_api_keys
226
309
 
227
310
  @cmd.handle_options %w[-k other]
228
- @cmd.remove_owners('freewill', ['user-remove1@example.com'])
311
+ @cmd.remove_owners("freewill", ["user-remove1@example.com"])
229
312
 
230
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
313
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
231
314
  end
232
315
 
233
316
  def test_remove_owners_missing
234
- response = 'Owner could not be found.'
235
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, 'Not Found']
317
+ response = "Owner could not be found."
318
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 404, msg: "Not Found")
236
319
 
237
320
  use_ui @stub_ui do
238
321
  @cmd.remove_owners("freewill", ["missing@example"])
@@ -242,28 +325,25 @@ EOF
242
325
  end
243
326
 
244
327
  def test_otp_verified_success
245
- response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
246
328
  response_success = "Owner added successfully."
247
-
248
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
249
- [response_fail, 401, 'Unauthorized'],
250
- [response_success, 200, 'OK'],
251
- ]
329
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
252
330
 
253
331
  @otp_ui = Gem::MockGemUi.new "111111\n"
254
332
  use_ui @otp_ui do
255
333
  @cmd.add_owners("freewill", ["user-new1@example.com"])
256
334
  end
257
335
 
258
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
259
- assert_match 'Code: ', @otp_ui.output
336
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
337
+ assert_match "Code: ", @otp_ui.output
260
338
  assert_match response_success, @otp_ui.output
261
- assert_equal '111111', @stub_fetcher.last_request['OTP']
339
+ assert_equal "111111", @stub_fetcher.last_request["OTP"]
262
340
  end
263
341
 
264
342
  def test_otp_verified_failure
265
343
  response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
266
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 401, 'Unauthorized']
344
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized")
345
+ @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] =
346
+ HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity")
267
347
 
268
348
  @otp_ui = Gem::MockGemUi.new "111111\n"
269
349
  use_ui @otp_ui do
@@ -271,9 +351,106 @@ EOF
271
351
  end
272
352
 
273
353
  assert_match response, @otp_ui.output
274
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
275
- assert_match 'Code: ', @otp_ui.output
276
- assert_equal '111111', @stub_fetcher.last_request['OTP']
354
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
355
+ assert_match "Code: ", @otp_ui.output
356
+ assert_equal "111111", @stub_fetcher.last_request["OTP"]
357
+ end
358
+
359
+ def test_with_webauthn_enabled_success
360
+ response_success = "Owner added successfully."
361
+ server = Gem::MockTCPServer.new
362
+
363
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
364
+ @stub_fetcher.respond_with_webauthn_url
365
+
366
+ TCPServer.stub(:new, server) do
367
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
368
+ use_ui @stub_ui do
369
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
370
+ end
371
+ end
372
+ end
373
+
374
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
375
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
376
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output
377
+ assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
378
+ assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"]
379
+ assert_match response_success, @stub_ui.output
380
+ end
381
+
382
+ def test_with_webauthn_enabled_failure
383
+ response_success = "Owner added successfully."
384
+ server = Gem::MockTCPServer.new
385
+ error = Gem::WebauthnVerificationError.new("Something went wrong")
386
+
387
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
388
+ @stub_fetcher.respond_with_webauthn_url
389
+
390
+ TCPServer.stub(:new, server) do
391
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
392
+ use_ui @stub_ui do
393
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
394
+ end
395
+ end
396
+ end
397
+
398
+ assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
399
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
400
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
401
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output
402
+ assert_match "ERROR: Security device verification failed: Something went wrong", @stub_ui.error
403
+ refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
404
+ refute_match response_success, @stub_ui.output
405
+ end
406
+
407
+ def test_with_webauthn_enabled_success_with_polling
408
+ response_success = "Owner added successfully."
409
+ server = Gem::MockTCPServer.new
410
+
411
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
412
+ @stub_fetcher.respond_with_webauthn_url
413
+ @stub_fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo")
414
+
415
+ TCPServer.stub(:new, server) do
416
+ use_ui @stub_ui do
417
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
418
+ end
419
+ end
420
+
421
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
422
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \
423
+ "command with the `--otp [your_code]` option.", @stub_ui.output
424
+ assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
425
+ assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"]
426
+ assert_match response_success, @stub_ui.output
427
+ end
428
+
429
+ def test_with_webauthn_enabled_failure_with_polling
430
+ response_success = "Owner added successfully."
431
+ server = Gem::MockTCPServer.new
432
+
433
+ @stub_fetcher.respond_with_require_otp(
434
+ "#{Gem.host}/api/v1/gems/freewill/owners",
435
+ response_success
436
+ )
437
+ @stub_fetcher.respond_with_webauthn_url
438
+ @stub_fetcher.respond_with_webauthn_polling_failure
439
+
440
+ TCPServer.stub(:new, server) do
441
+ use_ui @stub_ui do
442
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
443
+ end
444
+ end
445
+
446
+ assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
447
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
448
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \
449
+ "command with the `--otp [your_code]` option.", @stub_ui.output
450
+ assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \
451
+ "or been used already.", @stub_ui.error
452
+ refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
453
+ refute_match response_success, @stub_ui.output
277
454
  end
278
455
 
279
456
  def test_remove_owners_unathorized_api_key
@@ -281,10 +458,10 @@ EOF
281
458
  response_success = "Owner removed successfully."
282
459
 
283
460
  @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
284
- [response_forbidden, 403, 'Forbidden'],
285
- [response_success, 200, "OK"],
461
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
462
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
286
463
  ]
287
- @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
464
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
288
465
  @cmd.instance_variable_set :@scope, :remove_owner
289
466
 
290
467
  @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"
@@ -305,10 +482,10 @@ EOF
305
482
  response_success = "Owner added successfully."
306
483
 
307
484
  @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
308
- [response_forbidden, 403, 'Forbidden'],
309
- [response_success, 200, "OK"],
485
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
486
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
310
487
  ]
311
- @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
488
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
312
489
  @cmd.instance_variable_set :@scope, :add_owner
313
490
 
314
491
  @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"