rubygems-update 3.3.26 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/CONTRIBUTING.md +24 -1
  4. data/Manifest.txt +30 -27
  5. data/POLICIES.md +10 -8
  6. data/README.md +2 -2
  7. data/bin/gem +1 -4
  8. data/bin/update_rubygems +1 -1
  9. data/bundler/CHANGELOG.md +59 -0
  10. data/bundler/README.md +2 -2
  11. data/bundler/bundler.gemspec +2 -2
  12. data/bundler/exe/bundle +1 -4
  13. data/bundler/lib/bundler/build_metadata.rb +2 -2
  14. data/bundler/lib/bundler/cli/add.rb +1 -1
  15. data/bundler/lib/bundler/cli/check.rb +1 -1
  16. data/bundler/lib/bundler/cli/common.rb +1 -0
  17. data/bundler/lib/bundler/cli/console.rb +2 -2
  18. data/bundler/lib/bundler/cli/doctor.rb +4 -6
  19. data/bundler/lib/bundler/cli/gem.rb +62 -40
  20. data/bundler/lib/bundler/cli/install.rb +2 -3
  21. data/bundler/lib/bundler/cli/lock.rb +8 -5
  22. data/bundler/lib/bundler/cli/outdated.rb +1 -3
  23. data/bundler/lib/bundler/cli/viz.rb +1 -1
  24. data/bundler/lib/bundler/cli.rb +43 -2
  25. data/bundler/lib/bundler/compact_index_client/cache.rb +1 -1
  26. data/bundler/lib/bundler/compact_index_client/updater.rb +40 -39
  27. data/bundler/lib/bundler/constants.rb +1 -1
  28. data/bundler/lib/bundler/definition.rb +61 -31
  29. data/bundler/lib/bundler/dependency.rb +12 -11
  30. data/bundler/lib/bundler/digest.rb +1 -1
  31. data/bundler/lib/bundler/dsl.rb +1 -1
  32. data/bundler/lib/bundler/env.rb +1 -1
  33. data/bundler/lib/bundler/environment_preserver.rb +1 -0
  34. data/bundler/lib/bundler/errors.rb +1 -11
  35. data/bundler/lib/bundler/fetcher/compact_index.rb +9 -11
  36. data/bundler/lib/bundler/fetcher/dependency.rb +1 -1
  37. data/bundler/lib/bundler/fetcher/downloader.rb +2 -5
  38. data/bundler/lib/bundler/fetcher.rb +2 -6
  39. data/bundler/lib/bundler/force_platform.rb +18 -0
  40. data/bundler/lib/bundler/friendly_errors.rb +0 -3
  41. data/bundler/lib/bundler/gem_version_promoter.rb +52 -86
  42. data/bundler/lib/bundler/graph.rb +3 -3
  43. data/bundler/lib/bundler/index.rb +5 -13
  44. data/bundler/lib/bundler/injector.rb +1 -1
  45. data/bundler/lib/bundler/inline.rb +2 -2
  46. data/bundler/lib/bundler/installer/parallel_installer.rb +0 -31
  47. data/bundler/lib/bundler/installer.rb +6 -16
  48. data/bundler/lib/bundler/lazy_specification.rb +5 -1
  49. data/bundler/lib/bundler/lockfile_parser.rb +5 -5
  50. data/bundler/lib/bundler/man/bundle-add.1 +1 -1
  51. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  52. data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
  53. data/bundler/lib/bundler/man/bundle-check.1 +1 -1
  54. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  55. data/bundler/lib/bundler/man/bundle-config.1 +1 -1
  56. data/bundler/lib/bundler/man/bundle-console.1 +1 -1
  57. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  58. data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
  59. data/bundler/lib/bundler/man/bundle-gem.1 +27 -37
  60. data/bundler/lib/bundler/man/bundle-gem.1.ronn +5 -5
  61. data/bundler/lib/bundler/man/bundle-help.1 +1 -1
  62. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  63. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  64. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  65. data/bundler/lib/bundler/man/bundle-install.1 +1 -30
  66. data/bundler/lib/bundler/man/bundle-install.1.ronn +0 -29
  67. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  68. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  69. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  70. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  71. data/bundler/lib/bundler/man/bundle-platform.1 +2 -2
  72. data/bundler/lib/bundler/man/bundle-platform.1.ronn +1 -1
  73. data/bundler/lib/bundler/man/bundle-plugin.1 +1 -1
  74. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  75. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  76. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  77. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  78. data/bundler/lib/bundler/man/bundle-version.1 +1 -1
  79. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  80. data/bundler/lib/bundler/man/bundle.1 +1 -1
  81. data/bundler/lib/bundler/man/gemfile.5 +1 -1
  82. data/bundler/lib/bundler/mirror.rb +5 -7
  83. data/bundler/lib/bundler/plugin/index.rb +4 -4
  84. data/bundler/lib/bundler/plugin/installer/rubygems.rb +0 -4
  85. data/bundler/lib/bundler/resolver/base.rb +7 -11
  86. data/bundler/lib/bundler/resolver/candidate.rb +92 -0
  87. data/bundler/lib/bundler/resolver/incompatibility.rb +15 -0
  88. data/bundler/lib/bundler/resolver/package.rb +63 -0
  89. data/bundler/lib/bundler/resolver/root.rb +25 -0
  90. data/bundler/lib/bundler/resolver/spec_group.rb +26 -36
  91. data/bundler/lib/bundler/resolver.rb +294 -277
  92. data/bundler/lib/bundler/rubygems_ext.rb +11 -6
  93. data/bundler/lib/bundler/rubygems_gem_installer.rb +4 -2
  94. data/bundler/lib/bundler/rubygems_integration.rb +1 -9
  95. data/bundler/lib/bundler/runtime.rb +1 -5
  96. data/bundler/lib/bundler/settings.rb +0 -6
  97. data/bundler/lib/bundler/shared_helpers.rb +1 -0
  98. data/bundler/lib/bundler/source/git/git_proxy.rb +193 -67
  99. data/bundler/lib/bundler/source/git.rb +15 -17
  100. data/bundler/lib/bundler/source/metadata.rb +0 -1
  101. data/bundler/lib/bundler/source/path/installer.rb +1 -22
  102. data/bundler/lib/bundler/source/path.rb +5 -5
  103. data/bundler/lib/bundler/source/rubygems.rb +13 -67
  104. data/bundler/lib/bundler/source_list.rb +8 -2
  105. data/bundler/lib/bundler/spec_set.rb +7 -9
  106. data/bundler/lib/bundler/templates/Executable +1 -1
  107. data/bundler/lib/bundler/templates/Executable.bundler +4 -9
  108. data/bundler/lib/bundler/templates/Executable.standalone +2 -0
  109. data/bundler/lib/bundler/templates/newgem/Cargo.toml.tt +7 -0
  110. data/bundler/lib/bundler/templates/newgem/Gemfile.tt +3 -0
  111. data/bundler/lib/bundler/templates/newgem/README.md.tt +6 -4
  112. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +2 -1
  113. data/bundler/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  114. data/bundler/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +15 -0
  115. data/bundler/lib/bundler/templates/newgem/ext/newgem/{extconf.rb.tt → extconf-c.rb.tt} +0 -0
  116. data/bundler/lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt +6 -0
  117. data/bundler/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +12 -0
  118. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +10 -0
  119. data/bundler/lib/bundler/templates/newgem/gitignore.tt +3 -0
  120. data/bundler/lib/bundler/templates/newgem/gitlab-ci.yml.tt +8 -0
  121. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
  122. data/bundler/lib/bundler/ui/shell.rb +35 -12
  123. data/bundler/lib/bundler/ui/silent.rb +21 -5
  124. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +3 -3
  125. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -1
  126. data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +3 -1
  127. data/bundler/lib/bundler/vendor/fileutils/lib/fileutils.rb +1350 -408
  128. data/bundler/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  129. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  130. data/bundler/lib/bundler/vendor/pub_grub/LICENSE.txt +21 -0
  131. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  132. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +189 -0
  133. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  134. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb +151 -0
  135. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb +43 -0
  136. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  137. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  138. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb +19 -0
  139. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb +53 -0
  140. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  141. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  142. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb +124 -0
  143. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +409 -0
  144. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +240 -0
  145. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb +178 -0
  146. data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +31 -0
  147. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +1 -1
  148. data/bundler/lib/bundler/vendor/uri/lib/uri/common.rb +64 -16
  149. data/bundler/lib/bundler/vendor/uri/lib/uri/file.rb +7 -1
  150. data/bundler/lib/bundler/vendor/uri/lib/uri/ftp.rb +2 -1
  151. data/bundler/lib/bundler/vendor/uri/lib/uri/generic.rb +27 -7
  152. data/bundler/lib/bundler/vendor/uri/lib/uri/http.rb +40 -2
  153. data/bundler/lib/bundler/vendor/uri/lib/uri/https.rb +2 -1
  154. data/bundler/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  155. data/bundler/lib/bundler/vendor/uri/lib/uri/ldaps.rb +2 -1
  156. data/bundler/lib/bundler/vendor/uri/lib/uri/mailto.rb +2 -2
  157. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +13 -7
  158. data/bundler/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +10 -5
  159. data/bundler/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  160. data/bundler/lib/bundler/vendor/uri/lib/uri/ws.rb +1 -2
  161. data/bundler/lib/bundler/vendor/uri/lib/uri/wss.rb +2 -1
  162. data/bundler/lib/bundler/vendor/uri/lib/uri.rb +3 -2
  163. data/bundler/lib/bundler/vendored_persistent.rb +1 -33
  164. data/bundler/lib/bundler/{vendored_tmpdir.rb → vendored_pub_grub.rb} +1 -1
  165. data/bundler/lib/bundler/version.rb +5 -1
  166. data/bundler/lib/bundler/worker.rb +5 -7
  167. data/bundler/lib/bundler.rb +20 -64
  168. data/lib/rubygems/command_manager.rb +2 -2
  169. data/lib/rubygems/commands/fetch_command.rb +1 -1
  170. data/lib/rubygems/commands/install_command.rb +7 -3
  171. data/lib/rubygems/commands/rdoc_command.rb +3 -2
  172. data/lib/rubygems/commands/setup_command.rb +2 -2
  173. data/lib/rubygems/commands/unpack_command.rb +1 -1
  174. data/lib/rubygems/commands/update_command.rb +1 -7
  175. data/lib/rubygems/config_file.rb +33 -0
  176. data/lib/rubygems/core_ext/kernel_warn.rb +1 -2
  177. data/lib/rubygems/defaults.rb +15 -1
  178. data/lib/rubygems/dependency.rb +4 -1
  179. data/lib/rubygems/dependency_installer.rb +24 -24
  180. data/lib/rubygems/exceptions.rb +1 -3
  181. data/lib/rubygems/ext/builder.rb +3 -3
  182. data/lib/rubygems/ext/cargo_builder/link_flag_converter.rb +9 -5
  183. data/lib/rubygems/ext/cargo_builder.rb +15 -20
  184. data/lib/rubygems/ext/ext_conf_builder.rb +2 -0
  185. data/lib/rubygems/indexer.rb +1 -1
  186. data/lib/rubygems/installer.rb +5 -5
  187. data/lib/rubygems/optparse/lib/optparse.rb +20 -15
  188. data/lib/rubygems/package/tar_header.rb +11 -11
  189. data/lib/rubygems/platform.rb +0 -2
  190. data/lib/rubygems/request_set/gem_dependency_api.rb +104 -104
  191. data/lib/rubygems/requirement.rb +7 -7
  192. data/lib/rubygems/resolver/installer_set.rb +1 -1
  193. data/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb +1 -1
  194. data/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb +32 -26
  195. data/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb +1 -1
  196. data/lib/rubygems/security/policies.rb +40 -40
  197. data/lib/rubygems/security/trust_dir.rb +1 -1
  198. data/lib/rubygems/security.rb +3 -16
  199. data/lib/rubygems/source.rb +2 -2
  200. data/lib/rubygems/specification.rb +37 -49
  201. data/lib/rubygems/specification_policy.rb +14 -0
  202. data/lib/rubygems/stub_specification.rb +2 -2
  203. data/lib/rubygems/text.rb +1 -1
  204. data/lib/rubygems/tsort/lib/tsort.rb +308 -310
  205. data/lib/rubygems/update_suggestion.rb +69 -0
  206. data/lib/rubygems/util.rb +1 -5
  207. data/lib/rubygems/validator.rb +1 -1
  208. data/lib/rubygems.rb +8 -3
  209. data/rubygems-update.gemspec +2 -2
  210. data/test/rubygems/helper.rb +7 -3
  211. data/test/rubygems/test_bundled_ca.rb +1 -1
  212. data/test/rubygems/test_exit.rb +6 -0
  213. data/test/rubygems/test_gem.rb +4 -9
  214. data/test/rubygems/test_gem_bundler_version_finder.rb +2 -1
  215. data/test/rubygems/test_gem_command_manager.rb +1 -1
  216. data/test/rubygems/test_gem_commands_install_command.rb +19 -0
  217. data/test/rubygems/test_gem_commands_setup_command.rb +1 -8
  218. data/test/rubygems/test_gem_commands_update_command.rb +6 -6
  219. data/test/rubygems/test_gem_config_file.rb +1 -1
  220. data/test/rubygems/test_gem_dependency.rb +2 -0
  221. data/test/rubygems/test_gem_ext_builder.rb +3 -3
  222. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +22 -32
  223. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +1 -1
  224. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +22 -32
  225. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
  226. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +12 -0
  227. data/test/rubygems/test_gem_ext_cargo_builder.rb +22 -27
  228. data/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb +16 -16
  229. data/test/rubygems/test_gem_ext_cargo_builder_unit.rb +0 -10
  230. data/test/rubygems/test_gem_indexer.rb +39 -20
  231. data/test/rubygems/test_gem_installer.rb +68 -2
  232. data/test/rubygems/test_gem_package_tar_header.rb +13 -13
  233. data/test/rubygems/test_gem_platform.rb +59 -60
  234. data/test/rubygems/test_gem_remote_fetcher.rb +4 -4
  235. data/test/rubygems/test_gem_request_set.rb +2 -2
  236. data/test/rubygems/test_gem_requirement.rb +1 -1
  237. data/test/rubygems/test_gem_resolver_api_set.rb +12 -12
  238. data/test/rubygems/test_gem_resolver_api_specification.rb +19 -19
  239. data/test/rubygems/test_gem_resolver_git_specification.rb +1 -1
  240. data/test/rubygems/test_gem_security_policy.rb +10 -10
  241. data/test/rubygems/test_gem_security_trust_dir.rb +2 -2
  242. data/test/rubygems/test_gem_specification.rb +50 -37
  243. data/test/rubygems/test_gem_uninstaller.rb +1 -1
  244. data/test/rubygems/test_gem_update_suggestion.rb +208 -0
  245. data/test/rubygems/test_kernel.rb +10 -8
  246. data/test/rubygems/test_require.rb +70 -55
  247. metadata +34 -31
  248. data/bundler/lib/bundler/templates/newgem/travis.yml.tt +0 -6
  249. data/bundler/lib/bundler/vendor/molinillo/LICENSE +0 -9
  250. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +0 -57
  251. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +0 -88
  252. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +0 -36
  253. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +0 -66
  254. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +0 -62
  255. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +0 -63
  256. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +0 -61
  257. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +0 -126
  258. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +0 -46
  259. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +0 -36
  260. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +0 -164
  261. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +0 -255
  262. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +0 -149
  263. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +0 -6
  264. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +0 -112
  265. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +0 -67
  266. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +0 -839
  267. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +0 -46
  268. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +0 -58
  269. data/bundler/lib/bundler/vendor/molinillo/lib/molinillo.rb +0 -11
  270. data/bundler/lib/bundler/vendor/tmpdir/lib/tmpdir.rb +0 -154
  271. data/bundler/lib/bundler/vendored_molinillo.rb +0 -4
  272. data/bundler/lib/bundler/version_ranges.rb +0 -122
