summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2024-01-01 23:07:21 +0100
committerAki <please@ignore.pl>2024-01-01 23:07:21 +0100
commit91e85f9809ed406d2120e424aaa2f249ee18e2c2 (patch)
treee35c522db195727308d0795ee0b4f9b50b9b3c29
downloadensure-91e85f9809ed406d2120e424aaa2f249ee18e2c2.zip
ensure-91e85f9809ed406d2120e424aaa2f249ee18e2c2.tar.gz
ensure-91e85f9809ed406d2120e424aaa2f249ee18e2c2.tar.bz2
Implemented first and easy part of reading package lists
-rw-r--r--Makefile4
-rw-r--r--ensure.lua10
-rw-r--r--ensure/list.lua55
-rw-r--r--spec/list_spec.lua62
4 files changed, 131 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..beb6190
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+test:
+ busted
+
+.PHONY: test
diff --git a/ensure.lua b/ensure.lua
new file mode 100644
index 0000000..0dd264b
--- /dev/null
+++ b/ensure.lua
@@ -0,0 +1,10 @@
+#!/usr/bin/env lua
+local l = require "ensure.list"
+local loud = {
+ identifier = l.default.identifier,
+ invalid = function (_, name) io.stderr:write(string.format("invalid package name: %q\n", name)) end,
+}
+local p = l.all(arg[1] or os.getenv("ENSURE") or "/etc/ensure.d", loud)
+for _, name in pairs(p) do
+ print(name)
+end
diff --git a/ensure/list.lua b/ensure/list.lua
new file mode 100644
index 0000000..b38a62f
--- /dev/null
+++ b/ensure/list.lua
@@ -0,0 +1,55 @@
+local dir = require "pl.dir"
+local lpeg = require "lpeg"
+
+local list = {}
+
+
+local function apply (state, method, ...)
+ if state[method] then
+ return state[method](state, ...)
+ end
+ return nil
+end
+
+
+local first = lpeg.R"az" + lpeg.R"09" + lpeg.S"@+_"
+local rest = first + lpeg.S".-"
+local space = lpeg.S" \t\n\r"
+local boundary = #(space + lpeg.P(-1))
+local identifier = lpeg.Cc"identifier" * lpeg.C(first * rest^0) * boundary
+local invalid = lpeg.Cc"invalid" * lpeg.C((1 - space)^1) * boundary
+local entry = lpeg.Carg(1) * (identifier + invalid) / apply
+local packages = space^0 * lpeg.Ct((entry * (space^1 * entry)^0)^-1) * space^0 * -lpeg.P(1)
+-- TODO: Comments?
+list.default = {
+ identifier = function (self, name) return name end,
+ invalid = function (self, text) end,
+}
+
+
+function list.read (text, handler)
+ handler = handler or list.default
+ return packages:match(text, nil, handler)
+end
+
+
+function list.all (dirpath, handler)
+ local all = {}
+ local lists = dir.getfiles(dirpath, "*.list")
+ for _, path in pairs(lists) do
+ local handle = io.open(path)
+ local packages = list.read(handle:read"a", handler)
+ handle:close()
+ if packages then
+ for _, name in pairs(packages) do
+ table.insert(all, name)
+ end
+ else
+ error(string.format("invalid packages list: %s", config))
+ end
+ end
+ return all
+end
+
+
+return list
diff --git a/spec/list_spec.lua b/spec/list_spec.lua
new file mode 100644
index 0000000..d7b5889
--- /dev/null
+++ b/spec/list_spec.lua
@@ -0,0 +1,62 @@
+local list = require "ensure.list"
+
+
+local function handler_with_errors ()
+ local errors = {}
+ local handler = {
+ identifier = function (_, name)
+ return name
+ end,
+ invalid = function (_, text)
+ table.insert(errors, text)
+ end,
+ }
+ return handler, errors
+end
+
+
+describe("List reader", function()
+ it("should translate empty file into an empty table", function()
+ assert.are.same({}, list.read"")
+ end)
+
+ it("should match valid package names", function()
+ local samples = {"name", "@name", "+name", "_name", "name-1.45"}
+ for _, name in pairs(samples) do
+ assert.are.same({name}, list.read(name))
+ end
+ end)
+
+ it("should split package names on whitespace", function()
+ assert.are.same(
+ {"one", "two", "three", "four", "five"},
+ list.read [[one two three
+ four five]]
+ )
+ end)
+
+ it("should ignore leading and trailing whitespace", function()
+ assert.are.same({"name"}, list.read" name ")
+ end)
+
+ it("should not match invalid package names", function()
+ assert.are.same({}, list.read".hey")
+ assert.are.same({}, list.read"a=3")
+ end)
+
+ it("should allow custom handlers", function()
+ local handler = {}
+ stub(handler, "identifier")
+ stub(handler, "invalid")
+ local _ = list.read("correct .incorrect", handler)
+ assert.stub(handler.identifier).was.called()
+ assert.stub(handler.invalid).was.called()
+ end)
+
+ it("should match valid and invalid names together", function()
+ local handler, errors = handler_with_errors()
+ local output = list.read("correct .incorrect another -and-not", handler)
+ assert.are.same({"correct", "another"}, output)
+ assert.are.same({".incorrect", "-and-not"}, errors)
+ end)
+end)