fix(watcher): do not ignore any updates

Now the watcher handlers is debounced and throttled, the ignore list
is no longer necessary.

This avoids an issue where we sometimes trigger the handler too early
(as other files are still changing). Now the debounce and throttle logic
and take into account every single file change.
This commit is contained in:
Lewis Russell 2024-07-03 10:30:22 +01:00 committed by Lewis Russell
parent 6b1a14eabc
commit 5840f89c50
3 changed files with 24 additions and 28 deletions

View file

@ -31,7 +31,7 @@ local M = {}
--- @param hunks Gitsigns.Hunk.Hunk[]
--- @param top integer
--- @param bot integer
--- @param clear boolean
--- @param clear? boolean
--- @param untracked boolean
local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked)
if clear then
@ -65,13 +65,9 @@ end
--- @param bufnr integer
--- @param top integer
--- @param bot integer
--- @param clear boolean
--- @param clear? boolean
local function apply_win_signs(bufnr, top, bot, clear)
local bcache = cache[bufnr]
if not bcache then
return
end
local bcache = assert(cache[bufnr])
local untracked = bcache.git_obj.object_name == nil
apply_win_signs0(bufnr, signs_normal, bcache.hunks, top, bot, clear, untracked)
if signs_staged then
@ -318,7 +314,7 @@ function M.show_deleted_in_float(bufnr, nsd, hunk, staged)
virt_lines_leftcol = true,
})
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
local pbufnr = api.nvim_create_buf(false, true)
local text = staged and bcache.compare_text_head or bcache.compare_text
api.nvim_buf_set_lines(pbufnr, 0, -1, false, assert(text))
@ -420,7 +416,7 @@ end
--- @param bufnr integer
local function update_show_deleted(bufnr)
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
clear_deleted(bufnr)
if config.show_deleted then
@ -461,7 +457,7 @@ M.update = throttle_by_id(function(bufnr)
if not M.schedule(bufnr) then
return
end
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
local old_hunks, old_hunks_staged = bcache.hunks, bcache.hunks_staged
bcache.hunks, bcache.hunks_staged = nil, nil
@ -556,7 +552,7 @@ local function on_win(_cb, _winid, bufnr, topline, botline_guess)
end
local botline = math.min(botline_guess, api.nvim_buf_line_count(bufnr))
apply_win_signs(bufnr, topline + 1, botline + 1, false)
apply_win_signs(bufnr, topline + 1, botline + 1)
if not (config.word_diff and config.diff_opts.internal) then
return false

View file

@ -18,7 +18,7 @@ local dprintf = log.dprintf
--- @param bufnr integer
--- @param old_relpath string
local function handle_moved(bufnr, old_relpath)
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
local git_obj = bcache.git_obj
local new_name = git_obj:has_moved()
@ -73,6 +73,7 @@ local function watcher_handler0(bufnr)
-- Avoid cache hit for detached buffer
-- ref: https://github.com/lewis6991/gitsigns.nvim/issues/956
if not manager.schedule(bufnr) then
dprint('buffer invalid (1)')
return
end
@ -81,6 +82,7 @@ local function watcher_handler0(bufnr)
git_obj.repo:update_abbrev_head()
if not manager.schedule(bufnr) then
dprint('buffer invalid (2)')
return
end
@ -91,6 +93,7 @@ local function watcher_handler0(bufnr)
git_obj:update()
if not manager.schedule(bufnr) then
dprint('buffer invalid (3)')
return
end
@ -99,6 +102,7 @@ local function watcher_handler0(bufnr)
-- moved. Check if it was moved and switch to it.
handle_moved(bufnr, old_relpath)
if not manager.schedule(bufnr) then
dprint('buffer invalid (4)')
return
end
end
@ -108,9 +112,12 @@ local function watcher_handler0(bufnr)
require('gitsigns.manager').update(bufnr)
end
--- Debounce and throttle the handler.
--- We also throttle in case the debounce delay is not enough and to prevent
--- too many handlers from being launched (and interleaved).
--- Debounce to:
--- - wait for all changes to the gitdir to complete.
--- Throttle to:
--- - ensure handler is only triggered once per git operation.
--- - prevent updates to the same buffer from interleaving as the handler is
--- async.
local watcher_handler =
debounce_trailing(200, async.create(1, throttle_by_id(watcher_handler0, true)), 1)
@ -123,11 +130,6 @@ end
local M = {}
local WATCH_IGNORE = {
ORIG_HEAD = true,
FETCH_HEAD = true,
}
--- @param bufnr integer
--- @param gitdir string
--- @return uv.uv_fs_event_t
@ -141,17 +143,15 @@ function M.watch_gitdir(bufnr, gitdir)
return
end
local info = string.format("Git dir update: '%s' %s", filename, inspect(events))
-- The luv docs say filename is passed as a string but it has been observed
-- to sometimes be nil.
-- https://github.com/lewis6991/gitsigns.nvim/issues/848
if filename == nil or WATCH_IGNORE[filename] or vim.endswith(filename, '.lock') then
dprintf('%s (ignoring)', info)
if not filename then
log.eprint('No filename')
return
end
dprint(info)
dprintf("Git dir update: '%s' %s", filename, inspect(events))
watcher_handler(bufnr)
end)

View file

@ -63,7 +63,7 @@ describe('gitdir_watcher', function()
git({ 'mv', test_file, test_file2 })
match_dag({
"watcher_cb(1): Git dir update: 'index.lock' { rename = true } (ignoring)",
"watcher_cb(1): Git dir update: 'index.lock' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
})
@ -89,7 +89,7 @@ describe('gitdir_watcher', function()
git({ 'mv', test_file2, test_file3 })
match_dag({
"watcher_cb(1): Git dir update: 'index.lock' { rename = true } (ignoring)",
"watcher_cb(1): Git dir update: 'index.lock' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
})
@ -113,7 +113,7 @@ describe('gitdir_watcher', function()
git({ 'mv', test_file3, test_file })
match_dag({
"watcher_cb(1): Git dir update: 'index.lock' { rename = true } (ignoring)",
"watcher_cb(1): Git dir update: 'index.lock' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
"watcher_cb(1): Git dir update: 'index' { rename = true }",
})