mirror of
https://github.com/neovim/neovim.git
synced 2025-12-10 00:22:41 +00:00
fix(watch): ignore nonexistent paths (ENOENT)
Problem:
The `_watch.watch()` strategy may fail if the given path does not exist:
…/vim/_watch.lua:101: ENOENT: no such file or directory
stack traceback:
[C]: in function 'assert'
…/vim/_watch.lua:101: in function <…/vim/_watch.lua:61>
[string "<nvim>"]:5: in main chunk
- `_watch.watch()` actively asserts any error returned by `handle:start()`.
- whereas `_watch.watchdirs()` just ignores the result of `root_handle:start()`.
Servers may send "client/registerCapability" with "workspace/didChangeWatchedFiles"
item(s) (`baseUri`) which do not actually exist on the filesystem:
https://github.com/neovim/neovim/issues/28058#issuecomment-2189929424
{
method = "client/registerCapability",
params = {
registrations = { {
method = "workspace/didChangeWatchedFiles",
registerOptions = {
watchers = { {
globPattern = {
baseUri = "file:///Users/does/not/exist",
pattern = "**/*.{ts,js,mts,mjs,cjs,cts,json,svelte}"
}
},
...
}
Solution:
- Remove the assert in `_watch.watch()`.
- Show a once-only message for both cases.
- More detailed logging is blocked until we have `nvim_log` / `vim.log`.
fix #28058
This commit is contained in:
@@ -30,6 +30,8 @@ M.FileChangeType = {
|
||||
--- @class vim._watch.watch.Opts : vim._watch.Opts
|
||||
--- @field uvflags? uv.fs_event_start.flags
|
||||
|
||||
--- Decides if `path` should be skipped.
|
||||
---
|
||||
--- @param path string
|
||||
--- @param opts? vim._watch.Opts
|
||||
local function skip(path, opts)
|
||||
@@ -69,7 +71,7 @@ function M.watch(path, opts, callback)
|
||||
local uvflags = opts and opts.uvflags or {}
|
||||
local handle = assert(uv.new_fs_event())
|
||||
|
||||
local _, start_err = handle:start(path, uvflags, function(err, filename, events)
|
||||
local _, start_err, start_errname = handle:start(path, uvflags, function(err, filename, events)
|
||||
assert(not err, err)
|
||||
local fullpath = path
|
||||
if filename then
|
||||
@@ -96,7 +98,15 @@ function M.watch(path, opts, callback)
|
||||
callback(fullpath, change_type)
|
||||
end)
|
||||
|
||||
assert(not start_err, start_err)
|
||||
if start_err then
|
||||
if start_errname == 'ENOENT' then
|
||||
-- Server may send "workspace/didChangeWatchedFiles" with nonexistent `baseUri` path.
|
||||
-- This is mostly a placeholder until we have `nvim_log` API.
|
||||
vim.notify_once(('watch.watch: %s'):format(start_err), vim.log.levels.INFO)
|
||||
end
|
||||
-- TODO(justinmk): log important errors once we have `nvim_log` API.
|
||||
return function() end
|
||||
end
|
||||
|
||||
return function()
|
||||
local _, stop_err = handle:stop()
|
||||
@@ -193,7 +203,18 @@ function M.watchdirs(path, opts, callback)
|
||||
|
||||
local root_handle = assert(uv.new_fs_event())
|
||||
handles[path] = root_handle
|
||||
root_handle:start(path, {}, create_on_change(path))
|
||||
local _, start_err, start_errname = root_handle:start(path, {}, create_on_change(path))
|
||||
|
||||
if start_err then
|
||||
if start_errname == 'ENOENT' then
|
||||
-- Server may send "workspace/didChangeWatchedFiles" with nonexistent `baseUri` path.
|
||||
-- This is mostly a placeholder until we have `nvim_log` API.
|
||||
vim.notify_once(('watch.watchdirs: %s'):format(start_err), vim.log.levels.INFO)
|
||||
end
|
||||
-- TODO(justinmk): log important errors once we have `nvim_log` API.
|
||||
|
||||
-- Continue. vim.fs.dir() will return nothing, so the code below is harmless.
|
||||
end
|
||||
|
||||
--- "640K ought to be enough for anyone"
|
||||
--- Who has folders this deep?
|
||||
|
||||
Reference in New Issue
Block a user