bundler 1.9.0 → 1.17.3

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