feat(lsp): drop fswatch, use inotifywait (#29374)

This patch replaces fswatch with inotifywait from inotify-toools:

https://github.com/inotify-tools/inotify-tools

fswatch takes ~1min to set up recursively for the Samba source code
directory. inotifywait needs less than a second to do the same thing.

https://github.com/emcrisostomo/fswatch/issues/321

Also it fswatch seems to be unmaintained in the meantime.

Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Andreas Schneider
2024-07-06 11:44:19 +02:00
committed by GitHub
parent 91e5dcae3d
commit 55e4301036
7 changed files with 54 additions and 53 deletions

View File

@@ -227,11 +227,12 @@ end
--- @param data string
--- @param opts vim._watch.Opts?
--- @param callback vim._watch.Callback
local function fswatch_output_handler(data, opts, callback)
local function on_inotifywait_output(data, opts, callback)
local d = vim.split(data, '%s+')
-- only consider the last reported event
local fullpath, event = d[1], d[#d]
local path, event, file = d[1], d[2], d[#d]
local fullpath = vim.fs.joinpath(path, file)
if skip(fullpath, opts) then
return
@@ -240,20 +241,16 @@ local function fswatch_output_handler(data, opts, callback)
--- @type integer
local change_type
if event == 'Created' then
if event == 'CREATE' then
change_type = M.FileChangeType.Created
elseif event == 'Removed' then
elseif event == 'DELETE' then
change_type = M.FileChangeType.Deleted
elseif event == 'Updated' then
elseif event == 'MODIFY' then
change_type = M.FileChangeType.Changed
elseif event == 'Renamed' then
local _, staterr, staterrname = uv.fs_stat(fullpath)
if staterrname == 'ENOENT' then
change_type = M.FileChangeType.Deleted
else
assert(not staterr, staterr)
change_type = M.FileChangeType.Created
end
elseif event == 'MOVED_FROM' then
change_type = M.FileChangeType.Deleted
elseif event == 'MOVED_TO' then
change_type = M.FileChangeType.Created
end
if change_type then
@@ -265,24 +262,22 @@ end
--- @param opts vim._watch.Opts?
--- @param callback vim._watch.Callback Callback for new events
--- @return fun() cancel Stops the watcher
function M.fswatch(path, opts, callback)
-- debounce isn't the same as latency but close enough
local latency = 0.5 -- seconds
if opts and opts.debounce then
latency = opts.debounce / 1000
end
function M.inotify(path, opts, callback)
local obj = vim.system({
'fswatch',
'--event=Created',
'--event=Removed',
'--event=Updated',
'--event=Renamed',
'--event-flags',
'inotifywait',
'--quiet', -- suppress startup messages
'--no-dereference', -- don't follow symlinks
'--monitor', -- keep listening for events forever
'--recursive',
'--latency=' .. tostring(latency),
'--exclude',
'/.git/',
'--event',
'create',
'--event',
'delete',
'--event',
'modify',
'--event',
'move',
'@.git', -- ignore git directory
path,
}, {
stderr = function(err, data)
@@ -292,11 +287,11 @@ function M.fswatch(path, opts, callback)
if data and #vim.trim(data) > 0 then
vim.schedule(function()
if vim.fn.has('linux') == 1 and vim.startswith(data, 'Event queue overflow') then
data = 'inotify(7) limit reached, see :h fswatch-limitations for more info.'
if vim.fn.has('linux') == 1 and vim.startswith(data, 'Failed to watch') then
data = 'inotify(7) limit reached, see :h inotify-limitations for more info.'
end
vim.notify('fswatch: ' .. data, vim.log.levels.ERROR)
vim.notify('inotify: ' .. data, vim.log.levels.ERROR)
end)
end
end,
@@ -306,7 +301,7 @@ function M.fswatch(path, opts, callback)
end
for line in vim.gsplit(data or '', '\n', { plain = true, trimempty = true }) do
fswatch_output_handler(line, opts, callback)
on_inotifywait_output(line, opts, callback)
end
end,
-- --latency is locale dependent but tostring() isn't and will always have '.' as decimal point.