@@ -1,380 +1,397 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bundler
4
+ #
5
+ # This class implements the interface needed by PubGrub for resolution. It is
6
+ # equivalent to the `PubGrub::BasicPackageSource` class provided by PubGrub by
7
+ # default and used by the most simple PubGrub consumers.
8
+ #
4
9
  class Resolver
5
- require_relative "vendored_molinillo"
10
+ require_relative "vendored_pub_grub"
6
11
  require_relative "resolver/base"
7
- require_relative "resolver/spec_group"
12
+ require_relative "resolver/package"
13
+ require_relative "resolver/candidate"
14
+ require_relative "resolver/incompatibility"
15
+ require_relative "resolver/root"
8
16
 
9
17
  include GemHelpers
10
18
 
11
- def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
19
+ def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements)
12
20
  @source_requirements = source_requirements
13
21
  @base = Resolver::Base.new(base, additional_base_requirements)
14
- @resolver = Molinillo::Resolver.new(self, self)
15
- @results_for = {}
16
- @search_for = {}
17
- @platforms = platforms
18
- @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
19
22
  @gem_version_promoter = gem_version_promoter
20
23
  end
21
24
 
22
- def start(requirements, exclude_specs: [])
23
- @metadata_requirements, regular_requirements = requirements.partition {|dep| dep.name.end_with?("\0") }
24
-
25
+ def start(requirements, packages, exclude_specs: [])
25
26
  exclude_specs.each do |spec|
