From b78aa96d3858554c49d3a6521f1d458fb80c3105 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sun, 12 Jan 2014 14:56:39 -0200 Subject: Catch undeclared globals in rockspecs --- src/luarocks/fetch.lua | 3 ++- src/luarocks/manif_core.lua | 3 ++- src/luarocks/persist.lua | 12 +++++++++++- src/luarocks/type_check.lua | 29 ++++++++++++++++++++++++----- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua index 83ab6fa9..7960acb4 100644 --- a/src/luarocks/fetch.lua +++ b/src/luarocks/fetch.lua @@ -148,10 +148,11 @@ function load_local_rockspec(filename, quick) if not rockspec then return nil, "Could not load rockspec file "..filename.." ("..err..")" end + local globals = err local ok, err = true, nil if not quick then - ok, err = type_check.type_check_rockspec(rockspec) + ok, err = type_check.type_check_rockspec(rockspec, globals) if not ok then return nil, filename..": "..err end diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua index 6424a1e8..b9fe8ab9 100644 --- a/src/luarocks/manif_core.lua +++ b/src/luarocks/manif_core.lua @@ -22,8 +22,9 @@ function manifest_loader(file, repo_url, quick) if not manifest then return nil, "Failed loading manifest for "..repo_url..": "..err end + local globals = err if not quick then - local ok, err = type_check.type_check_manifest(manifest) + local ok, err = type_check.type_check_manifest(manifest, globals) if not ok then return nil, "Error checking manifest: "..err end diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index 5b92f9cb..8f07da75 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua @@ -20,6 +20,15 @@ function load_into_table(filename, tbl) local result, chunk, ran, err local result = tbl or {} + local globals = {} + local globals_mt = { + __index = function(t, n) + globals[n] = true + return rawget(t, n) + end + } + local save_mt = getmetatable(result) + setmetatable(result, globals_mt) if _VERSION == "Lua 5.1" then -- Lua 5.1 chunk, err = loadfile(filename) if chunk then @@ -32,6 +41,7 @@ function load_into_table(filename, tbl) ran, err = pcall(chunk) end end + setmetatable(result, save_mt) if not chunk then if err:sub(1,5) ~= filename:sub(1,5) then @@ -42,7 +52,7 @@ function load_into_table(filename, tbl) if not ran then return nil, "Error running file: "..err end - return result + return result, globals end local write_table diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua index a3d41efc..bf063bf9 100644 --- a/src/luarocks/type_check.lua +++ b/src/luarocks/type_check.lua @@ -5,9 +5,9 @@ module("luarocks.type_check", package.seeall) local cfg = require("luarocks.cfg") -rockspec_format = "1.0" +local rockspec_format = "1.0" -rockspec_types = { +local rockspec_types = { rockspec_format = "string", MUST_package = "string", MUST_version = "[%w.]+-[%d]+", @@ -97,7 +97,7 @@ rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dep rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source rockspec_types.hooks.platforms.ANY = rockspec_types.hooks -manifest_types = { +local manifest_types = { MUST_repository = { -- packages ANY = { @@ -248,18 +248,35 @@ type_check_table = function(tbl, types, context) return true end +local function check_undeclared_globals(globals, types) + local undeclared = {} + for glob, _ in pairs(globals) do + if not (types[glob] or types["MUST_"..glob]) then + table.insert(undeclared, glob) + end + end + if #undeclared == 1 then + return nil, "Unknown variable: "..undeclared[1] + elseif #undeclared > 1 then + return nil, "Unknown variables: "..table.concat(undeclared, ", ") + end + return true +end + --- Type check a rockspec table. -- Verify the correctness of elements from a -- rockspec table, reporting on unknown fields and type -- mismatches. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. -function type_check_rockspec(rockspec) +function type_check_rockspec(rockspec, globals) assert(type(rockspec) == "table") if rockspec.rockspec_format then -- relies on global state load_extensions() end + local ok, err = check_undeclared_globals(globals, rockspec_types) + if not ok then return nil, err end return type_check_table(rockspec, rockspec_types, "") end @@ -269,7 +286,9 @@ end -- mismatches. -- @return boolean or (nil, string): true if type checking -- succeeded, or nil and an error message if it failed. -function type_check_manifest(manifest) +function type_check_manifest(manifest, globals) assert(type(manifest) == "table") + local ok, err = check_undeclared_globals(globals, manifest_types) + if not ok then return nil, err end return type_check_table(manifest, manifest_types, "") end -- cgit v1.2.3-55-g6feb