From 2c4ff5240bf298fec07749f5984de2f08b8736ec Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Tue, 20 Feb 2024 13:43:44 -0300 Subject: fix: better normalization for paths and slashes Fixes #1195. --- src/luarocks/admin/cache.lua | 2 +- src/luarocks/cmd/doc.lua | 2 +- src/luarocks/cmd/init.lua | 4 +-- src/luarocks/core/cfg.lua | 82 +++++++++++++++++++++++++------------------- src/luarocks/core/dir.lua | 15 +++++--- src/luarocks/core/path.lua | 8 +++-- src/luarocks/core/util.lua | 8 +++-- src/luarocks/dir.lua | 21 ++++++++++-- src/luarocks/fetch.lua | 4 +-- src/luarocks/fs/lua.lua | 39 ++++++++++++--------- src/luarocks/fs/unix.lua | 6 ++-- src/luarocks/fs/win32.lua | 23 ++----------- 12 files changed, 122 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/luarocks/admin/cache.lua b/src/luarocks/admin/cache.lua index 10b273ea..7a4e4af8 100644 --- a/src/luarocks/admin/cache.lua +++ b/src/luarocks/admin/cache.lua @@ -45,7 +45,7 @@ function cache.split_server_url(url, user, password) user = credentials end end - local local_cache = cfg.local_cache .. "/" .. server_path:gsub("[\\/]", "_") + local local_cache = dir.path(cfg.local_cache, (server_path:gsub("[\\/]", "_"))) return local_cache, protocol, server_path, user, password end diff --git a/src/luarocks/cmd/doc.lua b/src/luarocks/cmd/doc.lua index ae471230..a3117007 100644 --- a/src/luarocks/cmd/doc.lua +++ b/src/luarocks/cmd/doc.lua @@ -96,7 +96,7 @@ function doc.command(args) return nil, "Documentation directory not found for "..name.." "..version end - docdir = dir.normalize(docdir):gsub("/+", "/") + docdir = dir.normalize(docdir) local files = fs.find(docdir) local htmlpatt = "%.html?$" local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" } diff --git a/src/luarocks/cmd/init.lua b/src/luarocks/cmd/init.lua index 1783750c..65513104 100644 --- a/src/luarocks/cmd/init.lua +++ b/src/luarocks/cmd/init.lua @@ -27,8 +27,8 @@ function init.add_to_parser(parser) end local function gitignore_path(pwd, wrapper_dir, filename) - local norm_cur = dir.normalize(fs.absolute_name(pwd)) - local norm_file = dir.normalize(fs.absolute_name(dir.path(wrapper_dir, filename))) + local norm_cur = fs.absolute_name(pwd) + local norm_file = fs.absolute_name(dir.path(wrapper_dir, filename)) if norm_file:sub(1, #norm_cur) == norm_cur then return norm_file:sub(#norm_cur + 2) else diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua index a3a7d6cb..b991f581 100644 --- a/src/luarocks/core/cfg.lua +++ b/src/luarocks/core/cfg.lua @@ -13,6 +13,7 @@ local table, pairs, require, os, pcall, ipairs, package, type, assert = table, pairs, require, os, pcall, ipairs, package, type, assert +local dir = require("luarocks.core.dir") local util = require("luarocks.core.util") local persist = require("luarocks.core.persist") local sysdetect = require("luarocks.core.sysdetect") @@ -53,21 +54,21 @@ local function detect_sysconfdir() if not debug then return end - local src = debug.getinfo(1, "S").source:gsub("\\", "/"):gsub("/+", "/") + local src = dir.normalize(debug.getinfo(1, "S")) if src:sub(1, 1) == "@" then src = src:sub(2) end - local basedir = src:match("^(.*)/luarocks/core/cfg.lua$") + local basedir = src:match("^(.*)[\\/]luarocks[\\/]core[\\/]cfg.lua$") if not basedir then return end -- If installed in a Unix-like tree, use a Unix-like sysconfdir - local installdir = basedir:match("^(.*)/share/lua/[^/]*$") + local installdir = basedir:match("^(.*)[\\/]share[\\/]lua[\\/][^/]*$") if installdir then if installdir == "/usr" then return "/etc/luarocks" end - return installdir .. "/etc/luarocks" + return dir.path(installdir, "etc", "luarocks") end -- Otherwise, use base directory of sources return basedir @@ -186,9 +187,9 @@ local function make_defaults(lua_version, target_cpu, platforms, home) cache_timeout = 60, cache_fail_timeout = 86400, - lua_modules_path = "/share/lua/"..lua_version, - lib_modules_path = "/lib/lua/"..lua_version, - rocks_subdir = "/lib/luarocks/rocks-"..lua_version, + lua_modules_path = dir.path("share", "lua", lua_version), + lib_modules_path = dir.path("lib", "lua", lua_version), + rocks_subdir = dir.path("lib", "luarocks", "rocks-"..lua_version), arch = "unknown", lib_extension = "unknown", @@ -283,10 +284,14 @@ local function make_defaults(lua_version, target_cpu, platforms, home) defaults.external_lib_extension = "dll" defaults.static_lib_extension = "lib" defaults.obj_extension = "obj" - defaults.external_deps_dirs = { "c:/external/", "c:/windows/system32" } + defaults.external_deps_dirs = { + dir.path("c:", "external"), + dir.path("c:", "windows", "system32"), + } defaults.makefile = "Makefile.win" defaults.variables.PWD = "echo %cd%" + defaults.variables.MKDIR = "md" defaults.variables.MAKE = os.getenv("MAKE") or "nmake" defaults.variables.CC = os.getenv("CC") or "cl" defaults.variables.RC = os.getenv("WINDRES") or "rc" @@ -313,9 +318,9 @@ local function make_defaults(lua_version, target_cpu, platforms, home) local localappdata = os.getenv("LOCALAPPDATA") if not localappdata then -- for Windows versions below Vista - localappdata = (os.getenv("USERPROFILE") or "c:/Users/All Users").."/Local Settings/Application Data" + localappdata = dir.path((os.getenv("USERPROFILE") or dir.path("c:", "Users", "All Users")), "Local Settings", "Application Data") end - defaults.local_cache = localappdata.."/LuaRocks/Cache" + defaults.local_cache = dir.path(localappdata, "LuaRocks", "Cache") defaults.web_browser = "start" defaults.external_deps_subdirs.lib = { "lib", "", "bin" } @@ -327,7 +332,11 @@ local function make_defaults(lua_version, target_cpu, platforms, home) if platforms.mingw32 then defaults.obj_extension = "o" defaults.static_lib_extension = "a" - defaults.external_deps_dirs = { "c:/external/", "c:/mingw", "c:/windows/system32" } + defaults.external_deps_dirs = { + dir.path("c:", "external"), + dir.path("c:", "mingw"), + dir.path("c:", "windows", "system32"), + } defaults.cmake_generator = "MinGW Makefiles" defaults.variables.MAKE = os.getenv("MAKE") or "mingw32-make" if target_cpu == "x86_64" then @@ -431,10 +440,13 @@ local function make_defaults(lua_version, target_cpu, platforms, home) local pipe = io.popen("cygpath --windows %MINGW_PREFIX%") local mingw_prefix = pipe:read("*l") pipe:close() - defaults.external_deps_dirs = { mingw_prefix, "c:/windows/system32" } + defaults.external_deps_dirs = { + mingw_prefix, + dir.path("c:", "windows", "system32"), + } defaults.makefile = "Makefile" defaults.cmake_generator = "MSYS Makefiles" - defaults.local_cache = home.."/.cache/luarocks" + defaults.local_cache = dir.path(home, ".cache", "luarocks") defaults.variables.MAKE = os.getenv("MAKE") or "make" defaults.variables.CC = os.getenv("CC") or "gcc" defaults.variables.RC = os.getenv("WINDRES") or "windres" @@ -668,17 +680,17 @@ function cfg.init(detected, warning) local sysconfdir = os.getenv("LUAROCKS_SYSCONFDIR") or hardcoded.SYSCONFDIR if platforms.windows and not platforms.msys2_mingw_w64 then cfg.home = os.getenv("APPDATA") or "c:" - cfg.home_tree = cfg.home.."/luarocks" - cfg.sysconfdir = sysconfdir or ((os.getenv("PROGRAMFILES") or "c:") .. "/luarocks") + cfg.home_tree = dir.path(cfg.home, "luarocks") + cfg.sysconfdir = sysconfdir or dir.path((os.getenv("PROGRAMFILES") or "c:"), "luarocks") else cfg.home = os.getenv("HOME") or "" - cfg.home_tree = cfg.home.."/.luarocks" + cfg.home_tree = dir.path(cfg.home, ".luarocks") cfg.sysconfdir = sysconfdir or detect_sysconfdir() or "/etc/luarocks" end end -- Load system configuration file - sys_config_file = (cfg.sysconfdir .. "/" .. config_file_name):gsub("\\", "/") + sys_config_file = dir.path(cfg.sysconfdir, config_file_name) local sys_config_ok, err = load_config_file(cfg, platforms, sys_config_file) if err then exit_ok, exit_err, exit_what = nil, err, "config" @@ -710,9 +722,9 @@ function cfg.init(detected, warning) -- try XDG config home if platforms.unix and not home_config_ok then - local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or cfg.home .. "/.config" - cfg.homeconfdir = xdg_config_home .. "/luarocks" - home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/") + local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or dir.path(cfg.home, ".config") + cfg.homeconfdir = dir.path(xdg_config_home, "luarocks") + home_config_file = dir.path(cfg.homeconfdir, config_file_name) home_config_ok, err = load_config_file(cfg, platforms, home_config_file) if err then exit_ok, exit_err, exit_what = nil, err, "config" @@ -722,7 +734,7 @@ function cfg.init(detected, warning) -- try the alternative defaults if there was no environment specified file or it didn't work if not home_config_ok then cfg.homeconfdir = cfg.home_tree - home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/") + home_config_file = dir.path(cfg.homeconfdir, config_file_name) home_config_ok, err = load_config_file(cfg, platforms, home_config_file) if err then exit_ok, exit_err, exit_what = nil, err, "config" @@ -731,7 +743,7 @@ function cfg.init(detected, warning) -- finally, use the project-specific config file if any if cfg.project_dir then - project_config_file = cfg.project_dir .. "/.luarocks/" .. config_file_name + project_config_file = dir.path(cfg.project_dir, ".luarocks", config_file_name) project_config_ok, err = load_config_file(cfg, platforms, project_config_file) if err then exit_ok, exit_err, exit_what = nil, err, "config" @@ -741,7 +753,7 @@ function cfg.init(detected, warning) -- backwards compatibility: if cfg.lua_interpreter and cfg.variables.LUA_BINDIR and not cfg.variables.LUA then - cfg.variables.LUA = (cfg.variables.LUA_BINDIR .. "/" .. cfg.lua_interpreter):gsub("\\", "/") + cfg.variables.LUA = dir.path(cfg.variables.LUA_BINDIR, cfg.lua_interpreter) end ---------------------------------------- @@ -776,7 +788,7 @@ function cfg.init(detected, warning) if platforms.windows and hardcoded.WIN_TOOLS then local tools = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", "WGET", } for _, tool in ipairs(tools) do - defaults.variables[tool] = '"' .. hardcoded.WIN_TOOLS .. "/" .. defaults.variables[tool] .. '.exe"' + defaults.variables[tool] = '"' .. dir.path(hardcoded.WIN_TOOLS, defaults.variables[tool] .. '.exe') .. '"' end else defaults.fs_use_modules = true @@ -785,9 +797,9 @@ function cfg.init(detected, warning) -- if only cfg.variables.LUA is given in config files, -- derive LUA_BINDIR and LUA_DIR from them. if cfg.variables.LUA and not cfg.variables.LUA_BINDIR then - cfg.variables.LUA_BINDIR = cfg.variables.LUA:match("^(.*)[/\\][^/\\]*$") + cfg.variables.LUA_BINDIR = cfg.variables.LUA:match("^(.*)[\\/][^\\/]*$") if not cfg.variables.LUA_DIR then - cfg.variables.LUA_DIR = cfg.variables.LUA_BINDIR:gsub("[/\\]bin$", "") or cfg.variables.LUA_BINDIR + cfg.variables.LUA_DIR = cfg.variables.LUA_BINDIR:gsub("[\\/]bin$", "") or cfg.variables.LUA_BINDIR end end @@ -826,13 +838,13 @@ function cfg.init(detected, warning) local function make_paths_from_tree(tree) local lua_path, lib_path, bin_path if type(tree) == "string" then - lua_path = tree..cfg.lua_modules_path - lib_path = tree..cfg.lib_modules_path - bin_path = tree.."/bin" + lua_path = dir.path(tree, cfg.lua_modules_path) + lib_path = dir.path(tree, cfg.lib_modules_path) + bin_path = dir.path(tree, "bin") else - lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path - lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path - bin_path = tree.bin_dir or tree.root.."/bin" + lua_path = tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path) + lib_path = tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path) + bin_path = tree.bin_dir or dir.path(tree.root, "bin") end return lua_path, lib_path, bin_path end @@ -841,9 +853,9 @@ function cfg.init(detected, warning) local new_path, new_cpath, new_bin = {}, {}, {} local function add_tree_to_paths(tree) local lua_path, lib_path, bin_path = make_paths_from_tree(tree) - table.insert(new_path, lua_path.."/?.lua") - table.insert(new_path, lua_path.."/?/init.lua") - table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension) + table.insert(new_path, dir.path(lua_path, "?.lua")) + table.insert(new_path, dir.path(lua_path, "?", "init.lua")) + table.insert(new_cpath, dir.path(lib_path, "?."..cfg.lib_extension)) table.insert(new_bin, bin_path) end if current then diff --git a/src/luarocks/core/dir.lua b/src/luarocks/core/dir.lua index 46dbeafd..5d6f2c9f 100644 --- a/src/luarocks/core/dir.lua +++ b/src/luarocks/core/dir.lua @@ -4,6 +4,8 @@ local dir = {} local require = nil -------------------------------------------------------------------------------- +local dir_sep = package.config:sub(1, 1) + local function unquote(c) local first, last = c:sub(1,1), c:sub(-1) if (first == '"' and last == '"') or @@ -30,7 +32,7 @@ function dir.path(...) for i, c in ipairs(t) do t[i] = unquote(c) end - return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", "")) + return dir.normalize(table.concat(t, "/")) end --- Split protocol and path from an URL or local pathname. @@ -51,8 +53,9 @@ function dir.split_url(url) end --- Normalize a url or local path. --- URLs should be in the "protocol://path" format. System independent --- forward slashes are used, removing trailing and double slashes +-- URLs should be in the "protocol://path" format. +-- Removes trailing and double slashes, and '.' and '..' components. +-- for 'file' URLs, the native system's slashes are used. -- @param url string: an URL or a local pathname. -- @return string: Normalized result. function dir.normalize(name) @@ -83,7 +86,11 @@ function dir.normalize(name) else pathname = drive .. table.concat(pieces, "/") end - if protocol ~= "file" then pathname = protocol .."://"..pathname end + if protocol ~= "file" then + pathname = protocol .. "://" .. pathname + else + pathname = pathname:gsub("/", dir_sep) + end return pathname end diff --git a/src/luarocks/core/path.lua b/src/luarocks/core/path.lua index b354a41a..2f037b41 100644 --- a/src/luarocks/core/path.lua +++ b/src/luarocks/core/path.lua @@ -5,6 +5,8 @@ local path = {} local cfg = require("luarocks.core.cfg") local dir = require("luarocks.core.dir") local require = nil + +local dir_sep = package.config:sub(1, 1) -------------------------------------------------------------------------------- function path.rocks_dir(tree) @@ -26,10 +28,10 @@ end -- @return string: a pathname with the same directory parts and a versioned basename. function path.versioned_name(file, prefix, name, version) assert(type(file) == "string") - assert(type(name) == "string" and not name:match("/")) + assert(type(name) == "string" and not name:match(dir_sep)) assert(type(version) == "string") - local rest = file:sub(#prefix+1):gsub("^/*", "") + local rest = file:sub(#prefix+1):gsub("^" .. dir_sep .. "*", "") local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_") return dir.path(prefix, name_version.."-"..rest) end @@ -57,7 +59,7 @@ function path.path_to_module(file) for ext, _ in pairs(exts) do name = file:match("(.*)%." .. ext .. "$") if name then - name = name:gsub("[/\\]", ".") + name = name:gsub("[\\/]", ".") break end end diff --git a/src/luarocks/core/util.lua b/src/luarocks/core/util.lua index 26e78369..e9abdd34 100644 --- a/src/luarocks/core/util.lua +++ b/src/luarocks/core/util.lua @@ -4,6 +4,8 @@ local util = {} local require = nil -------------------------------------------------------------------------------- +local dir_sep = package.config:sub(1, 1) + --- Run a process and read a its output. -- Equivalent to io.popen(cmd):read("*l"), except that it -- closes the fd right away. @@ -12,7 +14,6 @@ local require = nil -- May be used to read more, passing, for instance, "*a". -- @return string: the output of the program. function util.popen_read(cmd, spec) - local dir_sep = package.config:sub(1, 1) local tmpfile = (dir_sep == "\\") and (os.getenv("TMP") .. "/luarocks-" .. tostring(math.floor(math.random() * 10000))) or os.tmpname() @@ -165,6 +166,9 @@ end function util.cleanup_path(list, sep, lua_version, keep_first) assert(type(list) == "string") assert(type(sep) == "string") + + list = list:gsub(dir_sep, "/") + local parts = util.split_string(list, sep) local final, entries = {}, {} local start, stop, step @@ -191,7 +195,7 @@ function util.cleanup_path(list, sep, lua_version, keep_first) end end - return table.concat(final, sep) + return (table.concat(final, sep):gsub("/", dir_sep)) end -- from http://lua-users.org/wiki/SplitJoin diff --git a/src/luarocks/dir.lua b/src/luarocks/dir.lua index 74adbea2..be89e37b 100644 --- a/src/luarocks/dir.lua +++ b/src/luarocks/dir.lua @@ -8,6 +8,8 @@ dir.path = core.path dir.split_url = core.split_url dir.normalize = core.normalize +local dir_sep = package.config:sub(1, 1) + --- Strip the path off a path+filename. -- @param pathname string: A path+name, such as "/a/b/c" -- or "\a\b\c". @@ -15,8 +17,13 @@ dir.normalize = core.normalize function dir.base_name(pathname) assert(type(pathname) == "string") - local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)") - return base or pathname + local b + b = pathname:gsub("[/\\]", "/") -- canonicalize to forward slashes + b = b:gsub("/*$", "") -- drop trailing slashes + b = b:match(".*[/\\]([^/\\]*)") -- match last component + b = b or pathname -- fallback to original if no slashes + + return b end --- Strip the name off a path+filename. @@ -26,7 +33,15 @@ end -- no directory separators in input, "" is returned. function dir.dir_name(pathname) assert(type(pathname) == "string") - return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or "" + + local d + d = pathname:gsub("[/\\]", "/") -- canonicalize to forward slashes + d = d:gsub("/*$", "") -- drop trailing slashes + d = d:match("(.*)[/]+[^/]*") -- match all components but the last + d = d or "" -- switch to "" if there's no match + d = d:gsub("/", dir_sep) -- decanonicalize to native slashes + + return d end --- Returns true if protocol does not require additional tools. diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua index f17a9279..373a998f 100644 --- a/src/luarocks/fetch.lua +++ b/src/luarocks/fetch.lua @@ -133,7 +133,7 @@ function fetch.fetch_url(url, filename, cache, mirroring) local protocol, pathname = dir.split_url(url) if protocol == "file" then - local fullname = dir.normalize(fs.absolute_name(pathname)) + local fullname = fs.absolute_name(pathname) if not fs.exists(fullname) then local hint = (not pathname:match("^/")) and (" - note that given path in rockspec is not absolute: " .. url) @@ -141,7 +141,7 @@ function fetch.fetch_url(url, filename, cache, mirroring) return nil, "Local file not found: " .. fullname .. hint end filename = filename or dir.base_name(pathname) - local dstname = dir.normalize(fs.absolute_name(dir.path(".", filename))) + local dstname = fs.absolute_name(dir.path(".", filename)) local ok, err if fullname == dstname then ok = true diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index 934bba48..29ffb255 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -28,6 +28,8 @@ end local patch = require("luarocks.tools.patch") local tar = require("luarocks.tools.tar") +local dir_sep = package.config:sub(1, 1) + local dir_stack = {} --- Test is file/dir is writable. @@ -277,6 +279,11 @@ function fs_lua.system_temp_dir() return os.getenv("TMPDIR") or os.getenv("TEMP") or "/tmp" end +local function temp_dir_pattern(name_pattern) + return dir.path(fs.system_temp_dir(), + "luarocks_" .. dir.normalize(name_pattern):gsub("[/\\]", "_") .. "-") +end + --------------------------------------------------------------------- -- LuaFileSystem functions --------------------------------------------------------------------- @@ -361,12 +368,12 @@ function fs_lua.make_dir(directory) path = directory:sub(1, 2) directory = directory:sub(4) else - if directory:match("^/") then + if directory:match("^" .. dir_sep) then path = "" end end - for d in directory:gmatch("([^/]+)/*") do - path = path and path .. "/" .. d or d + for d in directory:gmatch("([^" .. dir_sep .. "]+)" .. dir_sep .. "*") do + path = path and path .. dir_sep .. d or d local mode = lfs.attributes(path, "mode") if not mode then local ok, err = lfs.mkdir(path) @@ -504,7 +511,8 @@ end -- @return boolean or (boolean, string): true on success, false on failure, -- plus an error message. function fs_lua.copy_contents(src, dest, perms) - assert(src and dest) + assert(src) + assert(dest) src = dir.normalize(src) dest = dir.normalize(dest) if not fs.is_dir(src) then @@ -589,7 +597,7 @@ local function recursive_find(cwd, prefix, result) table.insert(result, item) local pathname = dir.path(cwd, file) if lfs.attributes(pathname, "mode") == "directory" then - recursive_find(pathname, item.."/", result) + recursive_find(pathname, item .. dir_sep, result) end end end @@ -656,9 +664,8 @@ else -- if not lfs_ok function fs_lua.exists(file) assert(file) - file = dir.normalize(fs.absolute_name(file)) -- check if file exists by attempting to open it - return util.exists(file) + return util.exists(fs.absolute_name(file)) end end @@ -1072,9 +1079,8 @@ if posix.mkdtemp then -- @return string or (nil, string): name of temporary directory or (nil, error message) on failure. function fs_lua.make_temp_dir(name_pattern) assert(type(name_pattern) == "string") - name_pattern = dir.normalize(name_pattern) - return posix.mkdtemp(fs.system_temp_dir() .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-XXXXXX") + return posix.mkdtemp(temp_dir_pattern(name_pattern) .. "-XXXXXX") end end -- if posix.mkdtemp @@ -1085,20 +1091,21 @@ end -- Other functions --------------------------------------------------------------------- -if lfs_ok and not fs_lua.make_temp_dir then +if not fs_lua.make_temp_dir then function fs_lua.make_temp_dir(name_pattern) assert(type(name_pattern) == "string") - name_pattern = dir.normalize(name_pattern) - - local pattern = fs.system_temp_dir() .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-" - while true do - local name = pattern .. tostring(math.random(10000000)) - if lfs.mkdir(name) then + local ok, err + for _ = 1, 3 do + local name = temp_dir_pattern(name_pattern) .. tostring(math.random(10000000)) + ok, err = fs.make_dir(name) + if ok then return name end end + + return nil, err end end diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index 6bc183cb..f5f3b349 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua @@ -47,11 +47,11 @@ function unix.absolute_name(pathname, relative_to) pathname = unquoted end - relative_to = (relative_to or fs.current_dir()):gsub("/*$", "") + relative_to = relative_to or fs.current_dir() if pathname:sub(1,1) == "/" then - return pathname + return dir.normalize(pathname) else - return relative_to .. "/" .. pathname + return dir.path(relative_to, pathname) end end diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index 879f3e76..09ce7290 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua @@ -133,11 +133,11 @@ function win32.absolute_name(pathname, relative_to) local drive, root, rest = split_root(pathname) if root:match("[\\/]$") then -- It's an absolute path already. Ensure is not quoted. - return drive .. root .. rest + return dir.normalize(drive .. root .. rest) else -- It's a relative path, join it with base path. -- This drops drive letter from paths like "C:foo". - return relative_to .. "/" .. rest + return dir.path(relative_to, rest) end end @@ -237,7 +237,7 @@ function win32.copy_binary(filename, dest) dest = dir.dir_name(dest) if base:match(exe_pattern) then base = base:gsub(exe_pattern, ".lua") - local helpname = dest.."/"..base + local helpname = dest.."\\"..base local helper = io.open(helpname, "w") if not helper then return nil, "Could not open "..helpname.." for writing." @@ -331,23 +331,6 @@ function win32.is_writable(file) return result end ---- Create a temporary directory. --- @param name_pattern string: name pattern to use for avoiding conflicts --- when creating temporary directory. --- @return string or (nil, string): name of temporary directory or (nil, error message) on failure. -function win32.make_temp_dir(name_pattern) - assert(type(name_pattern) == "string") - name_pattern = dir.normalize(name_pattern) - - local temp_dir = os.getenv("TMP") .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-" .. tostring(math.floor(math.random() * 10000)) - local ok, err = fs.make_dir(temp_dir) - if ok then - return temp_dir - else - return nil, err - end -end - function win32.tmpname() local name = os.tmpname() local tmp = os.getenv("TMP") -- cgit v1.2.3-55-g6feb