commit 6560b7a5bc2375b200103d7cbd28e256e93a8c12 Author: Sam Roxanne Date: Fri Jun 5 13:59:13 2020 -0500 xpm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecbf039 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +test.lua \ No newline at end of file diff --git a/example-cfg/config.cfg b/example-cfg/config.cfg new file mode 100644 index 0000000..9fc7d5e --- /dev/null +++ b/example-cfg/config.cfg @@ -0,0 +1,51 @@ +{ + prefix = "/usr", + cache = { + clustersize = 20 + }, + repos = { + "OpenPrograms/mpmxyz-Programs", + "OpenPrograms/Altenius-Programs", + "OpenPrograms/pedrosgali-Programs", + "OpenPrograms/Gopher-Programs", + "OpenPrograms/ds84182-Programs", + "vifino/lua-cpuemus", + "OpenPrograms/Kenny-Programs", + "OpenPrograms/LizzyTrickster-Programs", + "OpenPrograms/Kilobyte-Programs", + "OpenPrograms/admicos-Programs", + "OpenPrograms/Wobbo-Programs", + "OpenPrograms/payonel-Programs", + "evgkul/moonscript-opencomputers", + "OpenPrograms/lperkins2-Programs", + "OpenPrograms/Forecaster-Programs", + "OpenPrograms/SuPeRMiNoR2-Programs", + "OpenPrograms/gamax92-Programs", + "OpenPrograms/Magik6k-Programs", + "OpenPrograms/Techokami-Programs", + "OpenPrograms/Wuerfel_21-OC-Toolkit", + "OpenPrograms/Wilma456-Programs", + "OpenPrograms/Sangar-Programs", + "OpenPrograms/luisau-Programs", + "OpenPrograms/Vexatos-Programs", + "OpenPrograms/Jomik-Programs", + "OpenPrograms/EvaKnievel-Programs", + "OpenPrograms/istasi-Programs", + "OpenPrograms/MiscPrograms", + "OpenPrograms/Starchasers-Programs", + "SolraBizna/SolrOC", + "OpenPrograms/Plan9k", + "OpenPrograms/asie-Programs", + "OpenPrograms/Antheus-Programs", + "ShadowKatStudios/OC-Minitel", + "Vexatos/Selene", + "OpenPrograms/Saphire-Programs", + "vilu85/OC-programs", + "OpenPrograms/Pixel-Programs", + "OpenPrograms/OpenPrograms.ru", + "OpenPrograms/Kubuxu-Programs", + "Kilobyte22/v", + "Akuukis/RobotColorWars", + "OpenPrograms/Fingercomp-Programs", + } +} \ No newline at end of file diff --git a/package.lua b/package.lua new file mode 100644 index 0000000..abe2354 --- /dev/null +++ b/package.lua @@ -0,0 +1,145 @@ +local repos = { + ["admicos' programs"]={ + repo="OpenPrograms/admicos-Programs", + }, + ["Akuukis' programs"]={ + repo="Akuukis/RobotColorWars", + }, + ["Altenius' programs"]={ + repo="OpenPrograms/Altenius-Programs", + }, + ["Antheus' programs"]={ + repo="OpenPrograms/Antheus-Programs", + }, + ["asie's programs"]={ + repo="OpenPrograms/asie-Programs", + }, + ["ds84182's programs"]={ + repo="OpenPrograms/ds84182-Programs", + }, + ["DustBin's programs"]={ + programs={ + ["LibCompress"]={ + repo="OpenPrograms/LibCompress/blob/master/LibCompress.lua", + desc="Compression API", + } + } + }, + ["EvaKnievel's programs"]={ + repo="OpenPrograms/EvaKnievel-Programs", + }, + ["Fingercomp's programs"]={ + repo="OpenPrograms/Fingercomp-Programs", + }, + ["Forecaster's programs"]={ + repo="OpenPrograms/Forecaster-Programs", + }, + ["gamax92's programs"]={ + repo="OpenPrograms/gamax92-Programs", + }, + ["Gopher's programs"]={ + repo="OpenPrograms/Gopher-Programs", + }, + ["istasi's programs"]={ + repo="OpenPrograms/istasi-Programs", + }, + ["Jomik's programs"]={ + repo="OpenPrograms/Jomik-Programs", + }, + ["LizzyTrickster's programs"]={ + repo="OpenPrograms/LizzyTrickster-Programs", + }, + ["lperkins2's programs"]={ + repo="OpenPrograms/lperkins2-Programs", + }, + ["Luisau's programs"]={ + repo="OpenPrograms/luisau-Programs", + }, + ["Kenny's programs"]={ + repo="OpenPrograms/Kenny-Programs", + }, + ["Kilobyte's programs"]={ + repo="OpenPrograms/Kilobyte-Programs", + }, + ["Kilobyte's programs (more)"]={ + repo="Kilobyte22/v", + }, + ["Kubuxu's programs"]={ + repo="OpenPrograms/Kubuxu-Programs", + }, + ["Magik6k's programs"]={ + repo="OpenPrograms/Magik6k-Programs", + }, + ["Minitel"]={ + repo="ShadowKatStudios/OC-Minitel", + }, + ["MoonOC"]={ + repo="evgkul/moonscript-opencomputers", + }, + ["mpmxyz's programs"]={ + repo="OpenPrograms/mpmxyz-Programs", + }, + ["OpenPrograms.ru"]={ + repo="OpenPrograms/OpenPrograms.ru", + }, + ["payonel's programs"]={ + repo="OpenPrograms/payonel-Programs", + }, + ["pedrosgali's programs"]={ + repo="OpenPrograms/pedrosgali-Programs", + }, + ["PixelToast's programs"]={ + repo="OpenPrograms/Pixel-Programs", + }, + ["Plan9k"]={ + repo="OpenPrograms/Plan9k", + }, + ["Sangar's programs"]={ + repo="OpenPrograms/Sangar-Programs", + }, + ["Saphire's programs"]={ + repo="OpenPrograms/Saphire-Programs", + }, + ["Selene"]={ + repo="Vexatos/Selene", + }, + ["SolraBizna's programs"]={ + repo="SolraBizna/SolrOC", + }, + ["Starchasers' programs"]={ + repo="OpenPrograms/Starchasers-Programs", + }, + ["SuPeRMiNoR2's programs"]={ + repo="OpenPrograms/SuPeRMiNoR2-Programs", + }, + ["Techokami's programs"]={ + repo="OpenPrograms/Techokami-Programs", + }, + ["Vexatos' programs"]={ + repo="OpenPrograms/Vexatos-Programs", + }, + ["vifino's Lua CPU emulators"]={ + repo="vifino/lua-cpuemus", + }, + ["vilu's programs"]={ + repo="vilu85/OC-programs", + }, + ["Wilma456's programs"]={ + repo="OpenPrograms/Wilma456-Programs", + }, + ["Wobbo's programs"]={ + repo="OpenPrograms/Wobbo-Programs", + }, + ["Wuerfel_21's programs"]={ + repo="OpenPrograms/Wuerfel_21-OC-Toolkit", + }, + ["Miscellaneous programs"]={ + repo="OpenPrograms/MiscPrograms", + }, +} + +for k, v in pairs(repos) do + if (v.repo) then + print(string.format("\""..v.repo.."\",")) + end +end \ No newline at end of file diff --git a/src/blt.lua b/src/blt.lua new file mode 100644 index 0000000..daf8252 --- /dev/null +++ b/src/blt.lua @@ -0,0 +1,247 @@ +-- BLT, made for Lua 5.3 + +local blt = {} + +do + local types + + local function serialize(val) + local t = type(val) + if (t == "number") then + t = math.type(val) + end + local b, str = types["s"..t](val) + b = (b << 3) | types[t] + return string.char(b) .. str + end + + local function deserialize(str, t) + local tb = str:byte(1) + local type_ = tb & 7 + local b = tb >> 3 + local v, l = types[type_](b, str:sub(2)) + return v, l+1 + end + + local function fromdouble(f) + return 0, string.pack(" 0xFFFFFFFFFFFFFF) then return _fromlongint(i) end + for j=0, 7 do + len = len + 1 + cmp2 = cmp2 | (0xFF << j) + --print("fromint", i+((cmp2//2)), cmp2) + --if (i+((cmp2//2)) <= cmp2) then + if (math.abs(i) <= cmp2//2) then + break + end + end + if (i < 0) then + i = i + (cmp2//2) + end + --i = i + (cmp2//2) + local tmp = "" + for j=0, len-1 do + tmp = tmp .. string.char((i & (0xFF << (j*8))) >> (j*8)) + end + --local tmp = string.pack(" 0) then + if (nindex == nmax) then + local ib, dat = fromarray(t) + tmp = tmp .. string.char(0) .. string.char(types.table_array | (ib << 3)) .. dat + else + for k, v in pairs(t) do + if (type(k) == "number" and math.type(k) == "integer") then + local ks = serialize(k) + local vs = serialize(v) + tmp = tmp .. ks .. vs + end + end + end + end + return 0, tmp .. string.char(0,0) --nil,nil terminated + end + + local function totbl(b, str) + local t = {} + local k = "" + local v = "" + local pos = 1 + --print("topen") + while true do + --print("k", str:byte(pos), str:byte(pos) & 7) + local k, l = deserialize(str:sub(pos)) + pos = pos + l + --print("v", str:byte(pos), str:byte(pos) & 7) + if (str:byte(pos) & 7 == 6) then + --print("ailen", str:byte(pos) & (7 ~ 0xFF)) + local r, l = deserialize(str:sub(pos)) + pos = pos + l + for i=1, #r do + t[i] = r[i] + end + else + local v, l = deserialize(str:sub(pos)) + pos = pos + l + if (not v and not k) then + --print("tclose") + break + end + --print("decode", k, v) + t[k] = v + end + end + return t, pos-1 --how + end + + -- Type LUT + types = { + ["nil"] = 0, + float = 1, + number = 1, + integer = 2, + string = 3, + boolean = 4, + table = 5, + table_array = 6, --Meta-value + [0] = function(b, str) return nil, 0 end, + [1] = todouble, + [2] = toint, + [3] = tostr, + [4] = tobool, + [5] = totbl, + [6] = toarray, + snil = function()return 0, ""end, + sfloat = fromdouble, + sinteger = fromint, + sstring = fromstr, + sboolean = frombool, + stable = fromtbl, + stable_array = fromarray + } + + function blt.serialize(...) + local args = {...} + local tmp = string.char(#args) + for i=1, #args do + local str = serialize(args[i]) + tmp = tmp .. str + end + return tmp + end + + local unpack = unpack or table.unpack + + function blt.deserialize(str) + local args = {} + local pos = 2 + local amt = str:byte(1) + local l + for i=1, amt do + local v, l = deserialize(str:sub(pos)) + args[i] = v + pos = pos + l + end + return unpack(args) + end +end \ No newline at end of file diff --git a/src/cache.lua b/src/cache.lua new file mode 100644 index 0000000..7651c12 --- /dev/null +++ b/src/cache.lua @@ -0,0 +1,188 @@ +local cache = {} +do + local function load_cache(name) + local cfile = io.open("/etc/xpm/cache/"..name.."/manifest.dat", "r") + local cachemf = blt.deserialize(cfile:read("*a")) + cfile:close() + local cached_files = {} + local mt = setmetatable({}, {__index=function(self, i) + if (cachemf[i]) then + local h = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, cachemf[i]), "r") + local t = blt.deserialize(h:read("*a")) + h:close() + for k, v in pairs(t) do + rawset(self, k, v) + end + return rawget(self, i) + end + end}) + rawset(mt, -1, cachemf) + return mt + end + local function save_cache(name, packages) + fs.makeDirectory("/etc/xpm/cache/"..name) + local manifest = io.open("/etc/xpm/cache/"..name.."/manifest.dat", "w") + local mf = {} + local current_cache = {} + local count = 0 + local idx = 0 + for k, v in pairs(packages) do + if (k ~= -1) then + mf[k] = count + current_cache[k] = v + idx = idx+1 + if (idx > config.cache.clustersize) then + idx = 0 + print(string.format("/etc/xpm/cache/%s/%x.dat", name, count)) + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, count), "w") + cf:write(blt.serialize(current_cache)) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 11 do + os.sleep(0) + end + end + end + end + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, count), "w") + cf:write(blt.serialize(current_cache)) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 10 do + os.sleep(0) + end + manifest:write(blt.serialize(mf)) + manifest:close() + end + local pcache = {} + local lcache = {} + if (fs.exists("/etc/xpm/cache/local")) then + lcache = load_cache("local") + end + + if (fs.exists("/etc/xpm/cache/remote")) then + pcache = load_cache("remote") + end + + function cache.check_cache(pkg) + return pcache[pkg] + end + + function cache.update_cache() + print("Updating cache...") + pcache = {} + fs.makeDirectory("/etc/xpm/cache/remote") + local manifest = io.open("/etc/xpm/cache/remote/manifest.dat", "w") + local mf = {} + local current_cache = {} + local count = 0 + local idx = 0 + for i=#config.repos, 1, -1 do + print("Hit "..(#config.repos-i)..": "..config.repos[i]) + local repo = serialization.unserialize(github_download(config.repos[i], "master/programs.cfg")) + if repo then + for k, v in pairs(repo) do + local e = {repo = config.repos[i], pkginfo=v} + mf[k] = count + current_cache[k] = e + idx = idx+1 + if (idx > config.cache.clustersize) then + idx = 0 + print(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count)) + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count), "w") + cf:write(blt.serialize(current_cache)) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 11 do + os.sleep(0) + end + end + end + else + print("Error "..(#config.repos-i)..": Not found.") + end + end + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count), "w") + cf:write(blt.serialize(current_cache)) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 10 do + os.sleep(0) + end + manifest:write(blt.serialize(mf)) + manifest:close() + --[[local h = io.open("/etc/xpm/cache/remote.dat", "w") + print("Serializing...") + local ser = blt.serialize(pcache) + print(#ser) + os.sleep(0) + print("Compressing...") + local comp = lzss.compress(ser) + print(#comp, "=", #ser/#comp) + h:write(comp) + h:close()]] + --save_cache("remote", pcache) + print("Saved cache.") + end + + function cache.get_upgradable() + if not fs.exists("/etc/xpm/cache/local") then + --cache.update_cache() + --local h = io.open("/etc/xpm/cache/local.dat", "w") + --h:write(lzss.compress(blt.serialize({xpm = pcache.xpm}))) + save_cache("local", {xpm = pcache.xpm}) + lcache = {xpm = pcache.xpm} + --h:close() + end + local upgradable = {} + for k, v in pairs(lcache) do + if (k ~= -1) then + local lpkg, rpkg = v.pkginfo, pcache[k].pkginfo + if lpkg.xpm and rpkg.xpm and lpkg.xpm.version ~= rpkg.xpm.version then + upgradable[#upgradable+1] = k + end + end + end + return upgradable + end + + function cache.fullload(cdat, name) + for k, v in pairs(cdat[-1]) do + if (not cdat[k]) then + local h = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, v), "r") + local t = blt.deserialize(h:read("*a")) + h:close() + for l, b in pairs(t) do + rawset(cdat, l, b) + end + end + end + end + + function cache.update_local_cache(pkg, info) + lcache[pkg] = info + --local h = io.open("/etc/xpm/cache/local.dat", "w") + --h:write(lzss.compress(blt.serialize(lcache))) + --h:close() + local mf = lcache[-1] + if not mf.loaded then + cache.fullload(lcache, "local") + mf.loaded = true + end + lcache[-1] = nil + save_cache("local", lcache) + lcache[-1] = mf + end + + function cache.getlocal() + return lcache + end + + function cache.getremote() + return pcache + end +end \ No newline at end of file diff --git a/src/config.lua b/src/config.lua new file mode 100644 index 0000000..51a4136 --- /dev/null +++ b/src/config.lua @@ -0,0 +1,7 @@ +local config = {} + +do + local fh = io.open("/etc/xpm/config.cfg", "r") + config = serialization.unserialize(fh:read("*a")) + fh:close() +end \ No newline at end of file diff --git a/src/github.lua b/src/github.lua new file mode 100644 index 0000000..78b3310 --- /dev/null +++ b/src/github.lua @@ -0,0 +1,23 @@ +local function download_file(url) + local result, response = pcall(internet.request, url) + --print(response) + local res = "" + if result then + local result, reason = pcall(function() + for chunk in response do + res = res .. chunk + end + end) + if not result then + return nil, reason -- for programs using wget as a function + end + else + return nil, response -- for programs using wget as a function + end + return res +end + +local function github_download(repo, file) + local url = string.format("https://raw.githubusercontent.com/%s/%s", repo, file) + return download_file(url) +end \ No newline at end of file diff --git a/src/includes.lua b/src/includes.lua new file mode 100644 index 0000000..64c0941 --- /dev/null +++ b/src/includes.lua @@ -0,0 +1,4 @@ +local internet = require("internet") +local fs = require("filesystem") +local serialization = require("serialization") +local event = require("event") \ No newline at end of file diff --git a/src/info.lua b/src/info.lua new file mode 100644 index 0000000..f477e67 --- /dev/null +++ b/src/info.lua @@ -0,0 +1,20 @@ +local function get_pkginfo(pkgname) + return cache.check_cache(pkgname) and cache.check_cache(pkgname).pkginfo +end + +local function pkg_installed(pkgname) + return cache.getlocal()[pkgname] +end + +local function get_version(pkgname) + local r, l = get_pkginfo(pkgname), pkg_installed(pkgname) and pkg_installed(pkgname).pkginfo + local rv, lv = true, not not l + if r.xpm and r.xpm.version then + rv = r.xpm.version + end + + if lv and l.xpm and l.xpm.version then + lv = l.xpm.version + end + return rv, lv +end \ No newline at end of file diff --git a/src/init.lua b/src/init.lua new file mode 100644 index 0000000..e08b0f4 --- /dev/null +++ b/src/init.lua @@ -0,0 +1,116 @@ +--#include "src/includes.lua" +--#include "src/config.lua" +--#include "src/blt.lua" +--#include "src/lzss.lua" +--#include "src/github.lua" +--#include "src/zcache.lua" +--#include "src/install.lua" +--#include "src/info.lua" +--#include "src/remove.lua" + +local args = table.pack(...) +if args[1] == "update" then + cache.update_cache() + local ug = cache.get_upgradable() + if (#ug > 0) then + print(#ug .. " packages can be upgraded.") + end + return true +elseif args[1] == "install" then + local deps = {} + print("Resolving dependencies...") + for i=2, #args do + resolve_deps(args[i], deps) + deps[#deps+1] = args[i] + deps[args[i]] = true + end + print("Packages to be installed:") + print(table.concat(deps, " ")) + while event.pull(0) do end + print("\nContinue with installation? [y/n]") + local sig = {event.pull("key_down")} + if (sig[3] ~= string.byte("y")) then + print("Canceling.") + os.exit(0) + end + for i=1, #deps do + print("Installing "..deps[i]) + deps[deps[i]] = install_pkg(deps[i]) + end + for i=1, #deps do + print("Running postinstall for "..deps[i]) + pkg_postinstall(deps[i], deps[deps[i]]) + end + return true +elseif args[1] == "info" then + local pi = get_pkginfo(args[2]) + if not pi then io.stderr:write("package not found\n") os.exit(1) end + local installed = pkg_installed(args[2]) + io.stdout:write(args[2] .. " ") + local remver, locver = get_version(args[2]) + if (type(remver) ~= "boolean" or type(locver) ~= "boolean") then + io.stdout:write("- "..remver) + if locver then + io.stdout:write(" (installed: "..locver..")") + end + end + print("") + print("Name: "..pi.name) + print("Authors: "..pi.authors) + print(pi.description) + if pi.note then + print("NOTE: "..pi.note) + end +elseif args[1] == "list" then + local lc = cache.getremote() + local mf = lc[-1] + local filter = args[2] or "." + for k, v in pairs(mf) do + if (k:match(filter) and not lc[k].pkginfo.hidden) then + print(k) + end + end +elseif args[1] == "list-installed" then + local mf = cache.getlocal()[-1] + local filter = args[2] or "." + for k, v in pairs(mf) do + if (k:match(filter)) then + print(k) + end + end +elseif args[1] == "remove" then + local deps = {} + cache.fullload(cache.getlocal(), "local") + print("Resolving dependencies...") + for i=2, #args do + deps[#deps+1] = args[i] + deps[args[i]] = true + get_removal_deps(args[i], deps) + end + print("Packages to be removed:") + print(table.concat(deps, " ")) + print("\nContinue with removal? [y/n]") + local sig = {event.pull("key_down")} + if (sig[3] ~= string.byte("y")) then + print("Canceling.") + os.exit(0) + end + for i=1, #deps do + print("Removing "..deps[i]) + remove_pkg(deps[i]) + end +elseif args[1] == "help" then + print("xpm update - Updates the cache") + print("xpm upgrade - Updates all packages that need to be updated.") + print("xpm install - Installs packages.") + print("xpm add-repo - Adds a package repo. Does not refresh cache.") + print("xpm remove-repo - Removes a repo. Does not refresh cache.") + print("xpm remove - Removes a package.") + print("xpm info - Gets package info.") + print("xpm deptree - Gets dependency tree.") + print("xpm list [filter] - Lists packages.") + print("xpm list-installed [filter] - Lists installed packages.") +else + print("invalid command") + return false +end \ No newline at end of file diff --git a/src/install.lua b/src/install.lua new file mode 100644 index 0000000..1fb101f --- /dev/null +++ b/src/install.lua @@ -0,0 +1,59 @@ +local function resolve_deps(pkgname, deps) + local pkg = cache.check_cache(pkgname) + if not pkg then + io.stderr:write("Package not found.\n") + os.exit(1) + end + local info = pkg.pkginfo + if (info.dependencies) then + for k, v in pairs(info.dependencies) do + if not cache.getlocal()[k] and not deps[k] then + resolve_deps(k, deps) + deps[#deps+1] = k + deps[k] = true + end + end + end +end + +local function install_pkg(pkgname, prefix) + prefix = prefix or config.prefix + -- Look up in cache + local pkg = cache.check_cache(pkgname) + if not pkg then + io.stderr:write("Package not found.\n") + os.exit(1) + end + pkg.tracked_files = {} + for k, v in pairs(pkg.pkginfo.files) do + if (v:sub(1, 2) ~= "//") then + v = config.prefix .. v + else + v = v:sub(2) + end + if (k:sub(1, 1) ~= ":") then + --print(k) + local fp = k:sub(#k:match("^(.+)/.+$")+1) + fs.makeDirectory(v) + --print(v..fp) + local f = io.open(v..fp, "w") + f:write(github_download(pkg.repo, k)) + f:close() + pkg.tracked_files[#pkg.tracked_files+1] = v .. fp + else + print(k) + end + end + return pkg +end + +local function pkg_postinstall(pkg, info) + cache.update_local_cache(pkg, info) + local pkgi = cache.getlocal()[pkg].pkginfo + if (pkgi.postinstall) then + local pi = pkgi.postinstall + for i=1, #pi do + os.execute(pi[i]) + end + end +end \ No newline at end of file diff --git a/src/lzss.lua b/src/lzss.lua new file mode 100644 index 0000000..4bbb7dd --- /dev/null +++ b/src/lzss.lua @@ -0,0 +1,122 @@ +--[[---------------------------------------------------------------------------- + LZSS - encoder / decoder + This is free and unencumbered software released into the public domain. + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + For more information, please refer to +--]]---------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +local lzss = {} +do + local string, table = string, table + + -------------------------------------------------------------------------------- + local POS_BITS = 12 + local LEN_BITS = 16 - POS_BITS + local POS_SIZE = 1 << POS_BITS + local LEN_SIZE = 1 << LEN_BITS + local LEN_MIN = 3 + + -------------------------------------------------------------------------------- + + local cout = require("computer").uptime + local lsleep = cout() + function lzss.compress(input) + local offset, output = 1, {} + local window = '' + if (cout() - lsleep > 4) then + os.sleep(0) + lsleep = cout() + end + local function search() + for i = LEN_SIZE + LEN_MIN - 1, LEN_MIN, -1 do + local str = string.sub(input, offset, offset + i - 1) + local pos = string.find(window, str, 1, true) + if pos then + return pos, str + end + end + end + + while offset <= #input do + local flags, buffer = 0, {} + + for i = 0, 7 do + if offset <= #input then + local pos, str = search() + if pos and #str >= LEN_MIN then + local tmp = ((pos - 1) << LEN_BITS) | (#str - LEN_MIN) + buffer[#buffer + 1] = string.pack('>I2', tmp) + else + flags = flags | (1 << i) + str = string.sub(input, offset, offset) + buffer[#buffer + 1] = str + end + window = string.sub(window .. str, -POS_SIZE) + offset = offset + #str + else + break + end + end + + if #buffer > 0 then + output[#output + 1] = string.char(flags) + output[#output + 1] = table.concat(buffer) + end + end + + return table.concat(output) + end + + -------------------------------------------------------------------------------- + function lzss.decompress(input) + local offset, output = 1, {} + local window = '' + + while offset <= #input do + local flags = string.byte(input, offset) + offset = offset + 1 + + for i = 1, 8 do + local str = nil + if (flags & 1) ~= 0 then + if offset <= #input then + str = string.sub(input, offset, offset) + offset = offset + 1 + end + else + if offset + 1 <= #input then + local tmp = string.unpack('>I2', input, offset) + offset = offset + 2 + local pos = (tmp >> LEN_BITS) + 1 + local len = (tmp & (LEN_SIZE - 1)) + LEN_MIN + str = string.sub(window, pos, pos + len - 1) + end + end + flags = flags >> 1 + if str then + output[#output + 1] = str + window = string.sub(window .. str, -POS_SIZE) + end + end + end + + return table.concat(output) + end +end \ No newline at end of file diff --git a/src/remove.lua b/src/remove.lua new file mode 100644 index 0000000..1b8224c --- /dev/null +++ b/src/remove.lua @@ -0,0 +1,20 @@ +local function get_removal_deps(pkgname, deps) + local packages = cache.getlocal() + for k, v in pairs(packages) do + if (k ~= -1) then + if (v.pkginfo.dependencies and v.pkginfo.dependencies[pkgname] and not deps[k]) then + deps[#deps+1] = k + deps[k] = true + get_removal_deps(k, deps) + end + end + end +end + +function remove_pkg(pkgname) + local files = cache.getlocal()[pkgname].tracked_files + for i=1, #files do + fs.remove(files[i]) + end + cache.update_local_cache(pkgname, nil) +end \ No newline at end of file diff --git a/src/tsar.lua b/src/tsar.lua new file mode 100644 index 0000000..e69de29 diff --git a/src/zcache.lua b/src/zcache.lua new file mode 100644 index 0000000..a26bed2 --- /dev/null +++ b/src/zcache.lua @@ -0,0 +1,175 @@ +local cache = {} +do + local function load_cache(name) + local cfile = io.open("/etc/xpm/cache/"..name.."/manifest.dat", "r") + local cachemf = blt.deserialize(lzss.decompress(cfile:read("*a"))) + cfile:close() + local cached_files = {} + local mt = setmetatable({}, {__index=function(self, i) + if (cachemf[i]) then + local h = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, cachemf[i]), "r") + local t = blt.deserialize(lzss.decompress(h:read("*a"))) + h:close() + for k, v in pairs(t) do + rawset(self, k, v) + end + return rawget(self, i) + end + end}) + rawset(mt, -1, cachemf) + return mt + end + local function save_cache(name, packages) + fs.makeDirectory("/etc/xpm/cache/"..name) + local manifest = io.open("/etc/xpm/cache/"..name.."/manifest.dat", "w") + local mf = {} + local current_cache = {} + local count = 0 + local idx = 0 + for k, v in pairs(packages) do + mf[k] = count + current_cache[k] = v + idx = idx+1 + if (idx > config.cache.clustersize) then + idx = 0 + print(string.format("/etc/xpm/cache/%s/%x.dat", name, count)) + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, count), "w") + cf:write(lzss.compress(blt.serialize(current_cache))) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 11 do + os.sleep(0) + end + end + end + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, count), "w") + cf:write(lzss.compress(blt.serialize(current_cache))) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 10 do + os.sleep(0) + end + manifest:write(lzss.compress(blt.serialize(mf))) + manifest:close() + end + local pcache = {} + local lcache = {} + if (fs.exists("/etc/xpm/cache/local")) then + lcache = load_cache("local") + end + + if (fs.exists("/etc/xpm/cache/remote")) then + pcache = load_cache("remote") + end + + function cache.check_cache(pkg) + return pcache[pkg] + end + + function cache.update_cache() + print("Updating cache...") + pcache = {} + fs.makeDirectory("/etc/xpm/cache/remote") + local manifest = io.open("/etc/xpm/cache/remote/manifest.dat", "w") + local mf = {} + local current_cache = {} + local count = 0 + local idx = 0 + for i=#config.repos, 1, -1 do + print("Hit "..(#config.repos-i)..": "..config.repos[i]) + local repo = serialization.unserialize(github_download(config.repos[i], "master/programs.cfg")) + if repo then + for k, v in pairs(repo) do + local e = {repo = config.repos[i], pkginfo=v} + mf[k] = count + current_cache[k] = e + idx = idx+1 + if (idx > config.cache.clustersize) then + idx = 0 + print(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count)) + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count), "w") + cf:write(lzss.compress(blt.serialize(current_cache))) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 11 do + os.sleep(0) + end + end + end + else + print("Error "..(#config.repos-i)..": Not found.") + end + end + local cf = io.open(string.format("/etc/xpm/cache/%s/%x.dat", "remote", count), "w") + cf:write(lzss.compress(blt.serialize(current_cache))) + cf:close() + current_cache = {} + count = count + 1 + for i=1, 10 do + os.sleep(0) + end + manifest:write(lzss.compress(blt.serialize(mf))) + manifest:close() + print("Saved cache.") + end + + function cache.get_upgradable() + if not fs.exists("/etc/xpm/cache/local") then + --cache.update_cache() + --local h = io.open("/etc/xpm/cache/local.dat", "w") + --h:write(lzss.compress(blt.serialize({xpm = pcache.xpm}))) + save_cache("local", {xpm = pcache.xpm}) + lcache = {xpm = pcache.xpm} + --h:close() + end + local upgradable = {} + for k, v in pairs(lcache) do + if k ~= -1 then + local lpkg, rpkg = v.pkginfo, pcache[k].pkginfo + if lpkg.xpm and rpkg.xpm and lpkg.xpm.version ~= rpkg.xpm.version then + upgradable[#upgradable+1] = k + end + end + end + return upgradable + end + + function cache.fullload(cdat, name) + for k, v in pairs(cdat[-1]) do + if (not cdat[k]) then + local h = io.open(string.format("/etc/xpm/cache/%s/%x.dat", name, v), "r") + local t = blt.deserialize(lzss.decompress(h:read("*a"))) + h:close() + for l, b in pairs(t) do + rawset(cdat, l, b) + end + end + end + end + + function cache.update_local_cache(pkg, info) + lcache[pkg] = info + --local h = io.open("/etc/xpm/cache/local.dat", "w") + --h:write(lzss.compress(blt.serialize(lcache))) + --h:close() + local mf = lcache[-1] + if not mf.loaded then + cache.fullload(lcache, "local") + mf.loaded = true + end + lcache[-1] = nil + save_cache("local", lcache) + lcache[-1] = mf + end + + function cache.getlocal() + return lcache + end + + function cache.getremote() + return pcache + end +end \ No newline at end of file