rubygems-update 3.5.3 → 3.7.1

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 (437) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1410 -686
  3. data/CODE_OF_CONDUCT.md +79 -28
  4. data/CONTRIBUTING.md +4 -226
  5. data/Manifest.txt +107 -83
  6. data/README.md +16 -11
  7. data/SECURITY.md +7 -0
  8. data/bundler/CHANGELOG.md +1525 -931
  9. data/bundler/README.md +9 -9
  10. data/bundler/bundler.gemspec +2 -2
  11. data/bundler/lib/bundler/build_metadata.rb +10 -11
  12. data/bundler/lib/bundler/checksum.rb +22 -12
  13. data/bundler/lib/bundler/cli/add.rb +3 -1
  14. data/bundler/lib/bundler/cli/binstubs.rb +1 -1
  15. data/bundler/lib/bundler/cli/check.rb +3 -3
  16. data/bundler/lib/bundler/cli/common.rb +1 -1
  17. data/bundler/lib/bundler/cli/config.rb +2 -2
  18. data/bundler/lib/bundler/cli/console.rb +8 -10
  19. data/bundler/lib/bundler/cli/doctor/diagnose.rb +167 -0
  20. data/bundler/lib/bundler/cli/doctor/ssl.rb +249 -0
  21. data/bundler/lib/bundler/cli/doctor.rb +27 -151
  22. data/bundler/lib/bundler/cli/exec.rb +1 -0
  23. data/bundler/lib/bundler/cli/fund.rb +1 -1
  24. data/bundler/lib/bundler/cli/gem.rb +74 -46
  25. data/bundler/lib/bundler/cli/info.rb +6 -6
  26. data/bundler/lib/bundler/cli/inject.rb +3 -3
  27. data/bundler/lib/bundler/cli/install.rb +19 -10
  28. data/bundler/lib/bundler/cli/issue.rb +3 -3
  29. data/bundler/lib/bundler/cli/lock.rb +32 -11
  30. data/bundler/lib/bundler/cli/outdated.rb +23 -23
  31. data/bundler/lib/bundler/cli/plugin.rb +3 -2
  32. data/bundler/lib/bundler/cli/pristine.rb +1 -1
  33. data/bundler/lib/bundler/cli/show.rb +3 -3
  34. data/bundler/lib/bundler/cli/update.rb +3 -3
  35. data/bundler/lib/bundler/cli.rb +75 -145
  36. data/bundler/lib/bundler/compact_index_client/cache.rb +48 -73
  37. data/bundler/lib/bundler/compact_index_client/cache_file.rb +0 -5
  38. data/bundler/lib/bundler/compact_index_client/parser.rb +84 -0
  39. data/bundler/lib/bundler/compact_index_client/updater.rb +6 -16
  40. data/bundler/lib/bundler/compact_index_client.rb +52 -85
  41. data/bundler/lib/bundler/constants.rb +8 -1
  42. data/bundler/lib/bundler/current_ruby.rb +48 -34
  43. data/bundler/lib/bundler/definition.rb +501 -328
  44. data/bundler/lib/bundler/dependency.rb +93 -47
  45. data/bundler/lib/bundler/dsl.rb +147 -103
  46. data/bundler/lib/bundler/endpoint_specification.rb +30 -3
  47. data/bundler/lib/bundler/env.rb +1 -1
  48. data/bundler/lib/bundler/environment_preserver.rb +5 -23
  49. data/bundler/lib/bundler/errors.rb +53 -5
  50. data/bundler/lib/bundler/feature_flag.rb +18 -18
  51. data/bundler/lib/bundler/fetcher/compact_index.rb +16 -25
  52. data/bundler/lib/bundler/fetcher/dependency.rb +2 -1
  53. data/bundler/lib/bundler/fetcher/downloader.rb +34 -8
  54. data/bundler/lib/bundler/fetcher.rb +63 -26
  55. data/bundler/lib/bundler/force_platform.rb +0 -2
  56. data/bundler/lib/bundler/friendly_errors.rb +3 -2
  57. data/bundler/lib/bundler/gem_helper.rb +1 -1
  58. data/bundler/lib/bundler/gem_version_promoter.rb +42 -40
  59. data/bundler/lib/bundler/index.rb +7 -2
  60. data/bundler/lib/bundler/injector.rb +14 -16
  61. data/bundler/lib/bundler/inline.rb +42 -17
  62. data/bundler/lib/bundler/installer/gem_installer.rb +4 -3
  63. data/bundler/lib/bundler/installer/parallel_installer.rb +3 -2
  64. data/bundler/lib/bundler/installer/standalone.rb +2 -5
  65. data/bundler/lib/bundler/installer.rb +22 -45
  66. data/bundler/lib/bundler/lazy_specification.rb +121 -48
  67. data/bundler/lib/bundler/lockfile_generator.rb +1 -1
  68. data/bundler/lib/bundler/lockfile_parser.rb +36 -9
  69. data/bundler/lib/bundler/man/bundle-add.1 +44 -27
  70. data/bundler/lib/bundler/man/bundle-add.1.ronn +52 -23
  71. data/bundler/lib/bundler/man/bundle-binstubs.1 +9 -6
  72. data/bundler/lib/bundler/man/bundle-binstubs.1.ronn +6 -3
  73. data/bundler/lib/bundler/man/bundle-cache.1 +32 -4
  74. data/bundler/lib/bundler/man/bundle-cache.1.ronn +31 -2
  75. data/bundler/lib/bundler/man/bundle-check.1 +7 -5
  76. data/bundler/lib/bundler/man/bundle-check.1.ronn +7 -2
  77. data/bundler/lib/bundler/man/bundle-clean.1 +3 -3
  78. data/bundler/lib/bundler/man/bundle-config.1 +180 -138
  79. data/bundler/lib/bundler/man/bundle-config.1.ronn +96 -99
  80. data/bundler/lib/bundler/man/bundle-console.1 +4 -6
  81. data/bundler/lib/bundler/man/bundle-console.1.ronn +2 -7
  82. data/bundler/lib/bundler/man/bundle-doctor.1 +46 -7
  83. data/bundler/lib/bundler/man/bundle-doctor.1.ronn +49 -5
  84. data/bundler/lib/bundler/man/bundle-env.1 +9 -0
  85. data/bundler/lib/bundler/man/bundle-env.1.ronn +10 -0
  86. data/bundler/lib/bundler/man/bundle-exec.1 +9 -6
  87. data/bundler/lib/bundler/man/bundle-exec.1.ronn +6 -3
  88. data/bundler/lib/bundler/man/bundle-fund.1 +22 -0
  89. data/bundler/lib/bundler/man/bundle-fund.1.ronn +25 -0
  90. data/bundler/lib/bundler/man/bundle-gem.1 +69 -28
  91. data/bundler/lib/bundler/man/bundle-gem.1.ronn +42 -6
  92. data/bundler/lib/bundler/man/bundle-help.1 +3 -3
  93. data/bundler/lib/bundler/man/bundle-info.1 +7 -4
  94. data/bundler/lib/bundler/man/bundle-info.1.ronn +6 -2
  95. data/bundler/lib/bundler/man/bundle-init.1 +5 -5
  96. data/bundler/lib/bundler/man/bundle-init.1.ronn +3 -2
  97. data/bundler/lib/bundler/man/bundle-inject.1 +13 -5
  98. data/bundler/lib/bundler/man/bundle-inject.1.ronn +10 -2
  99. data/bundler/lib/bundler/man/bundle-install.1 +20 -17
  100. data/bundler/lib/bundler/man/bundle-install.1.ronn +26 -23
  101. data/bundler/lib/bundler/man/bundle-issue.1 +45 -0
  102. data/bundler/lib/bundler/man/bundle-issue.1.ronn +37 -0
  103. data/bundler/lib/bundler/man/bundle-licenses.1 +9 -0
  104. data/bundler/lib/bundler/man/bundle-licenses.1.ronn +10 -0
  105. data/bundler/lib/bundler/man/bundle-list.1 +3 -3
  106. data/bundler/lib/bundler/man/bundle-list.1.ronn +4 -1
  107. data/bundler/lib/bundler/man/bundle-lock.1 +23 -8
  108. data/bundler/lib/bundler/man/bundle-lock.1.ronn +25 -4
  109. data/bundler/lib/bundler/man/bundle-open.1 +4 -4
  110. data/bundler/lib/bundler/man/bundle-open.1.ronn +2 -1
  111. data/bundler/lib/bundler/man/bundle-outdated.1 +10 -7
  112. data/bundler/lib/bundler/man/bundle-outdated.1.ronn +8 -4
  113. data/bundler/lib/bundler/man/bundle-platform.1 +3 -3
  114. data/bundler/lib/bundler/man/bundle-plugin.1 +9 -6
  115. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +7 -3
  116. data/bundler/lib/bundler/man/bundle-pristine.1 +3 -3
  117. data/bundler/lib/bundler/man/bundle-pristine.1.ronn +1 -1
  118. data/bundler/lib/bundler/man/bundle-remove.1 +3 -3
  119. data/bundler/lib/bundler/man/bundle-remove.1.ronn +1 -1
  120. data/bundler/lib/bundler/man/bundle-show.1 +7 -4
  121. data/bundler/lib/bundler/man/bundle-show.1.ronn +4 -0
  122. data/bundler/lib/bundler/man/bundle-update.1 +17 -11
  123. data/bundler/lib/bundler/man/bundle-update.1.ronn +17 -9
  124. data/bundler/lib/bundler/man/bundle-version.1 +3 -3
  125. data/bundler/lib/bundler/man/bundle-viz.1 +6 -6
  126. data/bundler/lib/bundler/man/bundle-viz.1.ronn +7 -3
  127. data/bundler/lib/bundler/man/bundle.1 +3 -3
  128. data/bundler/lib/bundler/man/gemfile.5 +7 -5
  129. data/bundler/lib/bundler/man/gemfile.5.ronn +8 -2
  130. data/bundler/lib/bundler/man/index.txt +4 -0
  131. data/bundler/lib/bundler/match_metadata.rb +13 -0
  132. data/bundler/lib/bundler/match_platform.rb +31 -12
  133. data/bundler/lib/bundler/materialization.rb +59 -0
  134. data/bundler/lib/bundler/mirror.rb +3 -3
  135. data/bundler/lib/bundler/plugin/api/source.rb +5 -4
  136. data/bundler/lib/bundler/plugin/events.rb +24 -0
  137. data/bundler/lib/bundler/plugin/index.rb +5 -1
  138. data/bundler/lib/bundler/plugin/installer/path.rb +26 -0
  139. data/bundler/lib/bundler/plugin/installer.rb +37 -17
  140. data/bundler/lib/bundler/plugin/source_list.rb +4 -4
  141. data/bundler/lib/bundler/plugin.rb +21 -2
  142. data/bundler/lib/bundler/process_lock.rb +10 -14
  143. data/bundler/lib/bundler/remote_specification.rb +6 -1
  144. data/bundler/lib/bundler/resolver/base.rb +14 -3
  145. data/bundler/lib/bundler/resolver/candidate.rb +18 -27
  146. data/bundler/lib/bundler/resolver/package.rb +20 -3
  147. data/bundler/lib/bundler/resolver/spec_group.rb +22 -27
  148. data/bundler/lib/bundler/resolver/strategy.rb +40 -0
  149. data/bundler/lib/bundler/resolver.rb +114 -52
  150. data/bundler/lib/bundler/retry.rb +1 -1
  151. data/bundler/lib/bundler/ruby_dsl.rb +12 -3
  152. data/bundler/lib/bundler/ruby_version.rb +7 -1
  153. data/bundler/lib/bundler/rubygems_ext.rb +303 -150
  154. data/bundler/lib/bundler/rubygems_gem_installer.rb +40 -5
  155. data/bundler/lib/bundler/rubygems_integration.rb +40 -73
  156. data/bundler/lib/bundler/runtime.rb +48 -35
  157. data/bundler/lib/bundler/self_manager.rb +36 -26
  158. data/bundler/lib/bundler/settings/validator.rb +0 -23
  159. data/bundler/lib/bundler/settings.rb +36 -27
  160. data/bundler/lib/bundler/setup.rb +6 -0
  161. data/bundler/lib/bundler/shared_helpers.rb +45 -25
  162. data/bundler/lib/bundler/source/gemspec.rb +1 -4
  163. data/bundler/lib/bundler/source/git/git_proxy.rb +26 -9
  164. data/bundler/lib/bundler/source/git.rb +113 -41
  165. data/bundler/lib/bundler/source/metadata.rb +4 -3
  166. data/bundler/lib/bundler/source/path.rb +14 -18
  167. data/bundler/lib/bundler/source/rubygems/remote.rb +12 -4
  168. data/bundler/lib/bundler/source/rubygems.rb +54 -48
  169. data/bundler/lib/bundler/source.rb +2 -0
  170. data/bundler/lib/bundler/source_list.rb +54 -12
  171. data/bundler/lib/bundler/source_map.rb +1 -1
  172. data/bundler/lib/bundler/spec_set.rb +227 -103
  173. data/bundler/lib/bundler/stub_specification.rb +29 -2
  174. data/bundler/lib/bundler/templates/Executable +0 -11
  175. data/bundler/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +77 -29
  176. data/bundler/lib/bundler/templates/newgem/Gemfile.tt +1 -3
  177. data/bundler/lib/bundler/templates/newgem/README.md.tt +7 -3
  178. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +17 -15
  179. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +14 -12
  180. data/bundler/lib/bundler/templates/newgem/rubocop.yml.tt +0 -5
  181. data/bundler/lib/bundler/ui/shell.rb +26 -4
  182. data/bundler/lib/bundler/ui/silent.rb +12 -1
  183. data/bundler/lib/bundler/uri_credentials_filter.rb +3 -3
  184. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +53 -3
  185. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  186. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +11 -0
  187. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +15 -13
  188. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  189. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +2 -1
  190. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +134 -57
  191. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +4 -24
  192. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +1 -0
  193. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -0
  194. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +20 -8
  195. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +17 -29
  196. data/bundler/lib/bundler/vendor/securerandom/COPYING +56 -0
  197. data/bundler/lib/bundler/vendor/securerandom/lib/securerandom.rb +102 -0
  198. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +3 -5
  199. data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +11 -0
  200. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +1 -4
  201. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +2 -2
  202. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +2 -1
  203. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +9 -9
  204. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +1 -1
  205. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +5 -21
  206. data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  207. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  208. data/bundler/lib/bundler/vendor/thor/lib/thor.rb +11 -0
  209. data/bundler/lib/bundler/vendor/uri/COPYING +56 -0
  210. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +43 -16
  211. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +3 -3
  212. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +1 -1
  213. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +28 -37
  214. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +2 -2
  215. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +16 -9
  216. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +26 -3
  217. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  218. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +9 -9
  219. data/bundler/lib/bundler/vendored_net_http.rb +20 -5
  220. data/bundler/lib/bundler/vendored_securerandom.rb +12 -0
  221. data/bundler/lib/bundler/vendored_timeout.rb +7 -3
  222. data/bundler/lib/bundler/vendored_uri.rb +18 -1
  223. data/bundler/lib/bundler/version.rb +10 -2
  224. data/bundler/lib/bundler/worker.rb +1 -1
  225. data/bundler/lib/bundler/yaml_serializer.rb +12 -7
  226. data/bundler/lib/bundler.rb +101 -61
  227. data/{bundler → doc/bundler}/UPGRADING.md +132 -127
  228. data/doc/rubygems/CONTRIBUTING.md +227 -0
  229. data/{POLICIES.md → doc/rubygems/POLICIES.md} +86 -17
  230. data/exe/update_rubygems +1 -1
  231. data/lib/rubygems/basic_specification.rb +50 -10
  232. data/lib/rubygems/bundler_version_finder.rb +1 -1
  233. data/lib/rubygems/command.rb +1 -4
  234. data/lib/rubygems/command_manager.rb +5 -6
  235. data/lib/rubygems/commands/build_command.rb +2 -11
  236. data/lib/rubygems/commands/cleanup_command.rb +3 -13
  237. data/lib/rubygems/commands/contents_command.rb +17 -10
  238. data/lib/rubygems/commands/environment_command.rb +5 -0
  239. data/lib/rubygems/commands/exec_command.rb +18 -11
  240. data/lib/rubygems/commands/fetch_command.rb +14 -0
  241. data/lib/rubygems/commands/help_command.rb +2 -2
  242. data/lib/rubygems/commands/install_command.rb +0 -4
  243. data/lib/rubygems/commands/pristine_command.rb +29 -19
  244. data/lib/rubygems/commands/push_command.rb +31 -6
  245. data/lib/rubygems/commands/rdoc_command.rb +3 -10
  246. data/lib/rubygems/commands/rebuild_command.rb +262 -0
  247. data/lib/rubygems/commands/setup_command.rb +13 -18
  248. data/lib/rubygems/commands/sources_command.rb +2 -2
  249. data/lib/rubygems/commands/uninstall_command.rb +9 -4
  250. data/lib/rubygems/commands/unpack_command.rb +0 -6
  251. data/lib/rubygems/commands/update_command.rb +13 -22
  252. data/lib/rubygems/config_file.rb +45 -16
  253. data/lib/rubygems/core_ext/kernel_require.rb +15 -3
  254. data/lib/rubygems/core_ext/kernel_warn.rb +2 -6
  255. data/lib/rubygems/defaults.rb +7 -7
  256. data/lib/rubygems/dependency.rb +12 -16
  257. data/lib/rubygems/dependency_list.rb +1 -1
  258. data/lib/rubygems/deprecate.rb +79 -77
  259. data/lib/rubygems/errors.rb +2 -1
  260. data/lib/rubygems/exceptions.rb +2 -9
  261. data/lib/rubygems/ext/builder.rb +21 -8
  262. data/lib/rubygems/ext/cargo_builder.rb +16 -26
  263. data/lib/rubygems/ext/cmake_builder.rb +7 -2
  264. data/lib/rubygems/ext/configure_builder.rb +7 -2
  265. data/lib/rubygems/ext/ext_conf_builder.rb +9 -5
  266. data/lib/rubygems/ext/rake_builder.rb +7 -4
  267. data/lib/rubygems/gem_runner.rb +9 -0
  268. data/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +11 -4
  269. data/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +3 -1
  270. data/lib/rubygems/gemcutter_utilities.rb +52 -26
  271. data/lib/rubygems/gemspec_helpers.rb +19 -0
  272. data/lib/rubygems/install_update_options.rb +5 -0
  273. data/lib/rubygems/installer.rb +76 -90
  274. data/lib/rubygems/local_remote_options.rb +8 -8
  275. data/lib/rubygems/package/tar_header.rb +31 -4
  276. data/lib/rubygems/package/tar_reader/entry.rb +1 -5
  277. data/lib/rubygems/package/tar_writer.rb +5 -4
  278. data/lib/rubygems/package.rb +13 -8
  279. data/lib/rubygems/platform.rb +148 -43
  280. data/lib/rubygems/psych_tree.rb +4 -0
  281. data/lib/rubygems/query_utils.rb +2 -2
  282. data/lib/rubygems/rdoc.rb +16 -3
  283. data/lib/rubygems/remote_fetcher.rb +6 -7
  284. data/lib/rubygems/request.rb +5 -5
  285. data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
  286. data/lib/rubygems/request_set.rb +4 -7
  287. data/lib/rubygems/requirement.rb +16 -12
  288. data/lib/rubygems/resolver/activation_request.rb +1 -1
  289. data/lib/rubygems/resolver/api_set/gem_parser.rb +2 -5
  290. data/lib/rubygems/resolver/api_set.rb +13 -8
  291. data/lib/rubygems/resolver/best_set.rb +1 -29
  292. data/lib/rubygems/resolver/composed_set.rb +3 -3
  293. data/lib/rubygems/resolver/git_set.rb +0 -1
  294. data/lib/rubygems/resolver/index_set.rb +2 -2
  295. data/lib/rubygems/resolver/source_set.rb +1 -1
  296. data/lib/rubygems/resolver/spec_specification.rb +7 -0
  297. data/lib/rubygems/resolver.rb +8 -8
  298. data/lib/rubygems/s3_uri_signer.rb +8 -6
  299. data/lib/rubygems/safe_marshal/reader.rb +31 -14
  300. data/lib/rubygems/safe_marshal/visitors/to_ruby.rb +29 -16
  301. data/lib/rubygems/safe_yaml.rb +10 -1
  302. data/lib/rubygems/security.rb +1 -1
  303. data/lib/rubygems/source/git.rb +22 -17
  304. data/lib/rubygems/source/installed.rb +3 -1
  305. data/lib/rubygems/source/local.rb +8 -4
  306. data/lib/rubygems/source/specific_file.rb +5 -3
  307. data/lib/rubygems/source.rb +37 -29
  308. data/lib/rubygems/source_list.rb +1 -1
  309. data/lib/rubygems/spec_fetcher.rb +47 -15
  310. data/lib/rubygems/specification.rb +110 -183
  311. data/lib/rubygems/specification_policy.rb +33 -13
  312. data/lib/rubygems/specification_record.rb +212 -0
  313. data/lib/rubygems/stub_specification.rb +32 -10
  314. data/lib/rubygems/target_rbconfig.rb +50 -0
  315. data/lib/rubygems/uninstaller.rb +42 -22
  316. data/lib/rubygems/uri.rb +6 -6
  317. data/lib/rubygems/uri_formatter.rb +2 -1
  318. data/lib/rubygems/util/licenses.rb +118 -1
  319. data/lib/rubygems/util.rb +1 -1
  320. data/lib/rubygems/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  321. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/delegates/specification_provider.rb +11 -11
  322. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/action.rb +1 -1
  323. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -1
  324. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -1
  325. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -1
  326. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -1
  327. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/log.rb +1 -1
  328. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -1
  329. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -1
  330. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph/vertex.rb +1 -1
  331. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  332. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/errors.rb +1 -1
  333. data/lib/rubygems/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
  334. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/modules/specification_provider.rb +2 -2
  335. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/modules/ui.rb +1 -1
  336. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/resolution.rb +4 -4
  337. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/resolver.rb +1 -1
  338. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo/state.rb +1 -1
  339. data/lib/rubygems/{resolver → vendor}/molinillo/lib/molinillo.rb +2 -2
  340. data/lib/rubygems/vendor/net-http/COPYING +56 -0
  341. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/generic_request.rb +9 -9
  342. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/header.rb +3 -3
  343. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/request.rb +3 -3
  344. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/requests.rb +35 -30
  345. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/response.rb +2 -2
  346. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/responses.rb +6 -6
  347. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/status.rb +1 -1
  348. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http.rb +149 -70
  349. data/lib/rubygems/{net-http → vendor/net-http}/lib/net/https.rb +1 -1
  350. data/lib/rubygems/vendor/optparse/COPYING +56 -0
  351. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/ac.rb +16 -0
  352. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/kwargs.rb +8 -3
  353. data/lib/rubygems/vendor/optparse/lib/optparse/uri.rb +7 -0
  354. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/version.rb +9 -0
  355. data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse.rb +158 -62
  356. data/lib/rubygems/vendor/resolv/COPYING +56 -0
  357. data/lib/rubygems/{resolv → vendor/resolv}/lib/resolv.rb +165 -69
  358. data/lib/rubygems/vendor/securerandom/COPYING +56 -0
  359. data/lib/rubygems/vendor/securerandom/lib/securerandom.rb +102 -0
  360. data/lib/rubygems/vendor/timeout/COPYING +56 -0
  361. data/lib/rubygems/{timeout → vendor/timeout}/lib/timeout.rb +10 -11
  362. data/lib/rubygems/{tsort → vendor/tsort}/lib/tsort.rb +2 -2
  363. data/lib/rubygems/vendor/uri/COPYING +56 -0
  364. data/lib/rubygems/vendor/uri/lib/uri/common.rb +880 -0
  365. data/lib/rubygems/vendor/uri/lib/uri/file.rb +100 -0
  366. data/lib/rubygems/vendor/uri/lib/uri/ftp.rb +267 -0
  367. data/lib/rubygems/vendor/uri/lib/uri/generic.rb +1579 -0
  368. data/lib/rubygems/vendor/uri/lib/uri/http.rb +125 -0
  369. data/lib/rubygems/vendor/uri/lib/uri/https.rb +23 -0
  370. data/lib/rubygems/vendor/uri/lib/uri/ldap.rb +261 -0
  371. data/lib/rubygems/vendor/uri/lib/uri/ldaps.rb +22 -0
  372. data/lib/rubygems/vendor/uri/lib/uri/mailto.rb +293 -0
  373. data/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb +546 -0
  374. data/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb +206 -0
  375. data/lib/rubygems/vendor/uri/lib/uri/version.rb +6 -0
  376. data/lib/rubygems/vendor/uri/lib/uri/ws.rb +83 -0
  377. data/lib/rubygems/vendor/uri/lib/uri/wss.rb +23 -0
  378. data/lib/rubygems/vendor/uri/lib/uri.rb +104 -0
  379. data/lib/rubygems/vendored_molinillo.rb +3 -0
  380. data/lib/rubygems/vendored_net_http.rb +5 -0
  381. data/lib/rubygems/vendored_optparse.rb +3 -0
  382. data/lib/rubygems/vendored_securerandom.rb +3 -0
  383. data/lib/rubygems/vendored_timeout.rb +5 -0
  384. data/lib/rubygems/vendored_tsort.rb +3 -0
  385. data/lib/rubygems/version.rb +26 -9
  386. data/lib/rubygems/yaml_serializer.rb +12 -7
  387. data/lib/rubygems.rb +160 -53
  388. data/rubygems-update.gemspec +11 -6
  389. data/setup.rb +1 -1
  390. metadata +124 -96
  391. data/bundler/lib/bundler/compact_index_client/gem_parser.rb +0 -32
  392. data/bundler/lib/bundler/gem_helpers.rb +0 -127
  393. data/bundler/lib/bundler/templates/Executable.bundler +0 -109
  394. data/bundler/lib/bundler/vendor/fileutils/.document +0 -1
  395. data/bundler/lib/bundler/vendor/net-http-persistent/.document +0 -1
  396. data/bundler/lib/bundler/vendor/pub_grub/.document +0 -1
  397. data/bundler/lib/bundler/vendor/thor/.document +0 -1
  398. data/bundler/lib/bundler/vendor/tsort/.document +0 -1
  399. data/bundler/lib/bundler/vendor/uri/.document +0 -1
  400. data/lib/rubygems/net/http.rb +0 -3
  401. data/lib/rubygems/net-http/.document +0 -1
  402. data/lib/rubygems/net-http/LICENSE.txt +0 -22
  403. data/lib/rubygems/net-http/lib/net/http/backward.rb +0 -40
  404. data/lib/rubygems/net-protocol/.document +0 -1
  405. data/lib/rubygems/net-protocol/LICENSE.txt +0 -22
  406. data/lib/rubygems/optparse/.document +0 -1
  407. data/lib/rubygems/optparse/lib/optparse/uri.rb +0 -7
  408. data/lib/rubygems/optparse.rb +0 -3
  409. data/lib/rubygems/resolv/.document +0 -1
  410. data/lib/rubygems/resolv/LICENSE.txt +0 -22
  411. data/lib/rubygems/resolver/molinillo/.document +0 -1
  412. data/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  413. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  414. data/lib/rubygems/resolver/molinillo.rb +0 -3
  415. data/lib/rubygems/shellwords.rb +0 -3
  416. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem +0 -21
  417. data/lib/rubygems/timeout/.document +0 -1
  418. data/lib/rubygems/timeout/LICENSE.txt +0 -22
  419. data/lib/rubygems/timeout.rb +0 -3
  420. data/lib/rubygems/tsort/.document +0 -1
  421. data/lib/rubygems/tsort/LICENSE.txt +0 -22
  422. data/lib/rubygems/tsort.rb +0 -3
  423. /data/{lib/rubygems/optparse → bundler/lib/bundler/vendor/fileutils}/COPYING +0 -0
  424. /data/{MAINTAINERS.txt → doc/MAINTAINERS.txt} +0 -0
  425. /data/{UPGRADING.md → doc/rubygems/UPGRADING.md} +0 -0
  426. /data/lib/rubygems/ssl_certs/rubygems.org/{GlobalSignRootCA_R3.pem → GlobalSign.pem} +0 -0
  427. /data/{bundler/lib/bundler/vendor/connection_pool → lib/rubygems/vendor}/.document +0 -0
  428. /data/lib/rubygems/{resolver → vendor}/molinillo/LICENSE +0 -0
  429. /data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/exceptions.rb +0 -0
  430. /data/lib/rubygems/{net-http → vendor/net-http}/lib/net/http/proxy_delta.rb +0 -0
  431. /data/{bundler/lib/bundler/vendor/fileutils → lib/rubygems/vendor/net-protocol}/LICENSE.txt +0 -0
  432. /data/lib/rubygems/{net-protocol → vendor/net-protocol}/lib/net/protocol.rb +0 -0
  433. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optionparser.rb +0 -0
  434. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/date.rb +0 -0
  435. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/shellwords.rb +0 -0
  436. /data/lib/rubygems/{optparse → vendor/optparse}/lib/optparse/time.rb +0 -0
  437. /data/{bundler/lib/bundler/vendor/uri → lib/rubygems/vendor/tsort}/LICENSE.txt +0 -0
