aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormitchell <70453897+orbitalquark@users.noreply.github.com>2020-10-25 10:50:01 -0400
committermitchell <70453897+orbitalquark@users.noreply.github.com>2020-10-25 10:50:01 -0400
commitaa141bc281d4895273fe1f9b7003f379a7abfb8f (patch)
tree846187c25d81f266a7c333d81b1f88fdc3f3a6fb
parente82eddd9e007597e8283922653de0e5abb94c0dc (diff)
downloadtextadept-aa141bc281d4895273fe1f9b7003f379a7abfb8f.tar.gz
textadept-aa141bc281d4895273fe1f9b7003f379a7abfb8f.zip
Handle more types of recursive symlinks in `lfs.walk()`.
-rw-r--r--core/lfs_ext.lua13
-rw-r--r--test/test.lua15
2 files changed, 23 insertions, 5 deletions
diff --git a/core/lfs_ext.lua b/core/lfs_ext.lua
index 5bbe609a..d55dbf0b 100644
--- a/core/lfs_ext.lua
+++ b/core/lfs_ext.lua
@@ -24,9 +24,9 @@ lfs.default_filter = {--[[Extensions]]'!.a','!.bmp','!.bz2','!.class','!.dll','!
-- @param level Utility value indicating the directory level this function is
-- at.
local function walk(dir, filter, n, include_dirs, seen, level)
+ if not seen then seen = {} end
local sep = not WIN32 and '/' or '\\'
- local os_dir = not WIN32 and dir or dir:gsub('/', sep)
- seen[os_dir], seen[os_dir .. sep] = true, true
+ seen[not WIN32 and dir or dir:gsub('/', sep)] = true
for basename in lfs.dir(dir) do
if basename:find('^%.%.?$') then goto continue end -- ignore . and ..
local filename = dir .. (dir ~= '/' and '/' or '') .. basename
@@ -50,8 +50,11 @@ local function walk(dir, filter, n, include_dirs, seen, level)
local os_filename = not WIN32 and filename or filename:gsub('/', sep)
if mode == 'file' then
coroutine.yield(os_filename)
- elseif mode == 'directory' and
- not seen[lfs.symlinkattributes(filename, 'target')] then
+ elseif mode == 'directory' then
+ local link = lfs.symlinkattributes(filename, 'target')
+ if link and seen[lfs.abspath(link .. sep, dir):gsub('[/\\]+$', '')] then
+ goto continue
+ end
if include_dirs then coroutine.yield(os_filename .. sep) end
if n and (level or 0) >= n then goto continue end
walk(filename, filter, n, include_dirs, seen, (level or 0) + 1)
@@ -109,7 +112,7 @@ function lfs.walk(dir, filter, n, include_dirs)
end
end
local co = coroutine.create(
- function() walk(dir, processed_filter, n, include_dirs, {}) end)
+ function() walk(dir, processed_filter, n, include_dirs) end)
return function() return select(2, coroutine.resume(co)) end
end
diff --git a/test/test.lua b/test/test.lua
index b1b4ee74..563cdb3f 100644
--- a/test/test.lua
+++ b/test/test.lua
@@ -742,6 +742,21 @@ function test_lfs_ext_walk_symlinks()
table.sort(expected_files)
assert_equal(files, expected_files)
os.execute('rm -r ' .. dir)
+
+ lfs.mkdir(dir)
+ io.open(dir .. '/foo', 'w'):close()
+ local cwd = lfs.currentdir()
+ lfs.chdir(dir)
+ lfs.link('.', 'bar', true)
+ lfs.mkdir(dir .. '/baz')
+ lfs.mkdir(dir .. '/baz/quux')
+ lfs.chdir(dir .. '/baz/quux')
+ lfs.link('../../baz/', 'foobar', true)
+ lfs.chdir(cwd)
+ local count = 0
+ for filename in lfs.walk(dir) do count = count + 1 end
+ assert_equal(count, 1)
+ os.execute('rm -r ' .. dir)
end
function test_lfs_ext_abs_path()