diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2018-07-01 20:14:59 -0300 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2018-07-01 22:54:08 -0300 |
| commit | d5eae550c9368bd07008104bdecbcc5eb28814e2 (patch) | |
| tree | 441a44a5b8a636d898f20b64d1cb1e938c481bcb /src | |
| parent | fbf60599a04cddab512e5e95165fe875d8c01303 (diff) | |
| download | luarocks-d5eae550c9368bd07008104bdecbcc5eb28814e2.tar.gz luarocks-d5eae550c9368bd07008104bdecbcc5eb28814e2.tar.bz2 luarocks-d5eae550c9368bd07008104bdecbcc5eb28814e2.zip | |
rockspec: fix handling of rockspec_format versions
* luarocks/type_check.lua:
* fix expansion of platforms
* luarocks/type/rockspec.lua:
* when a version fails checking, try with a later
version to produce a hint in the error message.
See #823.
Diffstat (limited to 'src')
| -rw-r--r-- | src/luarocks/type/rockspec.lua | 50 | ||||
| -rw-r--r-- | src/luarocks/type_check.lua | 37 |
2 files changed, 56 insertions, 31 deletions
diff --git a/src/luarocks/type/rockspec.lua b/src/luarocks/type/rockspec.lua index 8b2bdffa..8214516e 100644 --- a/src/luarocks/type/rockspec.lua +++ b/src/luarocks/type/rockspec.lua | |||
| @@ -17,7 +17,7 @@ type_rockspec.rockspec_format = "3.0" | |||
| 17 | -- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them. | 17 | -- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them. |
| 18 | -- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked. | 18 | -- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked. |
| 19 | 19 | ||
| 20 | local rockspec_formats = type_check.declare_schemas({ | 20 | local rockspec_formats, versions = type_check.declare_schemas({ |
| 21 | ["1.0"] = { | 21 | ["1.0"] = { |
| 22 | rockspec_format = { _type = "string" }, | 22 | rockspec_format = { _type = "string" }, |
| 23 | package = { _type = "string", _mandatory = true }, | 23 | package = { _type = "string", _mandatory = true }, |
| @@ -143,6 +143,22 @@ type_rockspec.order = {"rockspec_format", "package", "version", | |||
| 143 | "test_dependencies", { "test", {"type"} }, | 143 | "test_dependencies", { "test", {"type"} }, |
| 144 | "hooks"} | 144 | "hooks"} |
| 145 | 145 | ||
| 146 | local function check_rockspec_using_version(rockspec, globals, version) | ||
| 147 | local schema = rockspec_formats[version] | ||
| 148 | if not schema then | ||
| 149 | return nil, "unknown rockspec format " .. version | ||
| 150 | end | ||
| 151 | local ok, err = type_check.check_undeclared_globals(globals, schema) | ||
| 152 | if ok then | ||
| 153 | ok, err = type_check.type_check_table(version, rockspec, schema, "") | ||
| 154 | end | ||
| 155 | if ok then | ||
| 156 | return true | ||
| 157 | else | ||
| 158 | return nil, err | ||
| 159 | end | ||
| 160 | end | ||
| 161 | |||
| 146 | --- Type check a rockspec table. | 162 | --- Type check a rockspec table. |
| 147 | -- Verify the correctness of elements from a | 163 | -- Verify the correctness of elements from a |
| 148 | -- rockspec table, reporting on unknown fields and type | 164 | -- rockspec table, reporting on unknown fields and type |
| @@ -151,19 +167,33 @@ type_rockspec.order = {"rockspec_format", "package", "version", | |||
| 151 | -- succeeded, or nil and an error message if it failed. | 167 | -- succeeded, or nil and an error message if it failed. |
| 152 | function type_rockspec.check(rockspec, globals) | 168 | function type_rockspec.check(rockspec, globals) |
| 153 | assert(type(rockspec) == "table") | 169 | assert(type(rockspec) == "table") |
| 170 | |||
| 154 | local version = rockspec.rockspec_format or "1.0" | 171 | local version = rockspec.rockspec_format or "1.0" |
| 155 | local schema = rockspec_formats[version] | 172 | local ok, err = check_rockspec_using_version(rockspec, globals, version) |
| 156 | if not schema then | ||
| 157 | return nil, "unknown rockspec format " .. version | ||
| 158 | end | ||
| 159 | local ok, err = type_check.check_undeclared_globals(globals, schema) | ||
| 160 | if ok then | ||
| 161 | ok, err = type_check.type_check_table(version, rockspec, schema, "") | ||
| 162 | end | ||
| 163 | if ok then | 173 | if ok then |
| 164 | return true | 174 | return true |
| 165 | end | 175 | end |
| 166 | return nil, err .. " (rockspec format " .. version .. ")" | 176 | |
| 177 | -- Rockspec parsing failed. | ||
| 178 | -- Let's see if it would pass using a later version. | ||
| 179 | |||
| 180 | local found = false | ||
| 181 | for _, v in ipairs(versions) do | ||
| 182 | if not found then | ||
| 183 | if v == version then | ||
| 184 | found = true | ||
| 185 | end | ||
| 186 | else | ||
| 187 | local v_ok, v_err = check_rockspec_using_version(rockspec, globals, v) | ||
| 188 | if v_ok then | ||
| 189 | return nil, err .. " (using rockspec format " .. version .. " -- " .. | ||
| 190 | [[adding 'rockspec_format = "]] .. v .. [["' to the rockspec ]] .. | ||
| 191 | [[will fix this)]] | ||
| 192 | end | ||
| 193 | end | ||
| 194 | end | ||
| 195 | |||
| 196 | return nil, err .. " (using rockspec format " .. version .. ")" | ||
| 167 | end | 197 | end |
| 168 | 198 | ||
| 169 | return type_rockspec | 199 | return type_rockspec |
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua index b204f5ee..bdf8ecc8 100644 --- a/src/luarocks/type_check.lua +++ b/src/luarocks/type_check.lua | |||
| @@ -2,11 +2,14 @@ | |||
| 2 | local type_check = {} | 2 | local type_check = {} |
| 3 | 3 | ||
| 4 | local cfg = require("luarocks.core.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
| 5 | local vers = require("luarocks.core.vers") | 5 | local fun = require("luarocks.fun") |
| 6 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
| 7 | local vers = require("luarocks.core.vers") | ||
| 7 | -------------------------------------------------------------------------------- | 8 | -------------------------------------------------------------------------------- |
| 8 | 9 | ||
| 9 | type_check.MAGIC_PLATFORMS = {} | 10 | -- A magic constant that is not used anywhere in a schema definition |
| 11 | -- and retains equality when the table is deep-copied. | ||
| 12 | type_check.MAGIC_PLATFORMS = 0xEBABEFAC | ||
| 10 | 13 | ||
| 11 | do | 14 | do |
| 12 | local function fill_in_version(tbl, version) | 15 | local function fill_in_version(tbl, version) |
| @@ -26,7 +29,7 @@ do | |||
| 26 | tbl[k] = { | 29 | tbl[k] = { |
| 27 | _any = util.deep_copy(tbl) | 30 | _any = util.deep_copy(tbl) |
| 28 | } | 31 | } |
| 29 | tbl[k]._any[v] = nil | 32 | tbl[k]._any[k] = nil |
| 30 | elseif type(v) == "table" then | 33 | elseif type(v) == "table" then |
| 31 | expand_magic_platforms(v) | 34 | expand_magic_platforms(v) |
| 32 | end | 35 | end |
| @@ -38,34 +41,26 @@ do | |||
| 38 | -- and the value is a schema specification. Schema versions are considered | 41 | -- and the value is a schema specification. Schema versions are considered |
| 39 | -- incremental: version "2.0" only needs to specify what's new/changed from | 42 | -- incremental: version "2.0" only needs to specify what's new/changed from |
| 40 | -- version "1.0". | 43 | -- version "1.0". |
| 41 | function type_check.declare_schemas(versions) | 44 | function type_check.declare_schemas(inputs) |
| 42 | local schemas = {} | 45 | local schemas = {} |
| 43 | local parent_version | 46 | local parent_version |
| 44 | 47 | ||
| 45 | local version_list = {} | 48 | local versions = fun.reverse_in(fun.sort_in(util.keys(inputs), vers.compare_versions)) |
| 46 | -- FIXME sorting lexicographically! "1.9" > "1.10" | 49 | |
| 47 | for version, schema in util.sortedpairs(versions) do | 50 | for _, version in ipairs(versions) do |
| 48 | table.insert(version_list, version) | 51 | local schema = inputs[version] |
| 49 | if parent_version ~= nil then | 52 | if parent_version ~= nil then |
| 50 | local copy = util.deep_copy(schemas[parent_version]) | 53 | local copy = util.deep_copy(schemas[parent_version]) |
| 51 | util.deep_merge(copy, schema) | 54 | util.deep_merge(copy, schema) |
| 52 | schemas[version] = copy | 55 | schema = copy |
| 53 | else | ||
| 54 | schemas[version] = schema | ||
| 55 | end | 56 | end |
| 56 | fill_in_version(schemas[version], version) | 57 | fill_in_version(schema, version) |
| 57 | expand_magic_platforms(schemas[version]) | 58 | expand_magic_platforms(schema) |
| 58 | parent_version = version | 59 | parent_version = version |
| 59 | end | 60 | schemas[version] = schema |
| 60 | |||
| 61 | -- Merge future versions as fallbacks under the old versions, | ||
| 62 | -- so that error messages can inform users when they try | ||
| 63 | -- to use new features without bumping rockspec_format in their rockspecs. | ||
| 64 | for i = #version_list, 2, -1 do | ||
| 65 | util.deep_merge_under(schemas[version_list[i - 1]], schemas[version_list[i]]) | ||
| 66 | end | 61 | end |
| 67 | 62 | ||
| 68 | return schemas | 63 | return schemas, versions |
| 69 | end | 64 | end |
| 70 | end | 65 | end |
| 71 | 66 | ||
