lib/semantic_range/version.rb in semantic_range-0.1.1 vs lib/semantic_range/version.rb in semantic_range-0.2.0

- old
+ new

@@ -1,125 +1,70 @@ module SemanticRange - VERSION = "0.1.1" + VERSION = "0.2.0" class Version - def initialize(version, loose) + attr_reader :major, :minor, :patch, :prerelease + + def initialize(version, loose = false) @raw = version @loose = loose - if version.is_a?(Version) - @raw = version = version.raw - end + @raw = version.raw if version.is_a?(Version) - match = version.strip.match(loose ? LOOSE : FULL) - # TODO error handling + match = @raw.strip.match(loose ? LOOSE : FULL) + raise NoMatchFound.new(version) if match.nil? + @major = match[1] ? match[1].to_i : 0 @minor = match[2] ? match[2].to_i : 0 @patch = match[3] ? match[3].to_i : 0 - # TODO error handling + @prerelease = PreRelease.new match[4] - if !match[4] - @prerelease = [] - else - @prerelease = match[4].split('.').map do |id| - if /^[0-9]+$/.match(id) - num = id.to_i - # TODO error handling - else - id - end - end - end - @build = match[5] ? match[5].split('.') : [] - @version = format end - def version - @version - end - - def raw - @raw - end - - def major - @major - end - - def minor - @minor - end - - def patch - @patch - end - - def prerelease - @prerelease - end - def format v = "#{@major}.#{@minor}.#{@patch}" - if @prerelease.length > 0 - v += '-' + @prerelease.join('.') - end - v + prerelease.length > 0 ? "#{v}-#{prerelease}" : v end def to_s @version end + def version + format + end + + def raw + version + end + def compare(other) other = Version.new(other, @loose) unless other.is_a?(Version) res = truthy(compare_main(other)) || truthy(compare_pre(other)) res.is_a?(FalseClass) ? 0 : res end def compare_main(other) other = Version.new(other, @loose) unless other.is_a?(Version) - truthy(compare_identifiers(@major, other.major)) || truthy(compare_identifiers(@minor, other.minor)) || truthy(compare_identifiers(@patch, other.patch)) + truthy(self.class.compare_identifiers(@major, other.major)) || + truthy(self.class.compare_identifiers(@minor, other.minor)) || + truthy(self.class.compare_identifiers(@patch, other.patch)) end def truthy(val) return val unless val.is_a?(Integer) val.zero? ? false : val end def compare_pre(other) - other = Version.new(other, @loose) unless other.is_a?(Version) - - return -1 if truthy(@prerelease.length) && !truthy(other.prerelease.length) - - return 1 if !truthy(@prerelease.length) && truthy(other.prerelease.length) - - return 0 if !truthy(@prerelease.length) && !truthy(other.prerelease.length) - - i = 0 - while true - a = @prerelease[i] - b = other.prerelease[i] - - if a.nil? && b.nil? - return 0 - elsif b.nil? - return 1 - elsif a.nil? - return -1 - elsif a == b - - else - return compare_identifiers(a, b) - end - i += 1 - end + prerelease <=> other.prerelease end - def compare_identifiers(a,b) + def self.compare_identifiers(a,b) anum = /^[0-9]+$/.match(a.to_s) bnum = /^[0-9]+$/.match(b.to_s) if anum && bnum a = a.to_i @@ -129,8 +74,106 @@ return (anum && !bnum) ? -1 : (bnum && !anum) ? 1 : a < b ? -1 : a > b ? 1 : 0; + end + + def increment!(release, identifier) + case release + when 'premajor' + @prerelease.clear! + @patch = 0 + @minor = 0 + @major = @major + 1 + increment! 'pre', identifier + when 'preminor' + @prerelease.clear! + @patch = 0 + @minor = @minor + 1 + increment! 'pre', identifier + when 'prepatch' + # If this is already a prerelease, it will bump to the next version + # drop any prereleases that might already exist, since they are not + # relevant at this point. + @prerelease.clear! + increment! 'patch', identifier + increment! 'pre', identifier + + # If the input is a non-prerelease version, this acts the same as + # prepatch. + when 'prerelease' + if @prerelease.empty? + increment! 'patch', identifier + end + increment! 'pre', identifier + when 'major' + # If this is a pre-major version, bump up to the same major version. + # Otherwise increment major. + # 1.0.0-5 bumps to 1.0.0 + # 1.1.0 bumps to 2.0.0 + if @minor != 0 || @patch != 0 || @prerelease.empty? + @major = @major + 1 + end + @minor = 0 + @patch = 0 + @prerelease.clear! + when 'minor' + # If this is a pre-minor version, bump up to the same minor version. + # Otherwise increment minor. + # 1.2.0-5 bumps to 1.2.0 + # 1.2.1 bumps to 1.3.0 + if @patch != 0 || @prerelease.empty? + @minor = @minor + 1 + end + @patch = 0 + @prerelease.clear! + when 'patch' + # If this is not a pre-release version, it will increment the patch. + # If it is a pre-release it will bump up to the same patch version. + # 1.2.0-5 patches to 1.2.0 + # 1.2.0 patches to 1.2.1 + if @prerelease.empty? + @patch = @patch + 1 + end + @prerelease.clear! + + # This probably shouldn't be used publicly. + # 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + when 'pre' + if @prerelease.empty? + @prerelease.zero! + else + parts = @prerelease.parts + i = parts.length + while i >= 0 + if parts[i].is_a?(Fixnum) + parts[i] += 1 + i = -2 + else + i = i-1 + end + end + if i == -1 # didn't increment anything + parts << 0 + end + @prerelease = PreRelease.new(parts.join(".")) + end + if identifier + # 1.2.0-beta.1 bumps to 1.2.0-beta.2, + # 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if @prerelease.parts[0] == identifier + unless @prerelease.parts[1].kind_of?(Fixnum) + @prerelease = PreRelease.new([identifier, 0].join('.')) + end + else + @prerelease = PreRelease.new([identifier, 0].join('.')) + end + end + else + raise InvalidIncrement.new release + end + + self end end end