bundler 1.11.1 → 2.2.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (328) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +2125 -840
  3. data/LICENSE.md +18 -19
  4. data/README.md +33 -11
  5. data/bundler.gemspec +34 -21
  6. data/exe/bundle +36 -6
  7. data/exe/bundler +2 -18
  8. data/lib/bundler.rb +435 -160
  9. data/lib/bundler/build_metadata.rb +45 -0
  10. data/lib/bundler/capistrano.rb +9 -3
  11. data/lib/bundler/cli.rb +550 -130
  12. data/lib/bundler/cli/add.rb +47 -0
  13. data/lib/bundler/cli/binstubs.rb +26 -10
  14. data/lib/bundler/cli/cache.rb +25 -17
  15. data/lib/bundler/cli/check.rb +8 -7
  16. data/lib/bundler/cli/clean.rb +8 -8
  17. data/lib/bundler/cli/common.rb +69 -9
  18. data/lib/bundler/cli/config.rb +170 -76
  19. data/lib/bundler/cli/console.rb +6 -1
  20. data/lib/bundler/cli/doctor.rb +140 -0
  21. data/lib/bundler/cli/exec.rb +63 -21
  22. data/lib/bundler/cli/fund.rb +36 -0
  23. data/lib/bundler/cli/gem.rb +158 -42
  24. data/lib/bundler/cli/info.rb +73 -0
  25. data/lib/bundler/cli/init.rb +22 -7
  26. data/lib/bundler/cli/inject.rb +38 -10
  27. data/lib/bundler/cli/install.rb +139 -104
  28. data/lib/bundler/cli/issue.rb +40 -0
  29. data/lib/bundler/cli/list.rb +60 -0
  30. data/lib/bundler/cli/lock.rb +27 -5
  31. data/lib/bundler/cli/open.rb +13 -5
  32. data/lib/bundler/cli/outdated.rb +251 -46
  33. data/lib/bundler/cli/platform.rb +6 -2
  34. data/lib/bundler/cli/plugin.rb +41 -0
  35. data/lib/bundler/cli/pristine.rb +52 -0
  36. data/lib/bundler/cli/remove.rb +18 -0
  37. data/lib/bundler/cli/show.rb +5 -4
  38. data/lib/bundler/cli/update.rb +67 -26
  39. data/lib/bundler/cli/viz.rb +11 -6
  40. data/lib/bundler/compact_index_client.rb +125 -0
  41. data/lib/bundler/compact_index_client/cache.rb +110 -0
  42. data/lib/bundler/compact_index_client/gem_parser.rb +28 -0
  43. data/lib/bundler/compact_index_client/updater.rb +104 -0
  44. data/lib/bundler/constants.rb +2 -0
  45. data/lib/bundler/current_ruby.rb +51 -174
  46. data/lib/bundler/definition.rb +533 -216
  47. data/lib/bundler/dep_proxy.rb +18 -8
  48. data/lib/bundler/dependency.rb +39 -12
  49. data/lib/bundler/deployment.rb +7 -0
  50. data/lib/bundler/deprecate.rb +31 -2
  51. data/lib/bundler/dsl.rb +188 -91
  52. data/lib/bundler/endpoint_specification.rb +51 -10
  53. data/lib/bundler/env.rb +116 -48
  54. data/lib/bundler/environment_preserver.rb +82 -0
  55. data/lib/bundler/errors.rb +108 -31
  56. data/lib/bundler/feature_flag.rb +60 -0
  57. data/lib/bundler/fetcher.rb +81 -52
  58. data/lib/bundler/fetcher/base.rb +15 -3
  59. data/lib/bundler/fetcher/compact_index.rb +140 -0
  60. data/lib/bundler/fetcher/dependency.rb +36 -42
  61. data/lib/bundler/fetcher/downloader.rb +39 -12
  62. data/lib/bundler/fetcher/index.rb +34 -9
  63. data/lib/bundler/friendly_errors.rb +132 -88
  64. data/lib/bundler/gem_helper.rb +92 -50
  65. data/lib/bundler/gem_helpers.rb +90 -5
  66. data/lib/bundler/gem_tasks.rb +3 -1
  67. data/lib/bundler/gem_version_promoter.rb +190 -0
  68. data/lib/bundler/gemdeps.rb +29 -0
  69. data/lib/bundler/graph.rb +20 -41
  70. data/lib/bundler/index.rb +74 -57
  71. data/lib/bundler/injector.rb +242 -31
  72. data/lib/bundler/inline.rb +49 -23
  73. data/lib/bundler/installer.rb +190 -74
  74. data/lib/bundler/installer/gem_installer.rb +33 -20
  75. data/lib/bundler/installer/parallel_installer.rb +201 -97
  76. data/lib/bundler/installer/standalone.rb +10 -6
  77. data/lib/bundler/lazy_specification.rb +74 -10
  78. data/lib/bundler/lockfile_generator.rb +95 -0
  79. data/lib/bundler/lockfile_parser.rb +126 -74
  80. data/lib/bundler/{ssl_certs → man}/.document +0 -0
  81. data/lib/bundler/man/bundle-add.1 +66 -0
  82. data/lib/bundler/man/bundle-add.1.ronn +46 -0
  83. data/lib/bundler/man/bundle-binstubs.1 +42 -0
  84. data/lib/bundler/man/bundle-binstubs.1.ronn +41 -0
  85. data/lib/bundler/man/bundle-cache.1 +55 -0
  86. data/{man/bundle-package.ronn → lib/bundler/man/bundle-cache.1.ronn} +22 -16
  87. data/lib/bundler/man/bundle-check.1 +31 -0
  88. data/lib/bundler/man/bundle-check.1.ronn +26 -0
  89. data/lib/bundler/man/bundle-clean.1 +24 -0
  90. data/lib/bundler/man/bundle-clean.1.ronn +18 -0
  91. data/lib/bundler/man/bundle-config.1 +488 -0
  92. data/lib/bundler/man/bundle-config.1.ronn +388 -0
  93. data/lib/bundler/man/bundle-doctor.1 +44 -0
  94. data/lib/bundler/man/bundle-doctor.1.ronn +33 -0
  95. data/lib/bundler/man/bundle-exec.1 +165 -0
  96. data/{man/bundle-exec.ronn → lib/bundler/man/bundle-exec.1.ronn} +20 -4
  97. data/lib/bundler/man/bundle-gem.1 +102 -0
  98. data/{man/bundle-gem.ronn → lib/bundler/man/bundle-gem.1.ronn} +37 -13
  99. data/lib/bundler/man/bundle-info.1 +20 -0
  100. data/lib/bundler/man/bundle-info.1.ronn +17 -0
  101. data/lib/bundler/man/bundle-init.1 +25 -0
  102. data/lib/bundler/man/bundle-init.1.ronn +29 -0
  103. data/lib/bundler/man/bundle-inject.1 +33 -0
  104. data/lib/bundler/man/bundle-inject.1.ronn +22 -0
  105. data/lib/bundler/man/bundle-install.1 +338 -0
  106. data/{man/bundle-install.ronn → lib/bundler/man/bundle-install.1.ronn} +82 -76
  107. data/lib/bundler/man/bundle-list.1 +50 -0
  108. data/lib/bundler/man/bundle-list.1.ronn +33 -0
  109. data/lib/bundler/man/bundle-lock.1 +84 -0
  110. data/{man/bundle-lock.ronn → lib/bundler/man/bundle-lock.1.ronn} +47 -0
  111. data/lib/bundler/man/bundle-open.1 +32 -0
  112. data/lib/bundler/man/bundle-open.1.ronn +19 -0
  113. data/lib/bundler/man/bundle-outdated.1 +155 -0
  114. data/lib/bundler/man/bundle-outdated.1.ronn +111 -0
  115. data/lib/bundler/man/bundle-platform.1 +61 -0
  116. data/{man/bundle-platform.ronn → lib/bundler/man/bundle-platform.1.ronn} +1 -1
  117. data/lib/bundler/man/bundle-pristine.1 +34 -0
  118. data/lib/bundler/man/bundle-pristine.1.ronn +34 -0
  119. data/lib/bundler/man/bundle-remove.1 +31 -0
  120. data/lib/bundler/man/bundle-remove.1.ronn +23 -0
  121. data/lib/bundler/man/bundle-show.1 +23 -0
  122. data/lib/bundler/man/bundle-show.1.ronn +21 -0
  123. data/lib/bundler/man/bundle-update.1 +394 -0
  124. data/lib/bundler/man/bundle-update.1.ronn +350 -0
  125. data/lib/bundler/man/bundle-viz.1 +39 -0
  126. data/lib/bundler/man/bundle-viz.1.ronn +30 -0
  127. data/lib/bundler/man/bundle.1 +136 -0
  128. data/lib/bundler/man/bundle.1.ronn +111 -0
  129. data/lib/bundler/man/gemfile.5 +686 -0
  130. data/{man → lib/bundler/man}/gemfile.5.ronn +117 -95
  131. data/lib/bundler/man/index.txt +25 -0
  132. data/lib/bundler/match_platform.rb +15 -4
  133. data/lib/bundler/mirror.rb +223 -0
  134. data/lib/bundler/plugin.rb +330 -0
  135. data/lib/bundler/plugin/api.rb +81 -0
  136. data/lib/bundler/plugin/api/source.rb +304 -0
  137. data/lib/bundler/plugin/dsl.rb +53 -0
  138. data/lib/bundler/plugin/events.rb +61 -0
  139. data/lib/bundler/plugin/index.rb +182 -0
  140. data/lib/bundler/plugin/installer.rb +109 -0
  141. data/lib/bundler/plugin/installer/git.rb +38 -0
  142. data/lib/bundler/plugin/installer/rubygems.rb +27 -0
  143. data/lib/bundler/plugin/source_list.rb +27 -0
  144. data/lib/bundler/process_lock.rb +24 -0
  145. data/lib/bundler/psyched_yaml.rb +2 -6
  146. data/lib/bundler/remote_specification.rb +42 -9
  147. data/lib/bundler/resolver.rb +312 -225
  148. data/lib/bundler/resolver/spec_group.rb +122 -0
  149. data/lib/bundler/retry.rb +11 -5
  150. data/lib/bundler/ruby_dsl.rb +9 -2
  151. data/lib/bundler/ruby_version.rb +84 -61
  152. data/lib/bundler/rubygems_ext.rb +92 -53
  153. data/lib/bundler/rubygems_gem_installer.rb +84 -0
  154. data/lib/bundler/rubygems_integration.rb +320 -395
  155. data/lib/bundler/runtime.rb +87 -75
  156. data/lib/bundler/settings.rb +297 -119
  157. data/lib/bundler/settings/validator.rb +102 -0
  158. data/lib/bundler/setup.rb +13 -12
  159. data/lib/bundler/shared_helpers.rb +234 -53
  160. data/lib/bundler/similarity_detector.rb +5 -3
  161. data/lib/bundler/source.rb +63 -4
  162. data/lib/bundler/source/gemspec.rb +18 -0
  163. data/lib/bundler/source/git.rb +97 -50
  164. data/lib/bundler/source/git/git_proxy.rb +138 -65
  165. data/lib/bundler/source/metadata.rb +67 -0
  166. data/lib/bundler/source/path.rb +83 -47
  167. data/lib/bundler/source/path/installer.rb +42 -11
  168. data/lib/bundler/source/rubygems.rb +231 -116
  169. data/lib/bundler/source/rubygems/remote.rb +30 -1
  170. data/lib/bundler/source_list.rb +103 -21
  171. data/lib/bundler/spec_set.rb +96 -51
  172. data/lib/bundler/stub_specification.rb +87 -4
  173. data/lib/bundler/templates/.document +1 -0
  174. data/lib/bundler/templates/Executable +14 -1
  175. data/lib/bundler/templates/Executable.bundler +114 -0
  176. data/lib/bundler/templates/Executable.standalone +6 -4
  177. data/lib/bundler/templates/Gemfile +4 -1
  178. data/lib/bundler/templates/gems.rb +8 -0
  179. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +79 -44
  180. data/lib/bundler/templates/newgem/Gemfile.tt +18 -2
  181. data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
  182. data/lib/bundler/templates/newgem/README.md.tt +16 -10
  183. data/lib/bundler/templates/newgem/Rakefile.tt +22 -8
  184. data/lib/bundler/templates/newgem/bin/console.tt +2 -1
  185. data/lib/bundler/templates/newgem/circleci/config.yml.tt +13 -0
  186. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +2 -0
  187. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
  188. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
  189. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +18 -0
  190. data/lib/bundler/templates/newgem/gitignore.tt +5 -1
  191. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +9 -0
  192. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +9 -6
  193. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +6 -4
  194. data/lib/bundler/templates/newgem/newgem.gemspec.tt +27 -28
  195. data/lib/bundler/templates/newgem/rspec.tt +1 -0
  196. data/lib/bundler/templates/newgem/rubocop.yml.tt +13 -0
  197. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +4 -4
  198. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +15 -2
  199. data/lib/bundler/templates/newgem/test/{newgem_test.rb.tt → minitest/newgem_test.rb.tt} +3 -1
  200. data/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt +6 -0
  201. data/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt +15 -0
  202. data/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt +6 -0
  203. data/lib/bundler/templates/newgem/{.travis.yml.tt → travis.yml.tt} +2 -0
  204. data/lib/bundler/ui.rb +5 -3
  205. data/lib/bundler/ui/rg_proxy.rb +3 -1
  206. data/lib/bundler/ui/shell.rb +54 -21
  207. data/lib/bundler/ui/silent.rb +26 -1
  208. data/lib/bundler/uri_credentials_filter.rb +43 -0
  209. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +161 -0
  210. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +66 -0
  211. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +176 -0
  212. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +3 -0
  213. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1764 -0
  214. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +11 -5
  215. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
  216. data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +81 -0
  217. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +113 -134
  218. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
  219. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
  220. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
  221. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
  222. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
  223. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
  224. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
  225. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
  226. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +158 -0
  227. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +82 -8
  228. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +4 -1
  229. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +2 -0
  230. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +6 -2
  231. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +555 -150
  232. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +6 -3
  233. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +19 -12
  234. data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent.rb +310 -467
  235. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +40 -0
  236. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +53 -0
  237. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +79 -0
  238. data/lib/bundler/vendor/thor/lib/thor.rb +58 -25
  239. data/lib/bundler/vendor/thor/lib/thor/actions.rb +50 -33
  240. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +3 -2
  241. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +5 -3
  242. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +9 -19
  243. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +16 -8
  244. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +79 -22
  245. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +33 -20
  246. data/lib/bundler/vendor/thor/lib/thor/base.rb +110 -67
  247. data/lib/bundler/vendor/thor/lib/thor/command.rb +33 -24
  248. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -1
  249. data/lib/bundler/vendor/thor/lib/thor/error.rb +81 -3
  250. data/lib/bundler/vendor/thor/lib/thor/group.rb +16 -16
  251. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +5 -5
  252. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +2 -2
  253. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +2 -0
  254. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +6 -6
  255. data/lib/bundler/vendor/thor/lib/thor/nested_context.rb +29 -0
  256. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -4
  257. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +4 -7
  258. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +18 -18
  259. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +60 -26
  260. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +31 -13
  261. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +1 -0
  262. data/lib/bundler/vendor/thor/lib/thor/runner.rb +42 -39
  263. data/lib/bundler/vendor/thor/lib/thor/shell.rb +5 -5
  264. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +109 -39
  265. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +7 -3
  266. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +5 -5
  267. data/lib/bundler/vendor/thor/lib/thor/util.rb +26 -9
  268. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  269. data/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +154 -0
  270. data/lib/bundler/vendor/uri/lib/uri.rb +104 -0
  271. data/lib/bundler/vendor/uri/lib/uri/common.rb +744 -0
  272. data/lib/bundler/vendor/uri/lib/uri/file.rb +94 -0
  273. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +267 -0
  274. data/lib/bundler/vendor/uri/lib/uri/generic.rb +1568 -0
  275. data/lib/bundler/vendor/uri/lib/uri/http.rb +88 -0
  276. data/lib/bundler/vendor/uri/lib/uri/https.rb +23 -0
  277. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +261 -0
  278. data/lib/bundler/vendor/uri/lib/uri/ldaps.rb +21 -0
  279. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +294 -0
  280. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +546 -0
  281. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +125 -0
  282. data/lib/bundler/vendor/uri/lib/uri/version.rb +6 -0
  283. data/lib/bundler/vendored_fileutils.rb +4 -0
  284. data/lib/bundler/vendored_molinillo.rb +3 -1
  285. data/lib/bundler/vendored_persistent.rb +45 -9
  286. data/lib/bundler/vendored_thor.rb +8 -3
  287. data/lib/bundler/vendored_tmpdir.rb +4 -0
  288. data/lib/bundler/vendored_uri.rb +4 -0
  289. data/lib/bundler/version.rb +7 -4
  290. data/lib/bundler/version_ranges.rb +122 -0
  291. data/lib/bundler/vlad.rb +8 -2
  292. data/lib/bundler/worker.rb +38 -6
  293. data/lib/bundler/yaml_serializer.rb +89 -0
  294. metadata +164 -158
  295. data/.gitignore +0 -16
  296. data/.rspec +0 -3
  297. data/.rubocop.yml +0 -105
  298. data/.rubocop_todo.yml +0 -120
  299. data/.travis.yml +0 -97
  300. data/CODE_OF_CONDUCT.md +0 -42
  301. data/CONTRIBUTING.md +0 -32
  302. data/DEVELOPMENT.md +0 -118
  303. data/ISSUES.md +0 -96
  304. data/Rakefile +0 -309
  305. data/bin/rake +0 -14
  306. data/bin/rspec +0 -10
  307. data/bin/rubocop +0 -11
  308. data/exe/bundle_ruby +0 -60
  309. data/lib/bundler/cli/package.rb +0 -45
  310. data/lib/bundler/environment.rb +0 -41
  311. data/lib/bundler/gem_path_manipulation.rb +0 -8
  312. data/lib/bundler/gem_remote_fetcher.rb +0 -41
  313. data/lib/bundler/ssl_certs/AddTrustExternalCARoot-2048.pem +0 -25
  314. data/lib/bundler/ssl_certs/AddTrustExternalCARoot.pem +0 -32
  315. data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
  316. data/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +0 -23
  317. data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
  318. data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +0 -20
  319. data/lib/bundler/ssl_certs/certificate_manager.rb +0 -64
  320. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +0 -4
  321. data/lib/bundler/vendor/net/http/faster.rb +0 -26
  322. data/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb +0 -128
  323. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +0 -10
  324. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +0 -98
  325. data/man/bundle-config.ronn +0 -187
  326. data/man/bundle-update.ronn +0 -188
  327. data/man/bundle.ronn +0 -98
  328. data/man/index.txt +0 -8
