Merge pull request #123 from starkos/require-version

Add optional versions argument to require()
This commit is contained in:
starkos 2015-06-24 15:08:53 -04:00
commit cab15e8277
6 changed files with 298 additions and 16 deletions

View File

@ -7,6 +7,8 @@ PREP
* Create working branch for release prep
* Update version in src/host/premake.c and commit
* Make sure branch passes all tests on all platforms
* Prep release announcement for forums
@ -16,22 +18,10 @@ RELEASE
* Merge working branch with release branch
* Update the version number in src/host/premake.c and commit
* Merge working branch to development branches
* Close working branch
PACKAGE
* Run `premake5 package release source` (from Posix ideally)
* On each platform, run `premake5 package release binary`
PUBLISH
* Create new release on GitHub from CHANGES.txt; upload files
* Update the download page on github.io
@ -42,3 +32,12 @@ PUBLISH
* Add release to Freshmeat
http://freshmeat.net/projects/premake
CYCLE
* Update version in src/host/premake.c and commit
* Merge working branch to development branch
* Close working branch

View File

@ -4,10 +4,14 @@
---
premake = premake or {}
premake.modules = {}
premake._VERSION = _PREMAKE_VERSION
package.loaded["premake"] = premake
premake.modules = {}
premake.extensions = premake.modules
local p = premake
-- Keep track of warnings that have been shown, so they don't get shown twice
@ -86,10 +90,83 @@
---
-- Clears the list of already fired warning messages, allowing them
-- to be fired again.
-- Compare a version string of the form "major.minor.patch.dev" against a
-- version comparision string. Comparisions take the form of ">=5.0" (5.0 or
-- later), "5.0" (5.0 or later), ">=5.0 <6.0" (5.0 or later but not 6.0 or
-- later).
--
-- @param version
-- The version to be tested.
-- @param checks
-- The comparision string to be evaluated.
-- @return
-- True if the comparisions pass, false if any fail.
---
function p.checkVersion(version, checks)
if not version then
return false
end
local function parse(str)
local major, minor, patch, dev = str:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$")
major = tonumber(major) or 0
minor = tonumber(minor) or 0
patch = tonumber(patch) or 0
dev = dev or ""
return { major, minor, patch, dev }
end
local function compare(a, b)
for i=1,4 do
if a[i] > b[i] then return 1 end
if a[i] < b[i] then return -1 end
end
return 0
end
local function eq(r) return r == 0 end
local function le(r) return r <= 0 end
local function lt(r) return r < 0 end
local function ge(r) return r >= 0 end
local function gt(r) return r > 0 end
version = parse(version)
checks = string.explode(checks, " ", true)
for i = 1, #checks do
local check = checks[i]
local func
if check:startswith(">=") then
func = ge
check = check:sub(3)
elseif check:startswith(">") then
func = gt
check = check:sub(2)
elseif check:startswith("<=") then
func = le
check = check:sub(3)
elseif check:startswith("<") then
func = lt
check = check:sub(2)
elseif check:startswith("=") then
func = eq
check = check:sub(2)
else
func = ge
end
check = parse(check)
if not func(compare(version, check)) then
return false
end
end
return true
end
function premake.clearWarnings()
_warnings = {}
end

View File

@ -55,3 +55,29 @@
return dofile(fname)
end
end
---
-- Extend require() with a second argument to specify the expected
-- version of the loaded module. Raises an error if the version criteria
-- are not met.
--
-- @param modname
-- The name of the module to load.
-- @param versions
-- An optional version criteria string; see premake.checkVersion()
-- for more information on the format.
-- @return
-- If successful, the loaded module, which is also stored into the
-- global package.loaded table.
---
premake.override(_G, "require", function(base, modname, versions)
local mod = base(modname)
if mod and versions and not premake.checkVersion(mod._VERSION, versions) then
error(string.format("module %s %s does not meet version criteria %s",
modname, mod._VERSION or "(none)", versions), 3)
end
return mod
end)

View File

@ -14,7 +14,7 @@
#endif
#define VERSION "HEAD"
#define VERSION "5.0.0-dev"
#define COPYRIGHT "Copyright (C) 2002-2015 Jason Perkins and the Premake Project"
#define PROJECT_URL "https://github.com/premake/premake-core/wiki"
#define ERROR_MESSAGE "Error: %s\n"

View File

