Verified Commit e44a7a9d authored by Karel Koci's avatar Karel Koci 🤘

Allow replanning to be run when update finished not immediately

parent 6335e6c6
......@@ -485,9 +485,18 @@ reboot::
may be needed when the old version would prevent the rest of the
update from happening.
replan::
The package has an effect on the updater itself. Therefore,
interrupt the update after this package is set up and perform the
planning again.
The package has an effect on the updater itself. Therefore, updater
have to run planning again. When this happens is according to value.
finished;;
Replan is done after whole initial update was performed. Use this option
if your package changes some setting that updater reads. It can be some
uci config or even some additional updater configuration (usable for
example if you want to add repository by installing package).
immediate;;
When this is set it interrupts the update after this package is set
up. This causes updater to run planning again as soon as the change is made.
This should be used only for packages containing updater itself or
closely related packages.
abi_change::
The package changed its ABI (or some other interface) and some other
packages need to be reinstalled. If this is set to `true` and the
......
......@@ -136,7 +136,7 @@ local allowed_package_extras = {
["pre_rm"] = allowed_package_extras_hooks,
["post_rm"] = allowed_package_extras_hooks,
["reboot"] = utils.arr2set({"string"}),
["replan"] = utils.arr2set({"boolean"}),
["replan"] = utils.arr2set({"boolean", "string"}),
["abi_change"] = utils.arr2set({"table", "boolean"}),
["content"] = utils.arr2set({"string"}),
["priority"] = utils.arr2set({"number"}),
......
......@@ -56,7 +56,8 @@ module "sandbox"
local updater_features = utils.arr2set({
'priorities',
'provides',
'abi_change'
'abi_change',
'replan_string'
})
-- WARNING: BEGIN_MAGIC (read the design morphers documentation)
......
......@@ -388,6 +388,7 @@ function pkg_aggregate()
post_install = {},
post_remove = {},
reboot = false,
replan = false,
abi_change = {},
abi_change_deep = {}
}
......@@ -427,19 +428,30 @@ function pkg_aggregate()
set_merge("post_remove")
set_merge("abi_change")
set_merge("abi_change_deep")
local reboot_vals = {
local function flag_merge(name, vals)
if m[name] and not vals[m[name]] then
ERROR("Invalid " .. name .. " value " .. m[name] .. " on package " .. m.name)
elseif (vals[m[name]] or 0) > vals[modifier[name]] then
-- Pick the highest value (handle the case when there's no flag)
modifier[name] = m[name]
end
end
flag_merge("reboot", {
[false] = 0,
delayed = 1,
finished = 2,
immediate = 3
}
if m.reboot and not reboot_vals[m.reboot] then
ERROR("Invalid reboot value " .. m.reboot .. " on package " .. m.name)
elseif (reboot_vals[m.reboot] or 0) > reboot_vals[modifier.reboot] then
-- Pick the highest value for the reboot (handle the case when there's no reboot flag)
modifier.reboot = m.reboot
})
flag_merge("replan", {
[false] = 0,
finished = 1,
[true] = 2,
immediate = 2
})
if modifier.replan == true then
-- true is the same as immediate so replace it
modifier.replan = "immediate"
end
modifier.replan = modifier.replan or m.replan
modifier.virtual = modifier.virtual or m.virtual
end
-- Canonize dependencies
......
......@@ -410,10 +410,10 @@ local function build_plan(pkgs, requests, sat, satmap)
return r
end
-- We plan packages with replan first to ensure that replan happens as soon as possible.
-- We plan packages with immediate replan first to ensure that such replan happens as soon as possible.
for name, pkg in pairs(pkgs) do
-- pkgs contains all packages so we have to check if package is in sat at all
if utils.multi_index(pkg, 'modifier', 'replan') and satmap.pkg2sat[name] and not (satmap.missing[pkg] or satmap.missing[name]) then -- we ignore missing packages, as they wouldn't be planned anyway and error or warning should be given by requests and other packages later on.
if utils.multi_index(pkg, 'modifier', 'replan') == "immediate" and satmap.pkg2sat[name] and not (satmap.missing[pkg] or satmap.missing[name]) then -- we ignore missing packages, as they wouldn't be planned anyway and error or warning should be given by requests and other packages later on.
pkg_plan(name, false, false, 'Planned package with replan enabled'); -- we don't expect to see this parent_str because we are planning this first, but it theoretically can happen so this makes at least some what sense.
end
end
......@@ -718,14 +718,14 @@ function filter_required(status, requests, allow_replan)
req.action = "require"
end
table.insert(result, req)
if request.modifier.replan and allow_replan then
if request.modifier.replan == "immediate" and allow_replan then
replan = true
break
end
end
end
if not replan then
-- We don't remove unused packages just yet if we replan, we do it after the replanning.
-- We don't remove unused packages just yet if we do immediate replan, we do it after the replanning.
utils.arr_append(result, check_removal(status, unused))
end
return result
......
......@@ -1180,7 +1180,7 @@ function test_penalty_and_missing()
assert_plan_dep_order(expected, result)
end
-- Check if package with replan is planned as soon as possible
-- Check if package with immediate replan is planned as soon as possible
function test_replan_order()
local pkgs = {
pkg = {
......@@ -1191,7 +1191,7 @@ function test_replan_order()
candidates = {{Package = 'pkgreplan', deps = {}, repo = def_repo}},
modifier = {
deps = 'dep',
replan = true
replan = "immediate"
}
},
dep = {
......@@ -1230,7 +1230,7 @@ function test_replan_order()
package = {Package = 'pkgreplan', deps = {}, repo = def_repo},
modifier = {
deps = 'dep',
replan = true
replan = "immediate"
},
critical = false,
name = "pkgreplan"
......@@ -1359,7 +1359,7 @@ function test_replan()
},
critical = false,
modifier = {
replan = true
replan = "immediate"
}
},
{
......@@ -1379,6 +1379,38 @@ function test_replan()
}, result)
end
function test_replan_finished()
local requests = {
{
action = "require",
name = "pkg1",
package = {
Version = "1",
repo = def_repo
},
critical = false,
modifier = {
replan = "finished"
}
},
{
action = "require",
name = "pkg2",
package = {
Version = "13",
repo = def_repo
},
critical = false,
modifier = {}
}
}
local result = planner.filter_required({}, requests, true)
assert_table_equal({
requests[1],
requests[2]
}, result)
end
function test_abi_change()
local status = {
pkg1 = {
......
......@@ -357,7 +357,7 @@ function test_pkg_merge()
},
reboot = "finished",
abi_change = {[true] = true, ['another'] = true},
replan = true
replan = "immediate"
}
}
}
......@@ -372,7 +372,8 @@ function test_pkg_merge()
post_remove = {},
pre_install = {},
pre_remove = {},
reboot = false
reboot = false,
replan = false
}
for _, pkg in pairs(exp) do
for name, def in pairs(modifier_def) do
......@@ -433,6 +434,7 @@ function test_local_and_repo()
pre_install = {},
pre_remove = {},
reboot = false,
replan = false,
tp = "package"
}
}
......
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