@@ -1,12 +1,22 @@
1
- require "bundler/lockfile_parser"
2
- require "digest/sha1"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lockfile_parser"
3
4
  require "set"
4
5
 
5
6
  module Bundler
6
7
  class Definition
7
8
  include GemHelpers
8
9
 
9
- attr_reader :dependencies, :platforms, :ruby_version, :locked_deps
10
+ attr_reader(
11
+ :dependencies,
12
+ :locked_deps,
13
+ :locked_gems,
14
+ :platforms,
15
+ :requires,
16
+ :ruby_version,
17
+ :lockfile,
18
+ :gemfiles
19
+ )
10
20
 
11
21
  # Given a gemfile and lockfile creates a Bundler definition
12
22
  #
@@ -42,8 +52,16 @@ module Bundler
42
52
  # to be updated or true if all gems should be updated
43
53
  # @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
44
54
  # @param optional_groups [Array(String)] A list of optional groups
45
- def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [])
46
- @unlocking = unlock == true || !unlock.empty?
55
+ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
56
+ if [true, false].include?(unlock)
57
+ @unlocking_bundler = false
58
+ @unlocking = unlock
59
+ else
60
+ unlock = unlock.dup
61
+ @unlocking_bundler = unlock.delete(:bundler)
62
+ unlock.delete_if {|_k, v| Array(v).empty? }
63
+ @unlocking = !unlock.empty?
64
+ end
47
65
 
