mirror of
https://github.com/TangentFoxy/semver.lua.git
synced 2025-07-27 18:42:21 +00:00
prereleases and builds now working 100% like the spec
This commit is contained in:
48
semver.lua
48
semver.lua
@@ -19,12 +19,37 @@ end
|
||||
local function parseExtra(extra)
|
||||
if not present(extra) then return end
|
||||
|
||||
local sign, data = extra:match("([-+])([%w-][%.%w-]*)")
|
||||
assert(sign and data, ("The string %q must start with - or + followed by dashes, alphanumerics or dots."):format(extra))
|
||||
if sign == "-" then return data, nil end
|
||||
return nil,data
|
||||
local prereleaseWithSign, buildWithSign = extra:match("^(-[^+]+)(+.+)$")
|
||||
if not (prereleaseWithSign and buildWithSign) then
|
||||
prereleaseWithSign = extra:match("^(-.+)$")
|
||||
buildWithSign = extra:match("^(+.+)$")
|
||||
end
|
||||
assert(prereleaseWithSign or buildWithSign, ("The parameter %q must begin with + or - to denote a prerelease or a buld"):format(extra))
|
||||
|
||||
local prerelease, build
|
||||
|
||||
if prereleaseWithSign then
|
||||
prerelease = prereleaseWithSign:match("^-(%w[%.%w-]*)$")
|
||||
assert(prerelease, ("The prerelease %q is not a slash followed by alphanumerics, dots and slashes"):format(prereleaseWithSign))
|
||||
end
|
||||
|
||||
if buildWithSign then
|
||||
build = buildWithSign:match("^%+(%w[%.%w-]*)$")
|
||||
assert(build, ("The build %q is not a + sign followed by alphanumerics, dots and slashes"):format(buildWithSign))
|
||||
end
|
||||
|
||||
return prerelease, build
|
||||
end
|
||||
|
||||
local function parseString(str)
|
||||
local sMajor, sMinor, sPatch, extra = str:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$")
|
||||
assert(type(sMajor) == 'string', ("Could not extract version number(s) from %q"):format(str))
|
||||
local major, minor, patch = tonumber(sMajor), tonumber(sMinor), tonumber(sPatch)
|
||||
local prerelease, build = parseExtra(extra)
|
||||
return major,minor,patch,prerelease,build
|
||||
end
|
||||
|
||||
|
||||
-- return 0 if a == b, -1 if a < b, and 1 if a > b
|
||||
local function compare(a,b)
|
||||
return a == b and 0 or a < b and -1 or 1
|
||||
@@ -107,24 +132,19 @@ function mt:__pow(other)
|
||||
end
|
||||
function mt:__tostring()
|
||||
local buffer = { ("%d.%d.%d"):format(self.major, self.minor, self.patch) }
|
||||
if self.prerelease then buffer[2] = "-" .. self.prerelease
|
||||
elseif self.build then buffer[2] = "+" .. self.build
|
||||
end
|
||||
if self.prerelease then table.insert(buffer, "-" .. self.prerelease) end
|
||||
if self.build then table.insert(buffer, "+" .. self.build) end
|
||||
return table.concat(buffer)
|
||||
end
|
||||
|
||||
|
||||
-- defined as local at the begining of the file
|
||||
version = function(major, minor, patch, extra)
|
||||
version = function(major, minor, patch, prerelease, build)
|
||||
assert(major, "At least one parameter is needed")
|
||||
|
||||
if type(major) == 'string' then
|
||||
local sMajor, sMinor, sPatch
|
||||
sMajor, sMinor, sPatch, extra = major:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$")
|
||||
assert(type(sMajor) == 'string', ("Could not extract version number(s) from %q"):format(major))
|
||||
major, minor, patch = tonumber(sMajor), tonumber(sMinor), tonumber(sPatch)
|
||||
major,minor,patch,prerelease,build = parseString(major)
|
||||
end
|
||||
|
||||
patch = patch or 0
|
||||
minor = minor or 0
|
||||
|
||||
@@ -132,8 +152,6 @@ version = function(major, minor, patch, extra)
|
||||
checkPositiveInteger(minor, "minor")
|
||||
checkPositiveInteger(patch, "patch")
|
||||
|
||||
local prerelease, build = parseExtra(extra)
|
||||
|
||||
local result = {major=major, minor=minor, patch=patch, prerelease=prerelease, build=build}
|
||||
return setmetatable(result, mt)
|
||||
end
|
||||
|
@@ -26,10 +26,13 @@ context('semver', function()
|
||||
end)
|
||||
|
||||
it('parses prereleases', function()
|
||||
checkVersion(v(1,2,3,"-alpha"), 1,2,3,"alpha")
|
||||
checkVersion(v(1,2,3,"alpha"), 1,2,3,"alpha")
|
||||
end)
|
||||
it('parses builds', function()
|
||||
checkVersion(v(1,2,3,"+build.1"), 1,2,3,nil,"build.1")
|
||||
checkVersion(v(1,2,3,nil,"build.1"), 1,2,3,nil,"build.1")
|
||||
end)
|
||||
it('parses prereleases + builds', function()
|
||||
checkVersion(v(1,2,3,"alpha","build.1"), 1,2,3,"alpha","build.1")
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -52,6 +55,9 @@ context('semver', function()
|
||||
test("1.2.3+build.15", function()
|
||||
checkVersion( v'1.2.3+build.15', 1,2,3,nil,'build.15' )
|
||||
end)
|
||||
test("1.2.3-rc1+build.15", function()
|
||||
checkVersion( v'1.2.3-rc1+build.15', 1,2,3,'rc1','build.15' )
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('errors', function()
|
||||
@@ -80,6 +86,12 @@ context('semver', function()
|
||||
test('a non-string or number is passed', function()
|
||||
assert_error(function() v({}) end)
|
||||
end)
|
||||
test('an invalid prerelease', function()
|
||||
assert_error(function() v'1.2.3-%?' end)
|
||||
end)
|
||||
test('an invalid build', function()
|
||||
assert_error(function() v'1.2.3+%?' end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -89,10 +101,13 @@ context('semver', function()
|
||||
end)
|
||||
|
||||
it("works with a prerelease", function()
|
||||
assert_equal("1.2.3-beta", tostring(v(1,2,3,'-beta')))
|
||||
assert_equal("1.2.3-beta", tostring(v(1,2,3,'beta')))
|
||||
end)
|
||||
it("works with a build", function()
|
||||
assert_equal("1.2.3+foobar", tostring(v(1,2,3, '+foobar')))
|
||||
assert_equal("1.2.3+foobar", tostring(v(1,2,3,nil,'foobar')))
|
||||
end)
|
||||
it("works with a prerelease and a build", function()
|
||||
assert_equal("1.2.3-alpha+foobar", tostring(v'1.2.3-alpha+foobar'))
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -181,6 +196,10 @@ context('semver', function()
|
||||
assert_less_than(v'1.3.7+build.2.b8f12d7', v'1.3.7+build.11.e0f985a')
|
||||
end)
|
||||
end)
|
||||
test("prereleases + builds", function()
|
||||
assert_less_than(v'1.0.0-rc.1', v'1.0.0-rc.1+build.1')
|
||||
assert_less_than(v'1.0.0-rc.1+build.1', v'1.0.0')
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("nextPatch", function()
|
||||
@@ -193,8 +212,8 @@ context('semver', function()
|
||||
it("increases the minor number by 1", function()
|
||||
assert_equal(v'1.2.0', v'1.1.0':nextMinor())
|
||||
end)
|
||||
it("resets the patch number", function()
|
||||
assert_equal(v'1.2.0', v'1.1.7':nextMinor())
|
||||
it("resets the patch number, prerelease and build", function()
|
||||
assert_equal(v'1.2.0', v'1.1.7-a+b':nextMinor())
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -202,8 +221,8 @@ context('semver', function()
|
||||
it("increases the major number by 1", function()
|
||||
assert_equal(v'2.0.0', v'1.0.0':nextMajor())
|
||||
end)
|
||||
it("resets the patch number", function()
|
||||
assert_equal(v'2.0.0', v'1.2.3':nextMajor())
|
||||
it("resets the minor, patch, prerelease and build", function()
|
||||
assert_equal(v'2.0.0', v'1.2.3-a+b':nextMajor())
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -220,9 +239,11 @@ context('semver', function()
|
||||
assert_false(v(2,0,0) ^ v(1,0,0))
|
||||
end)
|
||||
|
||||
test("patch versions are always compatible", function()
|
||||
test("patches, prereleases and builds are ignored", function()
|
||||
assert_true(v(1,2,3) ^ v(1,2,0))
|
||||
assert_true(v(1,2,3) ^ v(1,2,5))
|
||||
assert_true(v(1,2,3,'foo') ^ v(1,2,3))
|
||||
assert_true(v(1,2,3,nil,'bar') ^ v(1,2,3))
|
||||
end)
|
||||
|
||||
test("it's safe to upgrade to a newer minor version", function()
|
||||
|
Reference in New Issue
Block a user