Merge pull request #8186 from SeekingMeaning/version/token-comparisons

version: extend token comparisons to strings, integers, and nil
This commit is contained in:
Seeker 2020-08-03 10:10:01 -07:00 committed by GitHub
commit 0653bb1d2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 11 deletions

View File

@ -16,6 +16,28 @@ describe Version::Token do
specify "#to_s" do
expect(described_class.new("foo").to_s).to eq("foo")
end
it "can be compared against nil" do
expect(described_class.create("2")).to be > nil
expect(described_class.create("p194")).to be > nil
end
it "can be compared against Version::NULL_TOKEN" do
expect(described_class.create("2")).to be > Version::NULL_TOKEN
expect(described_class.create("p194")).to be > Version::NULL_TOKEN
end
it "can be compared against strings" do
expect(described_class.create("2")).to be == "2"
expect(described_class.create("p194")).to be == "p194"
expect(described_class.create("1")).to be == 1
end
specify "comparison returns nil for non-token" do
v = described_class.create("1")
expect(v <=> Object.new).to be nil
expect { v > Object.new }.to raise_error(ArgumentError)
end
end
describe Version::NULL do

View File

@ -12,6 +12,30 @@ class Version
class Token
include Comparable
def self.create(val)
raise TypeError, "Token value must be a string; got a #{val.class} (#{val})" unless val.respond_to?(:to_str)
case val
when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
when /\A#{BetaToken::PATTERN}\z/o then BetaToken
when /\A#{RCToken::PATTERN}\z/o then RCToken
when /\A#{PreToken::PATTERN}\z/o then PreToken
when /\A#{PatchToken::PATTERN}\z/o then PatchToken
when /\A#{NumericToken::PATTERN}\z/o then NumericToken
when /\A#{StringToken::PATTERN}\z/o then StringToken
end.new(val)
end
def self.from(val)
case val
when Token then val
when String then Token.create(val)
when Integer then Token.create(val.to_s)
when nil then NULL_TOKEN
else NULL_TOKEN if val.respond_to?(:null?) && val.null?
end
end
attr_reader :value
def initialize(value)
@ -37,6 +61,8 @@ class Version
end
def <=>(other)
return unless other = Token.from(other)
case other
when NullToken
0
@ -64,6 +90,8 @@ class Version
end
def <=>(other)
return unless other = Token.from(other)
case other
when StringToken
value <=> other.value
@ -81,6 +109,8 @@ class Version
end
def <=>(other)
return unless other = Token.from(other)
case other
when NumericToken
value <=> other.value
@ -106,6 +136,8 @@ class Version
PATTERN = /alpha[0-9]*|a[0-9]+/i.freeze
def <=>(other)
return unless other = Token.from(other)
case other
when AlphaToken
rev <=> other.rev
@ -121,6 +153,8 @@ class Version
PATTERN = /beta[0-9]*|b[0-9]+/i.freeze
def <=>(other)
return unless other = Token.from(other)
case other
when BetaToken
rev <=> other.rev
@ -138,6 +172,8 @@ class Version
PATTERN = /pre[0-9]*/i.freeze
def <=>(other)
return unless other = Token.from(other)
case other
when PreToken
rev <=> other.rev
@ -155,6 +191,8 @@ class Version
PATTERN = /rc[0-9]*/i.freeze
def <=>(other)
return unless other = Token.from(other)
case other
when RCToken
rev <=> other.rev
@ -172,6 +210,8 @@ class Version
PATTERN = /p[0-9]*/i.freeze
def <=>(other)
return unless other = Token.from(other)
case other
when PatchToken
rev <=> other.rev
@ -465,17 +505,7 @@ class Version
end
def tokenize
version.scan(SCAN_PATTERN).map! do |token|
case token
when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
when /\A#{BetaToken::PATTERN}\z/o then BetaToken
when /\A#{RCToken::PATTERN}\z/o then RCToken
when /\A#{PreToken::PATTERN}\z/o then PreToken
when /\A#{PatchToken::PATTERN}\z/o then PatchToken
when /\A#{NumericToken::PATTERN}\z/o then NumericToken
when /\A#{StringToken::PATTERN}\z/o then StringToken
end.new(token)
end
version.scan(SCAN_PATTERN).map { |token| Token.create(token) }
end
end