diff --git a/lib/pkgman.lua b/lib/pkgman.lua index eaf193c..49662f7 100644 --- a/lib/pkgman.lua +++ b/lib/pkgman.lua @@ -1,10 +1,13 @@ 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" -require("pkgfs") +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") @@ -54,6 +57,31 @@ 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() @@ -76,7 +104,7 @@ function pkg.update() -- Re-download cached repository indexes. end end -function pkg.list(filter) -- string -- -- Print a list of available packages matching *filter*. +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 @@ -88,7 +116,8 @@ function pkg.list(filter) -- string -- -- Print a list of available packages mat end end for k,v in pairs(pkglist) do - print(string.format("%s/%s\n %s",v.repo,k,v.description)) + 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 @@ -104,25 +133,30 @@ function pkg.getMeta(pkgname) -- string -- table -- Returns the metadata for a t end end -function pkg.get(pkgname,auto) -- string boolean -- boolean -- Downloads and mounts a package, identified as *pkgname*, onto the pkgfs. +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) + 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 -- boolean -- Upgrades all packages on the system to the current version stored in the relevant repository. If *force* is set, re-download all packages. +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() @@ -130,13 +164,10 @@ function pkg.upgrade(force) -- boolean -- boolean -- Upgrades all packages on th for pkgname,pkginfo in pairs(getRepoMeta(repo)) do if installed[pkgname] and pkginfo.version ~= installed[pkgname].version or force then pkg.remove(pkgname) - dl(info.path.."/"..pkginfo.filename,"/boot/pkg/"..pkginfo.filename) - installed[pkgname] = pkg - pcall(activatePackage,"/boot/pkg/"..pkginfo.filename,pkginfo.compressed) + pkg.get(pkgname,pkginfo.auto) end end end - saveInstalled(installed) end function pkg.remove(pkgname) -- string -- boolean -- Remove the package *pkgname* from the pkgfs and package directory. @@ -145,6 +176,11 @@ function pkg.remove(pkgname) -- string -- boolean -- Remove the package *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