Verified Commit 82f0fe51 authored by Karel Koci's avatar Karel Koci 🤘

Export selected variables to subsequent script

parent a94b1a55
......@@ -535,6 +535,14 @@ ignore::
Don't error on missing content. If it's available from repository
then it is handled as missing.
Export and Unexport
~~~~~~~~~~~~~~~~~~~
Export "variable"
Unexport "variable"
These commands are described in section `Export variables to Script`.
StoreFlags
~~~~~~~~~~
......@@ -593,8 +601,8 @@ Logging
These commands allows printing of messages for their corresponding
verbosity levels.
Variables
---------
Predefined variables
--------------------
There are several global variables. These are set anew for each script
run, so one script can't damage them for another. Modifying them has
......@@ -701,6 +709,22 @@ Flags may be only strings.
Any modification to the own flags table is stored on successful
updater termination or when the script explicitly request it.
Export variables to Script
--------------------------
For security reasons individual scripts doesn't share variables. But it's
sometimes beneficial to have variable that can be read by sub-script. Such
variable is so called exported.
Export 'variable'
Unexport 'variable'
To export variable you have to call `Export` function with name of variable as
argument. To revert that you have to call `Unexport` function with same argument.
Be aware that changes done in sub-script to exported variables are not propagated
back to original script. But it's propagated to script executed from sub-script.
Hooks
-----
......
......@@ -292,10 +292,32 @@ local funcs = {
StoreFlags = {
mode = "morpher",
value = requests.store_flags
},
Unexport = {
mode = "morpher",
value = function(_, context, variable)
if type(variable) ~= "string" then
error(utils.exception("bad value", "Argument to Unexport must be string not '" .. type(variable) .. "'"))
end
context.exported[variable] = nil
end
}
}
}
-- Export function is checking the funcs table so we define it after we defined that table
funcs.Restricted.Export = {
mode = "morpher",
value = function(_, context, variable)
if type(variable) ~= "string" then
error(utils.exception("bad value", "Argument to Export must be string not '" .. type(variable) .. "'"))
end
if funcs.Full[variable] then
error(utils.exception("bad value", "Trying to export predefined variable '" .. tostring(variable) .. "'"))
end
context.exported[variable] = true
end
}
-- The operators for dependencies. They just wrap their arguments, nothing more.
for _, name in pairs({'And', 'Or', 'Not'}) do
local objname = "dep-" .. name:lower()
......@@ -456,8 +478,13 @@ function new(sec_level, parent, name)
result.root_parent.hierarchy[result.full_name or ""] = result
result.flags = backend.flags_get(result.full_name)
end
-- Propagate exported
result.exported = utils.shallow_copy(parent.exported or {})
-- Construct a new environment
result.env = {}
for var in pairs(parent.exported or {}) do
result.env[var] = utils.clone(parent.env[var])
end
local inject = utils.clone
if sec_level >= level("Full") then
inject = function (...) return ... end
......
-- Do not edit this file. It is the entry point. Edit the user.lua file.
l10n = {} -- global set with selected localizations
l10n = {} -- table with selected localizations
Export 'l10n'
-- This is helper function for including localization packages.
function for_l10n(fragment)
for _, lang in pairs(l10n or {}) do
Install(fragment .. lang, {ignore = {"missing"}})
end
end
Export 'for_l10n'
local branch = ""
local lists
......
......@@ -44,6 +44,7 @@ function test_context_new()
end
assert_equal("table", type(context))
assert_equal("table", type(context.env))
assert_equal("table", type(context.exported))
assert_equal("function", type(context.level_check))
-- There're some common functions in all of them
assert_equal(pairs, context.env.pairs)
......@@ -65,6 +66,7 @@ function test_context_new()
context.env.architectures[1] = 'changed'
assert_equal(sandbox.state_vars.architectures[1], 'all')
context.env = nil
context.exported = nil
context.level_check = nil
local expected = {sec_level = sandbox.level(level), tp = "context", flags = {}, name = '', full_name = ''}
expected.root_parent = expected
......@@ -162,6 +164,27 @@ function test_sandbox_run()
})
end
function test_exported()
local chunk_export = [[test = 'testing text'
nontest = 'missing text'
Export 'test']]
local c1 = sandbox.run_sandboxed(chunk_export, "Chunk name", "Full", nil, nil, nil)
assert_not_equal('error', c1.tp)
assert_equal('testing text', c1.env.test)
assert_equal('missing text', c1.env.nontest)
local c2 = sandbox.new("Full", c1)
local c3 = sandbox.new("Restricted", c2)
assert_equal(c1.env.test, c2.env.test)
assert_equal(c1.env.test, c3.env.test)
assert_nil(c2.env.nontest)
assert_nil(c3.env.nontest)
assert_table_equal({
tp = "error",
reason = "bad value",
msg = "Trying to export predefined variable 'pairs'"
}, sandbox.run_sandboxed("Export 'pairs'", "Chunk error", "Full", nil, nil, nil))
end
function test_level()
-- Creation and comparisons
local l1 = sandbox.level("Full")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment