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
@@ -0,0 +1,409 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bundler::PubGrub
4
+ class VersionRange
5
+ attr_reader :min, :max, :include_min, :include_max
6
+
7
+ alias_method :include_min?, :include_min
8
+ alias_method :include_max?, :include_max
9
+
10
+ class Empty < VersionRange
11
+ undef_method :min, :max
12
+ undef_method :include_min, :include_min?
13
+ undef_method :include_max, :include_max?
14
+
15
+ def initialize
16
+ end
17
+
18
+ def empty?
19
+ true
20
+ end
21
+
22
+ def eql?
23
+ other.empty?
24
+ end
25
+
26
+ def hash
27
+ [].hash
28
+ end
29
+
30
+ def intersects?(_)
31
+ false
32
+ end
33
+
34
+ def intersect(other)
35
+ self
36
+ end
37
+
38
+ def allows_all?(other)
39
+ other.empty?
40
+ end
41
+
42
+ def include?(_)
43
+ false
44
+ end
45
+
46
+ def any?
47
+ false
48
+ end
49
+
50
+ def to_s
51
+ "(no versions)"
52
+ end
53
+
54
+ def ==(other)
55
+ other.class == self.class
56
+ end
57
+
58
+ def invert
59
+ VersionRange.any
60
+ end
61
+
62
+ def select_versions(_)
63
+ []
64
+ end
65
+ end
66
+
67
+ EMPTY = Empty.new
68
+
69
+ def self.empty
70
+ EMPTY
71
+ end
72
+
73
+ def self.any
74
+ new
75
+ end
76
+
77
+ def initialize(min: nil, max: nil, include_min: false, include_max: false, name: nil)
78
+ @min = min
79
+ @max = max
80
+ @include_min = include_min
81
+ @include_max = include_max
82
+ @name = name
83
+ end
84
+
85
+ def hash
86
+ @hash ||= min.hash ^ max.hash ^ include_min.hash ^ include_max.hash
87
+ end
88
+
89
+ def eql?(other)
90
+ if other.is_a?(VersionRange)
91
+ min.eql?(other.min) &&
92
+ max.eql?(other.max) &&
93
+ include_min.eql?(other.include_min) &&
94
+ include_max.eql?(other.include_max)
95
+ else
96
+ ranges.eql?(other.ranges)
97
+ end
98
+ end
99
+
100
+ def ranges
101
+ [self]
102
+ end
103
+
104
+ def include?(version)
105
+ compare_version(version) == 0
106
+ end
107
+
108
+ # Partitions passed versions into [lower, within, higher]
109
+ #
110
+ # versions must be sorted
111
+ def partition_versions(versions)
112
+ min_index =
113
+ if !min || versions.empty?
114
+ 0
115
+ elsif include_min?
116
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] >= min }
117
+ else
118
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] > min }
119
+ end
120
+
121
+ lower = versions.slice(0, min_index)
122
+ versions = versions.slice(min_index, versions.size)
123
+
124
+ max_index =
125
+ if !max || versions.empty?
126
+ versions.size
127
+ elsif include_max?
128
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] > max }
129
+ else
130
+ (0..versions.size).bsearch { |i| versions[i].nil? || versions[i] >= max }
131
+ end
132
+
133
+ [
134
+ lower,
135
+ versions.slice(0, max_index),
136
+ versions.slice(max_index, versions.size)
137
+ ]
138
+ end
139
+
140
+ # Returns versions which are included by this range.
141
+ #
142
+ # versions must be sorted
143
+ def select_versions(versions)
144
+ return versions if any?
145
+
146
+ partition_versions(versions)[1]
147
+ end
148
+
149
+ def compare_version(version)
150
+ if min
151
+ case version <=> min
152
+ when -1
153
+ return -1
154
+ when 0
155
+ return -1 if !include_min
156
+ when 1
157
+ end
158
+ end
159
+
160
+ if max
161
+ case version <=> max
162
+ when -1
163
+ when 0
164
+ return 1 if !include_max
165
+ when 1
166
+ return 1
167
+ end
168
+ end
169
+
170
+ 0
171
+ end
172
+
173
+ def strictly_lower?(other)
174
+ return false if !max || !other.min
175
+
176
+ case max <=> other.min
177
+ when 0
178
+ !include_max || !other.include_min
179
+ when -1
180
+ true
181
+ when 1
182
+ false
183
+ end
184
+ end
185
+
186
+ def strictly_higher?(other)
187
+ other.strictly_lower?(self)
188
+ end
189
+
190
+ def intersects?(other)
191
+ return false if other.empty?
192
+ return other.intersects?(self) if other.is_a?(VersionUnion)
193
+ !strictly_lower?(other) && !strictly_higher?(other)
194
+ end
195
+ alias_method :allows_any?, :intersects?
196
+
197
+ def intersect(other)
198
+ return other if other.empty?
199
+ return other.intersect(self) if other.is_a?(VersionUnion)
200
+
201
+ min_range =
202
+ if !min
203
+ other
204
+ elsif !other.min
205
+ self
206
+ else
207
+ case min <=> other.min
208
+ when 0
209
+ include_min ? other : self
210
+ when -1
211
+ other
212
+ when 1
213
+ self
214
+ end
215
+ end
216
+
217
+ max_range =
218
+ if !max
219
+ other
220
+ elsif !other.max
221
+ self
222
+ else
223
+ case max <=> other.max
224
+ when 0
225
+ include_max ? other : self
226
+ when -1
227
+ self
228
+ when 1
229
+ other
230
+ end
231
+ end
232
+
233
+ if !min_range.equal?(max_range) && min_range.min && max_range.max
234
+ case min_range.min <=> max_range.max
235
+ when -1
236
+ when 0
237
+ if !min_range.include_min || !max_range.include_max
238
+ return EMPTY
239
+ end
240
+ when 1
241
+ return EMPTY
242
+ end
243
+ end
244
+
245
+ VersionRange.new(
246
+ min: min_range.min,
247
+ include_min: min_range.include_min,
248
+ max: max_range.max,
249
+ include_max: max_range.include_max
250
+ )
251
+ end
252
+
253
+ # The span covered by two ranges
254
+ #
255
+ # If self and other are contiguous, this builds a union of the two ranges.
256
+ # (if they aren't you are probably calling the wrong method)
257
+ def span(other)
258
+ return self if other.empty?
259
+
260
+ min_range =
261
+ if !min
262
+ self
263
+ elsif !other.min
264
+ other
265
+ else
266
+ case min <=> other.min
267
+ when 0
268
+ include_min ? self : other
269
+ when -1
270
+ self
271
+ when 1
272
+ other
273
+ end
274
+ end
275
+
276
+ max_range =
277
+ if !max
278
+ self
279
+ elsif !other.max
280
+ other
281
+ else
282
+ case max <=> other.max
283
+ when 0
284
+ include_max ? self : other
285
+ when -1
286
+ other
287
+ when 1
288
+ self
289
+ end
290
+ end
291
+
292
+ VersionRange.new(
293
+ min: min_range.min,
294
+ include_min: min_range.include_min,
295
+ max: max_range.max,
296
+ include_max: max_range.include_max
297
+ )
298
+ end
299
+
300
+ def union(other)
301
+ return other.union(self) if other.is_a?(VersionUnion)
302
+
303
+ if contiguous_to?(other)
304
+ span(other)
305
+ else
306
+ VersionUnion.union([self, other])
307
+ end
308
+ end
309
+
310
+ def contiguous_to?(other)
311
+ return false if other.empty?
312
+
313
+ intersects?(other) ||
314
+ (min == other.max && (include_min || other.include_max)) ||
315
+ (max == other.min && (include_max || other.include_min))
316
+ end
317
+
318
+ def allows_all?(other)
319
+ return true if other.empty?
320
+
321
+ if other.is_a?(VersionUnion)
322
+ return VersionUnion.new([self]).allows_all?(other)
323
+ end
324
+
325
+ return false if max && !other.max
326
+ return false if min && !other.min
327
+
328
+ if min
329
+ case min <=> other.min
330
+ when -1
331
+ when 0
332
+ return false if !include_min && other.include_min
333
+ when 1
334
+ return false
335
+ end
336
+ end
337
+
338
+ if max
339
+ case max <=> other.max
340
+ when -1
341
+ return false
342
+ when 0
343
+ return false if !include_max && other.include_max
344
+ when 1
345
+ end
346
+ end
347
+
348
+ true
349
+ end
350
+
351
+ def any?
352
+ !min && !max
353
+ end
354
+
355
+ def empty?
356
+ false
357
+ end
358
+
359
+ def to_s
360
+ @name ||= constraints.join(", ")
361
+ end
362
+
363
+ def inspect
364
+ "#<#{self.class} #{to_s}>"
365
+ end
366
+
367
+ def upper_invert
368
+ return self.class.empty unless max
369
+
370
+ VersionRange.new(min: max, include_min: !include_max)
371
+ end
372
+
373
+ def invert
374
+ return self.class.empty if any?
375
+
376
+ low = VersionRange.new(max: min, include_max: !include_min)
377
+ high = VersionRange.new(min: max, include_min: !include_max)
378
+
379
+ if !min
380
+ high
381
+ elsif !max
382
+ low
383
+ else
384
+ low.union(high)
385
+ end
386
+ end
387
+
388
+ def ==(other)
389
+ self.class == other.class &&
390
+ min == other.min &&
391
+ max == other.max &&
392
+ include_min == other.include_min &&
393
+ include_max == other.include_max
394
+ end
395
+
396
+ private
397
+
398
+ def constraints
399
+ return ["any"] if any?
400
+ return ["= #{min}"] if min == max
401
+
402
+ c = []
403
+ c << "#{include_min ? ">=" : ">"} #{min}" if min
404
+ c << "#{include_max ? "<=" : "<"} #{max}" if max
405
+ c
406
+ end
407
+
408
+ end
409
+ end
@@ -0,0 +1,240 @@
1
+ require_relative 'partial_solution'
2
+ require_relative 'term'
3
+ require_relative 'incompatibility'
4
+ require_relative 'solve_failure'
5
+
6
+ module Bundler::PubGrub
7
+ class VersionSolver
8
+ attr_reader :logger
9
+ attr_reader :source
10
+ attr_reader :solution
11
+
12
+ def initialize(source:, root: Package.root, logger: Bundler::PubGrub.logger)
13
+ @logger = logger
14
+
15
+ @source = source
16
+
17
+ # { package => [incompatibility, ...]}
18
+ @incompatibilities = Hash.new do |h, k|
19
+ h[k] = []
20
+ end
21
+
22
+ @seen_incompatibilities = {}
23
+
24
+ @solution = PartialSolution.new
25
+
26
+ add_incompatibility Incompatibility.new([
27
+ Term.new(VersionConstraint.any(root), false)
28
+ ], cause: :root)
29
+
30
+ propagate(root)
31
+ end
32
+
33
+ def solved?
34
+ solution.unsatisfied.empty?
35
+ end
36
+
37
+ # Returns true if there is more work to be done, false otherwise
38
+ def work
39
+ return false if solved?
40
+
41
+ next_package = choose_package_version
42
+ propagate(next_package)
43
+
44
+ if solved?
45
+ logger.info { "Solution found after #{solution.attempted_solutions} attempts:" }
46
+ solution.decisions.each do |package, version|
47
+ next if Package.root?(package)
48
+ logger.info { "* #{package} #{version}" }
49
+ end
50
+
51
+ false
52
+ else
53
+ true
54
+ end
55
+ end
56
+
57
+ def solve
58
+ work until solved?
59
+
60
+ solution.decisions
61
+ end
62
+
63
+ alias_method :result, :solve
64
+
65
+ private
66
+
67
+ def propagate(initial_package)
68
+ changed = [initial_package]
69
+ while package = changed.shift
70
+ @incompatibilities[package].reverse_each do |incompatibility|
71
+ result = propagate_incompatibility(incompatibility)
72
+ if result == :conflict
73
+ root_cause = resolve_conflict(incompatibility)
74
+ changed.clear
75
+ changed << propagate_incompatibility(root_cause)
76
+ elsif result # should be a Package
77
+ changed << result
78
+ end
79
+ end
80
+ changed.uniq!
81
+ end
82
+ end
83
+
84
+ def propagate_incompatibility(incompatibility)
85
+ unsatisfied = nil
86
+ incompatibility.terms.each do |term|
87
+ relation = solution.relation(term)
88
+ if relation == :disjoint
89
+ return nil
90
+ elsif relation == :overlap
91
+ # If more than one term is inconclusive, we can't deduce anything
92
+ return nil if unsatisfied
93
+ unsatisfied = term
94
+ end
95
+ end
96
+
97
+ if !unsatisfied
98
+ return :conflict
99
+ end
100
+
101
+ logger.debug { "derived: #{unsatisfied.invert}" }
102
+
103
+ solution.derive(unsatisfied.invert, incompatibility)
104
+
105
+ unsatisfied.package
106
+ end
107
+
108
+ def next_package_to_try
109
+ solution.unsatisfied.min_by do |term|
110
+ package = term.package
111
+ range = term.constraint.range
112
+ matching_versions = source.versions_for(package, range)
113
+ higher_versions = source.versions_for(package, range.upper_invert)
114
+
115
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
116
+ end.package
117
+ end
118
+
119
+ def choose_package_version
120
+ if solution.unsatisfied.empty?
121
+ logger.info "No packages unsatisfied. Solving complete!"
122
+ return nil
123
+ end
124
+
125
+ package = next_package_to_try
126
+ unsatisfied_term = solution.unsatisfied.find { |t| t.package == package }
127
+ version = source.versions_for(package, unsatisfied_term.constraint.range).first
128
+
129
+ if version.nil?
130
+ add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term)
131
+ return package
132
+ end
133
+
134
+ conflict = false
135
+
136
+ source.incompatibilities_for(package, version).each do |incompatibility|
137
+ if @seen_incompatibilities.include?(incompatibility)
138
+ logger.debug { "knew: #{incompatibility}" }
139
+ next
140
+ end
141
+ @seen_incompatibilities[incompatibility] = true
142
+
143
+ add_incompatibility incompatibility
144
+
145
+ conflict ||= incompatibility.terms.all? do |term|
146
+ term.package == package || solution.satisfies?(term)
147
+ end
148
+ end
149
+
150
+ unless conflict
151
+ logger.info { "selecting #{package} #{version}" }
152
+
153
+ solution.decide(package, version)
154
+ end
155
+
156
+ package
157
+ end
158
+
159
+ def resolve_conflict(incompatibility)
160
+ logger.info { "conflict: #{incompatibility}" }
161
+
162
+ new_incompatibility = false
163
+
164
+ while !incompatibility.failure?
165
+ most_recent_term = nil
166
+ most_recent_satisfier = nil
167
+ difference = nil
168
+
169
+ previous_level = 1
170
+
171
+ incompatibility.terms.each do |term|
172
+ satisfier = solution.satisfier(term)
173
+
174
+ if most_recent_satisfier.nil?
175
+ most_recent_term = term
176
+ most_recent_satisfier = satisfier
177
+ elsif most_recent_satisfier.index < satisfier.index
178
+ previous_level = [previous_level, most_recent_satisfier.decision_level].max
179
+ most_recent_term = term
180
+ most_recent_satisfier = satisfier
181
+ difference = nil
182
+ else
183
+ previous_level = [previous_level, satisfier.decision_level].max
184
+ end
185
+
186
+ if most_recent_term == term
187
+ difference = most_recent_satisfier.term.difference(most_recent_term)
188
+ if difference.empty?
189
+ difference = nil
190
+ else
191
+ difference_satisfier = solution.satisfier(difference.inverse)
192
+ previous_level = [previous_level, difference_satisfier.decision_level].max
193
+ end
194
+ end
195
+ end
196
+
197
+ if previous_level < most_recent_satisfier.decision_level ||
198
+ most_recent_satisfier.decision?
199
+
200
+ logger.info { "backtracking to #{previous_level}" }
201
+ solution.backtrack(previous_level)
202
+
203
+ if new_incompatibility
204
+ add_incompatibility(incompatibility)
205
+ end
206
+
207
+ return incompatibility
208
+ end
209
+
210
+ new_terms = []
211
+ new_terms += incompatibility.terms - [most_recent_term]
212
+ new_terms += most_recent_satisfier.cause.terms.reject { |term|
213
+ term.package == most_recent_satisfier.term.package
214
+ }
215
+ if difference
216
+ new_terms << difference.invert
217
+ end
218
+
219
+ incompatibility = Incompatibility.new(new_terms, cause: Incompatibility::ConflictCause.new(incompatibility, most_recent_satisfier.cause))
220
+
221
+ new_incompatibility = true
222
+
223
+ partially = difference ? " partially" : ""
224
+ logger.info { "! #{most_recent_term} is#{partially} satisfied by #{most_recent_satisfier.term}" }
225
+ logger.info { "! which is caused by #{most_recent_satisfier.cause}" }
226
+ logger.info { "! thus #{incompatibility}" }
227
+ end
228
+
229
+ raise SolveFailure.new(incompatibility)
230
+ end
231
+
232
+ def add_incompatibility(incompatibility)
233
+ logger.debug { "fact: #{incompatibility}" }
234
+ incompatibility.terms.each do |term|
235
+ package = term.package
236
+ @incompatibilities[package] << incompatibility
237
+ end
238
+ end
239
+ end
240
+ end