26
27
  remove_from_candidates(spec)
27
28
  end
28
29
 
29
- requirements.each {|dep| prerelease_specified[dep.name] ||= dep.prerelease? }
30
-
31
- verify_gemfile_dependencies_are_found!(requirements)
32
- result = @resolver.resolve(requirements).
33
- map(&:payload).
34
- reject {|sg| sg.name.end_with?("\0") }.
35
- map(&:to_specs).
36
- flatten
30
+ @requirements = requirements
31
+ @packages = packages
37
32
 
38
- SpecSet.new(SpecSet.new(result).for(regular_requirements, false, @platforms))
39
- rescue Molinillo::VersionConflict => e
40
- conflicts = e.conflicts
41
-
42
- deps_to_unlock = conflicts.values.inject([]) do |deps, conflict|
43
- deps |= conflict.requirement_trees.flatten.map {|req| base_requirements[req.name] }.compact
44
- end
33
+ root, logger = setup_solver
45
34
 
46
- if deps_to_unlock.any?
47
- @base.unlock_deps(deps_to_unlock)
48
- reset_spec_cache
49
- retry
50
- end
35
+ Bundler.ui.info "Resolving dependencies...", true
51
36
 
52
- message = version_conflict_message(e)
53
- raise VersionConflict.new(conflicts.keys.uniq, message)
54
- rescue Molinillo::CircularDependencyError => e
55
- names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
56
- raise CyclicDependencyError, "Your bundle requires gems that depend" \
57
- " on each other, creating an infinite loop. Please remove" \
58
- " #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
59
- " and try again."
37
+ solve_versions(:root => root, :logger => logger)
60
38
  end
