aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2018-07-01 20:14:59 -0300
committerHisham Muhammad <hisham@gobolinux.org>2018-07-01 22:54:08 -0300
commitd5eae550c9368bd07008104bdecbcc5eb28814e2 (patch)
tree441a44a5b8a636d898f20b64d1cb1e938c481bcb /src
parentfbf60599a04cddab512e5e95165fe875d8c01303 (diff)
downloadluarocks-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.lua50
-rw-r--r--src/luarocks/type_check.lua37
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
20local rockspec_formats = type_check.declare_schemas({ 20local 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
146local 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
160end
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.
152function type_rockspec.check(rockspec, globals) 168function 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 .. ")"
167end 197end
168 198
169return type_rockspec 199return 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 @@
2local type_check = {} 2local type_check = {}
3 3
4local cfg = require("luarocks.core.cfg") 4local cfg = require("luarocks.core.cfg")
5local vers = require("luarocks.core.vers") 5local fun = require("luarocks.fun")
6local util = require("luarocks.util") 6local util = require("luarocks.util")
7local vers = require("luarocks.core.vers")
7-------------------------------------------------------------------------------- 8--------------------------------------------------------------------------------
8 9
9type_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.
12type_check.MAGIC_PLATFORMS = 0xEBABEFAC
10 13
11do 14do
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
70end 65end
71 66