From 0f826b8a39268fa33aa0cd6f67faab127b2b8f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Garc=C3=ADa=20Cota?= Date: Sun, 15 Jan 2012 02:50:49 +0100 Subject: [PATCH] finished with prereleases --- semver.lua | 53 ++++++++++++++++++++++++++++++++++++++++++-- spec/semver_spec.lua | 25 ++++++++++++++++++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/semver.lua b/semver.lua index 2565aa8..998de58 100644 --- a/semver.lua +++ b/semver.lua @@ -19,11 +19,58 @@ end local function parsePrerelease(extra) if not present(extra) then return end - local prerelease = extra:match("-([%w-][%.%w-]+)") + local prerelease = extra:match("-([%w-][%.%w-]*)") assert(prerelease, ("The prerelease %q must start with a dash and be followed by dashes, alphanumerics or dots."):format(extra)) return prerelease 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 +end + +local function compareIds(selfId, otherId) + if not selfId and not otherId then return 0 + elseif not selfId then return 1 + elseif not otherId then return -1 + end + + local selfNumber, otherNumber = tonumber(selfId), tonumber(otherId) + + if selfNumber and otherNumber then -- numerical comparison + return compare(selfNumber, otherNumber) + elseif selfNumber then -- numericals are always smaller than alphanums + return -1 + else + return compare(selfId, otherId) -- alphanumerical comparison + end +end + +local function splitByDot(str) + local t, count = {}, 0 + str:gsub("([^%.]+)", function(c) + count = count + 1 + t[count] = c + end) + return t +end + +local function smallerExtra(selfExtra, otherExtra) + if selfExtra == otherExtra then return false end + + local selfIds, otherIds = splitByDot(selfExtra), splitByDot(otherExtra) + local selfLength = #selfIds + local comparison + + for i = 1, selfLength do + comparison = compareIds(selfIds[i], otherIds[i]) + if comparison ~= 0 then return comparison == -1 end + -- if comparison == 0, continue loop + end + + return selfLength < #otherIds +end + local methods = {} function methods:nextMajor() @@ -46,7 +93,9 @@ end function mt:__lt(other) return self.major < other.major or self.minor < other.minor or - self.patch < other.patch + self.patch < other.patch or + (self.prerelease and not other.prerelease) or + smallerExtra(self.prerelease, other.prerelease) end function mt:__pow(other) return self.major == other.major and diff --git a/spec/semver_spec.lua b/spec/semver_spec.lua index 9d63fb8..a6570ba 100644 --- a/spec/semver_spec.lua +++ b/spec/semver_spec.lua @@ -118,7 +118,30 @@ context('semver', function() assert_greater_than(v'0.0.2', v'0.0.1') end) describe("prereleases", function() - + test("false if exact same prerelease", function() + assert_false(v'1.0.0-beta' < v'1.0.0-beta') + end) + test("a prerelease version is less than the official version", function() + assert_less_than(v'1.0.0-rc1', v'1.0.0') + end) + test("identifiers with only digits are compared numerically", function() + assert_less_than(v'1.0.0-1', v'1.0.0-2') + assert_less_than(v'1.0.0-2', v'1.0.0-10') + end) + test("itendifiers with letters or dashes are compared lexiconumerically", function() + assert_less_than(v'1.0.0-alpha', v'1.0.0-beta') + assert_less_than(v'1.0.0-alpha-10', v'1.0.0-alpha-2') + end) + test("numerical ids always have less priority than lexiconumericals", function() + assert_less_than(v'1.0.0-1', v'1.0.0-alpha') + assert_less_than(v'1.0.0-2', v'1.0.0-1asdf') + end) + test("identifiers can be separated by colons; they must be compared individually", function() + assert_less_than(v'1.0.0-alpha', v'1.0.0-alpha.1') + assert_less_than(v'1.0.0-alpha.1', v'1.0.0-beta.2') + assert_less_than(v'1.0.0-beta.2', v'1.0.0-beta.11') + assert_less_than(v'1.0.0-beta.11', v'1.0.0-rc.1') + end) end) end)