diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-06 03:00:58 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-06 03:00:58 +0000 |
commit | 25f20b6d8ccd4edcdfec23c1a3c908516076ee06 (patch) | |
tree | f889e071118d7d2db80066d14d14b020c50a2238 /macros/latex/contrib/l3build/l3build-file-functions.lua | |
parent | 75db33dc347ec9cfbaa2f3ec538a2697351f571b (diff) |
CTAN sync 202105060300
Diffstat (limited to 'macros/latex/contrib/l3build/l3build-file-functions.lua')
-rw-r--r-- | macros/latex/contrib/l3build/l3build-file-functions.lua | 128 |
1 files changed, 77 insertions, 51 deletions
diff --git a/macros/latex/contrib/l3build/l3build-file-functions.lua b/macros/latex/contrib/l3build/l3build-file-functions.lua index 7d13fc933e..6ca1cc6011 100644 --- a/macros/latex/contrib/l3build/l3build-file-functions.lua +++ b/macros/latex/contrib/l3build/l3build-file-functions.lua @@ -1,6 +1,6 @@ --[[ -File l3build-file-functions.lua Copyright (C) 2018-2020 The LaTeX3 Project +File l3build-file-functions.lua Copyright (C) 2018-2020 The LaTeX Project It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this @@ -36,7 +36,6 @@ local execute = os.execute local exit = os.exit local getenv = os.getenv local remove = os.remove -local os_time = os.time local os_type = os.type local luatex_revision = status.luatex_revision @@ -171,14 +170,19 @@ function normalize_path(path) end -- Return an absolute path from a relative one +-- Due to chdir, path must exist and be accessible. function abspath(path) local oldpwd = currentdir() - chdir(path) - local result = currentdir() - chdir(oldpwd) - return escapepath(gsub(result, "\\", "/")) + local ok, msg = chdir(path) + if ok then + local result = currentdir() + chdir(oldpwd) + return escapepath(gsub(result, "\\", "/")) + end + error(msg) end +-- TODO: Fix the cross platform problem function escapepath(path) if os_type == "windows" then local path,count = gsub(path,'"','') @@ -210,22 +214,25 @@ end -- Copy files 'quietly' function cp(glob, source, dest) local errorlevel - for i,_ in pairs(tree(source, glob)) do - local source = source .. "/" .. i + for _,p in ipairs(tree(source, glob)) do + -- p_src is a path relative to `source` whereas + -- p_cwd is the counterpart relative to the current working directory if os_type == "windows" then - if attributes(source)["mode"] == "directory" then + if attributes(p.cwd, "mode") == "directory" then errorlevel = execute( - 'xcopy /y /e /i "' .. unix_to_win(source) .. '" "' - .. unix_to_win(dest .. '/' .. i) .. '" > nul' - ) + 'xcopy /y /e /i "' .. unix_to_win(p.cwd) .. '" "' + .. unix_to_win(dest .. '/' .. p.src) .. '" > nul' + ) and 0 or 1 else errorlevel = execute( - 'xcopy /y "' .. unix_to_win(source) .. '" "' + 'xcopy /y "' .. unix_to_win(p.cwd) .. '" "' .. unix_to_win(dest .. '/') .. '" > nul' - ) + ) and 0 or 1 end else - errorlevel = execute("cp -RLf '" .. source .. "' '" .. dest .. "'") + errorlevel = execute( + "cp -RLf '" .. p.cwd .. "' '" .. dest .. "'" + ) and 0 or 1 end if errorlevel ~=0 then return errorlevel @@ -255,7 +262,7 @@ function fileexists(file) f:close() return true else - return false + return false -- also file exits and is not readable end end @@ -283,54 +290,73 @@ function filelist(path, glob) return files end --- Does what filelist does, but can also glob subdirectories. In the returned --- table, the keys are paths relative to the given starting path, the values --- are their counterparts relative to the current working directory. -function tree(path, glob) +---@class tree_entry_t +---@field src string path relative to the source directory +---@field cwd string path counterpart relative to the current working directory + +---Does what filelist does, but can also glob subdirectories. +---In the returned table, the keys are paths relative to the given source path, +---the values are their counterparts relative to the current working directory. +---@param src_path string +---@param glob string +---@return table<integer,tree_entry_t> +function tree(src_path, glob) local function cropdots(path) - return gsub(gsub(path, "^%./", ""), "/%./", "/") + return path:gsub( "^%./", ""):gsub("/%./", "/") end + src_path = cropdots(src_path) + glob = cropdots(glob) local function always_true() return true end local function is_dir(file) - return attributes(file)["mode"] == "directory" + return attributes(file, "mode") == "directory" end - local dirs = {["."] = cropdots(path)} - for pattern, criterion in gmatch(cropdots(glob), "([^/]+)(/?)") do - local criterion = criterion == "/" and is_dir or always_true - function fill(path, dir, table) - for _, file in ipairs(filelist(dir, pattern)) do - local fullpath = path .. "/" .. file - if file ~= "." and file ~= ".." and - fullpath ~= builddir - then - local fulldir = dir .. "/" .. file - if criterion(fulldir) then - table[fullpath] = fulldir + ---@type table<integer,tree_entry_t> + local result = { { + src = ".", + cwd = src_path, + } } + for glob_part, sep in glob:gmatch("([^/]+)(/?)/*") do + local accept = sep == "/" and is_dir or always_true + ---Feeds the given table according to `glob_part` + ---@param p tree_entry_t path counterpart relative to the current working directory + ---@param table table + local function fill(p, table) + for _,file in ipairs(filelist(p.cwd, glob_part)) do + if file ~= "." and file ~= ".." then + local pp = { + src = p.src .. "/" .. file, + cwd = p.cwd .. "/" .. file, + } + if pp.cwd ~= builddir -- TODO: ensure that `builddir` is properly formatted + and accept(pp.cwd) + then + insert(table, pp) end end end end - local newdirs = {} - if pattern == "**" then + local new_result = {} + if glob_part == "**" then + local i = 1 while true do - path, dir = next(dirs) - if not path then + local p = result[i] + i = i + 1 + if not p then break end - dirs[path] = nil - newdirs[path] = dir - fill(path, dir, dirs) + insert(new_result, p) -- shorter path + fill(p, result) -- after longer end else - for path, dir in pairs(dirs) do - fill(path, dir, newdirs) + for _,p in ipairs(result) do + fill(p, new_result) end end - dirs = newdirs + result = new_result end - return dirs + return result end function remove_duplicates(a) @@ -353,7 +379,7 @@ function mkdir(dir) if os_type == "windows" then -- Windows (with the extensions) will automatically make directory trees -- but issues a warning if the dir already exists: avoid by including a test - local dir = unix_to_win(dir) + dir = unix_to_win(dir) return execute( "if not exist " .. dir .. "\\nul " .. "mkdir " .. dir ) @@ -364,10 +390,10 @@ end -- Rename function ren(dir, source, dest) - local dir = dir .. "/" + dir = dir .. "/" if os_type == "windows" then - local source = gsub(source, "^%.+/", "") - local dest = gsub(dest, "^%.+/", "") + source = gsub(source, "^%.+/", "") + dest = gsub(dest, "^%.+/", "") return execute("ren " .. unix_to_win(dir) .. source .. " " .. dest) else return execute("mv " .. dir .. source .. " " .. dir .. dest) @@ -376,8 +402,8 @@ end -- Remove file(s) based on a glob function rm(source, glob) - for i,_ in pairs(tree(source, glob)) do - rmfile(source,i) + for _,p in ipairs(tree(source, glob)) do + rmfile(source,p.src) end -- os.remove doesn't give a sensible errorlevel return 0 |