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