46517953e5
- add lua modules for spec parsing, lock state, fs helpers and the installer - add ArtiPackSync/ArtiPackClean/ArtiPackList commands and help doc - add headless nvim test harness and specs - add make test/lint/fmt/pre-commit and patch/minor/major bump targets - add woodpecker test, lint and pre-commit pipelines
89 lines
1.8 KiB
Lua
89 lines
1.8 KiB
Lua
local uv = vim.uv or vim.loop
|
|
|
|
local M = {}
|
|
|
|
local ZIP_MAGIC = 'PK\3\4'
|
|
local GZIP_MAGIC = '\31\139'
|
|
|
|
function M.join(...)
|
|
return table.concat({ ... }, '/')
|
|
end
|
|
|
|
function M.mkdirp(path)
|
|
vim.fn.mkdir(path, 'p')
|
|
return path
|
|
end
|
|
|
|
function M.rm_rf(path)
|
|
if uv.fs_stat(path) then
|
|
vim.fn.delete(path, 'rf')
|
|
end
|
|
end
|
|
|
|
function M.exists(path)
|
|
return uv.fs_stat(path) ~= nil
|
|
end
|
|
|
|
function M.entries(dir)
|
|
local handle = uv.fs_scandir(dir)
|
|
if not handle then
|
|
return {}
|
|
end
|
|
local out = {}
|
|
while true do
|
|
local name, kind = uv.fs_scandir_next(handle)
|
|
if not name then
|
|
break
|
|
end
|
|
table.insert(out, { name = name, kind = kind })
|
|
end
|
|
return out
|
|
end
|
|
|
|
-- Tag archives wrap everything in a single "<repo>-<tag>" directory. Detect it
|
|
-- rather than reconstructing the name, since the leading "v" is dropped.
|
|
function M.archive_root(dir)
|
|
local entries = M.entries(dir)
|
|
if #entries == 1 and entries[1].kind == 'directory' then
|
|
return M.join(dir, entries[1].name)
|
|
end
|
|
return dir
|
|
end
|
|
|
|
function M.read_head(path, bytes)
|
|
local fd = io.open(path, 'rb')
|
|
if not fd then
|
|
return nil
|
|
end
|
|
local head = fd:read(bytes)
|
|
fd:close()
|
|
return head
|
|
end
|
|
|
|
function M.verify_archive(path, ext)
|
|
local stat = uv.fs_stat(path)
|
|
if not stat or stat.size == 0 then
|
|
return false, 'downloaded archive is empty'
|
|
end
|
|
|
|
local magic = ext == 'zip' and ZIP_MAGIC or GZIP_MAGIC
|
|
local head = M.read_head(path, #magic)
|
|
if head ~= magic then
|
|
return false, string.format('downloaded archive is not a %s', ext)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function M.extract_cmd(archive, dest, ext)
|
|
if ext == 'zip' then
|
|
return { 'unzip', '-q', '-o', archive, '-d', dest }
|
|
end
|
|
return { 'tar', '-xzf', archive, '-C', dest }
|
|
end
|
|
|
|
function M.rename(from, to)
|
|
return uv.fs_rename(from, to)
|
|
end
|
|
|
|
return M
|