aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/fs.lua
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2026-10-05 12:53:44 -0400
committerGitHub <noreply@github.com>2026-10-05 12:53:44 -0400
commitcb075627fe76589f68ea5c0ebf99ca89d6ab7b5b (patch)
treed98bf22663b9d64dbc14ee28656a268a37a3e9c5 /runtime/lua/vim/fs.lua
parentb4b959bf3fc58e697d676ec5edc785a73b9e8725 (diff)
downloadrneovim-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.lua18
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