We need to subclass Numeric to force range comparisons not to try to iterate over SemVer and instead use numeric comparisons (eg >, <, >=, <=) Ruby 1.8 already did this for all ranges, but Ruby 1.9 changed range include behavior
# File lib/semver.rb, line 24 def self.[](range) range.gsub(/([><=])\s+/, '\1').split(/\b\s+(?!-)/).map do |r| case r when SemVer::VERSION SemVer.new(pre(r)) .. SemVer.new(r) when SemVer::SIMPLE_RANGE r += ".0" unless SemVer.valid?(r.gsub(/x/, '0')) SemVer.new(r.gsub(/x/, '0'))...SemVer.new(r.gsub(/(\d+)\.x/) { "#{$1.to_i + 1}.0" } + '-') when /\s+-\s+/ a, b = r.split(/\s+-\s+/) SemVer.new(pre(a)) .. SemVer.new(b) when /^~/ ver = r.sub(/~/, '').split('.').map(&:to_i) start = (ver + [0] * (3 - ver.length)).join('.') ver.pop unless ver.length == 1 ver[-1] = ver.last + 1 finish = (ver + [0] * (3 - ver.length)).join('.') SemVer.new(pre(start)) ... SemVer.new(pre(finish)) when /^>=/ ver = r.sub(/^>=/, '') SemVer.new(pre(ver)) .. SemVer::MAX when /^<=/ ver = r.sub(/^<=/, '') SemVer::MIN .. SemVer.new(ver) when /^>/ if r =~ /-/ ver = [r[1..-1]] else ver = r.sub(/^>/, '').split('.').map(&:to_i) ver[2] = ver.last + 1 end SemVer.new(ver.join('.') + '-') .. SemVer::MAX when /^</ ver = r.sub(/^</, '') SemVer::MIN ... SemVer.new(pre(ver)) else (1..1) end end.inject { |a,e| a & e } end
# File lib/semver.rb, line 16 def self.find_matching(pattern, versions) versions.select { |v| v.matched_by?("#{pattern}") }.sort.last end
# File lib/semver.rb, line 69 def initialize(ver) unless SemVer.valid?(ver) raise ArgumentError.new("Invalid version string '#{ver}'!") end @major, @minor, @tiny, @special = VERSION.match(ver).captures.map do |x| # Because Kernel#Integer tries to interpret hex and octal strings, which # we specifically do not want, and which cannot be overridden in 1.8.7. Float(x).to_i rescue x end end
# File lib/semver.rb, line 20 def self.pre(vstring) vstring =~ /-/ ? vstring : vstring + '-' end
# File lib/semver.rb, line 12 def self.valid?(ver) VERSION =~ ver end
# File lib/semver.rb, line 81 def <=>(other) other = SemVer.new("#{other}") unless other.is_a? SemVer return self.major <=> other.major unless self.major == other.major return self.minor <=> other.minor unless self.minor == other.minor return self.tiny <=> other.tiny unless self.tiny == other.tiny return 0 if self.special == other.special return 1 if self.special == '' return -1 if other.special == '' return self.special <=> other.special end
# File lib/semver.rb, line 113 def inspect @vstring || "v#{@major}.#{@minor}.#{@tiny}#{@special}" end
# File lib/semver.rb, line 94 def matched_by?(pattern) # For the time being, this is restricted to exact version matches and # simple range patterns. In the future, we should implement some or all of # the comparison operators here: # https://github.com/isaacs/node-semver/blob/d474801/semver.js#L340 case pattern when SIMPLE_RANGE pattern = SIMPLE_RANGE.match(pattern).captures pattern[1] = @minor unless pattern[1] && pattern[1] !~ /x/ pattern[2] = @tiny unless pattern[2] && pattern[2] !~ /x/ [@major, @minor, @tiny] == pattern.map { |x| x.to_i } when VERSION self == SemVer.new(pattern) else false end end