diff --git a/CHANGES.txt b/CHANGES.txt index 0ee64e8e..3045b051 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -26,3 +26,4 @@ Since 5.0-alpha1: * Added AVX2 to vectorextensions() * Embedded scripts now compressed with LuaSrcDiet (Oliver Schneider) * Checks to prevent self-linking (Mark Chandler) +* os.rmdir() can now removes dotted subdirectories (Alexey Orlov) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 0ea96356..7cd7a031 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -13,6 +13,8 @@ Builds and Infrastructure: * Nightly Jenkins builds and error reports Patch contributors: + Alexey Orlov + * add exclude arguments to os.match() Manu Evans * new APIs for specifying remote debugging parameters * new APIs for enabling and disabling specific warnings @@ -22,7 +24,7 @@ Patch contributors: Mihai Sebea * Xcode exporter fixes and improvements Oliver Schneider - * Compress embedded scripts with LuaSrcDiet + * compress embedded scripts with LuaSrcDiet Renaud Guillard * add library search paths argument to os.findlib() * return command exit code from os.outputof() diff --git a/src/base/os.lua b/src/base/os.lua index 0fb493d4..0b175bb1 100644 --- a/src/base/os.lua +++ b/src/base/os.lua @@ -250,11 +250,24 @@ -- directory name, "**" to recurse into subdirectories. -- @param matchFiles -- True to match against files, false to match directories. +-- @param excludeDirs +-- Lua Pattern. +-- If any encountered dir matches this pattern, it will be discarded (both from results and from recursive decent). +-- If it is nil, it will be set to "%..*", to keep backward compatibility. +-- To make it match all dirs, you need to pass un-matchable pattern; we use "a^" for this internally. +-- @param excludeFiles +-- Lua Pattern. +-- If any encountered file matches this pattern, it will be discarded from results. +-- If it is nil, it will be set to "a^" to match no files. -- @return -- A table containing the matched file or directory names. --- - function os.match(mask, matchFiles) + function os.match(mask, matchFiles, excludeDirs, excludeFiles) + -- patch up exclude masks to default values + excludeDirs = excludeDirs and excludeDirs or "%..*" + excludeFiles = excludeFiles and excludeFiles or "a^" + -- Strip any extraneous weirdness from the mask to ensure a good -- match against the paths returned by the OS. I don't know if I've -- caught all the possibilities here yet; will add more as I go. @@ -291,7 +304,7 @@ local isfile = os.matchisfile(m) if (matchFiles and isfile) or (not matchFiles and not isfile) then local fname = os.matchname(m) - if isfile or not fname:startswith(".") then + if (isfile and not fname:match(excludeFiles)) or (not isfile and not fname:match(excludeDirs)) then fname = path.join(basedir, fname) if fname:match(mask) == fname then table.insert(result, fname) @@ -307,7 +320,8 @@ while os.matchnext(m) do if not os.matchisfile(m) then local dirname = os.matchname(m) - if (not dirname:startswith(".")) then + -- always exclude phony dirs: . and .. + if not (dirname == "." or dirname == ".." or dirname:match(excludeDirs)) then matchwalker(path.join(basedir, dirname)) end end @@ -332,7 +346,7 @@ --- function os.matchdirs(mask) - return os.match(mask, false) + return os.match(mask, false, "%..*", nil) end @@ -347,7 +361,7 @@ --- function os.matchfiles(mask) - return os.match(mask, true) + return os.match(mask, true, "%..*", nil) end @@ -440,10 +454,12 @@ local builtin_rmdir = os.rmdir function os.rmdir(p) - -- recursively remove subdirectories - local dirs = os.matchdirs(p .. "/*") + -- recursively remove subdirectories: exclude no dirs apart builtin . and .. + local dirs = os.match(p .. "/*", false, "a^", nil) for _, dname in ipairs(dirs) do - os.rmdir(dname) + if not (dname:endswith("/.") or dname:endswith("/..")) then + os.rmdir(dname) + end end -- remove any files diff --git a/tests/base/test_os.lua b/tests/base/test_os.lua index ed0c319a..818679c1 100644 --- a/tests/base/test_os.lua +++ b/tests/base/test_os.lua @@ -78,8 +78,9 @@ end function suite.matchfiles_SkipsDotDirs_OnRecursive() - local result = os.matchfiles("**.lua") - test.isfalse(table.contains(result, ".svn/text-base/testfx.lua.svn-base")) + local result = os.matchfiles("../**.lua*") + test.istrue(table.contains(result, "../src/_manifest.lua")) + test.isfalse(table.contains(result, "../.hg/store/data/scripts/test.lua.i")) end function suite.matchfiles_OnSubfolderMatch() @@ -111,6 +112,31 @@ +-- +-- os.match() tests for exclude patterns +-- + + function suite.match_DirsCustomExcludeDirs() + local result = os.match("*", false, "a.*") + test.istrue(table.contains(result, "..")) + test.isfalse(table.contains(result, "actions")) + test.isfalse(table.contains(result, "api")) + end + + function suite.match_FilesCustomExcludeDirs() + local result = os.match("../**.lua*", true, "src") + test.isfalse(table.contains(result, "../src/_manifest.lua")) + test.istrue(table.contains(result, "../.hg/store/data/scripts/test.lua.i")) + end + + function suite.match_FilesCustomExcludeFiles() + local result = os.match("**.lua", true, nil, "ok.*") + test.istrue(table.contains(result, "folder/premake5.lua")) + test.isfalse(table.contains(result, "folder/ok.lua")) + end + + + -- -- os.pathsearch() tests -- @@ -172,3 +198,18 @@ } test.isequal("test a b", os.translateCommands("{COPY} a b", "test")) end + + + +-- +-- os.mkdir() and os.rmdir() tests +-- + + function suite.mkdirrmdir_WorksWithDottesDirs() + os.mkdir("__TEST/.TEST") + test.istrue(table.contains(os.matchdirs("*"), "__TEST")) + test.istrue(table.contains(os.match("**", false, "a^"), "__TEST/.TEST")) + os.rmdir("__TEST") + test.isfalse(table.contains(os.matchdirs("*"), "__TEST")) + test.isfalse(table.contains(os.match("**", false, "a^"), "__TEST/.TEST")) + end