61
39
 
62
- include Molinillo::UI
63
-
64
- # Conveys debug information to the user.
65
- #
66
- # @param [Integer] depth the current depth of the resolution process.
67
- # @return [void]
68
- def debug(depth = 0)
69
- return unless debug?
70
- debug_info = yield
71
- debug_info = debug_info.inspect unless debug_info.is_a?(String)
72
- puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
73
- end
40
+ def setup_solver
41
+ root = Resolver::Root.new(name_for_explicit_dependency_source)
42
+ root_version = Resolver::Candidate.new(0)
74
43
 
75
- def debug?
76
- return @debug_mode if defined?(@debug_mode)
77
- @debug_mode =
78
- ENV["BUNDLER_DEBUG_RESOLVER"] ||
79
- ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
80
- ENV["DEBUG_RESOLVER"] ||
81
- ENV["DEBUG_RESOLVER_TREE"] ||
82
- false
83
- end
44
+ @all_specs = Hash.new do |specs, name|
45
+ specs[name] = source_for(name).specs.search(name).sort_by {|s| [s.version, s.platform.to_s] }
46
+ end
84
47
 
85
- def before_resolution
86
- Bundler.ui.info "Resolving dependencies...", debug?
87
- end
48
+ @sorted_versions = Hash.new do |candidates, package|
49
+ candidates[package] = if package.root?
50
+ [root_version]
51
+ else
52
+ all_versions_for(package).sort
53
+ end
54
+ end
88
55
 
89
- def after_resolution
90
- Bundler.ui.info ""
91
- end
56
+ root_dependencies = prepare_dependencies(@requirements, @packages)
92
57
 
93
- def indicate_progress
94
- Bundler.ui.info ".", false unless debug?
95
- end
58
+ @cached_dependencies = Hash.new do |dependencies, package|
59
+ dependencies[package] = if package.root?
60
+ { root_version => root_dependencies }
61
+ else
62
+ Hash.new do |versions, version|
63
+ versions[version] = to_dependency_hash(version.dependencies, @packages)
64
+ end
65
+ end
66
+ end
96
67
 
