Skip to content

Commit 2f71334

Browse files
committed
perf: apply stage ops directly
When staging hunks, the cache would be fully invalidated which would cause the next update to re-read the file from git. Now the stage is applied directly to the cache and is now only partially validated. This should result in the signs updating faster. Note the index watcher will still eventually trigger and cause a full invalidate and update.
1 parent f7cc685 commit 2f71334

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

lua/gitsigns/actions.lua

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,15 @@ function M.stage_hunk(range, opts, callback)
273273
message.error(err)
274274
return
275275
end
276+
277+
if bcache.compare_text then
278+
bcache.compare_text = Hunks.apply_to_text(bcache.compare_text, hunk, invert)
279+
end
280+
276281
table.insert(bcache.staged_diffs, hunk)
277282
end)
278283

279-
bcache:invalidate(true)
284+
bcache:invalidate()
280285
update(bufnr)
281286
end)
282287
end
@@ -438,11 +443,14 @@ function M.stage_buffer(callback)
438443
end
439444

440445
for _, hunk in ipairs(hunks) do
446+
if bcache.compare_text then
447+
bcache.compare_text = Hunks.apply_to_text(bcache.compare_text, hunk)
448+
end
441449
table.insert(bcache.staged_diffs, hunk)
442450
end
443451
end)
444452

445-
bcache:invalidate(true)
453+
bcache:invalidate()
446454
update(bufnr)
447455
end)
448456
end

lua/gitsigns/hunks.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ function M.patch_lines(hunk, fileformat)
125125
return lines
126126
end
127127

128+
--- @param text string[]
129+
--- @param hunk Gitsigns.Hunk.Hunk
130+
--- @param reverse? boolean
131+
--- @return string[]
132+
function M.apply_to_text(text, hunk, reverse)
133+
local removed = reverse and hunk.added or hunk.removed
134+
local added = reverse and hunk.removed or hunk.added
135+
136+
local start = removed.start
137+
if start == 0 then
138+
start = 1
139+
end
140+
141+
local new = {} --- @type string[]
142+
if start > 1 then
143+
vim.list_extend(new, vim.list_slice(text, 1, start - 1))
144+
end
145+
if added.count > 0 then
146+
vim.list_extend(new, added.lines)
147+
end
148+
local tail_start = start + removed.count
149+
if tail_start <= #text then
150+
vim.list_extend(new, vim.list_slice(text, tail_start, #text))
151+
end
152+
return new
153+
end
154+
128155
local function tointeger(x)
129156
return tonumber(x) --[[@as integer]]
130157
end

0 commit comments

Comments
 (0)