xpm
This commit is contained in:
commit
6560b7a5bc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
test.lua
|
51
example-cfg/config.cfg
Normal file
51
example-cfg/config.cfg
Normal 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
145
package.lua
Normal 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
247
src/blt.lua
Normal 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
188
src/cache.lua
Normal 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
7
src/config.lua
Normal 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
23
src/github.lua
Normal 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
4
src/includes.lua
Normal 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
20
src/info.lua
Normal 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
116
src/init.lua
Normal 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
59
src/install.lua
Normal 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
122
src/lzss.lua
Normal 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
20
src/remove.lua
Normal 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
0
src/tsar.lua
Normal file
175
src/zcache.lua
Normal file
175
src/zcache.lua
Normal 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
|
Loading…
Reference in New Issue
Block a user