Files
vimpack/tests/minimal.lua
T
unkin-agent 35b9df9eba
ci/woodpecker/pr/pre-commit Pipeline failed
ci/woodpecker/pr/lint Pipeline failed
ci/woodpecker/pr/test Pipeline failed
Add vimpack: archive-based Neovim plugin manager
## Why
Cloning plugins from git ties the editor to GitHub uptime and moving branches; archives at a pinned version from our own registry are reproducible and reachable offline.

## How
- Add a registry resolver interface `(spec, registry) -> {url, headers, filename, sha256?}` with builtin `template` and `artifactapi` kinds, a per-plugin registry override and a `url` escape hatch.
- Take auth tokens only from an env var or a `token_cmd`; reject a literal token at setup.
- Download with curl, verify an optional sha256, extract to a staging dir and rename into `pack/vimpack/{start,opt}/<name>`, restoring the previous tree if the swap fails.
- Track installed name/version/sha256 in `stdpath('data')/vimpack/manifest.json` and skip plugins already at the wanted version.
- Add `:VimpackInstall`, `:VimpackUpdate`, `:VimpackClean` and `:VimpackStatus`, running downloads through `vim.system` under a concurrency cap.
- Hash with a pure-Lua SHA-256; `vim.fn.sha256()` rejects binary archives with E976.
- Add a dependency-free `tests/minimal.lua` harness and 57 specs covering resolution, auth, manifest, planning, checksum mismatch, orphan detection and end-to-end install.
- Add `.woodpecker/{test,lint,pre-commit}.yaml`, luacheck/stylua config and pre-commit hooks.
2026-09-05 13:28:53 +10:00

93 lines
2.4 KiB
Lua

-- Minimal busted-flavoured harness: no rocks, no vendored plugins.
-- Run with: nvim --headless --clean -l tests/minimal.lua tests/*_spec.lua
local root = vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':p:h:h')
vim.opt.runtimepath:prepend(root)
package.path = table.concat({ root .. '/lua/?.lua', root .. '/lua/?/init.lua', package.path }, ';')
local M = { passed = 0, failed = 0, failures = {} }
local stack = {}
local function describe(name, fn)
stack[#stack + 1] = name
fn()
stack[#stack] = nil
end
local function it(name, fn)
local label = table.concat(stack, ' ') .. ' ' .. name
local ok, err = pcall(fn)
if ok then
M.passed = M.passed + 1
io.write('ok ' .. label .. '\n')
else
M.failed = M.failed + 1
M.failures[#M.failures + 1] = label .. '\n ' .. tostring(err)
io.write('FAIL ' .. label .. '\n ' .. tostring(err) .. '\n')
end
end
local assert_eq = function(expected, got, msg)
if not vim.deep_equal(expected, got) then
error(
string.format('%sexpected %s, got %s', msg and (msg .. ': ') or '', vim.inspect(expected), vim.inspect(got)),
2
)
end
end
local assert_true = function(value, msg)
if not value then
error(msg or ('expected truthy, got ' .. vim.inspect(value)), 2)
end
end
local assert_nil = function(value, msg)
if value ~= nil then
error(msg or ('expected nil, got ' .. vim.inspect(value)), 2)
end
end
local assert_match = function(pattern, str, msg)
if type(str) ~= 'string' or not str:find(pattern, 1, true) then
error(string.format('%sexpected %s to contain %q', msg and (msg .. ': ') or '', vim.inspect(str), pattern), 2)
end
end
_G.describe = describe
_G.it = it
_G.assert_eq = assert_eq
_G.assert_true = assert_true
_G.assert_nil = assert_nil
_G.assert_match = assert_match
_G.tmpdir = function()
local dir = vim.fs.joinpath(vim.fn.tempname(), 'vimpack-test')
vim.fn.mkdir(dir, 'p')
return dir
end
local files = {}
for i = 1, #_G.arg do
files[#files + 1] = _G.arg[i]
end
if #files == 0 then
for name, kind in vim.fs.dir(root .. '/tests') do
if kind == 'file' and name:match('_spec%.lua$') then
files[#files + 1] = root .. '/tests/' .. name
end
end
table.sort(files)
end
for _, file in ipairs(files) do
dofile(file)
end
io.write(string.format('\n%d passed, %d failed\n', M.passed, M.failed))
if M.failed > 0 then
for _, failure in ipairs(M.failures) do
io.write('\n' .. failure .. '\n')
end
vim.cmd('cquit 1')
end
vim.cmd('quit')