diff options
| author | Justin M. Keyes <justinkz@gmail.com> | 2026-10-05 12:53:44 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-05 12:53:44 -0400 |
| commit | cb075627fe76589f68ea5c0ebf99ca89d6ab7b5b (patch) | |
| tree | d98bf22663b9d64dbc14ee28656a268a37a3e9c5 /runtime/lua/vim/fs.lua | |
| parent | b4b959bf3fc58e697d676ec5edc785a73b9e8725 (diff) | |
| download | rneovim-cb075627fe76589f68ea5c0ebf99ca89d6ab7b5b.tar.gz rneovim-cb075627fe76589f68ea5c0ebf99ca89d6ab7b5b.tar.bz2 rneovim-cb075627fe76589f68ea5c0ebf99ca89d6ab7b5b.zip | |
fix(vim.fs): find{follow=true} skips symlink targets of the given `type` #42246
Problem:
`vim.fs.find()` checks `type` against the symlink itself, so
`{ type='file', follow=true }` skips symlinked files (e.g. `:helptags`).
Solution:
With `follow=true`, a symlink has the type of its target. Thus
`type='link'` only matches broken symlinks (like `find -L -type l`).
Diffstat (limited to 'runtime/lua/vim/fs.lua')
| -rw-r--r-- | runtime/lua/vim/fs.lua | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index aeaf7ea638..4401541a55 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -417,7 +417,8 @@ end --- Stop searching when this directory is reached. The directory itself is not searched. --- @field stop? string --- ---- Find only items of the given type. If omitted, all items that match {names} are included. +--- Find only items of the given type. If omitted, all items that match `names` are included. +--- With `follow`, a symlink has the type of its target. --- @field type? string --- --- Stop searching after this many matches. Use `math.huge` for "unlimited". @@ -460,7 +461,7 @@ end --- Must be base names, paths and globs are not supported when {names} is a string or a table. --- If {names} is a function, it is called for each traversed item with args: --- - name: base name of the current item ---- - path: full path of the current item +--- - path: full path of the directory containing the current item --- --- The function should return `true` if the given item is considered a match. --- @@ -508,6 +509,9 @@ function M.find(names, opts) test = function(p) local t = {} for name, type, err in M.dir(p, { err = true }) do + if type == 'link' and opts.follow then + type = (uv.fs_stat(M.joinpath(p, name)) or {}).type or type + end if err ~= nil then table.insert(errors, err) elseif (not opts.type or opts.type == type) and names(name, p) then @@ -563,6 +567,9 @@ function M.find(names, opts) end for other, type_, err in M.dir(dir, { err = true }) do + if type_ == 'link' and opts.follow then + type_ = (uv.fs_stat(M.joinpath(dir, other)) or {}).type or type_ + end if err ~= nil then table.insert(errors, err) else @@ -584,11 +591,8 @@ function M.find(names, opts) end end - if type_ == 'directory' or (type_ == 'link' and opts.follow) then - local f = M.joinpath(dir, other) - if type_ == 'directory' or (uv.fs_stat(f) or {}).type == 'directory' then - dirs[#dirs + 1] = f - end + if type_ == 'directory' then + dirs[#dirs + 1] = M.joinpath(dir, other) end end end |