@@ -4,8 +4,6 @@ require_relative "lockfile_parser"
4
4
 
5
5
  module Bundler
6
6
  class Definition
7
- include GemHelpers
8
-
9
7
  class << self
10
8
  # Do not create or modify a lockfile (Makes #lock a noop)
11
9
  attr_accessor :no_lock
@@ -13,13 +11,14 @@ module Bundler
13
11
 
14
12
  attr_reader(
15
13
  :dependencies,
14
+ :locked_checksums,
16
15
  :locked_deps,
17
16
  :locked_gems,
18
17
  :platforms,
19
18
  :ruby_version,
20
19
  :lockfile,
21
20
  :gemfiles,
22
- :locked_checksums
21
+ :sources
23
22
  )
24
23
 
25
24
  # Given a gemfile and lockfile creates a Bundler definition
@@ -57,19 +56,31 @@ module Bundler
57
56
  # @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
58
57
  # @param optional_groups [Array(String)] A list of optional groups
59
58
  def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
60
- if [true, false].include?(unlock)
59
+ unlock ||= {}
60
+
61
+ if unlock == true
62
+ @unlocking_all = true
63
+ strict = false
61
64
  @unlocking_bundler = false
62
65
  @unlocking = unlock
66
+ @sources_to_unlock = []
67
+ @unlocking_ruby = false
68
+ @explicit_unlocks = []
69
+ conservative = false
63
70
  else
