Skip to content

Commit

Permalink
fix(watcher): improve debounce to be unique per file
Browse files Browse the repository at this point in the history
  • Loading branch information
lewis6991 committed Sep 5, 2023
1 parent 2b7e621 commit dafda77
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
13 changes: 10 additions & 3 deletions lua/gitsigns/debounce.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ local M = {}
--- @generic F: function
--- @param ms number Timeout in ms
--- @param fn F Function to debounce
--- @param hash? fun(...): any Function that determines id from arguments to fn
--- @return F Debounced function.
function M.debounce_trailing(ms, fn)
local timer = assert(uv.new_timer())
function M.debounce_trailing(ms, fn, hash)
local running = {} --- @type table<any,uv.uv_timer_t>
return function(...)
local id = hash and hash(...) or true
if running[id] == nil then
running[id] = assert(uv.new_timer())
end
local timer = running[id]
local argv = { ... }
timer:start(ms, 0, function()
timer:stop()
fn(unpack(argv))
running[id] = nil
fn(unpack(argv, 1, table.maxn(argv)))
end)
end
end
Expand Down
36 changes: 28 additions & 8 deletions lua/gitsigns/watcher.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ local function handle_moved(bufnr, old_relpath)
dprintf('%s buffer %d from %s to %s', msg, bufnr, old_name, bcache.file)
end

local watch_gitdir_handler = async.void(function(bufnr)
local handler = async.void(function(bufnr, file)
local __FUNC__ = 'watcher_handler'
dprint(file)
buf_check(bufnr)

local git_obj = cache[bufnr].git_obj
Expand All @@ -83,11 +85,28 @@ local watch_gitdir_handler = async.void(function(bufnr)
buf_check(bufnr)
end

cache[bufnr]:invalidate()
local bcache = cache[bufnr]

if not bcache.base and file == 'index' then
bcache.compare_text = nil
end

if file == 'HEAD' then
bcache.compare_text_head = nil
end

bcache.hunks = nil
bcache.hunks_staged = nil

require('gitsigns.manager').update(bufnr)
end)

local function handler_hash(bufnr, filename)
return string.format('%d:%s', bufnr, filename)
end

local handler_db = debounce_trailing(200, handler, handler_hash)

-- vim.inspect but on one line
--- @param x any
--- @return string
Expand All @@ -97,14 +116,15 @@ end

local M = {}

local WATCH_IGNORE = {
ORIG_HEAD = true,
FETCH_HEAD = true
}

--- @param bufnr integer
--- @param gitdir string
--- @return uv.uv_fs_event_t
function M.watch_gitdir(bufnr, gitdir)
-- Setup debounce as we create the luv object so the debounce is independent
-- to each watcher
local watch_gitdir_handler_db = debounce_trailing(200, watch_gitdir_handler)

dprintf('Watching git dir')
local w = assert(uv.new_fs_event())
w:start(gitdir, {}, function(err, filename, events)
Expand All @@ -119,14 +139,14 @@ function M.watch_gitdir(bufnr, gitdir)
-- 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 vim.endswith(filename, '.lock') then
if filename == nil or WATCH_IGNORE[filename] or vim.endswith(filename, '.lock') then
dprintf('%s (ignoring)', info)
return
end

dprint(info)

watch_gitdir_handler_db(bufnr)
handler_db(bufnr, filename)
end)
return w
end
Expand Down

0 comments on commit dafda77

Please sign in to comment.