Verified Commit 4a9bb680 authored by Karel Koci's avatar Karel Koci 🤘

Add version_cmp and version_match to configuration language

parent 96da75d6
......@@ -542,6 +542,24 @@ Export and Unexport
These commands are described in section `Export variables to Script`.
version_cmp and version_match
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
version_cmp("version1", "version2")
version_match("version", "version_relation")
Both of these functions implement way to compare versions of package.
`version_cmp` compares two version strings and returns `-1`, `0`, or `1`
if version in first argument is less, equal, or greater than version in second
argument respectively.
`version_match` allows you to use same syntax as in case of string dependency.
So you will pass version string as first argument and then string with version
relation as second argument (for example:
`version_match(installed['pkg'].version, '>=1.0.0')`)
It returns true if version matches given version relation, otherwise false.
StoreFlags
~~~~~~~~~~
......@@ -750,26 +768,28 @@ libraries are made available. They are available in the security level
listed and in all higher levels.
Restricted::
* `table` library.
* `string` library.
* `math` library.
* `assert`.
* `error`.
* `ipairs`.
* `next`.
* `pairs`.
* `pcall`.
* `select`.
* `tonumber`.
* `tostring`.
* `type`.
* `unpack`.
* `xpcall`.
* `DBG`.
* `INFO`.
* `WARN`.
* `ERROR`.
* `table` library
* `string` library
* `math` library
* `assert`
* `error`
* `ipairs`
* `next`
* `pairs`
* `pcall`
* `select`
* `tonumber`
* `tostring`
* `type`
* `unpack`
* `xpcall`
* `DBG`
* `INFO`
* `WARN`
* `ERROR`
* `version_cmp`
* `version_match`
Local::
* `uci` library.
* `uci` library
Full::
* The whole lua library.
* The whole lua library
......@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with Updater. If not, see <http://www.gnu.org/licenses/>.
]]--
local ERROR=ERROR
local error = error
local type = type
local pairs = pairs
......@@ -59,7 +60,7 @@ local locks = require "locks"
module "backend"
-- Functions and variables used in other files
-- luacheck: globals pkg_temp_dir repo_parse status_dump pkg_unpack pkg_examine collision_check not_installed_confs steal_configs dir_ensure pkg_merge_files pkg_merge_control pkg_config_info pkg_cleanup_files control_cleanup version_cmp flags_load flags_get script_run flags_get_ro flags_write flags_mark run_state
-- luacheck: globals pkg_temp_dir repo_parse status_dump pkg_unpack pkg_examine collision_check not_installed_confs steal_configs dir_ensure pkg_merge_files pkg_merge_control pkg_config_info pkg_cleanup_files control_cleanup version_cmp version_match flags_load flags_get script_run flags_get_ro flags_write flags_mark run_state
-- Variables that we want to access from outside (ex. for testing purposes)
-- luacheck: globals status_file info_dir root_dir pkg_temp_dir flags_storage cmd_timeout cmd_kill_timeout stored_flags dir_opkg_collided
-- Functions that we want to access from outside (ex. for testing purposes)
......@@ -1133,6 +1134,32 @@ function version_cmp(v1, v2)
end
end
--[[
Checks if given version string matches given rule. Rule is the string in format
same as in case of dependency description (text in parenthesis).
]]
function version_match(v, r)
-- We don't expect that version it self have space in it self, any space is removed.
local wildmatch, cmp_str, vers = r:gsub('%s*$', ''):match('^%s*(~?)([<>=]*)%s*(.*)$')
if wildmatch == '~' then
vers = cmp_str .. vers -- We might matched something so prepend it back
return v:match(vers) ~= nil
elseif cmp_str == "" then -- If no compare was located than do plain compare
return v == r
else
local cmp = version_cmp(vers, v)
local ch
if cmp == -1 then
ch = '>'
elseif cmp == 1 then
ch = '<'
else
ch = '='
end
return cmp_str:find(ch, 1, true) ~= nil
end
end
stored_flags = {}
local function flags_ro_proxy(flags)
......
......@@ -199,6 +199,8 @@ local rest_available_funcs = {
"INFO",
"DBG",
"TRACE",
"version_match",
"version_cmp",
"system_cas",
"no_crl"
}
......
......@@ -43,9 +43,6 @@ module "planner"
-- Choose candidates that complies to version requirement.
function candidates_choose(candidates, pkg_name, version, repository)
assert(version or repository)
-- We don't expect that version it self have space in it self, any space is removed.
local wildmatch, cmp_str, vers = (version or ""):gsub('%s*$', ''):match('^%s*(~?)([<>=]*)%s*(.*)$')
if wildmatch == '~' then vers = cmp_str .. vers end -- prepend cmd_str to vers if we have wildmatch
-- repository is table of strings and objects, canonize to objects and add it to set.
local repos = {}
for _, repo in pairs(repository or {}) do
......@@ -60,18 +57,11 @@ function candidates_choose(candidates, pkg_name, version, repository)
local compliant = {}
for _, candidate in pairs(candidates) do
assert(candidate.Version) -- Version have to be there but candidate.repo might not if it is content from configuration not from repository
local cmp = not version or (wildmatch == '~') or backend.version_cmp(vers, candidate.Version)
-- Add candidates matching version and repository limitation. Package
-- supplied using content field in configuration has no repository, so it
-- is never added when repository limitation is specified.
if (not version or (candidate.Package == pkg_name and (
(wildmatch == '~' and candidate.Version:match(vers)) or
(cmp_str:find('>', 1, true) and cmp == -1) or
(cmp_str:find('=', 1, true) and cmp == 0) or
(cmp_str:find('<', 1, true) and cmp == 1)))
) and (
not repository or (candidate.repo and repos[candidate.repo])
) then
if (not version or (candidate.Package == pkg_name and backend.version_match(candidate.Version, version))) and
(not repository or (candidate.repo and repos[candidate.repo])) then
table.insert(compliant, candidate)
end
end
......
......@@ -933,6 +933,19 @@ function test_version_cmp()
assert_equal(1, B.version_cmp("1.10", "1.2"))
end
function test_version_match()
assert_true(B.version_match("1.2.3", ">1.2.0"))
assert_false(B.version_match("1.2.3", ">1.2.3"))
assert_true(B.version_match("1.2.3", ">=1.2.3"))
assert_true(B.version_match("1.2.3", "=>1.2.3"))
assert_true(B.version_match("1.2.3", "<1.2.4"))
assert_false(B.version_match("1.2.3", "<1.2.3"))
assert_true(B.version_match("1.2.3", "~^1%..*$"))
assert_false(B.version_match("1.2.3", "~^2%..*$"))
assert_true(B.version_match("1.2.3", "1.2.3")) -- without comparator do exact match (just as corner case)
assert_false(B.version_match("1.2.3", "1.3.3"))
end
local function check_stored_flags(full, expected)
local test_root = mkdtemp()
table.insert(tmp_dirs, test_root)
......
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