spm works maybe?
This commit is contained in:
+426
-22
@@ -16,10 +16,11 @@ local spm = function(...)
|
||||
i = false,
|
||||
e = false,
|
||||
t = false,
|
||||
s = false,
|
||||
sysroot = "",
|
||||
init = false,
|
||||
help = false,
|
||||
source = false
|
||||
overwrite = false
|
||||
}
|
||||
|
||||
local i = 1
|
||||
@@ -27,7 +28,9 @@ local spm = function(...)
|
||||
local http = require("http")
|
||||
local json = require("json")
|
||||
local tar = require("tar")
|
||||
local minify = require("minify")
|
||||
local deflate = require("deflate")
|
||||
local bit32 = require("bit32")
|
||||
local httpcache = {}
|
||||
|
||||
local function get(url)
|
||||
@@ -93,6 +96,82 @@ local spm = function(...)
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
i=nil
|
||||
|
||||
if cloptions.help or cloptions.h then
|
||||
if cloptions.S then
|
||||
print("spm -S - Synchronize Packages")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -S [options] <packages>")
|
||||
print("")
|
||||
print("Options:")
|
||||
print(" -y Refresh package databases")
|
||||
print(" -u Upgrade installed packages")
|
||||
print(" -i Show remote package information")
|
||||
print(" -s Download source")
|
||||
print("")
|
||||
print("Examples:")
|
||||
print(" spm -Sy")
|
||||
print(" spm -S package")
|
||||
print(" spm -Syu")
|
||||
return
|
||||
|
||||
elseif cloptions.Q then
|
||||
print("spm -Q - Query Package Database")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -Q [options] [package]")
|
||||
print("")
|
||||
print("Options:")
|
||||
print(" -i Show installed package information")
|
||||
print(" -l List files owned by a package")
|
||||
print(" -o Find which package owns a file")
|
||||
print(" -e List explicitly installed packages")
|
||||
print(" -t List orphan packages")
|
||||
print("")
|
||||
print("Examples:")
|
||||
print(" spm -Q")
|
||||
print(" spm -Qi lua")
|
||||
print(" spm -Ql lua")
|
||||
print(" spm -Qo /bin/lua")
|
||||
return
|
||||
|
||||
elseif cloptions.R then
|
||||
print("spm -R - Remove Packages")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -R [options] <packages>")
|
||||
print("")
|
||||
print("Currently no remove-specific options are implemented.")
|
||||
print("")
|
||||
print("Example:")
|
||||
print(" spm -R package")
|
||||
return
|
||||
|
||||
else
|
||||
print("spm - HyperionOS Package Manager")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm <operation> [options] [targets]")
|
||||
print("")
|
||||
print("Operations:")
|
||||
print(" -S Synchronize packages")
|
||||
print(" -Q Query package database")
|
||||
print(" -R Remove packages")
|
||||
print("")
|
||||
print("General Options:")
|
||||
print(" -h, --help Show help")
|
||||
print(" --init Initialize spm")
|
||||
print(" --sysroot DIR Operate on alternate root")
|
||||
print("")
|
||||
print("For operation-specific help:")
|
||||
print(" spm -Sh")
|
||||
print(" spm -Qh")
|
||||
print(" spm -Rh")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if cloptions.sysroot=="" then
|
||||
syscall.chdir("/")
|
||||
@@ -113,6 +192,17 @@ local spm = function(...)
|
||||
print("spm not initialized run \"spm --init\"")
|
||||
return
|
||||
end
|
||||
local log = fs.open("var/log/spm.log", "w")
|
||||
|
||||
local function w(...)
|
||||
local args = {...}
|
||||
local output = ""
|
||||
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
|
||||
output = output:sub(1, -2)
|
||||
syscall.write(1, output.."\n")
|
||||
log.write(output.."\n")
|
||||
log.flush()
|
||||
end
|
||||
|
||||
local repodb = string.split(fs.readAllText("var/spm/db/repos.list"), "\n")
|
||||
local sourcelist = string.split(fs.readAllText("etc/spm/sources.list"), "\n")
|
||||
@@ -192,29 +282,29 @@ local spm = function(...)
|
||||
for _, url in ipairs(repodb) do
|
||||
local ok, repo = checkRepo(url)
|
||||
if not ok then
|
||||
print("Failed to contact repository:")
|
||||
print(url)
|
||||
print("Consider running 'spm -Sy' to remove broken repositories.")
|
||||
w("Failed to contact repository:")
|
||||
w(url)
|
||||
w("Consider running 'spm -Sy' to remove broken repositories.")
|
||||
else
|
||||
if repo.packages then
|
||||
if repo.packages[name] then
|
||||
local pkgurl = repo.packages[name]
|
||||
local resp = get(pkgurl)
|
||||
if not resp then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
if resp.code ~= 200 then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
local pkgjson = json.decode(resp.body)
|
||||
if not pkgjson then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
return {
|
||||
url=pkgurl,
|
||||
@@ -236,14 +326,207 @@ local spm = function(...)
|
||||
return false, "target not found: "..name
|
||||
end
|
||||
|
||||
local function flatten(t)
|
||||
local ret={}
|
||||
for _,v in ipairs(t.content) do
|
||||
if v.type == "dir" then
|
||||
local f=flatten(v)
|
||||
for i,c in pairs(f) do
|
||||
ret[i]=c
|
||||
end
|
||||
elseif v.type == "file" then
|
||||
ret[v.name]=v.content
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function ptar(t, pkg)
|
||||
t=t.content[1]
|
||||
if t.name~=pkg.id then w("Tar contains "..t.name.." not "..pkg.id) return false end
|
||||
local ret={}
|
||||
for i=1, #t.content do
|
||||
if t.content[i].name == "data" then
|
||||
local data=flatten(t.content[i])
|
||||
local new={}
|
||||
for p,v in pairs(data) do
|
||||
new[p:sub(#pkg.id+7)]=v
|
||||
end
|
||||
ret.data=new
|
||||
elseif t.content[i].name == "control" then
|
||||
local data=flatten(t.content[i])
|
||||
local new={}
|
||||
for p,v in pairs(data) do
|
||||
new[p:sub(#pkg.id+10)]=v
|
||||
end
|
||||
ret.control=new
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function mini(tabl)
|
||||
local ret={}
|
||||
for i,v in pairs(tabl) do
|
||||
if v:sub(1,12)=="--:Minify:--" then
|
||||
local ok, code = pcall(minify.minify,v)
|
||||
if not ok then w("Failed to minify "..i..":\n"..code) ret[i]=v
|
||||
else ret[i]=code end
|
||||
else
|
||||
ret[i]=v
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function md5(msg)
|
||||
local bit = bit32
|
||||
|
||||
local function rol(x, n)
|
||||
return bit.lrotate(x, n)
|
||||
end
|
||||
|
||||
local function F(x, y, z)
|
||||
return bit.bor(bit.band(x, y), bit.band(bit.bnot(x), z))
|
||||
end
|
||||
|
||||
local function G(x, y, z)
|
||||
return bit.bor(bit.band(x, z), bit.band(y, bit.bnot(z)))
|
||||
end
|
||||
|
||||
local function H(x, y, z)
|
||||
return bit.bxor(x, y, z)
|
||||
end
|
||||
|
||||
local function I(x, y, z)
|
||||
return bit.bxor(y, bit.bor(x, bit.bnot(z)))
|
||||
end
|
||||
|
||||
local function u32le(s, i)
|
||||
return s:byte(i)
|
||||
+ s:byte(i + 1) * 0x100
|
||||
+ s:byte(i + 2) * 0x10000
|
||||
+ s:byte(i + 3) * 0x1000000
|
||||
end
|
||||
|
||||
local function le32(x)
|
||||
return string.char(
|
||||
bit.band(x, 0xff),
|
||||
bit.band(bit.rshift(x, 8), 0xff),
|
||||
bit.band(bit.rshift(x, 16), 0xff),
|
||||
bit.band(bit.rshift(x, 24), 0xff)
|
||||
)
|
||||
end
|
||||
|
||||
-- MD5 padding
|
||||
local bitlen = #msg * 8
|
||||
|
||||
msg = msg .. "\128"
|
||||
|
||||
while #msg % 64 ~= 56 do
|
||||
msg = msg .. "\0"
|
||||
end
|
||||
|
||||
-- Append 64-bit little-endian length
|
||||
local lo = bitlen % 0x100000000
|
||||
local hi = math.floor(bitlen / 0x100000000)
|
||||
|
||||
msg = msg .. le32(lo) .. le32(hi)
|
||||
|
||||
local a0 = 0x67452301
|
||||
local b0 = 0xefcdab89
|
||||
local c0 = 0x98badcfe
|
||||
local d0 = 0x10325476
|
||||
|
||||
local S = {
|
||||
7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
|
||||
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
|
||||
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
|
||||
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
|
||||
}
|
||||
|
||||
local K = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
}
|
||||
|
||||
for chunk = 1, #msg, 64 do
|
||||
local M = {}
|
||||
|
||||
for i = 0, 15 do
|
||||
M[i] = u32le(msg, chunk + i * 4)
|
||||
end
|
||||
|
||||
local A = a0
|
||||
local B = b0
|
||||
local C = c0
|
||||
local D = d0
|
||||
|
||||
for i = 0, 63 do
|
||||
local f
|
||||
local g
|
||||
|
||||
if i < 16 then
|
||||
f = F(B, C, D)
|
||||
g = i
|
||||
elseif i < 32 then
|
||||
f = G(B, C, D)
|
||||
g = (5 * i + 1) % 16
|
||||
elseif i < 48 then
|
||||
f = H(B, C, D)
|
||||
g = (3 * i + 5) % 16
|
||||
else
|
||||
f = I(B, C, D)
|
||||
g = (7 * i) % 16
|
||||
end
|
||||
|
||||
local tmp = D
|
||||
D = C
|
||||
C = B
|
||||
|
||||
local x = A + f + K[i + 1] + M[g]
|
||||
x = x % 0x100000000
|
||||
|
||||
B = (B + rol(x, S[i + 1])) % 0x100000000
|
||||
|
||||
A = tmp
|
||||
end
|
||||
|
||||
a0 = (a0 + A) % 0x100000000
|
||||
b0 = (b0 + B) % 0x100000000
|
||||
c0 = (c0 + C) % 0x100000000
|
||||
d0 = (d0 + D) % 0x100000000
|
||||
end
|
||||
|
||||
local digest = le32(a0) .. le32(b0) .. le32(c0) .. le32(d0)
|
||||
|
||||
return (digest:gsub(".", function(c)
|
||||
return string.format("%02x", c:byte())
|
||||
end))
|
||||
end
|
||||
|
||||
if cloptions.S then
|
||||
if cloptions.y then
|
||||
print("Updating repositories...")
|
||||
w("Updating repositories...")
|
||||
repodb={}
|
||||
for _,v in ipairs(getRepos(sourcelist)) do
|
||||
repodb[#repodb+1]=v
|
||||
end
|
||||
print("Writing new data...")
|
||||
w("Writing new data...")
|
||||
local str = ""
|
||||
for _,v in ipairs(repodb) do
|
||||
str=str..v.."\n"
|
||||
@@ -257,7 +540,7 @@ local spm = function(...)
|
||||
local found = {}
|
||||
for i,v in ipairs(args) do
|
||||
local pkg, err = getPkg(v)
|
||||
if not pkg then print(err) syscall.exit(1) end
|
||||
if not pkg then w(err) syscall.exit(1) end
|
||||
needed[#needed+1] = pkg
|
||||
found[v]=true
|
||||
end
|
||||
@@ -286,10 +569,10 @@ local spm = function(...)
|
||||
if #needed==0 then
|
||||
syscall.exit()
|
||||
end
|
||||
print("")
|
||||
print("Packages("..tostring(#needed).."):")
|
||||
w("")
|
||||
w("Packages("..tostring(#needed).."):")
|
||||
printpkgs(needed)
|
||||
print("")
|
||||
w("")
|
||||
while true do
|
||||
local text = userinput(0, "Proceed with download [Y/n]", nil, 1)
|
||||
if text=="" then
|
||||
@@ -303,10 +586,131 @@ local spm = function(...)
|
||||
|
||||
local files = {}
|
||||
for _,v in ipairs(needed) do
|
||||
local file = http.get(v.tar)
|
||||
|
||||
if not pkgdb[v.id] or not pkgdb[v.id].hash==v.hash then
|
||||
w("Downloading "..v.id)
|
||||
local resp = get(v.tar)
|
||||
if not resp then
|
||||
w("Package "..v.id.." failed GET")
|
||||
syscall.exit()
|
||||
end
|
||||
if resp.code ~= 200 then
|
||||
w("Package "..v.id.." returned code "..tostring(resp.code))
|
||||
syscall.exit()
|
||||
end
|
||||
local ok, repotar = pcall(tar.unpack, resp.body)
|
||||
if not ok or not repotar then
|
||||
w("Package "..v.id.." failed tar parsing")
|
||||
syscall.exit()
|
||||
end
|
||||
local f=ptar(repotar, v)
|
||||
if not f or not f.data then syscall.exit() end
|
||||
if not cloptions.s then
|
||||
f.data=mini(f.data)
|
||||
end
|
||||
f.hash=v.hash
|
||||
files[v.id]=f
|
||||
else
|
||||
w("Package "..v.id.." hash already installed")
|
||||
end
|
||||
end
|
||||
|
||||
w("Checking for conflicts...")
|
||||
local seen={}
|
||||
for i,v in pairs(files) do
|
||||
for f,c in pairs(v.data) do
|
||||
if seen[f] then
|
||||
w(i.." and "..seen[f].." have conflicting file "..f)
|
||||
v.data[f]=nil
|
||||
else
|
||||
seen[f]=i
|
||||
end
|
||||
end
|
||||
end
|
||||
seen=nil
|
||||
w("Checking for modified files...")
|
||||
local block={}
|
||||
for i, v in pairs(files) do
|
||||
if pkgdb[i] then
|
||||
if not cloptions.overwrite then
|
||||
for f,h in pairs(v.data) do
|
||||
if pkgdb[i].files[f]~=md5(fs.readAllText(f)) then
|
||||
w(f.." was modified on disk, specify --overwrite to overwrite")
|
||||
block[f]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if not cloptions.overwrite then
|
||||
for f,h in pairs(v.data) do
|
||||
if fs.exists(f) then
|
||||
w(f.." already exists, specify --overwrite to overwrite or remove the file")
|
||||
syscall.exit()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Adding delete calls...")
|
||||
local delete={}
|
||||
for i,v in pairs(files) do
|
||||
if pkgdb[i] then
|
||||
for f,c in pairs(pkgdb[i].files) do
|
||||
if not v.data[f] then
|
||||
if c~=md5(fs.readAllText(f)) then
|
||||
w(f.." was modified on disk, specify --overwrite to overwrite")
|
||||
else
|
||||
delete[f]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Calculating useage...")
|
||||
local net=0
|
||||
for i,v in pairs(files) do
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
net=net+#c
|
||||
end
|
||||
end
|
||||
for f,c in pairs(delete) do
|
||||
net=net-#fs.readAllText(f)
|
||||
end
|
||||
end
|
||||
w("")
|
||||
w("Net Upgrade Size: "..tostring(net))
|
||||
w("")
|
||||
while true do
|
||||
local text = userinput(0, "Proceed with Installation [Y/n]", nil, 1)
|
||||
if text=="" then
|
||||
break
|
||||
elseif text:lower()=="y" then
|
||||
break
|
||||
elseif text:lower()=="n" then
|
||||
syscall.exit()
|
||||
end
|
||||
end
|
||||
w("Updatating db...")
|
||||
for i,v in pairs(files) do
|
||||
local content={}
|
||||
content.files={}
|
||||
for f,c in pairs(v.data) do
|
||||
content.files[f]=md5(c)
|
||||
end
|
||||
content.hash=v.hash
|
||||
fs.writeAllText("var/spm/db/installed/"..i, json.encode(content))
|
||||
end
|
||||
w("Writing changes...")
|
||||
for i,v in pairs(files) do
|
||||
w("Writing "..i)
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
fs.writeAllText(f,c)
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Install complete")
|
||||
log.close()
|
||||
|
||||
elseif cloptions.R then
|
||||
-- remove tree
|
||||
elseif cloptions.Q then
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
tar
|
||||
deflate
|
||||
json
|
||||
minify
|
||||
minify
|
||||
bit32
|
||||
Hyperion-core
|
||||
Reference in New Issue
Block a user