This commit is contained in:
Sam Roxanne 2020-06-05 13:59:13 -05:00
commit 6560b7a5bc
15 changed files with 1178 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test.lua

51
example-cfg/config.cfg Normal file
View File

@ -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",
}
}

145
package.lua Normal file
View File

@ -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

247
src/blt.lua Normal file
View File

@ -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("<d", f)
end
local function todouble(b, str)
return string.unpack("<d", str:sub(1, 8)), 8
end
local function _fromlongint(i)
--print("longint")
return 8, string.pack("<l", i)
end
local function fromint(i)
--Time to rabidly optimize this.
local len = 0
local cmp2 = 0
if (i > 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("<i["..len.."]", i)
return len, tmp
end
local function _tolongint(str)
--print("longint2")
return string.unpack("<l", str:sub(1, 8)), 8
end
local function toint(b, str)
if (b == 8) then return _tolongint(str) end
--return string.unpack("<i["..b.."]", str:sub(1, b)), b
local tmp = 0
for i=0, b-1 do
tmp = tmp | (str:byte(i+1) << (i*8))
end
local sign = (tmp & (0x80 << ((b-1)*8)))
sign = sign << (63 - (b*8))
local int = tmp & ((0x80 << ((b-1)*8)) ~ 0xFFFFFFFFFFFFFF)
return int | sign, b
end
local function frombool(b)
return b and 1 or 0, ""
end
local function tobool(b, str)
return b ~= 0, 0
end
local function fromstr(s)
local len, val = fromint(#s)
return len, val .. s
end
local function tostr(b, str)
local strl, l = toint(b, str)
local rtn = str:sub(1+l, l+strl)
return rtn, strl+l
end
local function fromarray(a)
local b, tmp = fromint(#a)
for i=1, #a do
tmp = tmp .. serialize(a[i])
end
--print("alen_s", #tmp)
return b, tmp
end
local function toarray(b, str, arr)
local arrl, l = toint(b, str)
--print("clen", l)
--print("arr len", arrl)
local arr = {}
local i = 0
for i=1, arrl do
--print("adec", i)
local v, z = deserialize(str:sub(1+l))
--print("arr", i, v)
l = l+z
--print("clen", l, z)
arr[i] = v
end
--print("alen", l)
return arr, l
end
local function fromtbl(t)
local tmp = ""
--See if the numerical keys are a list, and, if so, write a list
local nindex = 0
local nmax = 0
for k, v in pairs(t) do
if (type(k) == "number") then
if (math.type(k) == "integer") then
nindex = nindex + 1
if (nmax < k) then
nmax = k
end
end
else
local ks = serialize(k)
local vs = serialize(v)
tmp = tmp .. ks .. vs
end
end
if (nmax > 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

188
src/cache.lua Normal file
View File

@ -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

7
src/config.lua Normal file
View File

@ -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

23
src/github.lua Normal file
View File

@ -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

4
src/includes.lua Normal file
View File

@ -0,0 +1,4 @@
local internet = require("internet")
local fs = require("filesystem")
local serialization = require("serialization")
local event = require("event")

20
src/info.lua Normal file
View File

@ -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

116
src/init.lua Normal file
View File

@ -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 <pkg, ...> - Installs packages.")
print("xpm add-repo <repo, ...> - Adds a package repo. Does not refresh cache.")
print("xpm remove-repo <repo, ...> - Removes a repo. Does not refresh cache.")
print("xpm remove <pkg, ...> - Removes a package.")
print("xpm info <pkg> - Gets package info.")
print("xpm deptree <pkg> - Gets dependency tree.")
print("xpm list [filter] - Lists packages.")
print("xpm list-installed [filter] - Lists installed packages.")
else
print("invalid command")
return false
end

59
src/install.lua Normal file
View File

@ -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

122
src/lzss.lua Normal file
View File

@ -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 <http://unlicense.org/>
--]]----------------------------------------------------------------------------
--------------------------------------------------------------------------------
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

20
src/remove.lua Normal file
View File

@ -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

0
src/tsar.lua Normal file
View File

175
src/zcache.lua Normal file
View File

@ -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