perf(git): skip sidebar render when porcelain output unchanged
This commit is contained in:
+45
-4
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user