230 lines
5.5 KiB
Lua
230 lines
5.5 KiB
Lua
|
local serial = require "serialization"
|
||
|
local event = require "event"
|
||
|
local fs = require "filesystem"
|
||
|
local unicode = require "unicode"
|
||
|
|
||
|
local tArgs = {...}
|
||
|
local ipackages = {} -- installed packages
|
||
|
local rpath = tArgs[1] or install.from
|
||
|
local tpath = tArgs[2] or install.to
|
||
|
if tpath == "//" then
|
||
|
tpath = "/usr/"
|
||
|
end
|
||
|
|
||
|
tpath, rpath = fs.canonical(tpath), fs.canonical(rpath)
|
||
|
|
||
|
local fobj = io.open(rpath.."/master/programs.cfg","rb") -- read packages list from floppy
|
||
|
if not fobj then
|
||
|
error("installer disk not properly configured")
|
||
|
end
|
||
|
local packages = serial.unserialize(fobj:read("*a"))
|
||
|
fobj:close()
|
||
|
|
||
|
local function ripackages()
|
||
|
local fobj = io.open("/etc/opdata.svd","rb") -- attempt to read installed packages
|
||
|
if fobj then
|
||
|
ipackages = serial.unserialize(fobj:read("*a"))
|
||
|
fobj:close()
|
||
|
end
|
||
|
end
|
||
|
ripackages()
|
||
|
|
||
|
local function wipackages()
|
||
|
local fobj = io.open("/etc/opdata.svd","wb") -- attempt to read installed packages
|
||
|
if fobj then
|
||
|
fobj:write(serial.serialize(ipackages))
|
||
|
fobj:close()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local pkgmap = {} -- alphabetically sorted list of package names
|
||
|
for k,v in pairs(packages) do
|
||
|
pkgmap[#pkgmap+1] = k
|
||
|
end
|
||
|
table.sort(pkgmap)
|
||
|
|
||
|
local function clear()
|
||
|
io.write("\27[2J\27[H")
|
||
|
end
|
||
|
|
||
|
function info(pkg) -- shows info for pkg
|
||
|
clear()
|
||
|
print(string.format("%s - %s",pkg,packages[pkg].name))
|
||
|
print(packages[pkg].description)
|
||
|
if packages[pkg].files then
|
||
|
print("\nFiles:")
|
||
|
for k,v in pairs(packages[pkg].files) do
|
||
|
print(string.format("%s -> %s",k,v))
|
||
|
end
|
||
|
end
|
||
|
if packages[pkg].dependencies then
|
||
|
print("\nDependencies")
|
||
|
for k,v in pairs(packages[pkg].dependencies) do
|
||
|
print(" - "..k)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local preamble = false
|
||
|
local fobj = io.open(rpath.."/.info","rb") -- read the pre-inst screen
|
||
|
if fobj then
|
||
|
preamble = fobj:read("*a")
|
||
|
fobj:close()
|
||
|
end
|
||
|
|
||
|
if preamble then -- display pre-inst screen
|
||
|
clear()
|
||
|
if install.label then
|
||
|
print(install.label .. " installer")
|
||
|
end
|
||
|
print(preamble)
|
||
|
print("Press any key to continue.")
|
||
|
event.pull("key_down")
|
||
|
end
|
||
|
|
||
|
local selected = 1
|
||
|
|
||
|
local function drawmenu() -- draw the menu display - nothing but text and VT100 escape codes
|
||
|
clear()
|
||
|
if install.label then
|
||
|
print(install.label .. " installer")
|
||
|
end
|
||
|
for k,v in pairs(pkgmap) do
|
||
|
if k == selected then
|
||
|
io.write("\27[30;47m")
|
||
|
end
|
||
|
if packages[v].selected then
|
||
|
io.write(" "..unicode.char(0x25A0).." ")
|
||
|
else
|
||
|
io.write(" "..unicode.char(0x25A1).." ")
|
||
|
end
|
||
|
io.write(v)
|
||
|
print("\27[0m")
|
||
|
end
|
||
|
print("Use the arrow keys to navigate. (De)select options with space. View more info by pressing i, and quit by pressing q. Confirm with enter.")
|
||
|
end
|
||
|
|
||
|
--[[
|
||
|
Key codes:
|
||
|
0 208 down
|
||
|
0 200 up
|
||
|
13 28 enter
|
||
|
32 57 space
|
||
|
105 23 i
|
||
|
113 16 q
|
||
|
121 21 y
|
||
|
]]--
|
||
|
|
||
|
local run, install = true, true
|
||
|
while run do -- menu loop
|
||
|
drawmenu()
|
||
|
local _, _, ch, co = event.pull("key_down")
|
||
|
if ch == 13 and co == 28 then
|
||
|
run = false
|
||
|
elseif ch == 113 and co == 16 then
|
||
|
run = false
|
||
|
install = false
|
||
|
elseif ch == 105 and co == 23 then
|
||
|
info(pkgmap[selected])
|
||
|
print("\nPress any key to return to the menu.")
|
||
|
event.pull("key_down")
|
||
|
elseif ch == 0 and co == 208 then
|
||
|
selected = selected + 1
|
||
|
if selected > #pkgmap then
|
||
|
selected = #pkgmap
|
||
|
end
|
||
|
elseif ch == 0 and co == 200 then
|
||
|
selected = selected - 1
|
||
|
if selected < 1 then
|
||
|
selected = 1
|
||
|
end
|
||
|
elseif ch == 32 and co == 57 then
|
||
|
packages[pkgmap[selected]].selected = not packages[pkgmap[selected]].selected
|
||
|
end
|
||
|
end
|
||
|
|
||
|
clear()
|
||
|
|
||
|
if not install then -- pressed q
|
||
|
print("Aborted.")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local toinstall, postinstall = {}, {} -- table of commands to run after installation
|
||
|
|
||
|
print("Resolving dependencies...") -- build a table of what to install
|
||
|
for k,v in pairs(packages) do
|
||
|
if v.selected then
|
||
|
toinstall[k] = true
|
||
|
if v.dependencies then
|
||
|
for l,m in pairs(v.dependencies) do -- including dependencies
|
||
|
if not toinstall[l] then
|
||
|
print("Package "..k.." depends on "..l)
|
||
|
toinstall[l] = m
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
print("You have selected to install the following packages to "..tpath..":")
|
||
|
for k,v in pairs(toinstall) do
|
||
|
print(" - "..k)
|
||
|
end
|
||
|
print("Continue? [y/N] ")
|
||
|
_, _, _, co = event.pull("key_down")
|
||
|
if co ~= 21 then -- confirm they want the packages installed
|
||
|
print("Aborted.")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local function install(pkg,where) -- installs a package, pkg, to where
|
||
|
where = where or tpath
|
||
|
if type(where) ~= string then where = tpath end
|
||
|
print("Installing "..pkg.."...")
|
||
|
if packages[pkg] then
|
||
|
ipackages[pkg] = {}
|
||
|
print("Copying files...")
|
||
|
for l,m in pairs(packages[pkg].files) do
|
||
|
local lseg = fs.segments(l)
|
||
|
if m:sub(1,2) ~= "//" then
|
||
|
if not fs.exists(fs.canonical(where.."/"..m)) then
|
||
|
os.execute("mkdir "..fs.canonical(where.."/"..m))
|
||
|
end
|
||
|
os.execute("cp -v "..rpath.."/"..l.." "..fs.canonical(where.."/"..m))
|
||
|
ipackages[pkg][l] = fs.canonical(where.."/"..m).."/"..lseg[#lseg]
|
||
|
else
|
||
|
if not fs.exists(fs.canonical(m:sub(2))) then
|
||
|
os.execute("mkdir "..fs.canonical(m:sub(2)))
|
||
|
end
|
||
|
os.execute("cp -v "..rpath.."/"..l.." "..fs.canonical(m:sub(2)))
|
||
|
ipackages[pkg][l] = fs.canonical(m:sub(2)).."/"..lseg[#lseg]
|
||
|
end
|
||
|
end
|
||
|
if packages[pkg].postinstall then
|
||
|
for k,v in pairs(packages[pkg].postinstall) do
|
||
|
postinstall[#postinstall+1] = v
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
print("Package not on disk. Attempting to install via oppm.")
|
||
|
print("oppm install "..pkg.." "..where)
|
||
|
wipackages()
|
||
|
os.execute("oppm install "..pkg.." "..where)
|
||
|
ripackages()
|
||
|
end
|
||
|
wipackages()
|
||
|
end
|
||
|
|
||
|
for k,v in pairs(toinstall) do
|
||
|
install(k,v)
|
||
|
end
|
||
|
|
||
|
if #postinstall > 0 then
|
||
|
print("Running post-install commands...")
|
||
|
for k,v in pairs(postinstall) do
|
||
|
print(v)
|
||
|
os.execute(v)
|
||
|
end
|
||
|
end
|