perf(git): run rev-parse and git show <commit> sync

This commit is contained in:
2026-04-28 08:03:05 +02:00
parent 01c0f82e18
commit d2633ae9c2
3 changed files with 68 additions and 107 deletions
+40 -59
View File
@@ -135,68 +135,49 @@ end
---@param opts ow.Git.OpenCommitOpts?
function M.open_commit(worktree, ref, opts)
local split = opts and opts.split
repo.rev_parse(worktree, ref, true, function(resolved)
local sha = resolved 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
if split == false then
vim.cmd.normal({ "m'", bang = true })
vim.api.nvim_set_current_buf(existing)
else
vim.api.nvim_open_win(existing, true, {
split = split or (vim.o.splitbelow and "below" or "above"),
})
end
return
local sha = repo.rev_parse(worktree, ref, true) or ref
local name = "git://" .. sha .. "//"
-- Commit SHAs are immutable so a previously-opened buffer is still
-- valid. Reuse it instead of refetching.
local existing = vim.fn.bufnr(name)
if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then
if split == false then
vim.cmd.normal({ "m'", bang = true })
vim.api.nvim_set_current_buf(existing)
else
vim.api.nvim_open_win(existing, true, {
split = split or (vim.o.splitbelow and "below" or "above"),
})
end
return
end
local buf, win = git.new_scratch({ name = name, split = split })
vim.b[buf].git_worktree = worktree
vim.b[buf].git_ref = sha
local result = vim.system(
{ "git", "show", ref },
{ cwd = worktree, text = true }
)
:wait()
if result.code ~= 0 then
log.error("git show %s failed: %s", ref, vim.trim(result.stderr or ""))
return
end
vim.system(
{ "git", "show", ref },
{ cwd = worktree, text = true },
vim.schedule_wrap(function(result)
if result.code ~= 0 then
log.error(
"git show %s failed: %s",
ref,
vim.trim(result.stderr or "")
)
-- Drop the empty placeholder so a retry runs a fresh
-- fetch. With `split = false` the window falls back to
-- its alternate buffer (the gitlog); for a real split
-- we close the dedicated window to keep the layout tidy.
if split ~= false and vim.api.nvim_win_is_valid(win) then
pcall(vim.api.nvim_win_close, win, true)
end
if vim.api.nvim_buf_is_valid(buf) then
vim.api.nvim_buf_delete(buf, { force = true })
end
return
end
if not vim.api.nvim_buf_is_valid(buf) then
return
end
local lines = util.split_lines(result.stdout or "")
repo.rev_parse(worktree, ref .. "^", true, function(parent)
if not vim.api.nvim_buf_is_valid(buf) then
return
end
vim.b[buf].git_parent_ref = parent
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].modifiable = false
vim.bo[buf].modified = false
vim.bo[buf].filetype = "git"
end)
end)
)
end)
local parent = repo.rev_parse(worktree, ref .. "^", true)
local buf, _ = git.new_scratch({ name = name, split = split })
vim.b[buf].git_worktree = worktree
vim.b[buf].git_ref = sha
vim.b[buf].git_parent_ref = parent
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(
buf,
0,
-1,
false,
util.split_lines(result.stdout or "")
)
vim.bo[buf].modifiable = false
vim.bo[buf].modified = false
vim.bo[buf].filetype = "git"
end
---@return boolean dispatched true if the cursor was on an actionable line