48
66
  @dependencies = dependencies
49
67
  @sources = sources
@@ -52,64 +70,83 @@ module Bundler
52
70
  @remote = false
53
71
  @specs = nil
54
72
  @ruby_version = ruby_version
73
+ @gemfiles = gemfiles
55
74
 
56
- @lockfile_contents = ""
75
+ @lockfile = lockfile
76
+ @lockfile_contents = String.new
57
77
  @locked_bundler_version = nil
78
+ @locked_ruby_version = nil
79
+ @locked_specs_incomplete_for_platform = false
80
+ @new_platform = nil
58
81
 
59
82
  if lockfile && File.exist?(lockfile)
60
83
  @lockfile_contents = Bundler.read_file(lockfile)
61
- locked = LockfileParser.new(@lockfile_contents)
62
- @platforms = locked.platforms
63
- @locked_bundler_version = locked.bundler_version
84
+ @locked_gems = LockfileParser.new(@lockfile_contents)
85
+ @locked_platforms = @locked_gems.platforms
86
+ if Bundler.settings[:force_ruby_platform]
87
+ @platforms = [Gem::Platform::RUBY]
88
+ else
89
+ @platforms = @locked_platforms.dup
90
+ end
91
+ @locked_bundler_version = @locked_gems.bundler_version
92
+ @locked_ruby_version = @locked_gems.ruby_version
64
93
 
65
94
  if unlock != true
66
- @locked_deps = locked.dependencies
67
- @locked_specs = SpecSet.new(locked.specs)
68
- @locked_sources = locked.sources
95
+ @locked_deps = @locked_gems.dependencies
96
+ @locked_specs = SpecSet.new(@locked_gems.specs)
97
+ @locked_sources = @locked_gems.sources
69
98
  else
70
99
  @unlock = {}
71
- @locked_deps = []
100
+ @locked_deps = {}
72
101
  @locked_specs = SpecSet.new([])
