2020-06-06 14:58:15 +10:00
local serial = require " serialization "
local dl = require " download "
local pkg = { }
pkg.cfgPath = " /boot/cfg/pkg "
pkg.sourcePath = pkg.cfgPath .. " /sources.cfg "
pkg.installedPath = pkg.cfgPath .. " /installed.cfg "
local function getSources ( )
local f = io.open ( pkg.sourcePath , " rb " )
if not f then return { } 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
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 ) -- string -- -- Print a list of available packages matching *filter*.
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
print ( string.format ( " %s/%s \n %s " , v.repo , k , v.description ) )
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.
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 )
end
end
dl ( pkginfo.repository . path .. " / " .. pkginfo.filename , " /boot/pkg/ " .. pkginfo.filename )
local installed = getInstalled ( )
installed [ pkgname ] = pkginfo
saveInstalled ( installed )
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.
pkg.update ( )
fs.makeDirectory ( " /boot/pkg " )
local installed = getInstalled ( )
for repo , info in pairs ( getSources ( ) ) do
for pkgname , pkg in pairs ( getRepoMeta ( repo ) ) do
if pkg.version ~= installed [ pkgname ] . version or force then
2020-06-06 19:48:21 +10:00
pkg.remove ( pkgname )
2020-06-06 14:58:15 +10:00
dl ( info.path .. " / " .. pkg.filename , " /boot/pkg/ " .. pkg.filename )
installed [ pkgname ] = pkg
pcall ( activatePackage , " /boot/pkg/ " .. pkg.filename , pkg.compressed )
return true
end
end
end
saveInstalled ( installed )
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 error ( pkgname .. " not installed " ) end
pcall ( deactivatePackage , " /boot/pkg/ " .. pkginfo.filename )
fs.remove ( " /boot/pkg/ " .. pkginfo.filename )
installed [ pkgname ] = nil
saveInstalled ( installed )
return true
end
return pkg