local t = require('tests.harness') local fs = require('arti-pack.fs') local function tmpdir() local dir = vim.fn.tempname() vim.fn.mkdir(dir, 'p') return dir end local function write(path, contents) local fd = assert(io.open(path, 'wb')) fd:write(contents) fd:close() return path end t.describe('fs.archive_root', function() t.it('strips the single wrapper directory a tag archive unpacks to', function() local dir = tmpdir() vim.fn.mkdir(dir .. '/plenary.nvim-0.1.4/lua', 'p') t.eq(dir .. '/plenary.nvim-0.1.4', fs.archive_root(dir)) end) t.it('keeps the directory when the archive unpacked flat', function() local dir = tmpdir() vim.fn.mkdir(dir .. '/lua', 'p') write(dir .. '/README.md', 'hi') t.eq(dir, fs.archive_root(dir)) end) t.it('keeps the directory when its only entry is a file', function() local dir = tmpdir() write(dir .. '/init.lua', 'return {}') t.eq(dir, fs.archive_root(dir)) end) end) t.describe('fs.verify_archive', function() t.it('accepts a zip magic header', function() local path = write(tmpdir() .. '/a.zip', 'PK\3\4rest of the file') t.truthy(fs.verify_archive(path, 'zip')) end) t.it('accepts a gzip magic header', function() local path = write(tmpdir() .. '/a.tar.gz', '\31\139\8\0padding') t.truthy(fs.verify_archive(path, 'tar.gz')) end) t.it('rejects an empty download', function() local path = write(tmpdir() .. '/a.zip', '') local ok, err = fs.verify_archive(path, 'zip') t.falsy(ok) t.matches('empty', err) end) t.it('rejects an html error page served in place of a zip', function() local path = write(tmpdir() .. '/a.zip', '404') local ok, err = fs.verify_archive(path, 'zip') t.falsy(ok) t.matches('not a zip', err) end) t.it('rejects a zip when a tar.gz was expected', function() local path = write(tmpdir() .. '/a.tar.gz', 'PK\3\4rest') local ok, err = fs.verify_archive(path, 'tar.gz') t.falsy(ok) t.matches('not a tar%.gz', err) end) t.it('rejects a missing file', function() local ok, err = fs.verify_archive(tmpdir() .. '/absent.zip', 'zip') t.falsy(ok) t.matches('empty', err) end) end) t.describe('fs.digest', function() t.it('identifies file contents, not the file name', function() local dir = tmpdir() local a = write(dir .. '/a.zip', 'PK\3\4payload') local b = write(dir .. '/b.zip', 'PK\3\4payload') t.eq(fs.digest(a), fs.digest(b)) t.eq(64, #fs.digest(a), 'a sha256 hex digest') end) t.it('changes when the bytes change', function() local dir = tmpdir() local before = fs.digest(write(dir .. '/a.zip', 'PK\3\4one')) local after = fs.digest(write(dir .. '/a.zip', 'PK\3\4two')) t.truthy(before ~= after, 'a refetched archive with new contents digests differently') end) t.it('returns nothing for a missing file', function() t.eq(nil, fs.digest(tmpdir() .. '/absent.zip')) end) end) t.describe('fs.extract', function() t.it('reports a missing archive instead of raising', function() local ok, err = fs.extract(tmpdir() .. '/absent.zip', tmpdir(), 'zip') t.falsy(ok) t.truthy(err) end) t.it('reports an empty archive', function() local path = write(tmpdir() .. '/a.zip', '') local ok, err = fs.extract(path, tmpdir() .. '/dest', 'zip') t.falsy(ok) t.matches('empty', err) end) end) t.describe('fs.rm_rf', function() t.it('removes a populated directory tree', function() local dir = tmpdir() vim.fn.mkdir(dir .. '/a/b', 'p') write(dir .. '/a/b/c.txt', 'x') fs.rm_rf(dir .. '/a') t.falsy(fs.exists(dir .. '/a')) end) t.it('is a no-op on a path that is not there', function() fs.rm_rf(tmpdir() .. '/never-existed') end) end)