73
102
  @locked_sources = []
74
103
  end
75
104
  else
76
105
  @unlock = {}
77
106
  @platforms = []
78
- @locked_deps = []
107
+ @locked_gems = nil
108
+ @locked_deps = {}
79
109
  @locked_specs = SpecSet.new([])
80
110
  @locked_sources = []
111
+ @locked_platforms = []
81
112
  end
82
113
 
83
114
  @unlock[:gems] ||= []
84
115
  @unlock[:sources] ||= []
116
+ @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
117
+ @ruby_version.diff(locked_ruby_version_object)
118
+ end
119
+ @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
85
120
 
86
- current_platform = Bundler.rubygems.platforms.map {|p| generic(p) }.compact.last
87
- @new_platform = !@platforms.include?(current_platform)
88
- @platforms |= [current_platform]
121
+ add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
89
122
 
123
+ converge_path_sources_to_gemspec_sources
90
124
  @path_changes = converge_paths
91
- eager_unlock = expand_dependencies(@unlock[:gems])
92
- @unlock[:gems] = @locked_specs.for(eager_unlock).map(&:name)
93
-
94
125
  @source_changes = converge_sources
126
+
127
+ unless @unlock[:lock_shared_dependencies]
128
+ eager_unlock = expand_dependencies(@unlock[:gems], true)
129
+ @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
130
+ end
131
+
95
132
  @dependency_changes = converge_dependencies
96
133
  @local_changes = converge_locals
97
134
 
98
- fixup_dependency_types!
135
+ @requires = compute_requires
99
136
  end
100
137
 
101
- def fixup_dependency_types!
102
- # XXX This is a temporary workaround for a bug when using rubygems 1.8.15
103
- # where Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
104
- # doesn't carry a notion of the dependency type, if you use
105
- # add_development_dependency in a gemspec that's loaded with the gemspec
106
- # directive, the lockfile dependencies and resolved dependencies end up
107
- # with a mismatch on #type.
108
- # Test coverage to catch a regression on this is in gemspec_spec.rb
109
- @dependencies.each do |d|
110
- if ld = @locked_deps.find {|l| l.name == d.name }
111
- ld.instance_variable_set(:@type, d.type)
112
- end
138
+ def gem_version_promoter
139
+ @gem_version_promoter ||= begin
140
+ locked_specs =
141
+ if unlocking? && @locked_specs.empty? && !@lockfile_contents.empty?
142
+ # Definition uses an empty set of locked_specs to indicate all gems
143
+ # are unlocked, but GemVersionPromoter needs the locked_specs
144
+ # for conservative comparison.
145
+ Bundler::SpecSet.new(@locked_gems.specs)
146
+ else
147
+ @locked_specs
148
+ end
149
+ GemVersionPromoter.new(locked_specs, @unlock[:gems])
113
150
  end
114
151
  end
115
152
 
@@ -120,7 +157,7 @@ module Bundler
120
157
  end
121
158
 
122
159
  def resolve_remotely!
123
- raise "Specs already loaded" if @specs
160
+ return if @specs
124
161
  @remote = true
125
162
  sources.remote!
126
163
  specs
@@ -134,12 +171,20 @@ module Bundler
134
171
  # @return [Bundler::SpecSet]
135
172
  def specs
136
173
  @specs ||= begin
137
- specs = resolve.materialize(Bundler.settings[:cache_all_platforms] ? dependencies : requested_dependencies)
138
-
174
+ begin
175
+ specs = resolve.materialize(requested_dependencies)
176
+ rescue GemNotFound => e # Handle yanked gem
177
+ gem_name, gem_version = extract_gem_info(e)
178
+ locked_gem = @locked_specs[gem_name].last
179
+ raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
180
+ raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
181
+ "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
182
+ "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
183
+ "to a version other than #{locked_gem} that hasn't been removed in order to install."
184
+ end
139
185
  unless specs["bundler"].any?
140
- local = Bundler.settings[:frozen] ? rubygems_index : index
141
- bundler = local.search(Gem::Dependency.new("bundler", VERSION)).last
142
- specs["bundler"] = bundler if bundler
186
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
187
+ specs["bundler"] = bundler
143
188
  end
144
189
 
145
190
  specs
@@ -154,16 +199,27 @@ module Bundler
154
199
  @locked_specs - specs
155
200
  end
156
201
 
157
- def new_platform?
158
- @new_platform
159
- end
160
-
161
202
  def missing_specs
162
203
  missing = []
163
204
  resolve.materialize(requested_dependencies, missing)
164
205
  missing
165
206
  end
166
207
 
208
+ def missing_specs?
209
+ missing = missing_specs
210
+ return false if missing.empty?
211
+ Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
212
+ true
213
+ rescue BundlerError => e
214
+ @index = nil
215
+ @resolve = nil
216
+ @specs = nil
217
+ @gem_version_promoter = nil
218
+
219
+ Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
220
+ true
221
+ end
222
+
167
223
  def requested_specs
168
224
  @requested_specs ||= begin
169
225
  groups = requested_groups
@@ -172,16 +228,29 @@ module Bundler
172
228
  end
173
229
  end
174
230
 
231
+ def requested_dependencies
232
+ groups = requested_groups
233
+ groups.map!(&:to_sym)
234
+ dependencies_for(groups)
235
+ end
236
+
175
237
  def current_dependencies
176
- dependencies.reject {|d| !d.should_include? }
238
+ dependencies.select do |d|
239
+ d.should_include? && !d.gem_platforms(@platforms).empty?
240
+ end
177
241
  end
178
242
 
179
243
  def specs_for(groups)
180
- deps = dependencies.select {|d| (d.groups & groups).any? }
181
- deps.delete_if {|d| !d.should_include? }
244
+ deps = dependencies_for(groups)
182
245
  specs.for(expand_dependencies(deps))
183
246
  end
184
247
 
248
+ def dependencies_for(groups)
249
+ current_dependencies.reject do |d|
250
+ (d.groups & groups).empty?
251
+ end
252
+ end
253
+
185
254
  # Resolve all the dependencies specified in Gemfile. It ensures that
186
255
  # dependencies that have been already resolved via locked file and are fresh
187
256
  # are reused when resolving dependencies
@@ -190,13 +259,23 @@ module Bundler
190
259
  def resolve
191
260
  @resolve ||= begin
192
261
  last_resolve = converge_locked_specs
193
- if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
194
- last_resolve
195
- else
196
- # Run a resolve against the locally available gems
197
- requested_ruby_version = ruby_version.version if ruby_version
198
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, requested_ruby_version)
199
- end
262
+ resolve =
263
+ if Bundler.frozen_bundle?
264
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
265
+ last_resolve
266
+ elsif !unlocking? && nothing_changed?
267
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
268
+ last_resolve
269
+ else
270
+ # Run a resolve against the locally available gems
271
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
272
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
273
+ last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
274
+ end
275
+
276
+ # filter out gems that _can_ be installed on multiple platforms, but don't need
277
+ # to be
278
+ resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
200
279
  end
201
280
  end
202
281
 
@@ -205,41 +284,58 @@ module Bundler
205
284
  dependency_names = @dependencies.map(&:name)
206
285
 
207
286
  sources.all_sources.each do |source|
208
- source.dependency_names = dependency_names.dup
287
+ source.dependency_names = dependency_names - pinned_spec_names(source)
209
288
  idx.add_source source.specs