97
- include Molinillo::SpecificationProvider
68
+ logger = Bundler::UI::Shell.new
69
+ logger.level = debug? ? "debug" : "warn"
98
70
 
99
- def dependencies_for(specification)
100
- specification.dependencies_for_activated_platforms
71
+ [root, logger]
101
72
  end
102
73
 
103
- def search_for(dependency)
104
- @search_for[dependency] ||= begin
105
- name = dependency.name
106
- locked_results = @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
107
- locked_requirement = base_requirements[name]
108
- results = results_for(dependency) + locked_results
109
- results = results.select {|spec| requirement_satisfied_by?(locked_requirement, nil, spec) } if locked_requirement
110
- dep_platforms = dependency.gem_platforms(@platforms)
111
-
112
- @gem_version_promoter.sort_versions(dependency, results).group_by(&:version).reduce([]) do |groups, (_, specs)|
113
- relevant_platforms = dep_platforms.select {|platform| specs.any? {|spec| spec.match_platform(platform) } }
114
- next groups unless relevant_platforms.any?
115
-
116
- ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
117
- if ruby_specs.any?
118
- spec_group_ruby = SpecGroup.new(ruby_specs, [Gem::Platform::RUBY])
119
- spec_group_ruby.force_ruby_platform = dependency.force_ruby_platform
120
- groups << spec_group_ruby
121
- end
74
+ def solve_versions(root:, logger:)
75
+ solver = PubGrub::VersionSolver.new(:source => self, :root => root, :logger => logger)
76
+ result = solver.solve
77
+ result.map {|package, version| version.to_specs(package) }.flatten.uniq
78
+ rescue PubGrub::SolveFailure => e
79
+ incompatibility = e.incompatibility
80
+
81
+ names_to_unlock = []
82
+ extended_explanation = nil
122
83
 
123
- next groups if @resolving_only_for_ruby || dependency.force_ruby_platform
84
+ while incompatibility.conflict?
85
+ cause = incompatibility.cause
86
+ incompatibility = cause.incompatibility
124
87
 
125
- platform_specs = relevant_platforms.flat_map {|platform| select_best_platform_match(specs, platform) }
126
- next groups if platform_specs == ruby_specs
88
+ incompatibility.terms.each do |term|
89
+ name = term.package.name
90
+ names_to_unlock << name if base_requirements[name]
127
91
 
128
- spec_group = SpecGroup.new(platform_specs, relevant_platforms)
129
- groups << spec_group
92
+ no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
93
+ next unless no_versions_incompat
130
94
 
131
- groups
95
+ extended_explanation = no_versions_incompat.extended_explanation
132
96
  end
133
97
  end
134
- end
135
98
 
136
- def index_for(dependency)
137
- source_for(dependency.name).specs
138
- end
99
+ names_to_unlock.uniq!
139
100
 
140
- def source_for(name)
141
- @source_requirements[name] || @source_requirements[:default]
142
- end
101
+ if names_to_unlock.any?
102
+ Bundler.ui.debug "Found conflicts with locked dependencies. Retrying with #{names_to_unlock.join(", ")} unlocked...", true
143
103
 
144
- def results_for(dependency)
145
- @results_for[dependency] ||= index_for(dependency).search(dependency)
146
- end
104
+ @base.unlock_names(names_to_unlock)
147
105
 
148
- def name_for(dependency)
149
- dependency.name
150
- end
106
+ root, logger = setup_solver
151
107
 
152
- def name_for_explicit_dependency_source
153
- Bundler.default_gemfile.basename.to_s
154
- rescue StandardError
155
- "Gemfile"
156
- end
108
+ retry
109
+ end
157
110
 
158
- def requirement_satisfied_by?(requirement, activated, spec)
159
- requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
160
- end
111
+ explanation = e.message
161
112
 
162
- def sort_dependencies(dependencies, activated, conflicts)
163
- dependencies.sort_by do |dependency|
164
- name = name_for(dependency)
165
- vertex = activated.vertex_named(name)
166
- [
167
- @base[name].any? ? 0 : 1,
168
- vertex.payload ? 0 : 1,
169
- vertex.root? ? 0 : 1,
170
- amount_constrained(dependency),
171
- conflicts[name] ? 0 : 1,
172
- vertex.payload ? 0 : search_for(dependency).count,
173
- ]
113
+ if extended_explanation
114
+ explanation << "\n\n"
115
+ explanation << extended_explanation
174
116
  end
117
+
118
+ raise SolveFailure.new(explanation)
175
119
  end
176
120
 
177
- private
121
+ def parse_dependency(package, dependency)
122
+ range = if repository_for(package).is_a?(Source::Gemspec)
123
+ PubGrub::VersionRange.any
124
+ else
125
+ requirement_to_range(dependency)
126
+ end
178
127
 
179
- def base_requirements
180
- @base.base_requirements
128
+ PubGrub::VersionConstraint.new(package, :range => range)
181
129
  end
182
130
 
183
- def prerelease_specified
184
- @gem_version_promoter.prerelease_specified
131
+ def versions_for(package, range=VersionRange.any)
132
+ versions = range.select_versions(@sorted_versions[package])
133
+
134
+ sort_versions(package, versions)
185
135
  end
186
136
 
