perf(git): skip sidebar render when porcelain output unchanged

This commit is contained in:
2026-04-27 14:00:56 +02:00
parent c9b02989da
commit 26b12a4371
+45 -4
View File
@@ -37,6 +37,7 @@ local SIDEBAR_WIDTH = 50
---@field diff_right_win integer? ---@field diff_right_win integer?
---@field user_aucmd integer? ---@field user_aucmd integer?
---@field last_shown_key string? ---@field last_shown_key string?
---@field last_render_key string? fingerprint of the last rendered state
---@type table<integer, ow.Git.StatusState> ---@type table<integer, ow.Git.StatusState>
local state = {} local state = {}
@@ -328,10 +329,41 @@ local function render(bufnr, branch, groups)
}) })
end end
state[bufnr].lines = meta state[bufnr].lines = meta
-- The diff windows we last opened may now be showing content for an end
-- entry whose underlying file has changed. Drop the cache so the next
-- show_diff recomputes pre/post panes instead of short-circuiting. ---Build a stable fingerprint of the parsed branch + groups so refresh can
state[bufnr].last_shown_key = nil ---short-circuit when the porcelain state is byte-identical to the last
---successful render.
---@param branch ow.Git.BranchInfo
---@param groups table<string, ow.Git.StatusEntry[]>
---@return string
local function fingerprint(branch, groups)
local parts = {
branch.head or "",
branch.upstream or "",
tostring(branch.ahead),
tostring(branch.behind),
}
for _, section in ipairs(SECTIONS) do
local entries = groups[section]
if entries then
for _, e in ipairs(entries) do
table.insert(
parts,
e.section
.. ":"
.. (e.path or e.sha or "")
.. ":"
.. (e.orig or "")
.. ":"
.. (e.x or "")
.. ":"
.. (e.y or "")
)
end
end
end
return table.concat(parts, "\0")
end end
---@param bufnr integer ---@param bufnr integer
@@ -356,6 +388,15 @@ local function refresh(bufnr)
if not vim.api.nvim_buf_is_valid(bufnr) then if not vim.api.nvim_buf_is_valid(bufnr) then
return return
end end
-- Any fs-event that triggered this refresh might have changed the
-- worktree under the diff buffers we last opened; invalidate the
-- cache so the next show_diff recomputes panes.
s.last_shown_key = nil
local fp = fingerprint(branch, groups)
if fp == s.last_render_key then
return
end
s.last_render_key = fp
render(bufnr, branch, groups) render(bufnr, branch, groups)
if not saved_path and not saved_sha then if not saved_path and not saved_sha then
return return