71
+ @unlocking_all = false
72
+ strict = unlock.delete(:strict)
64
73
  @unlocking_bundler = unlock.delete(:bundler)
65
74
  @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
75
+ @sources_to_unlock = unlock.delete(:sources) || []
76
+ @unlocking_ruby = unlock.delete(:ruby)
77
+ @explicit_unlocks = unlock.delete(:gems) || []
78
+ conservative = unlock.delete(:conservative)
66
79
  end
67
80
 
68
81
  @dependencies = dependencies
69
82
  @sources = sources
70
- @unlock = unlock
71
83
  @optional_groups = optional_groups
72
- @remote = false
73
84
  @prefer_local = false
74
85
  @specs = nil
75
86
  @ruby_version = ruby_version
@@ -82,39 +93,39 @@ module Bundler
82
93
  @resolved_bundler_version = nil
83
94
 
84
95
  @locked_ruby_version = nil
85
- @new_platform = nil
86
- @removed_platform = nil
96
+ @new_platforms = []
97
+ @removed_platforms = []
98
+ @originally_invalid_platforms = []
87
99
 
88
100
  if lockfile_exists?
89
101
  @lockfile_contents = Bundler.read_file(lockfile)
90
- @locked_gems = LockfileParser.new(@lockfile_contents)
102
+ @locked_gems = LockfileParser.new(@lockfile_contents, strict: strict)
91
103
  @locked_platforms = @locked_gems.platforms