187
- def remove_from_candidates(spec)
188
- @base.delete(spec)
137
+ def no_versions_incompatibility_for(package, unsatisfied_term)
138
+ cause = PubGrub::Incompatibility::NoVersions.new(unsatisfied_term)
139
+ name = package.name
140
+ constraint = unsatisfied_term.constraint
141
+ constraint_string = constraint.constraint_string
142
+ requirements = constraint_string.split(" OR ").map {|req| Gem::Requirement.new(req.split(",")) }
143
+
144
+ if name == "bundler"
145
+ custom_explanation = "the current Bundler version (#{Bundler::VERSION}) does not satisfy #{constraint}"
146
+ extended_explanation = bundler_not_found_message(requirements)
147
+ else
148
+ specs_matching_other_platforms = filter_matching_specs(@all_specs[name], requirements)
189
149
 
190
- @results_for.keys.each do |dep|
191
- next unless dep.name == spec.name
150
+ platforms_explanation = specs_matching_other_platforms.any? ? " for any resolution platforms (#{package.platforms.join(", ")})" : ""
151
+ custom_explanation = "#{constraint} could not be found in #{repository_for(package)}#{platforms_explanation}"
192
152
 
193
- @results_for[dep].reject {|s| s.name == spec.name && s.version == spec.version }
153
+ label = "#{name} (#{constraint_string})"
154
+ extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
194
155
  end
195
156
 
196
- reset_spec_cache
157
+ Incompatibility.new([unsatisfied_term], :cause => cause, :custom_explanation => custom_explanation, :extended_explanation => extended_explanation)
197
158
  end
198
159
 
199
- def reset_spec_cache
200
- @search_for = {}
201
- @gem_version_promoter.reset
160
+ def debug?
161
+ ENV["BUNDLER_DEBUG_RESOLVER"] ||
162
+ ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
163
+ ENV["DEBUG_RESOLVER"] ||
164
+ ENV["DEBUG_RESOLVER_TREE"] ||
165
+ false
202
166
  end
203
167
 
204
- # returns an integer \in (-\infty, 0]
205
- # a number closer to 0 means the dependency is less constraining
206
- #
207
- # dependencies w/ 0 or 1 possibilities (ignoring version requirements)
208
- # are given very negative values, so they _always_ sort first,
209
- # before dependencies that are unconstrained
210
- def amount_constrained(dependency)
211
- @amount_constrained ||= {}
212
- @amount_constrained[dependency.name] ||= if (base = @base[dependency.name]) && !base.empty?
213
- dependency.requirement.satisfied_by?(base.first.version) ? 0 : 1
214
- else
215
- all = index_for(dependency).search(dependency.name).size
168
+ def incompatibilities_for(package, version)
169
+ package_deps = @cached_dependencies[package]
170
+ sorted_versions = @sorted_versions[package]
171
+ package_deps[version].map do |dep_package, dep_constraint|
172
+ if package == dep_package
173
+ cause = PubGrub::Incompatibility::CircularDependency.new(dep_package, dep_constraint.constraint_string)
174
+ return [PubGrub::Incompatibility.new([PubGrub::Term.new(dep_constraint, true)], :cause => cause)]
175
+ end
216
176
 
217
- if all <= 1
218
- all - 1_000_000
219
- else
220
- search = search_for(dependency)
221
- search = prerelease_specified[dependency.name] ? search.count : search.count {|s| !s.version.prerelease? }
222
- search - all
177
+ low = high = sorted_versions.index(version)
178
+
179
+ # find version low such that all >= low share the same dep
180
+ while low > 0 && package_deps[sorted_versions[low - 1]][dep_package] == dep_constraint
181
+ low -= 1
182
+ end
183
+ low =
184
+ if low == 0
185
+ nil
186
+ else
187
+ sorted_versions[low]
188
+ end
189
+
190
+ # find version high such that all < high share the same dep
191
+ while high < sorted_versions.length && package_deps[sorted_versions[high]][dep_package] == dep_constraint
192
+ high += 1
193
+ end
194
+ high =
195
+ if high == sorted_versions.length
196
+ nil
197
+ else
198
+ sorted_versions[high]
199
+ end
200
+
201
+ range = PubGrub::VersionRange.new(:min => low, :max => high, :include_min => true)
202
+
203
+ self_constraint = PubGrub::VersionConstraint.new(package, :range => range)
204
+
205
+ dep_term = PubGrub::Term.new(dep_constraint, false)
206
+ self_term = PubGrub::Term.new(self_constraint, true)
207
+
208
+ custom_explanation = if dep_package.meta? && package.root?
209
+ "current #{dep_package} version is #{dep_constraint.constraint_string}"
223
210
  end
211
+
212
+ PubGrub::Incompatibility.new([self_term, dep_term], :cause => :dependency, :custom_explanation => custom_explanation)
213
+ end
214
+ end
215
+
216
+ def all_versions_for(package)
217
+ name = package.name
218
+ results = (@base[name] + @all_specs[name]).uniq(&:full_name)
219
+ locked_requirement = base_requirements[name]
220
+ results = filter_matching_specs(results, locked_requirement) if locked_requirement
221
+
222
+ versions = results.group_by(&:version).reduce([]) do |groups, (version, specs)|
223
+ platform_specs = package.platforms.flat_map {|platform| select_best_platform_match(specs, platform) }
224
+ next groups if platform_specs.empty?
225
+
226
+ ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
227
+ groups << Resolver::Candidate.new(version, :specs => ruby_specs) if ruby_specs.any?
228
+
229
+ next groups if platform_specs == ruby_specs
230
+
231
+ groups << Resolver::Candidate.new(version, :specs => platform_specs)
232
+
233
+ groups
224
234
  end
