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() 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:) 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 ' 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 ' 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/' 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)