104
+ @most_specific_locked_platform = @locked_gems.most_specific_locked_platform
92
105
  @platforms = @locked_platforms.dup
93
106
  @locked_bundler_version = @locked_gems.bundler_version
94
107
  @locked_ruby_version = @locked_gems.ruby_version
108
+ @locked_deps = @locked_gems.dependencies
95
109
  @originally_locked_specs = SpecSet.new(@locked_gems.specs)
96
110
  @locked_checksums = @locked_gems.checksums
97
111
 
98
- if unlock != true
99
- @locked_deps = @locked_gems.dependencies
100
- @locked_specs = @originally_locked_specs
101
- @locked_sources = @locked_gems.sources
102
- else
103
- @unlock = {}
104
- @locked_deps = {}
112
+ if @unlocking_all
105
113
  @locked_specs = SpecSet.new([])
106
114
  @locked_sources = []
115
+ else
116
+ @locked_specs = @originally_locked_specs
117
+ @locked_sources = @locked_gems.sources
107
118
  end
108
119
  else
109
- @unlock = {}
120
+ @locked_gems = nil
121
+ @locked_platforms = []
122
+ @most_specific_locked_platform = nil
110
123
  @platforms = []
111
- @locked_gems = nil
112
124
  @locked_deps = {}
113
125
  @locked_specs = SpecSet.new([])
114
126
  @originally_locked_specs = @locked_specs
115
127
  @locked_sources = []
116
- @locked_platforms = []
117
- @locked_checksums = nil
128
+ @locked_checksums = Bundler.feature_flag.lockfile_checksums?
118
129
  end
119
130
 
120
131
  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@@ -130,23 +141,21 @@ module Bundler
130
141
  @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
131
142
  end
132
143
 
133
- @unlock[:sources] ||= []
134
- @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
144
+ @unlocking_ruby ||= if @ruby_version && locked_ruby_version_object
135
145
  @ruby_version.diff(locked_ruby_version_object)
136
146
  end
137
- @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
147
+ @unlocking ||= @unlocking_ruby ||= (!@locked_ruby_version ^ !@ruby_version)
138
148
 
139
- add_current_platform unless Bundler.frozen_bundle?
149
+ @current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
140
150
 
141
- converge_path_sources_to_gemspec_sources
142
- @path_changes = converge_paths
143
151
  @source_changes = converge_sources
152
+ @path_changes = converge_paths
144
153
 
145
- if @unlock[:conservative]
146
- @unlock[:gems] ||= @dependencies.map(&:name)
154
+ if conservative
155
+ @gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
147
156
  else
148
- eager_unlock = (@unlock[:gems] || []).map {|name| Dependency.new(name, ">= 0") }
149
- @unlock[:gems] = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
157
+ eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
158
+ @gems_to_unlock = @locked_specs.for(eager_unlock, platforms).map(&:name).uniq
150
159
  end
151
160
 
152
161
  @dependency_changes = converge_dependencies
@@ -159,38 +168,63 @@ module Bundler
159
168
  @gem_version_promoter ||= GemVersionPromoter.new
160
169
  end
161
170
 
162
- def resolve_only_locally!
163
- @remote = false
171
+ def check!
172
+ # If dependencies have changed, we need to resolve remotely. Otherwise,
173
+ # since we'll be resolving with a single local source, we may end up
174
+ # locking gems under the wrong source in the lockfile, and missing lockfile
175
+ # checksums
176
+ resolve_remotely! if @dependency_changes
177
+
178
+ # Now do a local only resolve, to verify if any gems are missing locally
164
179
  sources.local_only!
165
180
  resolve
166
181
  end
167
182
 
183
+ #
184
+ # Setup sources according to the given options and the state of the
185
+ # definition.
186
+ #
187
+ # @return [Boolean] Whether fetching remote information will be necessary or not
188
+ #
189
+ def setup_domain!(options = {})
190
+ prefer_local! if options[:"prefer-local"]
191
+
192
+ if options[:add_checksums] || (!options[:local] && install_needed?)
193
+ remotely!
194
+ true
195
+ else
196
+ Bundler.settings.set_command_option(:jobs, 1) unless install_needed? # to avoid the overhead of Bundler::Worker
197
+ with_cache!
198
+ false
199
+ end
200
+ end
201
+
168
202
  def resolve_with_cache!
169
- sources.cached!
203
+ with_cache!
204
+
170
205
  resolve
171
206
  end
172
207
 
208
+ def with_cache!
209
+ sources.local!
210
+ sources.cached!
211
+ end
212
+
173
213
  def resolve_remotely!
174
- @remote = true
175
- sources.remote!
214
+ remotely!
215
+
176
216
  resolve
177
217
  end
178
218
 
179
- def resolution_mode=(options)
180
- if options["local"]
181
- @remote = false
182
- else
183
- @remote = true
184
- @prefer_local = options["prefer-local"]
185
- end
219
+ def remotely!
220
+ sources.cached!
221
+ sources.remote!
186
222
  end
187
223
 
188
- def setup_sources_for_resolve
189
- if @remote == false
190
- sources.cached!
191
- else
192
- sources.remote!
193
- end
224
+ def prefer_local!
225
+ @prefer_local = true
226
+
227
+ sources.prefer_local!
194
228
  end
