From aa141bc281d4895273fe1f9b7003f379a7abfb8f Mon Sep 17 00:00:00 2001 From: mitchell <70453897+orbitalquark@users.noreply.github.com> Date: Sun, 25 Oct 2020 10:50:01 -0400 Subject: Handle more types of recursive symlinks in `lfs.walk()`. --- core/lfs_ext.lua | 13 ++++++++----- test/test.lua | 15 +++++++++++++++ 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() -- cgit v1.2.3