Skip to content

Commit

Permalink
fix(watcher): do not ignore any updates
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lewis6991 committed Jul 3, 2024
1 parent 6b1a14e commit 5840f89
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 28 deletions.
18 changes: 7 additions & 11 deletions lua/gitsigns/manager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
28 changes: 14 additions & 14 deletions lua/gitsigns/watcher.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand All @@ -91,6 +93,7 @@ local function watcher_handler0(bufnr)

git_obj:update()
if not manager.schedule(bufnr) then
dprint('buffer invalid (3)')
return
end

Expand All @@ -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
Expand All @@ -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)

Expand All @@ -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
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions test/gitdir_watcher_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 }",
})
Expand All @@ -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 }",
})
Expand All @@ -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 }",
})
Expand Down

0 comments on commit 5840f89

Please sign in to comment.