diff --git a/lua/git/show.lua b/lua/git/show.lua index bf419a7..05ed999 100644 --- a/lua/git/show.lua +++ b/lua/git/show.lua @@ -88,15 +88,20 @@ end ---@param ref string the commit ref the blob represents (e.g. `` or `^`) ---@return integer local function blob_buf(worktree, blob, path, ref) + local name = "git://" .. ref .. "/" .. path + -- Reuse an existing buffer with this name (commit refs and blobs are + -- immutable, so the content is stable); avoids E95 collisions and + -- prevents accumulating duplicate buffers as the user navigates. + local existing = vim.fn.bufnr(name) + if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then + return existing + end if is_zero(blob) then - return diff.empty_buf({ - name = "git://" .. ref .. "/" .. path, - bufhidden = "hide", - }) + return diff.empty_buf({ name = name, bufhidden = "hide" }) end ---@cast blob string local buf = diff.git_show_blob(worktree, blob) - diff.set_buf_name_and_filetype(buf, "git://" .. ref .. "/" .. path) + diff.set_buf_name_and_filetype(buf, name) return buf end @@ -133,6 +138,17 @@ end ---@param worktree string ---@param ref string function M.open_commit(worktree, ref) + local sha = repo.rev_parse(worktree, ref, true) or ref + local name = "git://" .. sha .. "/" + -- Reuse a previously-opened buffer for the same commit; commit SHAs + -- are immutable so the content is stable. + local existing = vim.fn.bufnr(name) + if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then + vim.cmd("normal! m'") + vim.cmd("buffer " .. existing) + return + end + local result = vim.system( { "git", "show", ref }, { cwd = worktree, text = true } @@ -143,7 +159,6 @@ function M.open_commit(worktree, ref) return end local lines = util.split_lines(result.stdout or "") - local sha = repo.rev_parse(worktree, ref, true) or ref local parent = repo.rev_parse(worktree, ref .. "^", true) local buf = vim.api.nvim_create_buf(false, true) vim.bo[buf].buftype = "nofile" @@ -152,7 +167,7 @@ function M.open_commit(worktree, ref) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) vim.bo[buf].modifiable = false vim.bo[buf].modified = false - pcall(vim.api.nvim_buf_set_name, buf, "git://" .. sha .. "/") + pcall(vim.api.nvim_buf_set_name, buf, name) vim.b[buf].git_worktree = worktree vim.b[buf].git_ref = sha vim.b[buf].git_parent_ref = parent