195
229
 
196
230
  # For given dependency list returns a SpecSet with Gemspec of all the required
@@ -212,7 +246,7 @@ module Bundler
212
246
  end
213
247
 
214
248
  def missing_specs
215
- resolve.materialize(requested_dependencies).missing_specs
249
+ resolve.missing_specs_for(requested_dependencies)
216
250
  end
217
251
 
218
252
  def missing_specs?
@@ -223,9 +257,9 @@ module Bundler
223
257
  rescue BundlerError => e
224
258
  @resolve = nil
225
259
  @resolver = nil
226
- @resolution_packages = nil
260
+ @resolution_base = nil
261
+ @source_requirements = nil
227
262
  @specs = nil
228
- @gem_version_promoter = nil
229
263
 
230
264
  Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
231
265
  true
@@ -248,7 +282,7 @@ module Bundler
248
282
  end
249
283
 
250
284
  def filter_relevant(dependencies)
251
- platforms_array = [generic_local_platform].freeze
285
+ platforms_array = [Bundler.generic_local_platform].freeze
252
286
  dependencies.select do |d|
253
287
  d.should_include? && !d.gem_platforms(platforms_array).empty?
254
288
  end
@@ -276,11 +310,7 @@ module Bundler
276
310
  groups.map!(&:to_sym)
277
311
  deps = current_dependencies # always returns a new array
278
312
  deps.select! do |d|
279
- if RUBY_VERSION >= "3.1"
280
- d.groups.intersect?(groups)
281
- else
282
- !(d.groups & groups).empty?
283
- end
313
+ d.groups.intersect?(groups)
284
314
  end
285
315
  deps
286
316
  end
@@ -300,67 +330,52 @@ module Bundler
300
330
  SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
301
331
  else
302
332
  Bundler.ui.debug "Found no changes, using resolution from the lockfile"
303
- if @removed_platform || @locked_gems.may_include_redundant_platform_specific_gems?
333
+ if @removed_platforms.any? || @locked_gems.may_include_redundant_platform_specific_gems?
304
334
  SpecSet.new(filter_specs(@locked_specs, @dependencies))
305
335
  else
306
336
  @locked_specs
307
337
  end
308
338
  end
309
339
  else
310
- Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
340
+ Bundler.ui.debug resolve_needed_reason
341
+
311
342
  start_resolution
312
343
  end
313
344
  end
314
345
 
315
- def should_complete_platforms?
316
- !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
317
- end
318
-
319
346
  def spec_git_paths
320
- sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
347
+ sources.git_sources.filter_map {|s| File.realpath(s.path) if File.exist?(s.path) }
321
348
  end
322
349
 
323
350
  def groups
324
- dependencies.map(&:groups).flatten.uniq
351
+ dependencies.flat_map(&:groups).uniq
325
352
  end
326
353
 
327
- def lock(file, preserve_unknown_sections = false)
328
- return if Definition.no_lock
329
-
330
- contents = to_lock
331
-
332
- # Convert to \r\n if the existing lock has them
333
- # i.e., Windows with `git config core.autocrlf=true`
334
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
335
-
336
- if @locked_bundler_version
337
- locked_major = @locked_bundler_version.segments.first
338
- current_major = bundler_version_to_lock.segments.first
339
-
340
- updating_major = locked_major < current_major
341
- end
354
+ def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
355
+ if [true, false, nil].include?(file_or_preserve_unknown_sections)
356
+ target_lockfile = lockfile
357
+ preserve_unknown_sections = file_or_preserve_unknown_sections
358
+ else
359
+ target_lockfile = file_or_preserve_unknown_sections
360
+ preserve_unknown_sections = preserve_unknown_sections_or_unused
342
361
 
343
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
362
+ suggestion = if target_lockfile == lockfile
363
+ "To fix this warning, remove it from the `Definition#lock` call."
364
+ else
365
+ "Instead, instantiate a new definition passing `#{target_lockfile}`, and call `lock` without a file argument on that definition"
366
+ end
344
367
 
345
- if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
346
- return if Bundler.frozen_bundle?
347
- SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
348
- return
349
- end
368
+ msg = "`Definition#lock` was passed a target file argument. #{suggestion}"
350
369
 
351
- if Bundler.frozen_bundle?
352
- Bundler.ui.error "Cannot write a changed lockfile while frozen."
353
- return
370
+ Bundler::SharedHelpers.major_deprecation 2, msg
354
371
  end
355
372
 
356
- SharedHelpers.filesystem_access(file) do |p|
357
- File.open(p, "wb") {|f| f.puts(contents) }
358
- end
373
+ write_lock(target_lockfile, preserve_unknown_sections)
359
374
  end
360
375
 
361
376
  def locked_ruby_version
362
377
  return unless ruby_version
363
- if @unlock[:ruby] || !@locked_ruby_version
378
+ if @unlocking_ruby || !@locked_ruby_version
364
379
  Bundler::RubyVersion.system
365
380
  else
366
381
  @locked_ruby_version
@@ -389,51 +404,22 @@ module Bundler
389
404
  end
390
405
 
391
406
  def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
392
- added = []
393
- deleted = []
394
- changed = []
395
-
396
- new_platforms = @platforms - @locked_platforms
397
- deleted_platforms = @locked_platforms - @platforms
398
- added.concat new_platforms.map {|p| "* platform: #{p}" }
399
- deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
400
-
401
- added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
402
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
403
-
404
- both_sources = Hash.new {|h, k| h[k] = [] }
405
- current_dependencies.each {|d| both_sources[d.name][0] = d }
406
- current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
407
+ return unless Bundler.frozen_bundle?
407
408
 
408
- both_sources.each do |name, (dep, lock_dep)|
409
- next if dep.nil? || lock_dep.nil?
409
+ raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
410
410
 
411
- gemfile_source = dep.source || default_source
412
- lock_source = lock_dep.source || default_source
413
- next if lock_source.include?(gemfile_source)
414
-
415
- gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
416
- lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
417
- changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
418
- end
419
-
420
- reason = change_reason
421
- msg = String.new
422
- msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
423
- msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
424
- msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
425
- msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
426
- msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n"
411
+ msg = lockfile_changes_summary("frozen mode is set")
412
+ return unless msg
427
413
 
428
414
  unless explicit_flag
429
415
  suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
430
416
  "bundle config set frozen false"
431
417
  end
432
- msg << "If this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
418
+ msg << "\n\nIf this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
433
419
  "freeze by running `#{suggested_command}`." if suggested_command
434
420
  end
435
421
 
436
- raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed?
422
+ raise ProductionError, msg
437
423
  end
438
424
 
439
425
  def validate_runtime!
@@ -467,62 +453,168 @@ module Bundler
467
453
  end
468
454
 
469
455
  def validate_platforms!
470
- return if current_platform_locked?
456
+ return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
471
457
 
472
458
  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
473
- "but your local platform is #{local_platform}. " \
474
- "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
459
+ "but your local platform is #{Bundler.local_platform}. " \
460
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
461
+ end
462
+
463
+ def normalize_platforms
464
+ resolve.normalize_platforms!(current_dependencies, platforms)
465
+
466
+ @resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
475
467
  end
476
468
 
477
469
  def add_platform(platform)
478
- @new_platform ||= !@platforms.include?(platform)
479
- @platforms |= [platform]
470
+ return if @platforms.include?(platform)
471
+
472
+ @new_platforms << platform
473
+ @platforms << platform
480
474
  end
481
475
 
482
476
  def remove_platform(platform)
483
- removed_platform = @platforms.delete(Gem::Platform.new(platform))
484
- @removed_platform ||= removed_platform
485
- return if removed_platform
486
- raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
487
- end
477
+ raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}" unless @platforms.include?(platform)
488
478
 
489
- def most_specific_locked_platform
490
- @platforms.min_by do |bundle_platform|
491
- platform_specificity_match(bundle_platform, local_platform)
492
- end
479
+ @removed_platforms << platform
480
+ @platforms.delete(platform)
493
481
  end
494
482
 
495
- attr_reader :sources
496
- private :sources
497
-
498
483
  def nothing_changed?
499
- !@source_changes &&
500
- !@dependency_changes &&
501
- !@new_platform &&
502
- !@path_changes &&
503
- !@local_changes &&
504
- !@missing_lockfile_dep &&
505
- !@unlocking_bundler &&
506
- !@locked_spec_with_missing_deps &&
507
- !@locked_spec_with_invalid_deps
484
+ !something_changed?
508
485
  end
509
486
 
510
487
  def no_resolve_needed?
511
- !unlocking? && nothing_changed?
488
+ !resolve_needed?
512
489
  end
513
490
 
514
491
  def unlocking?
515
492
  @unlocking
516
493
  end
517
494
 
495
+ attr_writer :source_requirements
496
+
497
+ def add_checksums
498
+ @locked_checksums = true
499
+
500
+ setup_domain!(add_checksums: true)
501
+
502
+ specs # force materialization to real specifications, so that checksums are fetched
503
+ end
504
+
518
505
  private
519
506
 