@ -15,6 +15,7 @@ return {
"base/test_table.lua",
"base/test_tree.lua",
"base/test_uuid.lua",
"base/test_versions.lua",
-- Solution object tests
"solution/test_eachconfig.lua",

View File

@ -0,0 +1,179 @@
--
-- tests/base/test_versions.lua
-- Verify the version comparisons.
-- Copyright (c) 2015 Jason Perkins and the Premake project
--
local suite = test.declare("premake_versions")
local p = premake
--
-- If only major version is specified, anything after should pass.
--
function suite.pass_majorOnly_sameMajor()
test.istrue(p.checkVersion("1.0.0", "1"))
end
function suite.pass_majorOnly_laterMajor()
test.istrue(p.checkVersion("2.0.0", "1"))
end
function suite.pass_majorOnly_laterMinor()
test.istrue(p.checkVersion("1.1.0", "1"))
end
function suite.pass_majorOnly_laterPatch()
test.istrue(p.checkVersion("1.0.1", "1"))
end
function suite.pass_majorOnly_alpha()
test.istrue(p.checkVersion("1.0.0.alpha1", "1"))
end
function suite.pass_majorOnly_dev()
test.istrue(p.checkVersion("1.0.0.dev", "1"))
end
function suite.fail_earlierMajor()
test.isfalse(p.checkVersion("0.9.0", "1"))
end
--
-- If major and minor are specified, anything after should pass
--
function suite.pass_majorMinor_sameMajorMinor()
test.istrue(p.checkVersion("1.1.0", "1.1"))
end
function suite.pass_majorMinor_sameMajorLaterMinor()
test.istrue(p.checkVersion("1.2.0", "1.1"))
end
function suite.pass_majorMinor_sameMajorLaterPath()
test.istrue(p.checkVersion("1.1.1", "1.1"))
end
function suite.pass_majorMinor_laterMajorSameMinor()
test.istrue(p.checkVersion("2.0.0", "1.1"))
end
function suite.pass_majorMinor_laterMajorEarlierMinor()
test.istrue(p.checkVersion("2.0.0", "1.1"))
end
function suite.pass_majorMinor_laterMajorLaterMinor()
test.istrue(p.checkVersion("2.2.0", "1.1"))
end
function suite.fail_majorMinor_sameMajorEarlierMinor()
test.isfalse(p.checkVersion("1.0.0", "1.1"))
end
function suite.fail_majorMinor_earlierMajor()
test.isfalse(p.checkVersion("0.9.0", "1.1"))
end
--
-- Alpha comes before beta comes before dev
--
function suite.pass_alphaBeforeBeta()
test.istrue(p.checkVersion("1.0.0.beta1", "1.0.0.alpha1"))
end
function suite.fail_alphaBeforeBeta()
test.isfalse(p.checkVersion("1.0.0.alpha1", "1.0.0.beta1"))
end
function suite.pass_betaBeforeDev()
test.istrue(p.checkVersion("1.0.0.dev", "1.0.0.beta1"))
end
function suite.fail_betaBeforeDev()
test.isfalse(p.checkVersion("1.0.0.beta1", "1.0.0.dev"))
end
--
-- Check ">=" operator
--
function suite.pass_ge_sameMajorMinorPatch()
test.istrue(p.checkVersion("1.1.0", ">=1.1"))
end
function suite.pass_ge_sameMajorMinorLaterPatch()
test.istrue(p.checkVersion("1.1.1", ">=1.1"))
end
function suite.pass_ge_laterMajorEarlierMinor()
test.istrue(p.checkVersion("2.0.1", ">=1.1"))
end
function suite.pass_ge_sameMajorLaterMinor()
test.istrue(p.checkVersion("1.2.1", ">=1.1"))
end
function suite.fail_ge_earlierMajor()
test.isfalse(p.checkVersion("0.1.1", ">=1.1"))
end
function suite.fail_ge_earlierMinor()
test.isfalse(p.checkVersion("1.0.1", ">=1.1"))
end
--
-- Check ">" operator
--
function suite.pass_gt_sameMajorMinorLaterPatch()
test.istrue(p.checkVersion("1.1.1", ">1.1"))
end
function suite.pass_gt_laterMajor()
test.istrue(p.checkVersion("2.0.1", ">1.1"))
end
function suite.pass_gt_laterMinor()
test.istrue(p.checkVersion("1.2.1", ">1.1"))
end
function suite.fail_gt_sameMajorMinorPatch()
test.isfalse(p.checkVersion("1.1.0", ">1.1"))
end
function suite.fail_gt_earlierMajor()
test.isfalse(p.checkVersion("0.1.1", ">1.1"))
end
function suite.fail_gt_earlierMinor()
test.isfalse(p.checkVersion("1.0.1", ">1.1"))
end
--
-- Check multiple conditions
--
function suite.pass_onMultipleConditions()
test.istrue(p.checkVersion("1.2.0.0", ">=1.0 <2.0"))
end
function suite.fail_onMultipleConditions()
test.isfalse(p.checkVersion("2.2.0.0", ">=1.0 <2.0"))
end
--
-- If there is no version information, fails.
--
function suite.fail_onNoVersion()
test.isfalse(p.checkVersion(nil, "1.0"))
end