|
- local serial = require "serialization"
- local dl = require "download"
- local mtar = require "libmtar"
- local pkg = {}
- pkg.cfgPath = "/boot/cfg/pkg"
- pkg.sourcePath = pkg.cfgPath .. "/sources.cfg"
- pkg.installedPath = pkg.cfgPath .. "/installed.cfg"
- local w, lz16 = pcall(require,"liblz16")
- if not w then lz16 = nil end
- require "pkgfs"
-
- local function getSources()
- local f = io.open(pkg.sourcePath,"rb")
- if not f then return {main={path="https://oc.shadowkat.net/psychos/pkg",cache=true,name="main"}} end
- local c = f:read("*a")
- f:close()
- return serial.unserialize(c)
- end
- local function saveSources(t)
- fs.makeDirectory(pkg.cfgPath)
- local f = io.open(pkg.sourcePath,"wb")
- f:write(serial.serialize(t))
- f:close()
- end
-
- local function getInstalled()
- local f = io.open(pkg.installedPath,"rb")
- if not f then return {} end
- local c = f:read("*a")
- f:close()
- return serial.unserialize(c)
- end
- local function saveInstalled(t)
- fs.makeDirectory(pkg.cfgPath)
- local f = io.open(pkg.installedPath,"wb")
- if not f then return false end
- f:write(serial.serialize(t))
- f:close()
- end
-
- local function getRepoMeta(repo)
- if not getSources()[repo].cache or not fs.exists("/boot/cfg/pkg/repo-"..repo..".cfg") then
- dl(getSources()[repo].path.."/packages.cfg","/boot/cfg/pkg/repo-"..repo..".cfg")
- end
- local f = io.open("/boot/cfg/pkg/repo-"..repo..".cfg","rb")
- local rt = serial.unserialize(f:read("*a"))
- f:close()
- if not getSources()[repo].cache then
- fs.remove("/boot/cfg/pkg/repo-"..repo..".cfg")
- end
- return rt
- end
-
- local function activatePackage(path,compressed)
- require("pkgfs").add(path,compressed)
- end
- local function deactivatePackage(path)
- require("pkgfs").remove(path)
- end
- local function fnormalize(s)
- return table.concat(fs.segments(s),"/")
- end
- local function installSystemPackage(path,comp)
- local f
- if comp and lz16 then
- f = lz16.open(path,"rb")
- else
- f = io.open(path,"rb")
- end
- for fname, read, size in mtar.iter(f) do
- local opath = "/boot/"..fnormalize(fname)
- print(opath..": "..tostring(size))
- fs.makeDirectory(opath:match("(.+)/[^/]+"))
- local of = io.open(opath,"wb")
- if not of then error("unable to open "..opath.." for writing") end
- local tmp
- repeat
- tmp = read(2048) or ""
- of:write(tmp)
- until not tmp or tmp:len() < 1
- of:close()
- end
- return true
- end
-
- function pkg.addRepo(name,path,cache) -- string string boolean -- boolean -- Adds a repository, referred to as *name*, to the list of package sources, with the remote path *path*. If *cache* is set, keep a local copy of the repository index.
- local sources = getSources()
- sources[name] = {path=path,cache=cache,name=name}
- saveSources(sources)
- end
-
- function pkg.delRepo(name) -- string -- boolean -- Removes a repository from the list of repositories.
- local sources = getSources()
- sources[name] = nil
- saveSources(sources)
- end
-
- function pkg.update() -- Re-download cached repository indexes.
- for repo,meta in pairs(getSources()) do
- fs.remove("/boot/cfg/pkg/repo-"..repo..".cfg")
- if meta.cache then
- getRepoMeta(repo)
- end
- end
- end
-
- function pkg.list(filter,installed) -- string boolean -- -- Print a list of available packages matching *filter*, optionally filtering to only installed packages if *installed* is set.
- filter = filter or ""
- local pkglist = {}
- for repo,_ in pairs(getSources()) do
- for pkg,meta in pairs(getRepoMeta(repo)) do
- if pkg:find(filter) or (pkg.meta or ""):find(filter) then
- meta.repo = repo
- pkglist[pkg] = meta
- end
- end
- end
- for k,v in pairs(pkglist) do
- if v.system then io.write("\27[31m") end
- print(string.format("%s/%s: %s\27[0m\n %s\n Authors: %s",v.repo,k,v.name,v.description,v.authors))
- end
- end
-
- function pkg.getMeta(pkgname) -- string -- table -- Returns the metadata for a the package specified in *pkgname*.
- print("Finding package "..pkgname)
- for repo,info in pairs(getSources()) do
- local pkg = getRepoMeta(repo)[pkgname]
- if pkg then
- print("Package "..pkgname.." located in repo "..repo.." at "..info.path)
- pkg.repository = info
- return pkg
- end
- end
- end
-
- function pkg.get(pkgname,auto) -- string boolean -- boolean -- Downloads and mounts a package, identified as *pkgname,* onto the pkgfs. Setting *auto* will flag the package as automatically installed; this is used for dependencies.
- local pkginfo = pkg.getMeta(pkgname)
- if not pkginfo then error("unable to locate package "..pkgname) end
- pkginfo.manual = not auto
- fs.makeDirectory("/boot/pkg")
- for k,v in ipairs(pkginfo.dependencies or {}) do
- if not getInstalled()[v] then
- pkg.get(v,true)
- end
- end
- dl(pkginfo.repository.path.."/"..pkginfo.filename,"/boot/pkg/"..pkginfo.filename)
- local installed = getInstalled()
- installed[pkgname] = pkginfo
- saveInstalled(installed)
- if pkginfo.system then
- local rv = installSystemPackage("/boot/pkg/"..pkginfo.filename,pkginfo.compressed)
- fs.remove("/boot/pkg/"..pkginfo.filename)
- return rv
- end
- pcall(activatePackage,"/boot/pkg/"..pkginfo.filename,pkginfo.compressed)
- return true
- end
-
- function pkg.upgrade(force) -- boolean -- -- Upgrades all packages on the system to the current version stored in the relevant repository. If *force* is set, re-download all packages.
- pkg.update()
- fs.makeDirectory("/boot/pkg")
- local installed = getInstalled()
- for repo,info in pairs(getSources()) do
- for pkgname,pkginfo in pairs(getRepoMeta(repo)) do
- if installed[pkgname] and pkginfo.version ~= installed[pkgname].version or force then
- pkg.remove(pkgname)
- pkg.get(pkgname,pkginfo.auto)
- end
- end
- end
- end
-
- function pkg.remove(pkgname) -- string -- boolean -- Remove the package *pkgname* from the pkgfs and package directory.
- local installed = getInstalled()
- local pkginfo = installed[pkgname]
- if not pkginfo then return true end
- pcall(deactivatePackage,"/boot/pkg/"..pkginfo.filename)
- fs.remove("/boot/pkg/"..pkginfo.filename)
- if pkginfo.system then
- for k,v in pairs(pkginfo.files) do
- fs.remove(v)
- end
- end
- installed[pkgname] = nil
- saveInstalled(installed)
- return true
- end
-
- return pkg
|