LOCALLUALIBS= digest.lua e2build.lua e2tool.lua environment.lua \
policy.lua scm.lua licence.lua chroot.lua project.lua \
- source.lua sl.lua result.lua
+ source.lua sl.lua result.lua projenv.lua
LOCALTOOLS = $(LOCALLUATOOLS)
.PHONY: all install uninstall local install-local doc install-doc
local e2tool = require("e2tool")
local err = require("err")
local hash = require("hash")
+local projenv = require("projenv")
local strict = require("strict")
--- On disk chroot configuration.
t = nil
local g = {
e2chroot = function (data) t = data end,
- env = info.env,
+ env = projenv.safe_global_res_env_table(),
string = e2lib.safe_string_table(),
}
local plugin = require("plugin")
local policy = require("policy")
local project = require("project")
+local projenv = require("projenv")
local result = require("result")
local scm = require("scm")
local source = require("source")
-- @field default_files_server string: name of the default files server
-- @field result_storage (deprecated)
-- @field project_location string: project location relative to the servers
--- @field env table: env table
--- @field env_files table: list of env files
-- @field local_template_path Path to the local templates (string).
local _info = false
---- env - environment table from "proj/env"
--- @name env
--- @class table
-
--- Open debug logfile.
-- @param info Info table.
-- @return True on success, false on error.
return false, e:append("configuration syntax mismatch")
end
---- load env config.
-local function load_env_config(info, file)
- e2lib.logf(4, "loading environment: %s", file)
- local e = err.new("loading environment: %s", file)
- local rc, re
-
- local load_env_config = load_env_config
- local merge_error = false
- local function mergeenv(data)
- -- upvalues: info, load_env_config(), merge_error
- local rc, re
- if type(data) == "string" then
- -- include file
- rc, re = load_env_config(info, data)
- if not rc then
- -- no error checking in place, so set upvalue and return
- merge_error = re
- return
- end
- else
- -- environment table
- for var, val in pairs(data) do
- if type(var) ~= "string" or
- (type(val) ~= "string" and type(val) ~= "table") then
- merge_error = err.new("invalid environment entry in %s: %s=%s",
- file, tostring(var), tostring(val))
- return nil
- end
- if type(val) == "string" then
- e2lib.logf(4, "global env: %-15s = %-15s", var, val)
- info.env[var] = val
- info.global_env:set(var, val)
- elseif type(val) == "table" then
- for var1, val1 in pairs(val) do
- if type(var1) ~= "string" or
- (type(val1) ~= "string" and type(val1) ~= "table") then
- merge_error = err.new(
- "invalid environment entry in %s [%s]: %s=%s",
- file, var, tostring(var1), tostring(val1))
- return nil
- end
- e2lib.logf(4, "result env: %-15s = %-15s [%s]",
- var1, val1, var)
- info.env[var] = info.env[var] or {}
- info.env[var][var1] = val1
- info.result_env[var] = info.result_env[var] or environment.new()
- info.result_env[var]:set(var1, val1)
- end
- end
- end
- end
- return true
- end
-
- table.insert(info.env_files, file)
- local path = e2lib.join(info.root, file)
- local g = {
- e2env = info.env,
- env = mergeenv,
- string = e2lib.safe_string_table(),
- }
- rc, re = e2lib.dofile2(path, g)
- if not rc then
- return false, e:cat(re)
- end
- if merge_error then
- return false, merge_error
- end
- e2lib.logf(4, "loading environment done: %s", file)
- return true
-end
-
--- Gather source paths.
-- @param info Info table.
-- @param basedir Nil or directory from where to start scanning for more
end
-- read environment configuration
- info.env = {} -- global and result specfic env (deprecated)
- info.env_files = {} -- a list of environment files
- info.global_env = environment.new()
- info.result_env = {} -- result specific env only
- rc, re = load_env_config(info, "proj/env")
+ rc, re = projenv.load_env_config("proj/env")
if not rc then
return false, e:cat(re)
end
return false, e:cat(re)
end
- -- distribute result specific environment to the results,
- -- provide environment for all results, even if it is empty
- for r, res in pairs(info.results) do
- if not info.result_env[r] then
- info.result_env[r] = environment.new()
- end
- res._env = info.result_env[r]
+ -- project result envs must be checked after loading results
+ projenv.verify_result_envs()
+ if not rc then
+ return false, e:cat(re)
end
- -- check for environment for non-existent results
- for r, t in pairs(info.result_env) do
- if not info.results[r] then
- e:append("configured environment for non existent result: %s", r)
- end
- end
if e:getcount() > 1 then
return false, e
end
-- more details.
local licence = {}
+package.loaded["licence"] = licence
+
local class = require("class")
local e2lib = require("e2lib")
local e2tool = require("e2tool")
local err = require("err")
local hash = require("hash")
+local projenv = require("projenv")
local strict = require("strict")
--- Licence base class.
ltable = nil
local g = {
e2licence = function(data) ltable = data end,
- env = info.env,
+ env = projenv.safe_global_res_env_table(),
string = e2lib.safe_string_table(),
}
-- more details.
local project = {}
+
local buildconfig = require("buildconfig")
local e2lib = require("e2lib")
local e2tool = require("e2tool")
local err = require("err")
local hash = require("hash")
+local projenv = require("projenv")
local strict = require("strict")
local _prj = {}
prj = nil
local g = {
e2project = function(data) prj = data end,
- env = info.env,
+ env = projenv.safe_global_res_env_table(),
string = e2lib.safe_string_table(),
}
--- /dev/null
+--- Project environment module. Deals with the project-wide global and result
+-- specific configuration. It handles evaluating and verifying the file
+-- 'proj/env' and its include directives.
+-- @module local.projenv
+local projenv = {}
+package.loaded["projenv"] = projenv
+
+local e2lib = require("e2lib")
+local e2tool = require("e2tool")
+local environment = require("environment")
+local err = require("err")
+local result = require("result")
+local strict = require("strict")
+
+local _global_env = false
+local _result_env = {}
+
+--- Get the project wide global environment
+-- @return Environment object
+function projenv.get_global_env()
+ if not _global_env then
+ _global_env = environment.new()
+ end
+ return _global_env
+end
+
+--- Get the project wide *result* environment.
+-- Note that an unknown resultname will return a new environment.
+-- @param resultname Result name
+-- @return Environment object
+function projenv.get_result_env(resultname)
+ assertIsStringN(resultname)
+
+ if not _result_env[resultname] then
+ _result_env[resultname] = environment.new()
+ end
+ return _result_env[resultname]
+end
+
+--- Get a *copy* of the project wide environment and project wide result
+-- environment merged into one. Very similar to proj/env and friends.
+-- Writes to this table do not propagate to other results etc.
+-- @return Table filled just like proj/env
+function projenv.safe_global_res_env_table()
+ local gt = projenv.get_global_env():get_dict()
+
+ for resultname, resenv in pairs(_result_env) do
+ gt[resultname] = resenv:get_dict()
+ end
+
+ return gt
+end
+
+local function _load_env_config(file)
+ e2lib.logf(3, "loading environment: %s", file)
+ local e = err.new("loading environment: %s", file)
+ local rc, re
+ local merge_error = false
+
+ local function mergeenv(data)
+ -- upvalues: file, _load_env_config(), merge_error
+ local rc, re
+
+ if type(data) == "string" then
+ -- filename
+ rc, re = _load_env_config(data)
+ if not rc then
+ merge_error = re
+ return
+ end
+ elseif type(data) == "table" then
+ -- environment table
+ for key, value in pairs(data) do
+
+ if type(key) ~= "string" or
+ (type(value) ~= "string" and type(value) ~= "table") then
+ merge_error = err.new("invalid environment entry in %s: %s=%s",
+ file, tostring(key), tostring(value))
+ return
+ end
+
+ if type(value) == "string" then
+
+ e2lib.logf(3, "global env: %-15s = %-15s", key, value)
+ projenv.get_global_env():set(key, value)
+
+ else
+ local resultname = key
+
+ for key1, value1 in pairs(value) do
+ if type(key1) ~= "string" or type(value1) ~= "string" then
+ merge_error = err.new(
+ "invalid environment entry in %s [%s]: %s=%s",
+ file, key, tostring(key1), tostring(value1))
+ return
+ end
+
+ e2lib.logf(3, "result env: %-15s = %-15s [%s]", key1, value1, key)
+
+ projenv.get_result_env(key):set(key1, value1)
+ end
+ end
+ end
+ else
+ merge_error = err.new("invalid environment type: %s", tostring(data))
+ end
+ end
+
+ local info = e2tool.info()
+ local path = e2lib.join(info.root, file)
+
+ local mt = {
+ __index = function(t, key)
+ -- simulate a table that's updating itself as we read the config
+ -- called for env[key] and e2env[key]
+ return projenv.safe_global_res_env_table()[key]
+ end,
+ __call = function(t, data)
+ -- called for env "string" and env {}
+ -- use not documented for e2env
+ mergeenv(data)
+ end
+ }
+
+ local g = {
+ e2env = setmetatable({}, mt), -- XXX: no longer necessary, alias for env
+ env = setmetatable({}, mt),
+ string = e2lib.safe_string_table(),
+ }
+ rc, re = e2lib.dofile2(path, g)
+ if not rc then
+ return false, e:cat(re)
+ end
+
+ if merge_error then
+ return false, merge_error
+ end
+ return true
+end
+
+
+--- Load the environment config. Follows includes.
+-- @param file File name of config
+-- @return True on success, false on failure
+-- @return Err object on failure.
+-- @see projenv.verify_result_envs
+function projenv.load_env_config(file)
+ return _load_env_config(file)
+end
+
+--- Check load_env_config() didn't create any result environments for unknown
+-- results.
+-- @return True on success, false on failure
+-- @return Err object on failure.
+function projenv.verify_result_envs()
+ local e
+
+ e = err.new("in project environment config:")
+
+ -- check for environment for non-existent results
+ for resultname in pairs(_result_env) do
+ if not result.results[resultname] then
+ e:append("found environment for unknown result: %s",
+ resultname)
+ end
+ end
+
+ if e:getcount() > 1 then
+ return false, e
+ end
+
+ return true
+end
+
+return strict.lock(projenv)
+
local err = require("err")
local hash = require("hash")
local project = require("project")
+local projenv = require("projenv")
local sl = require("sl")
local source = require("source")
local strict = require("strict")
loadcnt = 0
g = {
e2result = function(data) rawres = data loadcnt = loadcnt + 1 end,
- env = info.env,
+ env = projenv.safe_global_res_env_table(),
string = e2lib.safe_string_table(),
}
local environment = require("environment")
local err = require("err")
local licence = require("licence")
+local projenv = require("projenv")
local sl = require("sl")
local strict = require("strict")
loadcnt = 0
g = {
e2source = function(data) rawsrc = data loadcnt = loadcnt + 1 end,
- env = info.env,
+ env = projenv.safe_global_res_env_table(),
string = e2lib.safe_string_table(),
}