210
- dependency_names -= pinned_spec_names(source.specs)
211
- dependency_names.push(*source.unmet_deps).uniq!
289
+ dependency_names.concat(source.unmet_deps).uniq!
290
+ end
291
+
292
+ double_check_for_index(idx, dependency_names)
293
+ end
294
+ end
295
+
296
+ # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
297
+ # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
298
+ # but will not have found any versions of Bar from source B, which is a problem if the requested version
299
+ # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
300
+ # each spec we found, we add all possible versions from all sources to the index.
301
+ def double_check_for_index(idx, dependency_names)
302
+ pinned_names = pinned_spec_names
303
+ loop do
304
+ idxcount = idx.size
305
+
306
+ names = :names # do this so we only have to traverse to get dependency_names from the index once
307
+ unmet_dependency_names = lambda do
308
+ return names unless names == :names
309
+ new_names = sources.all_sources.map(&:dependency_names_to_double_check)
310
+ return names = nil if new_names.compact!
311
+ names = new_names.flatten(1).concat(dependency_names)
312
+ names.uniq!
313
+ names -= pinned_names
314
+ names
212
315
  end
213
- end
214
- end
215
316
 
216
- # used when frozen is enabled so we can find the bundler
217
- # spec, even if (say) a git gem is not checked out.
218
- def rubygems_index
219
- @rubygems_index ||= Index.build do |idx|
220
- sources.rubygems_sources.each do |rubygems|
221
- idx.add_source rubygems.specs
317
+ sources.all_sources.each do |source|
318
+ source.double_check_for(unmet_dependency_names)
222
319
  end
320
+
321
+ break if idxcount == idx.size
223
322
  end
224
323
  end
324
+ private :double_check_for_index
225
325
 
226
326
  def has_rubygems_remotes?
227
327
  sources.rubygems_sources.any? {|s| s.remotes.any? }
228
328
  end
229
329
 
230
- def has_local_dependencies?
231
- !sources.path_sources.empty? || !sources.git_sources.empty?
232
- end
233
-
234
330
  def spec_git_paths
235
- sources.git_sources.map {|s| s.path.to_s }
331
+ sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
236
332
  end
237
333
 
238
334
  def groups
239
335
  dependencies.map(&:groups).flatten.uniq
240
336
  end
241
337
 
242
- def lock(file, preserve_bundled_with = false)
338
+ def lock(file, preserve_unknown_sections = false)
243
339
  contents = to_lock
244
340
 
245
341
  # Convert to \r\n if the existing lock has them
@@ -256,10 +352,11 @@ module Bundler
256
352
  end
257
353
  end
258
354
 
259
- preserve_bundled_with ||= !updating_major && (Bundler.settings[:frozen] || !@unlocking)
260
- return if lockfiles_equal?(@lockfile_contents, contents, preserve_bundled_with)
355
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
261
356
 
262
- if Bundler.settings[:frozen]
357
+ return if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
358
+
359
+ if Bundler.frozen_bundle?
263
360
  Bundler.ui.error "Cannot write a changed lockfile while frozen."
264
361
  return
265
362
  end
@@ -269,9 +366,7 @@ module Bundler
269
366
  end
270
367
  end
271
368
 
272
- # Returns the version of Bundler that is creating or has created
273
- # Gemfile.lock. Used in #to_lock.
274
- def lock_version
369
+ def locked_bundler_version
275
370
  if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
276
371
  new_version = Bundler::VERSION
277
372
  end
@@ -279,68 +374,72 @@ module Bundler
279
374
  new_version || @locked_bundler_version || Bundler::VERSION
280
375
  end
281
376
 
282
- def to_lock
283
- out = ""
284
-
285
- sources.lock_sources.each do |source|
286
- # Add the source header
287
- out << source.to_lock
288
- # Find all specs for this source
289
- resolve.
290
- select {|s| source.can_lock?(s) }.
291
- # This needs to be sorted by full name so that
292
- # gems with the same name, but different platform
293
- # are ordered consistently
294
- sort_by(&:full_name).
295
- each do |spec|
296
- next if spec.name == "bundler"
297
- out << spec.to_lock
298
- end
299
- out << "\n"
300
- end
301
-
302
- out << "PLATFORMS\n"
303
-
304
- platforms.map(&:to_s).sort.each do |p|
305
- out << " #{p}\n"
377
+ def locked_ruby_version
378
+ return unless ruby_version
379
+ if @unlock[:ruby] || !@locked_ruby_version
380
+ Bundler::RubyVersion.system
381
+ else
382
+ @locked_ruby_version
306
383
  end
384
+ end
307
385
 
308
- out << "\n"
309
- out << "DEPENDENCIES\n"
310
-
311
- handled = []
312
- dependencies.sort_by(&:to_s).each do |dep|
313
- next if handled.include?(dep.name)
314
- out << dep.to_lock
315
- handled << dep.name
386
+ def locked_ruby_version_object
387
+ return unless @locked_ruby_version
388
+ @locked_ruby_version_object ||= begin
389
+ unless version = RubyVersion.from_string(@locked_ruby_version)
390
+ raise LockfileError, "The Ruby version #{@locked_ruby_version} from " \
391
+ "#{@lockfile} could not be parsed. " \
392
+ "Try running bundle update --ruby to resolve this."
393
+ end
394
+ version
316
395
  end
396
+ end
317
397
 
318
- # Record the version of Bundler that was used to create the lockfile
319
- out << "\nBUNDLED WITH\n"
320
- out << " #{lock_version}\n"
321
-
322
- out
398
+ def to_lock
399
+ require_relative "lockfile_generator"
400
+ LockfileGenerator.generate(self)
323
401
  end
324
402
 
325
403
  def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
326
- msg = "You are trying to install in deployment mode after changing\n" \
327
- "your Gemfile. Run `bundle install` elsewhere and add the\n" \
328
- "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
404
+ msg = String.new
405
+ msg << "You are trying to install in deployment mode after changing\n" \
406
+ "your Gemfile. Run `bundle install` elsewhere and add the\n" \
407
+ "updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
329
408
 
330
409
  unless explicit_flag
331
- msg += "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
332
- "freeze \nby running `bundle install --no-deployment`."
410
+ suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
411
+ "bundle config unset frozen"
412
+ elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
413
+ "bundle config unset deployment"
414
+ end
415
+ msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
416
+ "freeze \nby running `#{suggested_command}`."
333
417
  end
334
418
 
335
419
  added = []
336
420
  deleted = []
337
421
  changed = []
338
422
 
423
+ new_platforms = @platforms - @locked_platforms
424
+ deleted_platforms = @locked_platforms - @platforms
425
+ added.concat new_platforms.map {|p| "* platform: #{p}" }
426
+ deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
427
+
339
428
  gemfile_sources = sources.lock_sources
340
- if @locked_sources != gemfile_sources
341
- new_sources = gemfile_sources - @locked_sources
342
- deleted_sources = @locked_sources - gemfile_sources
343
429
 
430
+ new_sources = gemfile_sources - @locked_sources
431
+ deleted_sources = @locked_sources - gemfile_sources
432
+
433
+ new_deps = @dependencies - @locked_deps.values
434
+ deleted_deps = @locked_deps.values - @dependencies
435
+
436
+ # Check if it is possible that the source is only changed thing
437
+ if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
438
+ new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
439
+ deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
440
+ end
441
+
442
+ if @locked_sources != gemfile_sources
344
443
  if new_sources.any?
345
444
  added.concat new_sources.map {|source| "* source: #{source}" }
346
445
  end