235
+
236
+ sort_versions(package, versions)
225
237
  end
226
238
 
227
- def verify_gemfile_dependencies_are_found!(requirements)
228
- requirements.map! do |requirement|
229
- name = requirement.name
230
- next requirement if name == "bundler"
231
- next if requirement.gem_platforms(@platforms).empty?
232
- next requirement unless search_for(requirement).empty?
233
- next unless requirement.current_platform?
239
+ def source_for(name)
240
+ @source_requirements[name] || @source_requirements[:default]
241
+ end
234
242
 
235
- raise GemNotFound, gem_not_found_message(name, requirement, source_for(name))
236
- end.compact!
243
+ def name_for_explicit_dependency_source
244
+ Bundler.default_gemfile.basename.to_s
245
+ rescue StandardError
246
+ "Gemfile"
237
247
  end
238
248
 
239
- def gem_not_found_message(name, requirement, source, extra_message = "")
240
- specs = source.specs.search(name).sort_by {|s| [s.version, s.platform.to_s] }
249
+ def raise_not_found!(package)
250
+ name = package.name
251
+ source = source_for(name)
252
+ specs = @all_specs[name]
241
253
  matching_part = name
242
- requirement_label = SharedHelpers.pretty_dependency(requirement)
254
+ requirement_label = SharedHelpers.pretty_dependency(package.dependency)
243
255
  cache_message = begin
244
256
  " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
245
257
  rescue GemfileNotFound
246
258
  nil
247
259
  end
248
- specs_matching_requirement = specs.select {| spec| requirement.matches_spec?(spec) }
260
+ specs_matching_requirement = filter_matching_specs(specs, package.dependency.requirement)
249
261
 
250
262
  if specs_matching_requirement.any?
251
263
  specs = specs_matching_requirement
252
264
  matching_part = requirement_label
253
- platforms = requirement.gem_platforms(@platforms)
265
+ platforms = package.platforms
254
266
  platform_label = platforms.size == 1 ? "platform '#{platforms.first}" : "platforms '#{platforms.join("', '")}"
255
267
  requirement_label = "#{requirement_label}' with #{platform_label}"
256
268
  end
257
269
 
258
- message = String.new("Could not find gem '#{requirement_label}'#{extra_message} in #{source}#{cache_message}.\n")
270
+ message = String.new("Could not find gem '#{requirement_label}' in #{source}#{cache_message}.\n")
259
271
 
260
272
  if specs.any?
261
- message << "\nThe source contains the following gems matching '#{matching_part}':\n"
262
- message << specs.map {|s| " * #{s.full_name}" }.join("\n")
273
+ message << "\n#{other_specs_matching_message(specs, matching_part)}"
263
274
  end
264
275
 
265
- message
276
+ raise GemNotFound, message
277
+ end
278
+
279
+ private
280
+
281
+ def filter_matching_specs(specs, requirements)
282
+ Array(requirements).flat_map do |requirement|
283
+ specs.select {| spec| requirement_satisfied_by?(requirement, spec) }
284
+ end
266
285
  end
267
286
 
268
- def version_conflict_message(e)
269
- # only show essential conflicts, if possible
270
- conflicts = e.conflicts.dup
287
+ def requirement_satisfied_by?(requirement, spec)
288
+ requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
289
+ end
271
290
 
272
- if conflicts["bundler"]
273
- conflicts.replace("bundler" => conflicts["bundler"])
291
+ def sort_versions(package, versions)
292
+ if versions.size > 1
293
+ @gem_version_promoter.sort_versions(package, versions).reverse
274
294
  else
275
- conflicts.delete_if do |_name, conflict|
276
- deps = conflict.requirement_trees.map(&:last).flatten(1)
277
- !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
278
- end
295
+ versions
279
296
  end
297
+ end
280
298
 
281
- e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
299
+ def repository_for(package)
300
+ source_for(package.name)
301
+ end
282
302
 
