diff --git a/lib/bundler/version_ranges.rb b/lib/bundler/version_ranges.rb index ec25716cde7..12a956d6a0a 100644 --- a/lib/bundler/version_ranges.rb +++ b/lib/bundler/version_ranges.rb @@ -5,11 +5,42 @@ module VersionRanges NEq = Struct.new(:version) ReqR = Struct.new(:left, :right) class ReqR - Endpoint = Struct.new(:version, :inclusive) + Endpoint = Struct.new(:version, :inclusive) do + def <=>(other) + if version.equal?(INFINITY) + return 0 if other.version.equal?(INFINITY) + return 1 + elsif other.version.equal?(INFINITY) + return -1 + end + + comp = version <=> other.version + return comp unless comp.zero? + + if inclusive && !other.inclusive + 1 + elsif !inclusive && other.inclusive + -1 + else + 0 + end + end + end + def to_s "#{left.inclusive ? "[" : "("}#{left.version}, #{right.version}#{right.inclusive ? "]" : ")"}" end - INFINITY = Object.new.freeze + INFINITY = begin + inf = Object.new + def inf.to_s + "∞" + end + def inf.<=>(other) + return 0 if other.equal?(self) + 1 + end + inf.freeze + end ZERO = Gem::Version.new("0.a") def cover?(v) @@ -32,6 +63,15 @@ def single? left.version == right.version end + def <=>(other) + return -1 if other.equal?(INFINITY) + + comp = left <=> other.left + return comp unless comp.zero? + + right <=> other.right + end + UNIVERSAL = ReqR.new(ReqR::Endpoint.new(Gem::Version.new("0.a"), true), ReqR::Endpoint.new(ReqR::INFINITY, false)).freeze end @@ -57,7 +97,7 @@ def self.for(requirement) end.uniq ranges, neqs = ranges.partition {|r| !r.is_a?(NEq) } - [ranges.sort_by {|range| [range.left.version, range.left.inclusive ? 0 : 1] }, neqs.map(&:version)] + [ranges.sort, neqs.map(&:version)] end def self.empty?(ranges, neqs) @@ -66,8 +106,14 @@ def self.empty?(ranges, neqs) next false if curr_range.single? && neqs.include?(curr_range.left.version) next curr_range if last_range.right.version == ReqR::INFINITY case last_range.right.version <=> curr_range.left.version - when 1 then next curr_range - when 0 then next(last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version) && curr_range) + # higher + when 1 then next ReqR.new(curr_range.left, last_range.right) + # equal + when 0 + if last_range.right.inclusive && curr_range.left.inclusive && !neqs.include?(curr_range.left.version) + ReqR.new(curr_range.left, [curr_range.right, last_range.right].max) + end + # lower when -1 then next false end end diff --git a/spec/bundler/version_ranges_spec.rb b/spec/bundler/version_ranges_spec.rb index ccbb9285d5a..bca044b0c01 100644 --- a/spec/bundler/version_ranges_spec.rb +++ b/spec/bundler/version_ranges_spec.rb @@ -25,9 +25,12 @@ include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" include_examples "empty?", false, "~> 1" include_examples "empty?", false, "~> 2.0", "~> 2.1" + include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1" + include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4" include_examples "empty?", true, "!= 1", "< 2", "> 2" include_examples "empty?", true, "!= 1", "<= 1", ">= 1" include_examples "empty?", true, "< 2", "> 2" + include_examples "empty?", true, "< 2", "> 2", "= 2" include_examples "empty?", true, "= 1", "!= 1" include_examples "empty?", true, "= 1", "= 2" include_examples "empty?", true, "= 1", "~> 2"