@@ -350,38 +449,41 @@ module Bundler
350
449
  end
351
450
  end
352
451
 
353
- new_deps = @dependencies - @locked_deps
354
- deleted_deps = @locked_deps - @dependencies
355
-
356
452
  added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
357
-
358
453
  if deleted_deps.any?
359
454
  deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
360
455
  end
361
456
 
362
457
  both_sources = Hash.new {|h, k| h[k] = [] }
363
458
  @dependencies.each {|d| both_sources[d.name][0] = d }
364
- @locked_deps.each {|d| both_sources[d.name][1] = d.source }
459
+ @locked_deps.each {|name, d| both_sources[name][1] = d.source }
365
460
 
366
461
  both_sources.each do |name, (dep, lock_source)|
367
- next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
462
+ next if lock_source.nil? || (dep && lock_source.can_lock?(dep))
368
463
  gemfile_source_name = (dep && dep.source) || "no specified source"
369
- lockfile_source_name = lock_source || "no specified source"
464
+ lockfile_source_name = lock_source
370
465
  changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
371
466
  end
372
467
 
468
+ reason = change_reason
469
+ msg << "\n\n#{reason.split(", ").map(&:capitalize).join("\n")}" unless reason.strip.empty?
373
470
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
374
471
  msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
375
472
  msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
376
473
  msg << "\n"
377
474
 
378
- raise ProductionError, msg if added.any? || deleted.any? || changed.any?
475
+ raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed?
476
+ end
477
+
478
+ def validate_runtime!
479
+ validate_ruby!
480
+ validate_platforms!
379
481
  end
380
482
 
381
483
  def validate_ruby!
382
484
  return unless ruby_version
383
485
 
384
- if diff = ruby_version.diff(Bundler.ruby_version)
486
+ if diff = ruby_version.diff(Bundler::RubyVersion.system)
385
487
  problem, expected, actual = diff
386
488
 
387
489
  msg = case problem
@@ -390,7 +492,7 @@ module Bundler
390
492
  when :version
391
493
  "Your Ruby version is #{actual}, but your Gemfile specified #{expected}"
392
494
  when :engine_version
393
- "Your #{Bundler.ruby_version.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
495
+ "Your #{Bundler::RubyVersion.system.engine} version is #{actual}, but your Gemfile specified #{ruby_version.engine} #{expected}"
394
496
  when :patchlevel
395
497
  if !expected.is_a?(String)
396
498
  "The Ruby patchlevel in your Gemfile must be a string"
@@ -403,43 +505,117 @@ module Bundler
403
505
  end
404
506
  end
405
507
 
508
+ def validate_platforms!
509
+ return if current_platform_locked?
510
+
511
+ raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
512
+ "but your local platform is #{Bundler.local_platform}. " \
513
+ "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
514
+ end
515
+
516
+ def add_platform(platform)
517
+ @new_platform ||= !@platforms.include?(platform)
518
+ @platforms |= [platform]
519
+ end
520
+
521
+ def remove_platform(platform)
522
+ return if @platforms.delete(Gem::Platform.new(platform))
523
+ raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
524
+ end
525
+
526
+ def most_specific_locked_platform
527
+ @platforms.min_by do |bundle_platform|
528
+ platform_specificity_match(bundle_platform, local_platform)
529
+ end
530
+ end
531
+
532
+ def find_resolved_spec(current_spec)
533
+ specs.find_by_name_and_platform(current_spec.name, current_spec.platform)
534
+ end
535
+
536
+ def find_indexed_specs(current_spec)
537
+ index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
538
+ end
539
+
406
540
  attr_reader :sources
407
541
  private :sources
408
542
 
409
- private
410
-
411
543
  def nothing_changed?
412
- !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes
544
+ !@source_changes && !@dependency_changes && !@new_platform && !@path_changes && !@local_changes && !@locked_specs_incomplete_for_platform
545
+ end
546
+
547
+ def unlocking?
548
+ @unlocking
549
+ end
550
+
551
+ private
552
+
553
+ def current_ruby_platform_locked?
554
+ return false unless generic_local_platform == Gem::Platform::RUBY
555
+
556
+ current_platform_locked?
557
+ end
558
+
559
+ def current_platform_locked?
560
+ @platforms.any? do |bundle_platform|
561
+ MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform)
562
+ end
563
+ end
564
+
565
+ def add_current_platform
566
+ add_platform(local_platform)
567
+ end
568
+
569
+ def change_reason
570
+ if unlocking?
571
+ unlock_reason = @unlock.reject {|_k, v| Array(v).empty? }.map do |k, v|
572
+ if v == true
573
+ k.to_s
574
+ else
575
+ v = Array(v)
576
+ "#{k}: (#{v.join(", ")})"
577
+ end
578
+ end.join(", ")
579
+ return "bundler is unlocking #{unlock_reason}"
580
+ end
581
+ [
582
+ [@source_changes, "the list of sources changed"],
583
+ [@dependency_changes, "the dependencies in your gemfile changed"],
584
+ [@new_platform, "you added a new platform to your gemfile"],
585
+ [@path_changes, "the gemspecs for path gems changed"],
586
+ [@local_changes, "the gemspecs for git local gems changed"],
587
+ [@locked_specs_incomplete_for_platform, "the lockfile does not have all gems needed for the current platform"],
588
+ ].select(&:first).map(&:last).join(", ")
413
589
  end
414
590
 
415
591
  def pretty_dep(dep, source = false)
416
- msg = "#{dep.name}"
417
- msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
418
- msg << " from the `#{dep.source}` source" if source && dep.source
419
- msg
592
+ SharedHelpers.pretty_dependency(dep, source)
420
593
  end
421
594
 
422
595
  # Check if the specs of the given source changed
423
- # according to the locked source. A block should be
424
- # in order to specify how the locked version of
425
- # the source should be found.
426
- def specs_changed?(source, &block)
427
- locked = @locked_sources.find(&block)
428
-
429
- if locked
430
- unlocking = @locked_specs.any? do |locked_spec|
431
- locked_spec.source.class == locked.class && locked_spec.source != locked
432
- end
433
- end
596
+ # according to the locked source.
597
+ def specs_changed?(source)
598
+ locked = @locked_sources.find {|s| s == source }
434
599
 
435
- !locked || unlocking || dependencies_for_source_changed?(locked) || source.specs != locked.specs
600
+ !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
436
601
  end
437
602
 
438
- def dependencies_for_source_changed?(source)
603
+ def dependencies_for_source_changed?(source, locked_source = source)
439
604
  deps_for_source = @dependencies.select {|s| s.source == source }
440
- locked_deps_for_source = @locked_deps.select {|s| s.source == source }
605
+ locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
606
+
607
+ Set.new(deps_for_source) != Set.new(locked_deps_for_source)
608
+ end
609
+
610
+ def specs_for_source_changed?(source)
611
+ locked_index = Index.new
612
+ locked_index.use(@locked_specs.select {|s| source.can_lock?(s) })
441
613
 
442
- deps_for_source != locked_deps_for_source
614
+ # order here matters, since Index#== is checking source.specs.include?(locked_index)
615
+ locked_index != source.specs
616
+ rescue PathError, GitError => e
617
+ Bundler.ui.debug "Assuming that #{source} has not changed since fetching its specs errored (#{e})"
618
+ false
443
619
  end
444
620
 
445
621
  # Get all locals and override their matching sources.
@@ -457,35 +633,62 @@ module Bundler
457
633
  end