283
- e.message_with_trees(
284
- :full_message_for_conflict => lambda do |name, conflict|
285
- trees = conflict.requirement_trees
303
+ def base_requirements
304
+ @base.base_requirements
305
+ end
286
306
 
287
- # called first, because we want to reduce the amount of work required to find maximal empty sets
288
- trees = trees.uniq {|t| t.flatten.map {|dep| [dep.name, dep.requirement] } }
307
+ def remove_from_candidates(spec)
308
+ @base.delete(spec)
309
+ end
289
310
 
290
- # bail out if tree size is too big for Array#combination to make any sense
291
- if trees.size <= 15
292
- maximal = 1.upto(trees.size).map do |size|
293
- trees.map(&:last).flatten(1).combination(size).to_a
294
- end.flatten(1).select do |deps|
295
- Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
296
- end.min_by(&:size)
311
+ def prepare_dependencies(requirements, packages)
312
+ to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
313
+ name = dep_package.name
314
+
315
+ # If a dependency is scoped to a platform different from the current
316
+ # one, we ignore it. However, it may reappear during resolution as a
317
+ # transitive dependency of another package, so we need to reset the
318
+ # package so the proper versions are considered if reintroduced later.
319
+ if dep_package.platforms.empty?
320
+ @packages.delete(name)
321
+ next
322
+ end
297
323
 
298
- trees.reject! {|t| !maximal.include?(t.last) } if maximal
324
+ next [dep_package, dep_constraint] if name == "bundler"
325
+ next [dep_package, dep_constraint] unless versions_for(dep_package, dep_constraint.range).empty?
326
+ next unless dep_package.current_platform?
299
327
 
300
- trees.sort_by! {|t| t.reverse.map(&:name) }
301
- end
328
+ raise_not_found!(dep_package)
329
+ end.compact.to_h
330
+ end
302
331
 
303
- if trees.size > 1 || name == "bundler"
304
- o = if name.end_with?("\0")
305
- String.new("Bundler found conflicting requirements for the #{name} version:")
306
- else
307
- String.new("Bundler could not find compatible versions for gem \"#{name}\":")
308
- end
309
- o << %(\n)
310
- o << %( In #{name_for_explicit_dependency_source}:\n)
311
- o << trees.map do |tree|
312
- t = "".dup
313
- depth = 2
314
-
315
- base_tree = tree.first
316
- base_tree_name = base_tree.name
317
-
318
- if base_tree_name.end_with?("\0")
319
- t = nil
320
- else
321
- tree.each do |req|
322
- t << " " * depth << SharedHelpers.pretty_dependency(req)
323
- unless tree.last == req
324
- if spec = conflict.activated_by_name[req.name]
325
- t << %( was resolved to #{spec.version}, which)
326
- end
327
- t << %( depends on)
328
- end
329
- t << %(\n)
330
- depth += 1
331
- end
332
- end
333
- t
334
- end.compact.join("\n")
335
- else
336
- o = String.new
337
- end
332
+ def other_specs_matching_message(specs, requirement)
333
+ message = String.new("The source contains the following gems matching '#{requirement}':\n")
334
+ message << specs.map {|s| " * #{s.full_name}" }.join("\n")
335
+ message
336
+ end
338
337
 
339
- if name == "bundler"
340
- o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
341
-
342
- conflict_dependency = conflict.requirement
343
- conflict_requirement = conflict_dependency.requirement
344
- other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
345
-
346
- if other_bundler_required
347
- o << "\n\n"
348
-
349
- candidate_specs = source_for(:default_bundler).specs.search(conflict_dependency)
350
- if candidate_specs.any?
351
- target_version = candidate_specs.last.version
352
- new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
353
- o << "Your bundle requires a different version of Bundler than the one you're running.\n"
354
- o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
355
- else
356
- o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
357
- end
358
- end
359
- elsif name.end_with?("\0")
360
- o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(@metadata_requirements.find {|req| req.name == name })}\n\n)
361
- elsif !conflict.existing
362
- o << "\n"
363
-
364
- relevant_source = conflict.requirement.source || source_for(name)
365
-
366
- extra_message = if trees.first.size > 1
367
- ", which is required by gem '#{SharedHelpers.pretty_dependency(trees.first[-2])}',"
368
- else
369
- ""
370
- end
371
-
372
- o << gem_not_found_message(name, conflict.requirement, relevant_source, extra_message)
373
- end
338
+ def requirement_to_range(requirement)
339
+ ranges = requirement.requirements.map do |(op, version)|
340
+ ver = Resolver::Candidate.new(version)
341
+
342
+ case op
343
+ when "~>"
344
+ name = "~> #{ver}"
345
+ bump = Resolver::Candidate.new(version.bump.to_s + ".A")
346
+ PubGrub::VersionRange.new(:name => name, :min => ver, :max => bump, :include_min => true)
347
+ when ">"
348
+ PubGrub::VersionRange.new(:min => ver)
349
+ when ">="
350
+ PubGrub::VersionRange.new(:min => ver, :include_min => true)
351
+ when "<"
352
+ PubGrub::VersionRange.new(:max => ver)
353
+ when "<="
354
+ PubGrub::VersionRange.new(:max => ver, :include_max => true)
355
+ when "="
356
+ PubGrub::VersionRange.new(:min => ver, :max => ver, :include_min => true, :include_max => true)
357
+ when "!="
358
+ PubGrub::VersionRange.new(:min => ver, :max => ver, :include_min => true, :include_max => true).invert
359
+ else
360
+ raise "bad version specifier: #{op}"
361
+ end
362
+ end
363
+
364
+ ranges.inject(&:intersect)
365
+ end
366
+
367
+ def to_dependency_hash(dependencies, packages)
368
+ dependencies.inject({}) do |deps, dep|
369
+ package = packages[dep.name]
370
+
371
+ current_req = deps[package]
372
+ new_req = parse_dependency(package, dep.requirement)
374
373
 
375
- o
374
+ deps[package] = if current_req
375
+ current_req.intersect(new_req)
376
+ else
377
+ new_req
376
378
  end
377
- )
379
+
380
+ deps
381
+ end
382
+ end
383
+
384
+ def bundler_not_found_message(conflict_dependencies)
385
+ candidate_specs = filter_matching_specs(source_for(:default_bundler).specs.search("bundler"), conflict_dependencies)
386
+
387
+ if candidate_specs.any?
388
+ target_version = candidate_specs.last.version
389
+ new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
390
+ "Your bundle requires a different version of Bundler than the one you're running.\n" \
391
+ "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
392
+ else
393
+ "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
394
+ end
378
395
  end
379
396
  end
380
397
  end