507
+ def lockfile_changes_summary(update_refused_reason)
508
+ added = []
509
+ deleted = []
510
+ changed = []
511
+
512
+ added.concat @new_platforms.map {|p| "* platform: #{p}" }
513
+ deleted.concat @removed_platforms.map {|p| "* platform: #{p}" }
514
+
515
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
516
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
517
+
518
+ both_sources = Hash.new {|h, k| h[k] = [] }
519
+ current_dependencies.each {|d| both_sources[d.name][0] = d }
520
+ current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
521
+
522
+ both_sources.each do |name, (dep, lock_dep)|
523
+ next if dep.nil? || lock_dep.nil?
524
+
525
+ gemfile_source = dep.source || default_source
526
+ lock_source = lock_dep.source || default_source
527
+ next if lock_source.include?(gemfile_source)
528
+
529
+ gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
530
+ lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
531
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
532
+ end
533
+
534
+ return unless added.any? || deleted.any? || changed.any? || resolve_needed?
535
+
536
+ msg = String.new("#{change_reason.capitalize.strip}, but ")
537
+ msg << "the lockfile " unless msg.start_with?("Your lockfile")
538
+ msg << "can't be updated because #{update_refused_reason}"
539
+ msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
540
+ msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
541
+ msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
542
+ msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.\n" unless unlocking?
543
+ msg
544
+ end
545
+
546
+ def install_needed?
547
+ resolve_needed? || missing_specs?
548
+ end
549
+
550
+ def something_changed?
551
+ return true unless lockfile_exists?
552
+
553
+ @source_changes ||
554
+ @dependency_changes ||
555
+ @current_platform_missing ||
556
+ @new_platforms.any? ||
557
+ @path_changes ||
558
+ @local_changes ||
559
+ @missing_lockfile_dep ||
560
+ @unlocking_bundler ||
561
+ @locked_spec_with_missing_checksums ||
562
+ @locked_spec_with_missing_deps ||
563
+ @locked_spec_with_invalid_deps
564
+ end
565
+
566
+ def resolve_needed?
567
+ unlocking? || something_changed?
568
+ end
569
+
570
+ def should_add_extra_platforms?
571
+ !lockfile_exists? && Bundler::MatchPlatform.generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
572
+ end
573
+
520
574
  def lockfile_exists?
521
575
  lockfile && File.exist?(lockfile)
522
576
  end
523
577
 
578
+ def write_lock(file, preserve_unknown_sections)
579
+ return if Definition.no_lock || file.nil?
580
+
581
+ contents = to_lock
582
+
583
+ # Convert to \r\n if the existing lock has them
584
+ # i.e., Windows with `git config core.autocrlf=true`
585
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
586
+
587
+ if @locked_bundler_version
588
+ locked_major = @locked_bundler_version.segments.first
589
+ current_major = bundler_version_to_lock.segments.first
590
+
591
+ updating_major = locked_major < current_major
592
+ end
593
+
594
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
595
+
596
+ if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
597
+ return if Bundler.frozen_bundle?
598
+ SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
599
+ return
600
+ end
601
+
602
+ if Bundler.frozen_bundle?
603
+ Bundler.ui.error "Cannot write a changed lockfile while frozen."
604
+ return
605
+ end
606
+
607
+ begin
608
+ SharedHelpers.filesystem_access(file) do |p|
609
+ File.open(p, "wb") {|f| f.puts(contents) }
610
+ end
611
+ rescue ReadOnlyFileSystemError
612
+ raise ProductionError, lockfile_changes_summary("file system is read-only")
613
+ end
614
+ end
615
+
524
616
  def resolver
525
- @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
617
+ @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
526
618
  end
527
619
 
528
620
  def expanded_dependencies
@@ -531,36 +623,65 @@ module Bundler
531
623
 
532
624
  def dependencies_with_bundler
533
625
  return dependencies unless @unlocking_bundler
534
- return dependencies if dependencies.map(&:name).include?("bundler")
626
+ return dependencies if dependencies.any? {|d| d.name == "bundler" }
535
627
 
536
628
  [Dependency.new("bundler", @unlocking_bundler)] + dependencies
537
629
  end
538
630
 
539
- def resolution_packages
540
- @resolution_packages ||= begin
631
+ def resolution_base
632
+ @resolution_base ||= begin
541
633
  last_resolve = converge_locked_specs
542
- remove_invalid_platforms!(current_dependencies)
543
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlock[:gems], prerelease: gem_version_promoter.pre?)
544
- additional_base_requirements_for_resolve(packages, last_resolve)
634
+ remove_invalid_platforms!
635
+ new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
636
+ base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
637
+ base = additional_base_requirements_to_prevent_downgrades(base)
638
+ base = additional_base_requirements_to_force_updates(base)
639
+ base
545
640
  end
546
641
  end
547
642
 
548
- def filter_specs(specs, deps)
549
- SpecSet.new(specs).for(deps, false, platforms)
643
+ def filter_specs(specs, deps, skips: [])
644
+ SpecSet.new(specs).for(deps, platforms, skips: skips)
550
645
  end
551
646
 
552
647
  def materialize(dependencies)
553
- specs = resolve.materialize(dependencies)
554
- missing_specs = specs.missing_specs
648
+ # Tracks potential endless loops trying to re-resolve.
649
+ # TODO: Remove as dead code if not reports are received in a while
650
+ incorrect_spec = nil
651
+
652
+ specs = begin
653
+ resolve.materialize(dependencies)
654
+ rescue IncorrectLockfileDependencies => e
655
+ raise if Bundler.frozen_bundle?
656
+
657
+ spec = e.spec
658
+ raise "Infinite loop while fixing lockfile dependencies" if incorrect_spec == spec
659
+
660
+ incorrect_spec = spec
661
+ reresolve_without([spec])
662
+ retry
663
+ end
664
+
665
+ missing_specs = resolve.missing_specs
555
666
 
556
667
  if missing_specs.any?
557
668
  missing_specs.each do |s|
558
669
  locked_gem = @locked_specs[s.name].last
559
- next if locked_gem.nil? || locked_gem.version != s.version || !@remote
560
- raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
561
- "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
562
- "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
563
- "removed in order to install."
670
+ next if locked_gem.nil? || locked_gem.version != s.version || sources.local_mode?
671
+
672
+ message = if sources.implicit_global_source?
673
+ "Because your Gemfile specifies no global remote source, your bundle is locked to " \
674
+ "#{locked_gem} from #{locked_gem.source}. However, #{locked_gem} is not installed. You'll " \
675
+ "need to either add a global remote source to your Gemfile or make sure #{locked_gem} is " \
676
+ "available locally before rerunning Bundler."
677
+ else
678
+ "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
679
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
680
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
681
+ "removed in order to install."
682
+ end
683
+
684
+ raise GemNotFound, message
564
685
  end
565
686
 
566
687
  missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
@@ -570,98 +691,164 @@ module Bundler
570
691
  raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
571
692
  end
572
693
 
573
- incomplete_specs = specs.incomplete_specs
694
+ partially_missing_specs = resolve.partially_missing_specs
695
+
696
+ if partially_missing_specs.any? && !sources.local_mode?
697
+ Bundler.ui.warn "Some locked specs have possibly been yanked (#{partially_missing_specs.map(&:full_name).join(", ")}). Ignoring them..."
698
+
699
+ resolve.delete(partially_missing_specs)
700
+ end
701
+
702
+ incomplete_specs = resolve.incomplete_specs
574
703
  loop do
575
704
  break if incomplete_specs.empty?
576
705
 
577
706
  Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
578
- setup_sources_for_resolve
579
- resolution_packages.delete(incomplete_specs)
580
- @resolve = start_resolution
707
+ sources.remote!
708
+ reresolve_without(incomplete_specs)
581
709
  specs = resolve.materialize(dependencies)
582
710
 
583
- still_incomplete_specs = specs.incomplete_specs
711
+ still_incomplete_specs = resolve.incomplete_specs
584
712
 
585
713
  if still_incomplete_specs == incomplete_specs
586
- package = resolution_packages.get_package(incomplete_specs.first.name)
587
- resolver.raise_not_found! package
714
+ resolver.raise_incomplete! incomplete_specs
588
715
  end
589
716
 
590
717
  incomplete_specs = still_incomplete_specs
591
718
  end
592
719
 
720
+ insecurely_materialized_specs = resolve.insecurely_materialized_specs
721
+
722
+ if insecurely_materialized_specs.any?
723
+ Bundler.ui.warn "The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version:\n" \
724
+ " * #{insecurely_materialized_specs.map(&:full_name).join("\n * ")}\n" \
725
+ "Please run `bundle lock --normalize-platforms` and commit the resulting lockfile.\n" \
726
+ "Alternatively, you may run `bundle lock --add-platform <list-of-platforms-that-you-want-to-support>`"
727
+ end
728
+
593
729
  bundler = sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
594
730
  specs["bundler"] = bundler
595
731
 
596
732
  specs
597
733
  end
598
734
 
735
+ def reresolve_without(incomplete_specs)
736
+ resolution_base.delete(incomplete_specs)
737
+ @resolve = start_resolution
738
+ end
739
+
599
740
  def start_resolution
741
+ local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(Bundler.local_platform)
742
+ @platforms << Bundler.local_platform if local_platform_needed_for_resolvability
743
+ add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
744
+
600
745
  result = SpecSet.new(resolver.start)
601
746
 
602
747
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
603
- @platforms = result.complete_platforms!(platforms) if should_complete_platforms?
604
748
 
605
- SpecSet.new(result.for(dependencies, false, @platforms))
606
- end
749
+ @new_platforms.each do |platform|
750
+ incomplete_specs = result.incomplete_specs_for_platform(current_dependencies, platform)
607
751
 
