bliss

KISS in Lua
git clone git://bvnf.space/bliss.git
Log | Files | Refs | README | LICENSE

commit ffb747b8b5c7a877d3f0846833942f0f1340a4e0
parent c532d46cafe0f7e2f873289b35bb1c38d8c794f8
Author: aabacchus <ben@bvnf.space>
Date:   Wed, 14 Jun 2023 03:50:41 +0100

make dirs and add pkg_clean traps

to implement the EXIT handler, a finalizer (__gc) is used. This adds the
requirements of 1) keeping a reference to atexit throughout the program,
2) always calling os.exit with the second argument as true (so that the Lua
state is properly closed and finalizers run). To achieve (2), monkey-patch
os.exit.

Diffstat:
Mbliss/list.lua | 4++--
Mbliss/search.lua | 4++--
Mbliss/utils.lua | 99++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mmain.lua | 2+-
4 files changed, 85 insertions(+), 24 deletions(-)

diff --git a/bliss/list.lua b/bliss/list.lua @@ -4,7 +4,7 @@ local dirent = require 'posix.dirent' local function list(env, arg) if #arg == 0 then - for file in dirent.files(env.pkg_db) do + for file in dirent.files(env.sys_db) do if string.sub(file, 1, 1) ~= '.' then table.insert(arg, file) end @@ -12,7 +12,7 @@ local function list(env, arg) table.sort(arg) end for _,a in ipairs(arg) do - local ver = pkg.find_version(a, {env.pkg_db}) + local ver = pkg.find_version(a, {env.sys_db}) io.write(string.format("%s %s-%s\n", a, ver[1], ver[2])) end end diff --git a/bliss/search.lua b/bliss/search.lua @@ -4,9 +4,9 @@ local sys_stat = require 'posix.sys.stat' local function search(env, arg) - -- append pkg_db to search path + -- append sys_db to search path local path = utils.shallowcopy(env.PATH) - table.insert(path, env.pkg_db) + table.insert(path, env.sys_db) for _, a in ipairs(arg) do local res = {} diff --git a/bliss/utils.lua b/bliss/utils.lua @@ -1,39 +1,65 @@ -- Copyright 2023 phoebos local sys_stat = require 'posix.sys.stat' local unistd = require 'posix.unistd' +local signal = require 'posix.signal' local colors = {"", "", ""} -local setup, setup_colors, check_execute, get_available, split, mkdirp, log, warn, die, run, capture, shallowcopy +local setup, setup_colors, check_execute, get_available, trap_on, trap_off, split, mkdirp, rm_rf, log, warn, die, run, capture, shallowcopy function setup() colors = setup_colors() check_execute() local env = { + _LVL = 1 + (os.getenv("_KISS_LVL") or 0), CHK = os.getenv("KISS_CHK") or get_available("openssl", "sha256sum", "sha256", "shasum", "digest") or warn("No sha256 utility found"), COMPRESS= os.getenv("KISS_COMPRESS") or "gz", - DEBUG = os.getenv("KISS_DEBUG"), - FORCE = os.getenv("KISS_FORCE"), + DEBUG = os.getenv("KISS_DEBUG") or 0, + FORCE = os.getenv("KISS_FORCE") or 0, GET = os.getenv("KISS_GET") or get_available("aria2c", "axel", "curl", "wget", "wget2") or warn("No download utility found (aria2c, axel, curl, wget, wget2"), HOOK = split(os.getenv("KISS_HOOK"), ':'), - KEEPLOG = os.getenv("KISS_KEEPLOG"), + KEEPLOG = os.getenv("KISS_KEEPLOG") or 0, PATH = split(os.getenv("KISS_PATH"), ':'), PID = os.getenv("KISS_PID") or unistd.getpid(), - PROMPT = os.getenv("KISS_PROMPT"), + PROMPT = os.getenv("KISS_PROMPT") or 1, ROOT = os.getenv("KISS_ROOT") or "", SU = os.getenv("KISS_SU") or get_available("ssu", "sudo", "doas", "su"), TMPDIR = os.getenv("KISS_TMPDIR"), time = os.date("%Y-%m-%d-%H:%M"), } - -- pkg_db depends on ROOT so must be set after env is constructed - env.pkg_db = env.ROOT .. "/var/db/kiss/installed" + -- sys_db depends on ROOT so must be set after env is constructed + env.pkg_db = "var/db/kiss/installed" + env.cho_db = "var/db/kiss/choices" + env.sys_db = env.ROOT .. "/" .. env.pkg_db + env.sys_ch = env.ROOT .. "/" .. env.cho_db + + env.cac_dir = (os.getenv("XDG_CACHE_HOME") or (os.getenv("HOME") .. "/.cache")) .. "/kiss" + env.src_dir = env.cac_dir .. "/sources" + env.log_dir = env.cac_dir .. "/logs/" .. string.sub(env.time, 1, 10) + env.bin_dir = env.cac_dir .. "/bin" + + env.TMPDIR = env.TMPDIR or (env.cac_dir .. "/proc") + env.proc = env.TMPDIR .. '/' .. env.PID + + env.mak_dir = env.proc .. "/build" + env.pkg_dir = env.proc .. "/pkg" + env.tar_dir = env.proc .. "/extract" + env.tmp_dir = env.proc .. "/tmp" mkdirp(env.ROOT .. '/') - return env + mkdirp(env.src_dir, env.log_dir, env.bin_dir, + env.mak_dir, env.pkg_dir, env.tar_dir, env.tmp_dir) + + -- make sure os.exit always closes the Lua state + local o = os.exit + os.exit = function(code, close) o(code, not close) end + + local atexit = trap_on(env) + return env, atexit end function setup_colors() @@ -60,6 +86,31 @@ function get_available(...) return nil end +function trap_on(env) + signal.signal(signal.SIGINT, function () os.exit(false) end) + -- use a finalizer to get pkg_clean to run on EXIT. A reference to atexit must + -- be kept for the whole duration of the program (should it be a global?) + local atexit = setmetatable({}, {__gc = get_pkg_clean(env)}) + return atexit +end + +function trap_off(atexit) + signal.signal(signal.SIGINT, signal.SIG_DFL) + setmetatable(atexit, {}) +end + +-- returns a function with cached env so that it can be called without args or globals. +function get_pkg_clean(env) + return function () + if env.DEBUG ~= 0 then return end + if env._LVL == 1 then + rm_rf(env.proc) + else + rm_rf(env.tar_dir) + end + end +end + function split(s, sep) local c = {} for a in string.gmatch(s, "[^%s"..sep.."]+") do @@ -68,21 +119,28 @@ function split(s, sep) return c end -function mkdirp(path) - assert(string.sub(path, 1, 1) == '/') - local t = split(path, '/') - local p = '' - for _, v in ipairs(t) do - p = p .. '/' .. v - - local sb = sys_stat.stat(p) - if not sb then - local c, msg = sys_stat.mkdir(p) - if not c then die("mkdir " .. msg) end +function mkdirp(...) + for i = 1, select('#', ...) do + local path = select(i, ...) + assert(string.sub(path, 1, 1) == '/') + local t = split(path, '/') + local p = '' + for _, v in ipairs(t) do + p = p .. '/' .. v + + local sb = sys_stat.stat(p) + if not sb then + local c, msg = sys_stat.mkdir(p) + if not c then die("mkdir " .. msg) end + end end end end +function rm_rf(path) + os.execute("rm -rf \"" .. path .. "\"") +end + function log(name, msg, category) -- This is a direct translation of kiss's log(). Quite hacky. io.stderr:write(string.format("%s%s %s%s%s %s\n", @@ -128,8 +186,11 @@ end local M = { setup = setup, + trap_on = trap_on, + trap_off = trap_off, split = split, mkdirp = mkdirp, + rm_rf = rm_rf, log = log, warn = warn, die = die, diff --git a/main.lua b/main.lua @@ -55,5 +55,5 @@ local function args(arg) end end -env = bliss.setup() +env, atexit = bliss.setup() args(arg)