bliss

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

commit 0d1bf8c9df4b48c50786c9849cad07cb66aab878
parent 5e087386088827aee5d4ec78fcc7fcd29bb3827d
Author: phoebos <ben@bvnf.space>
Date:   Fri, 30 Jun 2023 01:24:18 +0100

Merge branch 'pkg_order'

Diffstat:
Mbliss/pkg.lua | 52+++++++++++++++++++++++++++++++++++++++++++++++++++-
Abliss/tsort.lua | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontrib/bliss-fulldepends | 31+++++++++++++++++++++++++++++++
3 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/bliss/pkg.lua b/bliss/pkg.lua @@ -1,4 +1,5 @@ local utils = require "bliss.utils" +local tsort = require "bliss.tsort" local sys_stat = require "posix.sys.stat" local function read_lines(file) @@ -6,7 +7,9 @@ local function read_lines(file) local f = io.open(file) if not f then return {} end for line in f:lines() do - table.insert(t, utils.split(line, " ")) + if #line ~= 0 and string.sub(line, 1, 1) ~= '#' then + table.insert(t, utils.split(line, " ")) + end end f:close() return t @@ -37,6 +40,11 @@ local function find_checksums(pkg, repo_dir) return read_lines(p) end +local function find_depends(pkg, path) + local p = find(pkg, path) .. "/depends" + return read_lines(p) +end + local function find_sources(pkg, repo_dir) local p = repo_dir .. "/sources" @@ -81,11 +89,53 @@ local function resolve(pkg, sources, env, repo_dir) return caches end +local function recurse_all_deps(env, pkgs, deps) + for _, p in ipairs(pkgs) do + if not deps[p] then + local d = find_depends(p, env.PATH) + -- ignore make, just get pkg names + local d_ = {} + for _,v in ipairs(d) do + table.insert(d_, v[1]) + end + + -- recurse + deps = recurse_all_deps(env, d_, deps) + + deps[p] = d_ + end + end + return deps +end + +local function order(env, pkgs) + local t = tsort.new() + + local deps = recurse_all_deps(env, pkgs, {}) + for k,v in pairs(deps) do + t:add(k, v) + end + + local s, x,y = t:sort() + if not s then + utils.die("Circular dependency detected: " .. x .. " <> " .. y) + end + + -- return s reversed (in order to be built) + local r = {} + for i = #s, 1, -1 do + r[i] = s[i] + end + return r +end + local M = { find = find, find_version = find_version, find_checksums = find_checksums, + find_depends = find_depends, find_sources = find_sources, resolve = resolve, + order = order, } return M diff --git a/bliss/tsort.lua b/bliss/tsort.lua @@ -0,0 +1,77 @@ +-- This module is not included in init.lua, but used locally by pkg.lua. +local tsort = {} + +-- Returns a table of reverse deps +local function reverse(input) + local reversed = {} + for k,v in pairs(input) do + for _,w in ipairs(v) do + reversed[w] = reversed[w] or {} + table.insert(reversed[w], k) + end + end + return reversed +end + +local function find_cycle(revlinks, start) + local ret = {[start] = 1} + local old + + local t = revlinks[start][1] + while t and not ret[t] do + ret[t] = 1 + old = t + t = revlinks[t][1] + end + return t, old +end + +function tsort.new() + return setmetatable({nodes={}}, {__index = tsort}) +end + +function tsort:add(node, deps) + self.nodes[node] = deps +end + +function tsort:sort() + if not self.nodes then return nil end + local L = {} + local reversed = reverse(self.nodes) + + -- find nodes with no incoming edges + local S = {} + for k in pairs(self.nodes) do + if not reversed[k] or #reversed[k] == 0 then + table.insert(S, k) + end + end + + while #S ~= 0 do + local n = table.remove(S, 1) + table.insert(L, n) + for _,v in ipairs(self.nodes[n] or {}) do + -- remove edge n -> v + for i,j in ipairs(reversed[v]) do + if j == n then + table.remove(reversed[v], i) + end + end + if not reversed[v] or #reversed[v] == 0 then + table.insert(S, v) + reversed[v] = nil + end + end + end + + for k,v in pairs(reversed) do + if #v ~= 0 then + -- cycle detected + local x,y = find_cycle(reversed, k) + return nil, x, y + end + end + return L +end + +return tsort diff --git a/contrib/bliss-fulldepends b/contrib/bliss-fulldepends @@ -0,0 +1,31 @@ +#!/usr/bin/env lua +-- Display all dependencies of packages (recursively) +local bliss = require "bliss" +local dirent = require "posix.dirent" + +local function lists(env, arg) + if #arg == 0 then + for file in dirent.files(env.sys_db) do + if string.sub(file, 1, 1) ~= "." then + table.insert(arg, {file, #bliss.order(env, {file})}) + end + end + table.sort(arg, function (a,b) return a[2]<b[2] end) + for _,v in ipairs(arg) do print(v[1],v[2]) end + else + local deps = bliss.order(env, {arg[1]}) + for _,v in ipairs(deps) do print(v) end + end +end + +if arg[1] == "-h" then + print("usage: "..arg[0].." [pkg]") + print(" With no args, list installed packages by total number of dependencies") + print(" With an arg, list full dependencies of pkg") + os.exit() +end + +local env, atexit = bliss.setup() +table.insert(env.PATH, 1, env.sys_db) + +lists(env, arg)