458
634
  end
459
635
 
460
- locals.any? do |source, changed|
461
- changed || specs_changed?(source) {|o| source.class == o.class && source.uri == o.uri }
462
- end
636
+ sources_with_changes = locals.select do |source, changed|
637
+ changed || specs_changed?(source)
638
+ end.map(&:first)
639
+ !sources_with_changes.each {|source| @unlock[:sources] << source.name }.empty?
463
640
  end
464
641
 
465
642
  def converge_paths
466
643
  sources.path_sources.any? do |source|
467
- specs_changed?(source) do |ls|
468
- ls.class == source.class && ls.path == source.path
469
- end
644
+ specs_changed?(source)
470
645
  end
471
646
  end
472
647
 
473
- def converge_sources
648
+ def converge_path_source_to_gemspec_source(source)
649
+ return source unless source.instance_of?(Source::Path)
650
+ gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
651
+ gemspec_source || source
652
+ end
653
+
654
+ def converge_path_sources_to_gemspec_sources
655
+ @locked_sources.map! do |source|
656
+ converge_path_source_to_gemspec_source(source)
657
+ end
658
+ @locked_specs.each do |spec|
659
+ spec.source &&= converge_path_source_to_gemspec_source(spec.source)
660
+ end
661
+ @locked_deps.each do |_, dep|
662
+ dep.source &&= converge_path_source_to_gemspec_source(dep.source)
663
+ end
664
+ end
665
+
666
+ def converge_rubygems_sources
667
+ return false if Bundler.feature_flag.disable_multisource?
668
+
474
669
  changes = false
475
670
 
476
- # Get the Rubygems sources from the Gemfile.lock
671
+ # Get the RubyGems sources from the Gemfile.lock
477
672
  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
478
- # Get the Rubygems remotes from the Gemfile
673
+ # Get the RubyGems remotes from the Gemfile
479
674
  actual_remotes = sources.rubygems_remotes
480
675
 
481
- # If there is a Rubygems source in both
676
+ # If there is a RubyGems source in both
482
677
  if !locked_gem_sources.empty? && !actual_remotes.empty?
483
678
  locked_gem_sources.each do |locked_gem|
484
679
  # Merge the remotes from the Gemfile into the Gemfile.lock
485
- changes |= locked_gem.replace_remotes(actual_remotes)
680
+ changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
486
681
  end
487
682
  end
488
683
 
684
+ changes
685
+ end
686
+
687
+ def converge_sources
688
+ changes = false
689
+
690
+ changes |= converge_rubygems_sources
691
+
489
692
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
490
693
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
491
694
  # source in the Gemfile.lock, use the one from the Gemfile.
@@ -507,10 +710,43 @@ module Bundler
507
710
  end
508
711
 
509
712
  def converge_dependencies
510
- (@dependencies + @locked_deps).each do |dep|
511
- dep.source = sources.get(dep.source) if dep.source
713
+ frozen = Bundler.frozen_bundle?
714
+ (@dependencies + @locked_deps.values).each do |dep|
715
+ locked_source = @locked_deps[dep.name]
716
+ # This is to make sure that if bundler is installing in deployment mode and
717
+ # after locked_source and sources don't match, we still use locked_source.
718
+ if frozen && !locked_source.nil? &&
719
+ locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
720
+ dep.source = locked_source.source
721
+ elsif dep.source
722
+ dep.source = sources.get(dep.source)
723
+ end
512
724
  end
513
- Set.new(@dependencies) != Set.new(@locked_deps)
725
+
726
+ changes = false
727
+ # We want to know if all match, but don't want to check all entries
728
+ # This means we need to return false if any dependency doesn't match
729
+ # the lock or doesn't exist in the lock.
730
+ @dependencies.each do |dependency|
731
+ unless locked_dep = @locked_deps[dependency.name]
732
+ changes = true
733
+ next
734
+ end
735
+
736
+ # Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
737
+ # doesn't carry a notion of the dependency type, if you use
738
+ # add_development_dependency in a gemspec that's loaded with the gemspec
739
+ # directive, the lockfile dependencies and resolved dependencies end up
740
+ # with a mismatch on #type. Work around that by setting the type on the
741
+ # dep from the lockfile.
742
+ locked_dep.instance_variable_set(:@type, dependency.type)
743
+
744
+ # We already know the name matches from the hash lookup
745
+ # so we only need to check the requirement now
746
+ changes ||= dependency.requirement != locked_dep.requirement
747
+ end
748
+
749
+ changes
514
750
  end
515
751
 
516
752
  # Remove elements from the locked specs that are expired. This will most
@@ -523,12 +759,11 @@ module Bundler
523
759
  # and Gemfile.lock. If the Gemfile modified a dependency, but
524
760
  # the gem in the Gemfile.lock still satisfies it, this is fine
525
761
  # too.
526
- locked_deps_hash = @locked_deps.inject({}) do |hsh, dep|
527
- hsh[dep] = dep
528
- hsh
529
- end
530
762
  @dependencies.each do |dep|
531
- locked_dep = locked_deps_hash[dep]
763
+ locked_dep = @locked_deps[dep.name]
764
+
765
+ # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
766
+ locked_dep = nil unless locked_dep == dep
532
767
 
533
768
  if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
534
769
  deps << dep
@@ -542,6 +777,8 @@ module Bundler
542
777
  end
543
778
  end
544
779
 
780
+ unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
781
+
545
782
  converged = []
546
783
  @locked_specs.each do |s|
547
784
  # Replace the locked dependency's source with the equivalent source from the Gemfile
@@ -549,42 +786,56 @@ module Bundler
549
786
  s.source = (dep && dep.source) || sources.get(s.source)
550
787
 
551
788
  # Don't add a spec to the list if its source is expired. For example,
552
- # if you change a Git gem to Rubygems.
553
- next if s.source.nil? || @unlock[:sources].include?(s.source.name)
789
+ # if you change a Git gem to RubyGems.
790
+ next if s.source.nil?
791
+ next if @unlock[:sources].include?(s.source.name)
554
792
 
555
793
  # XXX This is a backwards-compatibility fix to preserve the ability to
556
794
  # unlock a single gem by passing its name via `--source`. See issue #3759
557
- next if s.source.nil? || @unlock[:sources].include?(s.name)
795
+ # TODO: delete in Bundler 2
796
+ next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
558
797
 
559
798
  # If the spec is from a path source and it doesn't exist anymore
560
- # then we just unlock it.
799
+ # then we unlock it.
561
800
 
562
801
  # Path sources have special logic
563
- if s.source.instance_of?(Source::Path)
564
- other = s.source.specs[s].first
802
+ if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
803
+ new_specs = begin
804
+ s.source.specs
805
+ rescue PathError, GitError
806
+ # if we won't need the source (according to the lockfile),
807
+ # don't error if the path/git source isn't available
808
+ next if @locked_specs.
809
+ for(requested_dependencies, [], false, true, false).
810
+ none? {|locked_spec| locked_spec.source == s.source }
811
+
812
+ raise
813
+ end
814
+
815
+ new_spec = new_specs[s].first
565
816
 
566
817
  # If the spec is no longer in the path source, unlock it. This
567
818
  # commonly happens if the version changed in the gemspec
568
- next unless other
819
+ next unless new_spec
569
820
 
570
- deps2 = other.dependencies.select {|d| d.type != :development }
571
- # If the dependencies of the path source have changed, unlock it
572
- next unless s.dependencies.sort == deps2.sort
821
+ s.dependencies.replace(new_spec.dependencies)
573
822
  end