608
- def precompute_source_requirements_for_indirect_dependencies?
609
- sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
610
- end
611
-
612
- def pin_locally_available_names(source_requirements)
613
- source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
614
- local_source = original_source.dup
615
- local_source.local_only!
752
+ if incomplete_specs.any?
753
+ resolver.raise_incomplete! incomplete_specs
754
+ end
755
+ end
616
756
 
617
- new_source_requirements[name] = if local_source.specs.search(name).any?
618
- local_source
619
- else
620
- original_source
757
+ if @most_specific_non_local_locked_platform
758
+ if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
759
+ @platforms.delete(@most_specific_non_local_locked_platform)
760
+ elsif local_platform_needed_for_resolvability
761
+ @platforms.delete(Bundler.local_platform)
621
762
  end
622
763
  end
623
- end
624
764
 
625
- def current_ruby_platform_locked?
626
- return false unless generic_local_platform_is_ruby?
627
- return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
765
+ if should_add_extra_platforms?
766
+ result.add_extra_platforms!(platforms)
767
+ elsif @originally_invalid_platforms.any?
768
+ result.add_originally_invalid_platforms!(platforms, @originally_invalid_platforms)
769
+ end
770
+
771
+ SpecSet.new(result.for(dependencies, @platforms | [Gem::Platform::RUBY]))
772
+ end
628
773
 
629
- current_platform_locked?
774
+ def precompute_source_requirements_for_indirect_dependencies?
775
+ sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
630
776
  end
631
777
 
632
778
  def current_platform_locked?
633
779
  @platforms.any? do |bundle_platform|
634
- MatchPlatform.platforms_match?(bundle_platform, local_platform)
780
+ Bundler.generic_local_platform == bundle_platform || Bundler.local_platform === bundle_platform
635
781
  end
636
782
  end
637
783
 
638
784
  def add_current_platform
639
- return if current_ruby_platform_locked?
785
+ return if @platforms.include?(Bundler.local_platform)
640
786
 
641
- add_platform(local_platform)
787
+ @most_specific_non_local_locked_platform = find_most_specific_locked_platform
788
+ return if @most_specific_non_local_locked_platform
789
+
790
+ @platforms << Bundler.local_platform
791
+ true
792
+ end
793
+
794
+ def find_most_specific_locked_platform
795
+ return unless current_platform_locked?
796
+
797
+ @most_specific_locked_platform
798
+ end
799
+
800
+ def resolve_needed_reason
801
+ if lockfile_exists?
802
+ if unlocking?
803
+ "Re-resolving dependencies because #{unlocking_reason}"
804
+ else
805
+ "Found changes from the lockfile, re-resolving dependencies because #{lockfile_changed_reason}"
806
+ end
807
+ else
808
+ "Resolving dependencies because there's no lockfile"
809
+ end
642
810
  end
643
811
 
644
812
  def change_reason
645
- if unlocking?
646
- unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
647
- if v == true
648
- k.to_s
649
- else
650
- v = Array(v)
651
- "#{k}: (#{v.join(", ")})"
652
- end
653
- end.join(", ")
654
- return "bundler is unlocking #{unlock_reason}"
813
+ if resolve_needed?
814
+ if unlocking?
815
+ unlocking_reason
816
+ else
817
+ lockfile_changed_reason
818
+ end
819
+ else
820
+ "some dependencies were deleted from your gemfile"
655
821
  end
