1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
module Semverse
class Version
class << self
# Coerce the object into a version.
#
# @param [Version, String]
#
# @return [Version]
def coerce(object)
object.is_a?(self) ? object : new(object)
end
# @param [#to_s] version_string
#
# @raise [InvalidVersionFormat]
#
# @return [Array]
def split(version_string)
case version_string.to_s
when /^(\d+)\.(\d+)\.(\d+)(-([0-9a-z\-\.]+))?(\+([0-9a-z\-\.]+))?$/i
[ $1.to_i, $2.to_i, $3.to_i, $5, $7 ]
when /^(\d+)\.(\d+)\.(\d+)?$/
[ $1.to_i, $2.to_i, $3.to_i ]
when /^(\d+)\.(\d+)?$/
[ $1.to_i, $2.to_i, 0 ]
when /^(\d+)$/
[ $1.to_i, 0, 0 ]
else
raise InvalidVersionFormat.new(version_string)
end
end
end
include Comparable
attr_reader :major
attr_reader :minor
attr_reader :patch
attr_reader :pre_release
attr_reader :build
# @overload initialize(version_array)
# @param [Array] version_array
#
# @example
# Version.new([1, 2, 3, 'rc.1', 'build.1']) => #<Version: @major=1, @minor=2, @patch=3, @pre_release='rc.1', @build='build.1'>
#
# @overload initialize(version_string)
# @param [#to_s] version_string
#
# @example
# Version.new("1.2.3-rc.1+build.1") => #<Version: @major=1, @minor=2, @patch=3, @pre_release='rc.1', @build='build.1'>
#
# @overload initialize(version)
# @param [Semverse::Version] version
#
# @example
# Version.new(Version.new("1.2.3-rc.1+build.1")) => #<Version: @major=1, @minor=2, @pre_release='rc.1', @build='build.1'>
#
def initialize(*args)
if args.first.is_a?(Array)
@major, @minor, @patch, @pre_release, @build = args.first
else
@major, @minor, @patch, @pre_release, @build = self.class.split(args.first.to_s)
end
@major ||= 0
@minor ||= 0
@patch ||= 0
@pre_release ||= nil
@build ||= nil
end
# @param [Semverse::Version] other
#
# @return [Integer]
def <=>(other)
[:major, :minor, :patch].each do |release|
ans = self.send(release) <=> other.send(release)
return ans if ans != 0
end
ans = pre_release_and_build_presence_score <=> other.pre_release_and_build_presence_score
return ans if ans != 0
ans = identifiers_comparaison(other, :pre_release)
return ans if ans != 0
if build && other.build
return identifiers_comparaison(other, :build)
else
return build.to_s <=> other.build.to_s
end
0
end
# @return [Array]
def identifiers(release)
send(release).to_s.split('.').map do |str|
str.to_i.to_s == str ? str.to_i : str
end
end
def pre_release?
!!pre_release
end
def zero?
[major, minor, patch].all? { |n| n == 0 }
end
# @return [Integer]
def pre_release_and_build_presence_score
pre_release ? 0 : (build.nil? ? 1 : 2)
end
# @param [Semverse::Version] other
#
# @return [Integer]
def identifiers_comparaison(other, release)
[identifiers(release).length, other.identifiers(release).length].max.times do |i|
if identifiers(release)[i].class == other.identifiers(release)[i].class
ans = identifiers(release)[i] <=> other.identifiers(release)[i]
return ans if ans != 0
elsif identifiers(release)[i] && other.identifiers(release)[i]
return identifiers(release)[i].class.to_s <=> other.identifiers(release)[i].class.to_s
elsif identifiers(release)[i] || other.identifiers(release)[i]
return other.identifiers(release)[i].class.to_s <=> identifiers(release)[i].class.to_s
end
end
0
end
# @param [Semverse::Version] other
#
# @return [Boolean]
def eql?(other)
other.is_a?(Version) && self == other
end
def inspect
"#<#{self.class.to_s} #{to_s}>"
end
def to_s
str = "#{major}.#{minor}.#{patch}"
str += "-#{pre_release}" if pre_release
str += "+#{build}" if build
str
end
end
end
|