Verified Commit 6d3cad56 authored by Karel Koci's avatar Karel Koci 🤘 Committed by Karel Koci

Drop morpher

Morpher is obsoleted for more than year and should not be used any more.
We are doing now huge changes with approaching Turris OS 4.0 and that is
best time to drop this.
parent 91d4fd18
......@@ -196,7 +196,7 @@ has been run).
The package has no methods, it's just a stupid structure.
]]
function package(result, content, pkg, extra)
function package(content, pkg, extra)
-- Minimal typo verification. Further verification is done when actually using the package.
extra = allowed_extras_check_type(allowed_package_extras, "package", extra or {})
extra_check_verification("package", extra)
......@@ -231,6 +231,7 @@ function package(result, content, pkg, extra)
extra_check_table("package", name, value, {"deps", "validation", "installation"})
end
end
local result = {}
utils.table_merge(result, extra)
result.name = pkg
result.tp = "package"
......@@ -241,6 +242,7 @@ function package(result, content, pkg, extra)
-- We start downloading right away
utils.private(result).content_uri = uri(content, extra.content, extra)
end
return result
end
--[[
......@@ -253,9 +255,7 @@ function package_wrap(context, pkg)
-- It is already a package object
return pkg
else
local result = {}
package(result, context, pkg)
return result
return package(context, pkg)
end
end
......@@ -286,7 +286,7 @@ all the configuration scripts are run, parsed and used as a source of
packages. Then it shall mutate into a parsed repository object, but
until then, it is just a stupid data structure without any methods.
]]
function repository(result, context, name, repo_uri, extra)
function repository(context, name, repo_uri, extra)
-- Catch possible typos
extra = allowed_extras_check_type(allowed_repository_extras, 'repository', extra or {})
extra_check_verification("repository", extra)
......@@ -301,6 +301,7 @@ function repository(result, context, name, repo_uri, extra)
extra_check_table("repository", name, value, {"missing", "integrity", "syntax"})
end
end
local result = {}
utils.table_merge(result, extra)
result.repo_uri = repo_uri
utils.private(result).context = context
......@@ -337,6 +338,7 @@ function repository(result, context, name, repo_uri, extra)
result.tp = "repository"
known_repositories[name] = result
table.insert(known_repositories_all, result)
return result
end
-- Either return the repo, if it is one already, or look it up. Nil if it doesn't exist.
......@@ -397,7 +399,7 @@ local function content_request(context, cmd, allowed, ...)
submit({})
end
function install(_, context, ...)
function install(context, ...)
return content_request(context, "install", allowed_install_extras, ...)
end
......@@ -405,7 +407,7 @@ local allowed_uninstall_extras = {
["priority"] = utils.arr2set({"number"})
}
function uninstall(_, context, ...)
function uninstall(context, ...)
return content_request(context, "uninstall", allowed_uninstall_extras, ...)
end
......@@ -433,7 +435,7 @@ to their appropriate variables.
Originally filler contained name of script.
]]
function script(result, context, filler, script_uri, extra)
function script(context, filler, script_uri, extra)
if (not extra and not script_uri) or type(script_uri) == "table" then
extra = script_uri
script_uri = filler
......@@ -446,6 +448,7 @@ function script(result, context, filler, script_uri, extra)
extra_check_table("script", script_uri, value, {"missing", "integrity"})
end
end
local result = {}
local u = uri(context, script_uri, extra)
local ok, content = u:get()
if not ok then
......@@ -454,7 +457,7 @@ function script(result, context, filler, script_uri, extra)
result.tp = "script"
result.name = script_uri
result.ignored = true
return
return result
end
-- If couldn't get the script, propagate the error
error(content)
......@@ -481,6 +484,7 @@ function script(result, context, filler, script_uri, extra)
-- Return a dummy handle, just as a formality
result.tp = "script"
result.uri = script_uri
return result
end
return _M
......@@ -31,10 +31,6 @@ local pcall = pcall
local setmetatable = setmetatable
local tostring = tostring
local error = error
local unpack = unpack
local assert = assert
local next = next
local TRACE = TRACE
local WARN = WARN
local ERROR = ERROR
local run_command = run_command
......@@ -49,7 +45,7 @@ local uci_ok, uci = pcall(require, "uci")
module "sandbox"
-- luacheck: globals morpher state_vars level new run_sandboxed load_state_vars
-- luacheck: globals state_vars level new run_sandboxed load_state_vars
-- This can be changed often (always when we add some new feature). So it is defined here at top and not buried in code.
local updater_features = utils.arr2set({
......@@ -61,122 +57,6 @@ local updater_features = utils.arr2set({
'replan_string'
})
-- WARNING: BEGIN_MAGIC (read the design morphers documentation)
--[[
In short, morphers allow creating functions that can be called like:
function "Param" "Param" { x = 1, y = 2 }
They do so by accumulating the parameters through several separate function
calls and then doing the real call before use or when another morpher is called.
The function shall return the data in a table passed to it as a first parameter.
That table is empty and it can be filled with whatever object, possibly with
a meta table.
That table is actually the same one as the morpher object that accumulated the
parameters, but it has been gutted now, so the same address is shared
by the real result.
]]
-- The currently active morpher, so we can morph it as soon as we know we're done with it.
local active_morpher = nil
--[[
Return a morpher object calling the given function when done. The function
is called with any additional parameters passed here, concatenated with
the parameters accumulated later on.
Tip for use: The result is single use only. So, plug something like
function (...)
return morpher(fname, func, context, ...)
end
into the environment, instead of
morpher(func, context)
]]
function morpher(fname, func, ...)
if active_morpher then
active_morpher:morph()
end
local params = {...}
local index_pos = #params
--[[
We provide an empty table with meta table. This way,
the __index and __newindex events happen every time,
no matter what field is requested.
The meta table contains references to closures,
so the data is actually passed here in local variables.
]]
local result = {}
local name = tostring(result)
-- Accumulate some more parameters into the parameter list
local function call(table, ...)
WARN("Morpher is obsoleted! You have used morpher syntax with function: " .. fname)
local new_params = {...}
--[[
Just append the new parameters, by shifting
the index by the appropriate number. We don't
need (slightly slower) ipairs, since we don't
need to copy them in order, they'll end up at
the correct place.
]]
for i, v in pairs(new_params) do
params[i + index_pos] = v
end
index_pos = index_pos + #new_params
TRACE("Added ", #new_params, " parameters to ", name)
-- Pass the morpher further, to allow more calls
return table
end
local function morph(result)
TRACE("Morphing ", name)
-- The morpher is no longer active
active_morpher = nil
-- Get rid of the old meta table
setmetatable(result, nil)
-- The table should actually be empty
assert(not next(result))
-- We don't support multiple results yet. We may do so in future somehow, if needed.
func(result, unpack(params))
-- return the table we morphed into, just for good order.
return result
end
local meta = {
-- We accumulate the parameters by repeatedly invoking this behind the scenes
__call = call,
--[[
Selection of operations. They first morph into the result
and propagate the operation further.
More operations are possible, we just don't think they'd be needed. If they
are, they may be simply added.
]]
__index = function (table, key)
if key == "morph" then
-- Allow direct morphing by a request (shouldn't be much needed externally)
return morph
end
morph(table)
return table[key]
end,
__newindex = function (table, key, value)
morph(table)
table[key] = value
end,
__tostring = function (table)
morph(table)
return tostring(table)
end
}
TRACE("Creating morpher ", name, " with ", #params, " parameters")
active_morpher = result
return setmetatable(result, meta)
end
-- END_MAGIC
-- Available functions and "constants" from global environment
local rest_available_funcs = {
"table",
......@@ -288,28 +168,28 @@ local funcs = {
},
Restricted = {
Package = {
mode = "morpher",
mode = "wrap",
value = requests.package
},
Repository = {
mode = "morpher",
mode = "wrap",
value = requests.repository
},
Install = {
mode = "morpher",
mode = "wrap",
value = requests.install
},
Uninstall = {
mode = "morpher",
mode = "wrap",
value = requests.uninstall
},
Script = {
mode = "morpher",
mode = "wrap",
value = requests.script
},
Unexport = {
mode = "morpher",
value = function(_, context, variable)
mode = "wrap",
value = function(context, variable)
if type(variable) ~= "string" then
error(utils.exception("bad value", "Argument to Unexport must be string not '" .. type(variable) .. "'"))
end
......@@ -321,8 +201,8 @@ local funcs = {
-- 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)
mode = "wrap",
value = function(context, variable)
if type(variable) ~= "string" then
error(utils.exception("bad value", "Argument to Export must be string not '" .. type(variable) .. "'"))
end
......@@ -437,7 +317,7 @@ level is set to the one given (if nil is given, it is also
inherited).
A new environment, corresponding to the security level,
is constructed and stored in the result as „env“.
is constructed and stored in the wrap as „env“.
]]
function new(sec_level, parent)
sec_level = level(sec_level)
......@@ -476,10 +356,6 @@ function new(sec_level, parent)
result.env[n] = function(...)
return v.value(result, ...)
end
elseif v.mode == "morpher" then
result.env[n] = function(...)
return morpher(n, v.value, result, ...)
end
else
DIE("Unknown environment func mode " .. v.mode)
end
......@@ -519,7 +395,6 @@ The <reason> is one of:
are simply passed.
]]
function run_sandboxed(chunk, name, sec_level, parent, context_merge, context_mod)
assert(active_morpher == nil)
if type(chunk) == "string" then
local err
chunk, err = loadstring(chunk, name)
......@@ -533,11 +408,6 @@ function run_sandboxed(chunk, name, sec_level, parent, context_merge, context_mo
context_mod(context)
local func = setfenv(chunk, context.env)
local ok, err = pcall(func)
if ok and active_morpher then
ok, err = pcall(function () active_morpher:morph() end)
else
active_morpher = nil
end
if ok then
return context
else
......
......@@ -79,7 +79,7 @@ pkg-list::
intermediate product during repository processing.
script::
Return value of the `Script` command. This is mostly a dummy handle,
since morphers require to have a return value.
because there is not much to return.
dep-and, dep-or, dep-not::
Dependency composition objects. They contain the field `sub`, which
is a table of sub-dependencies.
......
......@@ -43,12 +43,12 @@ local function run_sandbox_fun(func_code, level)
end
function test_package()
local p1 = run_sandbox_fun "Package 'pkg_name'"
local p1 = run_sandbox_fun("Package('pkg_name')")
assert_table_equal({
tp = "package",
name = "pkg_name"
}, p1)
local p2 = run_sandbox_fun "Package 'pkg_name' {replan = true, reboot = 'delayed', priority = 42}"
local p2 = run_sandbox_fun("Package('pkg_name', {replan = true, reboot = 'delayed', priority = 42})")
assert_table_equal({
tp = "package",
name = "pkg_name",
......@@ -61,7 +61,7 @@ end
function test_repository()
requests.repo_serial = 1
local r1 = run_sandbox_fun "Repository 'test-repo' 'http://example.org/repo'"
local r1 = run_sandbox_fun("Repository('test-repo', 'http://example.org/repo')")
assert_table_equal({
tp = "repository",
name = "test-repo",
......@@ -73,7 +73,7 @@ function test_repository()
assert_table_equal({
index_uri = {[""] = {u = "http://example.org/repo/Packages.gz"}}
}, utils.private(r1))
local r2 = run_sandbox_fun "Repository 'test-repo-2' 'http://example.org/repo-2' {subdirs = {'a', 'b'}, priority = 60}"
local r2 = run_sandbox_fun("Repository('test-repo-2', 'http://example.org/repo-2', {subdirs = {'a', 'b'}, priority = 60})")
assert_table_equal({
tp = "repository",
name = "test-repo-2",
......@@ -86,7 +86,7 @@ function test_repository()
assert_table_equal({
index_uri = {["/a"] = {u = "http://example.org/repo-2/a/Packages.gz"}, ["/b"] = {u = "http://example.org/repo-2/b/Packages.gz"}}
}, utils.private(r2))
local r3 = run_sandbox_fun "Repository 'test-repo-other' 'http://example.org/repo-other' {index = 'https://example.org/repo-other/Packages.gz'}"
local r3 = run_sandbox_fun("Repository('test-repo-other', 'http://example.org/repo-other', {index = 'https://example.org/repo-other/Packages.gz'})")
assert_table_equal({
tp = "repository",
name = "test-repo-other",
......@@ -113,9 +113,9 @@ end
function test_install_uninstall()
local result = sandbox.run_sandboxed([[
Install "pkg1" "pkg2" {priority = 45} "pkg3" {priority = 14} "pkg4" "pkg5"
Uninstall "pkg6" {priority = 75} "pkg7"
Install "pkg8"
Install("pkg1", "pkg2", {priority = 45}, "pkg3", {priority = 14}, "pkg4", "pkg5")
Uninstall("pkg6", {priority = 75}, "pkg7")
Install("pkg8")
]], "test_install_uninstall_chunk", "Restricted")
local function req(num, mode, prio)
return {
......
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