822
+ end
823
+
824
+ def unlocking_reason
825
+ unlock_targets = if @gems_to_unlock.any?
826
+ ["gems", @gems_to_unlock]
827
+ elsif @sources_to_unlock.any?
828
+ ["sources", @sources_to_unlock]
829
+ end
830
+
831
+ unlock_reason = if unlock_targets
832
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
833
+ else
834
+ @unlocking_ruby ? "ruby" : ""
835
+ end
836
+
837
+ "bundler is unlocking #{unlock_reason}"
838
+ end
839
+
840
+ def lockfile_changed_reason
656
841
  [
657
842
  [@source_changes, "the list of sources changed"],
658
843
  [@dependency_changes, "the dependencies in your gemfile changed"],
659
- [@new_platform, "you added a new platform to your gemfile"],
844
+ [@current_platform_missing, "your lockfile is missing the current platform"],
845
+ [@new_platforms.any?, "you are adding a new platform to your lockfile"],
660
846
  [@path_changes, "the gemspecs for path gems changed"],
661
847
  [@local_changes, "the gemspecs for git local gems changed"],
662
- [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
848
+ [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
663
849
  [@unlocking_bundler, "an update to the version of Bundler itself was requested"],
664
- [@locked_spec_with_missing_deps, "your lock file includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
850
+ [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
851
+ [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
665
852
  [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
666
853
  ].select(&:first).map(&:last).join(", ")
667
854
  end
@@ -678,8 +865,8 @@ module Bundler
678
865
  !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
679
866
  end
680
867
 
681
- def dependencies_for_source_changed?(source, locked_source = source)
682
- deps_for_source = @dependencies.select {|s| s.source == source }
868
+ def dependencies_for_source_changed?(source, locked_source)
869
+ deps_for_source = @dependencies.select {|dep| dep.source == source }
683
870
  locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
684
871
 
685
872
  deps_for_source.uniq.sort != locked_deps_for_source.sort
@@ -687,7 +874,7 @@ module Bundler
687
874
 
688
875
  def specs_for_source_changed?(source)
689
876
  locked_index = Index.new
690
- locked_index.use(@locked_specs.select {|s| source.can_lock?(s) })
877
+ locked_index.use(@locked_specs.select {|s| s.replace_source_with!(source) })
691
878
 
692
879
  !locked_index.subset?(source.specs)
693
880
  rescue PathError, GitError => e
@@ -705,7 +892,7 @@ module Bundler
705
892
  spec = @dependencies.find {|s| s.name == k }
706
893
  source = spec&.source
707
894
  if source&.respond_to?(:local_override!)
708
- source.unlock! if @unlock[:gems].include?(spec.name)
895
+ source.unlock! if @gems_to_unlock.include?(spec.name)
709
896
  locals << [source, source.local_override!(v)]
710
897
  end
711
898
  end
@@ -713,33 +900,33 @@ module Bundler
713
900
  sources_with_changes = locals.select do |source, changed|
714
901
  changed || specs_changed?(source)
715
902
  end.map(&:first)
716
- !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
903
+ !sources_with_changes.each {|source| @sources_to_unlock << source.name }.empty?
717
904
  end
718
905
 
719
906
  def check_lockfile
720
- @missing_lockfile_dep = nil
721
-
722
907
  @locked_spec_with_invalid_deps = nil
723
908
  @locked_spec_with_missing_deps = nil
909
+ @locked_spec_with_missing_checksums = nil
724
910
 
725
- missing = []
911
+ missing_deps = []
912
+ missing_checksums = []
726
913
  invalid = []
727
914
 
728
915
  @locked_specs.each do |s|
916
+ missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
917
+
729
918
  validation = @locked_specs.validate_deps(s)
730
919
 
731
- missing << s if validation == :missing
920
+ missing_deps << s if validation == :missing
732
921
  invalid << s if validation == :invalid
733
922
  end
734
923
 
735
- if missing.any?
736
- @locked_specs.delete(missing)
924
+ @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
925
+
926
+ if missing_deps.any?
927
+ @locked_specs.delete(missing_deps)
737
928
 
738
- @locked_spec_with_missing_deps = missing.first.name
739
- elsif !@dependency_changes
740
- @missing_lockfile_dep = current_dependencies.find do |d|
741
- @locked_specs[d.name].empty? && d.name != "bundler"
742
- end&.name
929
+ @locked_spec_with_missing_deps = missing_deps.first.name
743
930
  end
744
931
 
745
932
  if invalid.any?
@@ -755,24 +942,6 @@ module Bundler
755
942
  end
756
943
  end
757
944
 
758
- def converge_path_source_to_gemspec_source(source)
759
- return source unless source.instance_of?(Source::Path)
760
- gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
761
- gemspec_source || source
762
- end
763
-
764
- def converge_path_sources_to_gemspec_sources
765
- @locked_sources.map! do |source|
766
- converge_path_source_to_gemspec_source(source)
767
- end
768
- @locked_specs.each do |spec|
769
- spec.source &&= converge_path_source_to_gemspec_source(spec.source)
770
- end
771
- @locked_deps.each do |_, dep|
772
- dep.source &&= converge_path_source_to_gemspec_source(dep.source)
773
- end
774
- end
775
-
776
945
  def converge_sources
777
946
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
778
947
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
@@ -790,7 +959,7 @@ module Bundler
790
959
  # gem), unlock it. For git sources, this means to unlock the revision, which
791
960
  # will cause the `ref` used to be the most recent for the branch (or master) if
792
961
  # an explicit `ref` is not used.
793
- if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name)
962
+ if source.respond_to?(:unlock!) && @sources_to_unlock.include?(source.name)
794
963
  source.unlock!
795
964
  changes = true
796
965
  end
@@ -800,34 +969,39 @@ module Bundler
800
969
  end
801
970
 
802
971
  def converge_dependencies
803
- changes = false
972
+ @missing_lockfile_dep = nil
973
+ @changed_dependencies = []
804
974
 
805
- @dependencies.each do |dep|
975
+ current_dependencies.each do |dep|
806
976
  if dep.source
807
977
  dep.source = sources.get(dep.source)
808
978
  end
809
979
 
810
- next if unlocking?
980
+ name = dep.name
811
981
 
812
- unless locked_dep = @locked_deps[dep.name]
813
- changes = true
814
- next
815
- end
982
+ dep_changed = @locked_deps[name].nil?
816
983
 
817
- # Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
818
- # doesn't carry a notion of the dependency type, if you use
819
- # add_development_dependency in a gemspec that's loaded with the gemspec
820
- # directive, the lockfile dependencies and resolved dependencies end up
821
- # with a mismatch on #type. Work around that by setting the type on the
822
- # dep from the lockfile.
823
- locked_dep.instance_variable_set(:@type, dep.type)
984
+ unless name == "bundler"
985
+ locked_specs = @originally_locked_specs[name]
824
986
 
825
- # We already know the name matches from the hash lookup
826
- # so we only need to check the requirement now
827
- changes ||= dep.requirement != locked_dep.requirement
987
+ if locked_specs.empty?
988
+ @missing_lockfile_dep = name if dep_changed == false
989
+ else
990
+ if locked_specs.map(&:source).uniq.size > 1
991
+ @locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
992
+ end
993
+
994
+ unless dep.matches_spec?(locked_specs.first)
995
+ @gems_to_unlock << name
996
+ dep_changed = true
997
+ end
998
+ end
999
+ end
1000
+
1001
+ @changed_dependencies << name if dep_changed
828
1002
  end
829
1003
 
830
- changes
1004
+ @changed_dependencies.any?
831
1005
  end
832
1006
 
833
1007
  # Remove elements from the locked specs that are expired. This will most
@@ -836,7 +1010,7 @@ module Bundler
836
1010
  def converge_locked_specs
837
1011
  converged = converge_specs(@locked_specs)
838
1012
 
839
- resolve = SpecSet.new(converged.reject {|s| @unlock[:gems].include?(s.name) })
1013
+ resolve = SpecSet.new(converged)
840
1014
 
841
1015
  diff = nil
842
1016
 
@@ -857,61 +1031,41 @@ module Bundler
857
1031
  converged = []
858
1032
  deps = []
859
1033
 
860
- @specs_that_changed_sources = []
861
-
862
1034
  specs.each do |s|
863
1035
  name = s.name
864
1036
  dep = @dependencies.find {|d| s.satisfies?(d) }
865
1037
  lockfile_source = s.source
866
1038
 
867
1039
  if dep
868
- gemfile_source = dep.source || default_source
869
-
870
- @specs_that_changed_sources << s if gemfile_source != lockfile_source
871
- deps << dep if !dep.source || lockfile_source.include?(dep.source)
872
- @unlock[:gems] << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
1040
+ replacement_source = dep.source
873
1041
 
874
- # Replace the locked dependency's source with the equivalent source from the Gemfile
875
- s.source = gemfile_source
1042
+ deps << dep if !replacement_source || lockfile_source.include?(replacement_source) || new_deps.include?(dep)
876
1043
  else
877
- # Replace the locked dependency's source with the default source, if the locked source is no longer in the Gemfile
878
- s.source = default_source unless sources.get(lockfile_source)
1044
+ replacement_source = sources.get(lockfile_source)
879
1045
  end
880
1046
 
881
- next if @unlock[:sources].include?(s.source.name)
1047
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
1048
+ s.source = replacement_source || default_source
882
1049
 
883
- # Path sources have special logic
884
- if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
885
- new_specs = begin
886
- s.source.specs
887
- rescue PathError
888
- # if we won't need the source (according to the lockfile),
889
- # don't error if the path source isn't available
890
- next if specs.
891
- for(requested_dependencies, false).
892
- none? {|locked_spec| locked_spec.source == s.source }
893
-
894
- raise
895
- end
1050
+ source = s.source
1051
+ next if @sources_to_unlock.include?(source.name)
896
1052
 
897
- new_spec = new_specs[s].first
1053
+ # Path sources have special logic
1054
+ if source.instance_of?(Source::Path) || source.instance_of?(Source::Gemspec) || (source.instance_of?(Source::Git) && !@gems_to_unlock.include?(name) && deps.include?(dep))
1055
+ new_spec = source.specs[s].first
898
1056
  if new_spec
899
- s.dependencies.replace(new_spec.dependencies)
1057
+ s.runtime_dependencies.replace(new_spec.runtime_dependencies)
900
1058
  else
901
1059
  # If the spec is no longer in the path source, unlock it. This
902
1060
  # commonly happens if the version changed in the gemspec
903
- @unlock[:gems] << name
1061
+ @gems_to_unlock << name
904
1062
  end
905
1063
  end
906
1064
 
907
- if dep.nil? && requested_dependencies.find {|d| name == d.name }
908
- @unlock[:gems] << s.name
909
- else
910
- converged << s
911
- end
1065
+ converged << s
912
1066
  end
913
1067
 
914
- filter_specs(converged, deps)
1068
+ filter_specs(converged, deps, skips: @gems_to_unlock)
915
1069
  end
916
1070
 
917
1071
  def metadata_dependencies
@@ -922,17 +1076,20 @@ module Bundler
922
1076
  end
923
1077
 
924
1078
  def source_requirements
1079
+ @source_requirements ||= find_source_requirements
1080
+ end
1081
+
1082
+ def find_source_requirements
925
1083
  # Record the specs available in each gem's source, so that those
926
1084
  # specs will be available later when the resolver knows where to
927
1085
  # look for that gemspec (or its dependencies)
928
1086
  source_requirements = if precompute_source_requirements_for_indirect_dependencies?
929
1087
  all_requirements = source_map.all_requirements
930
- all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
931
1088
  { default: default_source }.merge(all_requirements)
932
1089
  else
933
1090
  { default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
934
1091
  end
935
- source_requirements.merge!(source_map.locked_requirements) unless @remote
1092
+ source_requirements.merge!(source_map.locked_requirements) if nothing_changed?
936
1093
  metadata_dependencies.each do |dep|
937
1094
  source_requirements[dep.name] = sources.metadata_source
938
1095
  end
@@ -946,7 +1103,6 @@ module Bundler
946
1103
  source_requirements["bundler"] = sources.metadata_source # needs to come last to override
947
1104
  end
948
1105
 
949
- verify_changed_sources!
950
1106
  source_requirements
951
1107
  end
952
1108
 
@@ -954,14 +1110,6 @@ module Bundler
954
1110
  sources.default_source
955
1111
  end
956
1112
 
957
- def verify_changed_sources!
958
- @specs_that_changed_sources.each do |s|
959
- if s.source.specs.search(s.name).empty?
960
- raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
961
- end
962
- end
963
- end
964
-
965
1113
  def requested_groups
966
1114
  values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
967
1115
  values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
@@ -982,28 +1130,53 @@ module Bundler
982
1130
  current == proposed
983
1131
  end
984
1132
 
985
- def additional_base_requirements_for_resolve(resolution_packages, last_resolve)
986
- return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
987
- converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
1133
+ def additional_base_requirements_to_prevent_downgrades(resolution_base)
1134
+ return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1135
+ @originally_locked_specs.each do |locked_spec|
988
1136
  next if locked_spec.source.is_a?(Source::Path)
989
- resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
1137
+
1138
+ name = locked_spec.name
1139
+ next if @changed_dependencies.include?(name)
1140
+
1141
+ resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
990
1142
  end
991
- resolution_packages
1143
+ resolution_base
992
1144
  end
993
1145
 
994
- def remove_invalid_platforms!(dependencies)
1146
+ def additional_base_requirements_to_force_updates(resolution_base)
1147
+ return resolution_base if @explicit_unlocks.empty?
1148
+ full_update = dup_for_full_unlock.resolve
1149
+ @explicit_unlocks.each do |name|
1150
+ version = full_update.version_for(name)
1151
+ resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1152
+ end
1153
+ resolution_base
1154
+ end
1155
+
1156
+ def dup_for_full_unlock
1157
+ unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
1158
+ unlocked_definition.source_requirements = source_requirements
1159
+ unlocked_definition.gem_version_promoter.tap do |gvp|
1160
+ gvp.level = gem_version_promoter.level
1161
+ gvp.strict = gem_version_promoter.strict
1162
+ gvp.pre = gem_version_promoter.pre
1163
+ end
1164
+ unlocked_definition
1165
+ end
1166
+
1167
+ def remove_invalid_platforms!
995
1168
  return if Bundler.frozen_bundle?
996
1169
 
997
- platforms.reverse_each do |platform|
998
- next if local_platform == platform ||
999
- (@new_platform && platforms.last == platform) ||
1000
- @path_changes ||
1001
- @dependency_changes ||
1002
- !@originally_locked_specs.incomplete_for_platform?(dependencies, platform)
1170
+ skips = (@new_platforms + [Bundler.local_platform]).uniq
1003
1171
 
1004
- remove_platform(platform)
1005
- add_current_platform if platform == Gem::Platform::RUBY
1006
- end
1172
+ # We should probably avoid removing non-ruby platforms, since that means
1173
+ # lockfile will no longer install on those platforms, so a error to give
1174
+ # heads up to the user may be better. However, we have tests expecting
1175
+ # non ruby platform autoremoval to work, so leaving that in place for
1176
+ # now.
1177
+ skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
1178
+
1179
+ @originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
1007
1180
  end
1008
1181
 
1009
1182
  def source_map