summaryrefslogtreecommitdiff
path: root/lib/bundler/resolver/strategy.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bundler/resolver/strategy.rb')
-rw-r--r--lib/bundler/resolver/strategy.rb43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/bundler/resolver/strategy.rb b/lib/bundler/resolver/strategy.rb
new file mode 100644
index 0000000000..7519d38968
--- /dev/null
+++ b/lib/bundler/resolver/strategy.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Resolver
+ class Strategy
+ def initialize(source)
+ @source = source
+ @package_priority_cache = {}
+ end
+
+ def next_package_and_version(unsatisfied)
+ package, range = next_term_to_try_from(unsatisfied)
+
+ [package, most_preferred_version_of(package, range).first]
+ end
+
+ private
+
+ def next_term_to_try_from(unsatisfied)
+ unsatisfied.min_by do |package, range|
+ @package_priority_cache[[package, range]] ||= begin
+ matching_versions = @source.versions_for(package, range)
+ higher_versions = @source.versions_for(package, range.upper_invert)
+
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ end
+ end
+ end
+
+ def most_preferred_version_of(package, range)
+ versions = @source.versions_for(package, range)
+
+ # Conditional avoids (among other things) calling
+ # sort_versions_by_preferred with the root package
+ if versions.size > 1
+ @source.sort_versions_by_preferred(package, versions)
+ else
+ versions
+ end
+ end
+ end
+ end
+end