574
823
 
575
824
  converged << s
576
825
  end
577
826
 
578
827
  resolve = SpecSet.new(converged)
579
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems])
580
- diff = @locked_specs.to_a - resolve.to_a
828
+ @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(requested_dependencies & deps), @unlock[:gems], true, true)
829
+ resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
830
+ diff = nil
581
831
 
582
832
  # Now, we unlock any sources that do not have anymore gems pinned to it
583
833
  sources.all_sources.each do |source|
584
834
  next unless source.respond_to?(:unlock!)
585
835
 
586
836
  unless resolve.any? {|s| s.source == source }
587
- source.unlock! if !diff.empty? && diff.any? {|s| s.source == source }
837
+ diff ||= @locked_specs.to_a - resolve.to_a
838
+ source.unlock! if diff.any? {|s| s.source == source }
588
839
  end
589
840
  end
590
841
 
@@ -599,11 +850,33 @@ module Bundler
599
850
  end
600
851
 
601
852
  def satisfies_locked_spec?(dep)
602
- @locked_specs.any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
853
+ @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
854
+ end
855
+
856
+ def metadata_dependencies
857
+ @metadata_dependencies ||= begin
858
+ ruby_versions = ruby_version_requirements(@ruby_version)
859
+ [
860
+ Dependency.new("Ruby\0", ruby_versions),
861
+ Dependency.new("RubyGems\0", Gem::VERSION),
862
+ ]
863
+ end
603
864
  end
604
865
 
605
- def expanded_dependencies
606
- @expanded_dependencies ||= expand_dependencies(dependencies, @remote)
866
+ def ruby_version_requirements(ruby_version)
867
+ return [] unless ruby_version
868
+ if ruby_version.patchlevel
869
+ [ruby_version.to_gem_version_with_patchlevel]
870
+ else
871
+ ruby_version.versions.map do |version|
872
+ requirement = Gem::Requirement.new(version)
873
+ if requirement.exact?
874
+ "~> #{version}.0"
875
+ else
876
+ requirement
877
+ end
878
+ end
879
+ end
607
880
  end
608
881
 
609
882
  def expand_dependencies(dependencies, remote = false)
@@ -611,17 +884,16 @@ module Bundler
611
884
  dependencies.each do |dep|
612
885
  dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
613
886
  next unless remote || dep.current_platform?
614
- dep.gem_platforms(@platforms).each do |p|
615
- deps << DepProxy.new(dep, p) if remote || p == generic(Gem::Platform.local)
616
- end
887
+ target_platforms = dep.gem_platforms(remote ? Resolver.sort_platforms(@platforms) : [generic_local_platform])
888
+ deps += expand_dependency_with_platforms(dep, target_platforms)
617
889
  end
618
890
  deps
619
891
  end
620
892
 
621
- def requested_dependencies
622
- groups = requested_groups
623
- groups.map!(&:to_sym)
624
- dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? }
893
+ def expand_dependency_with_platforms(dep, platforms)
894
+ platforms.map do |p|
895
+ DepProxy.get_proxy(dep, p)
896
+ end
625
897
  end
626
898
 
627
899
  def source_requirements
@@ -631,39 +903,84 @@ module Bundler
631
903
  # Record the specs available in each gem's source, so that those
632
904
  # specs will be available later when the resolver knows where to
633
905
  # look for that gemspec (or its dependencies)
634
- source_requirements = {}
906
+ default = sources.default_source
907
+ source_requirements = { :default => default }
908
+ default = nil unless Bundler.feature_flag.disable_multisource?
635
909
  dependencies.each do |dep|
636
- next unless dep.source
637
- source_requirements[dep.name] = dep.source.specs
910
+ next unless source = dep.source || default
911
+ source_requirements[dep.name] = source
638
912
  end
913
+ metadata_dependencies.each do |dep|
914
+ source_requirements[dep.name] = sources.metadata_source
915
+ end
916
+ source_requirements["bundler"] = sources.metadata_source # needs to come last to override
639
917
  source_requirements
640
918
  end
641
919
 
642
- def pinned_spec_names(specs)
643
- names = []
644
- specs.each do |s|
645
- # TODO: when two sources without blocks is an error, we can change
646
- # this check to !s.source.is_a?(Source::LocalRubygems). For now,
647
- # we need to ask every Rubygems for every gem name.
648
- if s.source.is_a?(Source::Git) || s.source.is_a?(Source::Path)
649
- names << s.name
650
- end
920
+ def pinned_spec_names(skip = nil)
921
+ pinned_names = []
922
+ default = Bundler.feature_flag.disable_multisource? && sources.default_source
923
+ @dependencies.each do |dep|
924
+ next unless dep_source = dep.source || default
925
+ next if dep_source == skip
926
+ pinned_names << dep.name
651
927
  end
652
- names.uniq!
653
- names
928
+ pinned_names
654
929
  end
655
930
 
656
931
  def requested_groups
657
- groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
932
+ groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
658
933
  end
659
934
 
660
- def lockfiles_equal?(current, proposed, preserve_bundled_with)
661
- if preserve_bundled_with
662
- pattern = /\n\n#{LockfileParser::BUNDLED}\n\s+#{Gem::Version::VERSION_PATTERN}\n/
663
- current.sub(pattern, "\n") == proposed.sub(pattern, "\n")
664
- else
665
- current == proposed
935
+ def lockfiles_equal?(current, proposed, preserve_unknown_sections)
936
+ if preserve_unknown_sections
937
+ sections_to_ignore = LockfileParser.sections_to_ignore(@locked_bundler_version)
938
+ sections_to_ignore += LockfileParser.unknown_sections_in_lockfile(current)
939
+ sections_to_ignore += LockfileParser::ENVIRONMENT_VERSION_SECTIONS
940
+ pattern = /#{Regexp.union(sections_to_ignore)}\n(\s{2,}.*\n)+/
941
+ whitespace_cleanup = /\n{2,}/
942
+ current = current.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
943
+ proposed = proposed.gsub(pattern, "\n").gsub(whitespace_cleanup, "\n\n").strip
944
+ end
945
+ current == proposed
946
+ end
947
+
948
+ def extract_gem_info(error)
949
+ # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
950
+ # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
951
+ error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
952
+ end
953
+
954
+ def compute_requires
955
+ dependencies.reduce({}) do |requires, dep|
956
+ next requires unless dep.should_include?
957
+ requires[dep.name] = Array(dep.autorequire || dep.name).map do |file|
958
+ # Allow `require: true` as an alias for `require: <name>`
959
+ file == true ? dep.name : file
960
+ end
961
+ requires
666
962
  end
667
963
  end
964
+
965
+ def additional_base_requirements_for_resolve
966
+ return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
967
+ dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
968
+ @locked_gems.specs.reduce({}) do |requirements, locked_spec|
969
+ name = locked_spec.name
970
+ dependency = dependencies_by_name[name]
971
+ next requirements unless dependency
972
+ next requirements if @locked_gems.dependencies[name] != dependency
973
+ next requirements if dependency.source.is_a?(Source::Path)
974
+ dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
975
+ requirements[name] = DepProxy.get_proxy(dep, locked_spec.platform)
976
+ requirements
977
+ end.values
978
+ end
979
+
980
+ def equivalent_rubygems_remotes?(source)
981
+ return false unless source.is_a?(Source::Rubygems)
982
+
983
+ Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
984
+ end
668
985
  end
669
986
  end