test(git/object): cover URI parsing, M.open, and open_under_cursor
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
local Revision = require("git.revision")
|
||||
local h = require("test.git.helpers")
|
||||
local object = require("git.object")
|
||||
local t = require("test")
|
||||
|
||||
require("git").init()
|
||||
|
||||
---@return integer? buf
|
||||
local function find_git_buf()
|
||||
for _, b in ipairs(vim.api.nvim_list_bufs()) do
|
||||
if vim.api.nvim_buf_get_name(b):match("^git://") then
|
||||
return b
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param buf integer
|
||||
---@param prefix string
|
||||
---@return integer? lnum
|
||||
local function find_line(buf, prefix)
|
||||
for i, l in ipairs(vim.api.nvim_buf_get_lines(buf, 0, -1, false)) do
|
||||
if l:sub(1, #prefix) == prefix then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
t.test("parse_uri / format_uri round-trip for base", function()
|
||||
local uri = "git://HEAD"
|
||||
local rev = assert(object.parse_uri(uri))
|
||||
t.eq(object.format_uri(rev), uri)
|
||||
end)
|
||||
|
||||
t.test("parse_uri / format_uri round-trip for base + path", function()
|
||||
local uri = "git://HEAD:lua/foo.lua"
|
||||
local rev = assert(object.parse_uri(uri))
|
||||
t.eq(object.format_uri(rev), uri)
|
||||
end)
|
||||
|
||||
t.test("parse_uri / format_uri round-trip for stage + path", function()
|
||||
local uri = "git://:2:lua/foo.lua"
|
||||
local rev = assert(object.parse_uri(uri))
|
||||
t.eq(object.format_uri(rev), uri)
|
||||
end)
|
||||
|
||||
t.test("parse_uri normalizes bare :path to stage 0", function()
|
||||
local rev = assert(object.parse_uri("git://:foo"))
|
||||
t.eq(rev.stage, 0)
|
||||
t.eq(rev.path, "foo")
|
||||
t.eq(object.format_uri(rev), "git://:0:foo")
|
||||
end)
|
||||
|
||||
t.test("parse_uri returns nil for non-git URIs", function()
|
||||
t.falsy(object.parse_uri("file:///tmp/x"))
|
||||
t.falsy(object.parse_uri("/tmp/x"))
|
||||
t.falsy(object.parse_uri("gitlog:///tmp/x"))
|
||||
end)
|
||||
|
||||
t.test("M.open(HEAD) names buffer with full sha", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local sha = h.git(dir, "rev-parse", "HEAD").stdout
|
||||
|
||||
object.open(r, "HEAD", { split = false })
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. sha)
|
||||
end)
|
||||
|
||||
t.test("M.open(<short sha>) canonicalizes to full sha", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local sha = h.git(dir, "rev-parse", "HEAD").stdout
|
||||
local short = h.git(dir, "rev-parse", "--short", "HEAD").stdout
|
||||
t.truthy(#short < #sha, "short sha must be shorter than full")
|
||||
|
||||
object.open(r, short, { split = false })
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. sha)
|
||||
end)
|
||||
|
||||
t.test("M.open(HEAD:<path>) loads file content at HEAD", function()
|
||||
local dir = h.make_repo({ ["a.txt"] = "first\nsecond\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local sha = h.git(dir, "rev-parse", "HEAD").stdout
|
||||
|
||||
object.open(r, "HEAD:a.txt", { split = false })
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. sha .. ":a.txt")
|
||||
t.eq(
|
||||
vim.api.nvim_buf_get_lines(0, 0, -1, false),
|
||||
{ "first", "second" }
|
||||
)
|
||||
end)
|
||||
|
||||
t.test("M.open errors on a bogus base, no buffer is opened", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
|
||||
t.quietly(function()
|
||||
object.open(r, "deadbeefdeadbeef", { split = false })
|
||||
end)
|
||||
t.falsy(find_git_buf(), "no git:// buffer should exist")
|
||||
end)
|
||||
|
||||
t.test("M.open errors on a missing path, no buffer is opened", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
|
||||
t.quietly(function()
|
||||
object.open(r, "HEAD:does-not-exist", { split = false })
|
||||
end)
|
||||
t.falsy(find_git_buf(), "no git:// buffer should exist")
|
||||
end)
|
||||
|
||||
t.test("read_uri opens stage-0 entry as a writable index buffer", function()
|
||||
local dir = h.make_repo({ ["a.txt"] = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local rev = Revision.new({ stage = 0, path = "a.txt" })
|
||||
|
||||
local buf = object.buf_for(r, rev)
|
||||
t.eq(vim.bo[buf].buftype, "acwrite")
|
||||
t.truthy(vim.bo[buf].modifiable)
|
||||
t.eq(vim.api.nvim_buf_get_lines(buf, 0, -1, false), { "first" })
|
||||
end)
|
||||
|
||||
t.test("open_under_cursor on a 'tree <sha>' line opens the tree", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local tree_sha = h.git(dir, "rev-parse", "HEAD^{tree}").stdout
|
||||
|
||||
object.open(r, "HEAD", { split = false })
|
||||
local lnum = assert(find_line(0, "tree "), "expected a tree line")
|
||||
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||
|
||||
t.truthy(object.open_under_cursor())
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. tree_sha)
|
||||
end)
|
||||
|
||||
t.test("open_under_cursor on a 'parent <sha>' line opens the parent", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
t.write(dir, "a", "second\n")
|
||||
h.git(dir, "add", "a")
|
||||
h.git(dir, "commit", "-q", "-m", "second")
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local parent_sha = h.git(dir, "rev-parse", "HEAD~").stdout
|
||||
|
||||
object.open(r, "HEAD", { split = false })
|
||||
local lnum = assert(find_line(0, "parent "), "expected a parent line")
|
||||
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||
|
||||
t.truthy(object.open_under_cursor())
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. parent_sha)
|
||||
end)
|
||||
|
||||
t.test("open_under_cursor on a '+++ b/<path>' line loads the blob", function()
|
||||
local dir = h.make_repo({ ["a.txt"] = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
local blob_sha = h.git(dir, "rev-parse", "HEAD:a.txt").stdout
|
||||
|
||||
object.open(r, "HEAD", { split = false })
|
||||
local lnum = assert(find_line(0, "+++ b/a.txt"), "expected a +++ line")
|
||||
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||
|
||||
t.truthy(object.open_under_cursor())
|
||||
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. blob_sha)
|
||||
end)
|
||||
|
||||
t.test("open_under_cursor returns false on a non-dispatchable line", function()
|
||||
local dir = h.make_repo({ a = "first\n" })
|
||||
local r = assert(require("git.repo").resolve(dir))
|
||||
|
||||
object.open(r, "HEAD", { split = false })
|
||||
local lnum = assert(find_line(0, "author "), "expected an author line")
|
||||
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||
|
||||
t.falsy(object.open_under_cursor())
|
||||
end)
|
||||
@@ -161,4 +161,17 @@ function M.wait_for(cond, msg, timeout)
|
||||
M.truthy(vim.wait(timeout or 1000, cond), "timed out waiting for: " .. msg)
|
||||
end
|
||||
|
||||
---Run `fn` with `vim.notify` stubbed to a no-op so error/warning paths
|
||||
---don't bleed onto the test runner's stdout.
|
||||
---@param fn fun()
|
||||
function M.quietly(fn)
|
||||
local orig = vim.notify
|
||||
vim.notify = function() end
|
||||
local ok, err = pcall(fn)
|
||||
vim.notify = orig
|
||||
if not ok then
|
||||
error(err, 0)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user