-- acf model for packages (apk) module (..., package.seeall) require("apk") require("modelfunctions") local configfile = "/etc/apk/repositories" local worldfile = "/var/lib/apk/world" local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " local repo = nil local install_cache = false local toplevel -- ################################################################################ -- LOCAL FUNCTIONS local function gettoplevel() if not toplevel then toplevel = {} local top = format.string_to_table(fs.read_file(worldfile) or "", "%s+") for i,name in ipairs(top) do toplevel[name] = i end end return toplevel end local run_apk_cmd = function(cmd) local c = path.."apk "..cmd.." 2>&1" local f = io.popen(c) local cmdresult = f:read("*a") f:close() return cmdresult end local reload_installed = function() if repo then -- clear out installed info for name,value in pairs(repo) do if value then value.installed = nil value.comment = nil end end -- read in which are installed local f = io.popen(path.."apk info -vv 2>/dev/null") for line in f:lines() do local name, ver, comment = string.match(line, "(%S+)%-(%d+%S*)%s+%-%s+(.*)") if not repo[name] then repo[name] = {} end repo[name].installed = ver repo[name].comment = comment end f:close() install_cache = true end return repo end local repository = function() if not repo then -- read in all of the packages local f = io.popen(path.."apk search 2>/dev/null") repo = {} install_cache = false for line in f:lines() do local name, ver = string.match(line, "(.*)%-(%d+.*)") if name then repo[name] = {} repo[name].version = ver end end f:close() end if not install_cache then reload_installed() end return repo end -- Find all the packages that depend on this package (using recursion) -- package is the name of the package -- tab saves dependants for already processed packages -- saved marks when package included in output -- output is the output function find_dependants(package) repo = repo or repository() if not repo[package] then return {} end if not repo[package].dependants then repo[package].dependants = {} local cmd = path .. "apk info -R "..package local f = io.popen(cmd) for line in f:lines() do if not line:find("depends on:") and not line:find("^%s*$") then table.insert(repo[package].dependants, line) for i,dep in ipairs(find_dependants(line, saved, output)) do table.insert(repo[package].dependants, dep) end end end end return repo[package].dependants end local function upgrade_available(package) local retval = false repo = repo or repository() if repo[package] and repo[package].version > repo[package].installed then retval = true else -- check the dependants for i,dep in ipairs(find_dependants(package)) do if repo[dep] and repo[dep].version > repo[dep].installed then retval = true break end end end return retval end -- ################################################################################ -- PUBLIC FUNCTIONS get_loaded_packages = function() repo = repository() toplevel = gettoplevel() -- read in the loaded packages local top = cfe({ type="list", value={}, label="Top Level Packages"}) local depend = cfe({ type="list", value={}, label="Dependant Packages"}) for name,value in pairs(repo) do if value.installed then local temp = {} temp.name = name temp.version = value.installed temp.description = value.comment if toplevel[name] then temp.upgrade = upgrade_available(name) top.value[#top.value+1] = temp else depend.value[#depend.value+1] = temp end end end table.sort(top.value, function(a,b) return (a.name < b.name) end) table.sort(depend.value, function(a,b) return (a.name < b.name) end) return cfe({ type="group", value={toplevel=top, dependant=depend}, label="Loaded Packages" }) end get_available_packages = function() repo = repository() -- available are all except same version installed local available = cfe({ type="list", value={}, label="Available Packages" }) for name,value in pairs(repo) do if value.version ~= value.installed then local temp = {} temp.name = name temp.version = value.version if value.installed and value.version > value.installed then temp.upgrade = true end available.value[#available.value + 1] = temp end end table.sort(available.value, function(a,b) return (a.name < b.name) end) return available end delete_package = function(package, sessiondata) local success, cmdresult = apk.delete(package) if success then -- Destroy menu and permissions info in session so recalculated if sessiondata then sessiondata.menu = nil end if sessiondata then sessiondata.permissions = nil end end return cfe({ value=cmdresult, label="Result of Delete" }) end install_package = function(package,sessiondata) local success, cmdresult = apk.install(package) if success then -- Destroy menu and permissions info in session so recalculated if sessiondata then sessiondata.menu = nil end if sessiondata then sessiondata.permissions = nil end end return cfe({ value=cmdresult, label="Result of Install" }) end upgrade_package = function(package) return cfe({ value=run_apk_cmd("add -u "..package), label="Result of Package Upgrade" }) end update_all = function() return cfe({ value=run_apk_cmd("update"), label="Result of Update" }) end upgrade_all = function() return cfe({ value=run_apk_cmd("upgrade"), label="Result of Upgrade" }) end get_configfile = function() return modelfunctions.getfiledetails(configfile) end update_configfile = function(newconfig) return modelfunctions.setfiledetails(newconfig, {configfile}) end get_package_details = function(package) repo = repo or repository() local details = {} details.package = cfe({ value=package, label="Package" }) details.version = cfe({ label="Available Version" }) details.installed = cfe({ label="Installed Version" }) details.comment = cfe({ label="Description" }) details.webpage = cfe({ label="Web Page" }) details.size = cfe({ label="Size" }) details.upgrade = cfe({ label="Upgrade Details" }) if not repo[package] then details.package.errtxt = "Invalid package" else details.version.value = repo[package].version if repo[package].installed then --details.installed.value = string.match(cmdresult[1], "%S*") details.installed.value = repo[package].installed details.comment.value = repo[package].comment local cmdresult = format.string_to_table(run_apk_cmd("info -ws "..package), "\n") details.webpage.value = cmdresult[2] or "" details.size.value = cmdresult[5] or "" local dependants = find_dependants(package) table.insert(dependants, 1, package) local revdeps = {} details.upgrade.value = {} for i,val in ipairs(dependants) do if not revdeps[val] then revdeps[val] = true if repo[val].version > repo[val].installed then table.insert(details.upgrade.value, val.." "..repo[val].installed.." -> "..repo[val].version) end end end details.upgrade.value = table.concat(details.upgrade.value, "\n") end end return cfe({ type="group", value=details, label="Package Details" }) end