aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2024-02-20 13:43:44 -0300
committerHisham Muhammad <hisham@gobolinux.org>2024-02-23 20:47:09 -0300
commit2c4ff5240bf298fec07749f5984de2f08b8736ec (patch)
treef0b4dfec401fa1a132fc5786467fb8683d17bdcb /src
parent79bd1739d8ca004ddd0b2fa5e24da4a6f4b776fa (diff)
downloadluarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.tar.gz
luarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.tar.bz2
luarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.zip
fix: better normalization for paths and slashes
Fixes #1195.
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/admin/cache.lua2
-rw-r--r--src/luarocks/cmd/doc.lua2
-rw-r--r--src/luarocks/cmd/init.lua4
-rw-r--r--src/luarocks/core/cfg.lua82
-rw-r--r--src/luarocks/core/dir.lua15
-rw-r--r--src/luarocks/core/path.lua8
-rw-r--r--src/luarocks/core/util.lua8
-rw-r--r--src/luarocks/dir.lua21
-rw-r--r--src/luarocks/fetch.lua4
-rw-r--r--src/luarocks/fs/lua.lua39
-rw-r--r--src/luarocks/fs/unix.lua6
-rw-r--r--src/luarocks/fs/win32.lua23
12 files changed, 122 insertions, 92 deletions
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)
45 user = credentials 45 user = credentials
46 end 46 end
47 end 47 end
48 local local_cache = cfg.local_cache .. "/" .. server_path:gsub("[\\/]", "_") 48 local local_cache = dir.path(cfg.local_cache, (server_path:gsub("[\\/]", "_")))
49 return local_cache, protocol, server_path, user, password 49 return local_cache, protocol, server_path, user, password
50end 50end
51 51
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)
96 return nil, "Documentation directory not found for "..name.." "..version 96 return nil, "Documentation directory not found for "..name.." "..version
97 end 97 end
98 98
99 docdir = dir.normalize(docdir):gsub("/+", "/") 99 docdir = dir.normalize(docdir)
100 local files = fs.find(docdir) 100 local files = fs.find(docdir)
101 local htmlpatt = "%.html?$" 101 local htmlpatt = "%.html?$"
102 local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" } 102 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)
27end 27end
28 28
29local function gitignore_path(pwd, wrapper_dir, filename) 29local function gitignore_path(pwd, wrapper_dir, filename)
30 local norm_cur = dir.normalize(fs.absolute_name(pwd)) 30 local norm_cur = fs.absolute_name(pwd)
31 local norm_file = dir.normalize(fs.absolute_name(dir.path(wrapper_dir, filename))) 31 local norm_file = fs.absolute_name(dir.path(wrapper_dir, filename))
32 if norm_file:sub(1, #norm_cur) == norm_cur then 32 if norm_file:sub(1, #norm_cur) == norm_cur then
33 return norm_file:sub(#norm_cur + 2) 33 return norm_file:sub(#norm_cur + 2)
34 else 34 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 @@
13local table, pairs, require, os, pcall, ipairs, package, type, assert = 13local table, pairs, require, os, pcall, ipairs, package, type, assert =
14 table, pairs, require, os, pcall, ipairs, package, type, assert 14 table, pairs, require, os, pcall, ipairs, package, type, assert
15 15
16local dir = require("luarocks.core.dir")
16local util = require("luarocks.core.util") 17local util = require("luarocks.core.util")
17local persist = require("luarocks.core.persist") 18local persist = require("luarocks.core.persist")
18local sysdetect = require("luarocks.core.sysdetect") 19local sysdetect = require("luarocks.core.sysdetect")
@@ -53,21 +54,21 @@ local function detect_sysconfdir()
53 if not debug then 54 if not debug then
54 return 55 return
55 end 56 end
56 local src = debug.getinfo(1, "S").source:gsub("\\", "/"):gsub("/+", "/") 57 local src = dir.normalize(debug.getinfo(1, "S"))
57 if src:sub(1, 1) == "@" then 58 if src:sub(1, 1) == "@" then
58 src = src:sub(2) 59 src = src:sub(2)
59 end 60 end
60 local basedir = src:match("^(.*)/luarocks/core/cfg.lua$") 61 local basedir = src:match("^(.*)[\\/]luarocks[\\/]core[\\/]cfg.lua$")
61 if not basedir then 62 if not basedir then
62 return 63 return
63 end 64 end
64 -- If installed in a Unix-like tree, use a Unix-like sysconfdir 65 -- If installed in a Unix-like tree, use a Unix-like sysconfdir
65 local installdir = basedir:match("^(.*)/share/lua/[^/]*$") 66 local installdir = basedir:match("^(.*)[\\/]share[\\/]lua[\\/][^/]*$")
66 if installdir then 67 if installdir then
67 if installdir == "/usr" then 68 if installdir == "/usr" then
68 return "/etc/luarocks" 69 return "/etc/luarocks"
69 end 70 end
70 return installdir .. "/etc/luarocks" 71 return dir.path(installdir, "etc", "luarocks")
71 end 72 end
72 -- Otherwise, use base directory of sources 73 -- Otherwise, use base directory of sources
73 return basedir 74 return basedir
@@ -186,9 +187,9 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
186 cache_timeout = 60, 187 cache_timeout = 60,
187 cache_fail_timeout = 86400, 188 cache_fail_timeout = 86400,
188 189
189 lua_modules_path = "/share/lua/"..lua_version, 190 lua_modules_path = dir.path("share", "lua", lua_version),
190 lib_modules_path = "/lib/lua/"..lua_version, 191 lib_modules_path = dir.path("lib", "lua", lua_version),
191 rocks_subdir = "/lib/luarocks/rocks-"..lua_version, 192 rocks_subdir = dir.path("lib", "luarocks", "rocks-"..lua_version),
192 193
193 arch = "unknown", 194 arch = "unknown",
194 lib_extension = "unknown", 195 lib_extension = "unknown",
@@ -283,10 +284,14 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
283 defaults.external_lib_extension = "dll" 284 defaults.external_lib_extension = "dll"
284 defaults.static_lib_extension = "lib" 285 defaults.static_lib_extension = "lib"
285 defaults.obj_extension = "obj" 286 defaults.obj_extension = "obj"
286 defaults.external_deps_dirs = { "c:/external/", "c:/windows/system32" } 287 defaults.external_deps_dirs = {
288 dir.path("c:", "external"),
289 dir.path("c:", "windows", "system32"),
290 }
287 291
288 defaults.makefile = "Makefile.win" 292 defaults.makefile = "Makefile.win"
289 defaults.variables.PWD = "echo %cd%" 293 defaults.variables.PWD = "echo %cd%"
294 defaults.variables.MKDIR = "md"
290 defaults.variables.MAKE = os.getenv("MAKE") or "nmake" 295 defaults.variables.MAKE = os.getenv("MAKE") or "nmake"
291 defaults.variables.CC = os.getenv("CC") or "cl" 296 defaults.variables.CC = os.getenv("CC") or "cl"
292 defaults.variables.RC = os.getenv("WINDRES") or "rc" 297 defaults.variables.RC = os.getenv("WINDRES") or "rc"
@@ -313,9 +318,9 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
313 local localappdata = os.getenv("LOCALAPPDATA") 318 local localappdata = os.getenv("LOCALAPPDATA")
314 if not localappdata then 319 if not localappdata then
315 -- for Windows versions below Vista 320 -- for Windows versions below Vista
316 localappdata = (os.getenv("USERPROFILE") or "c:/Users/All Users").."/Local Settings/Application Data" 321 localappdata = dir.path((os.getenv("USERPROFILE") or dir.path("c:", "Users", "All Users")), "Local Settings", "Application Data")
317 end 322 end
318 defaults.local_cache = localappdata.."/LuaRocks/Cache" 323 defaults.local_cache = dir.path(localappdata, "LuaRocks", "Cache")
319 defaults.web_browser = "start" 324 defaults.web_browser = "start"
320 325
321 defaults.external_deps_subdirs.lib = { "lib", "", "bin" } 326 defaults.external_deps_subdirs.lib = { "lib", "", "bin" }
@@ -327,7 +332,11 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
327 if platforms.mingw32 then 332 if platforms.mingw32 then
328 defaults.obj_extension = "o" 333 defaults.obj_extension = "o"
329 defaults.static_lib_extension = "a" 334 defaults.static_lib_extension = "a"
330 defaults.external_deps_dirs = { "c:/external/", "c:/mingw", "c:/windows/system32" } 335 defaults.external_deps_dirs = {
336 dir.path("c:", "external"),
337 dir.path("c:", "mingw"),
338 dir.path("c:", "windows", "system32"),
339 }
331 defaults.cmake_generator = "MinGW Makefiles" 340 defaults.cmake_generator = "MinGW Makefiles"
332 defaults.variables.MAKE = os.getenv("MAKE") or "mingw32-make" 341 defaults.variables.MAKE = os.getenv("MAKE") or "mingw32-make"
333 if target_cpu == "x86_64" then 342 if target_cpu == "x86_64" then
@@ -431,10 +440,13 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
431 local pipe = io.popen("cygpath --windows %MINGW_PREFIX%") 440 local pipe = io.popen("cygpath --windows %MINGW_PREFIX%")
432 local mingw_prefix = pipe:read("*l") 441 local mingw_prefix = pipe:read("*l")
433 pipe:close() 442 pipe:close()
434 defaults.external_deps_dirs = { mingw_prefix, "c:/windows/system32" } 443 defaults.external_deps_dirs = {
444 mingw_prefix,
445 dir.path("c:", "windows", "system32"),
446 }
435 defaults.makefile = "Makefile" 447 defaults.makefile = "Makefile"
436 defaults.cmake_generator = "MSYS Makefiles" 448 defaults.cmake_generator = "MSYS Makefiles"
437 defaults.local_cache = home.."/.cache/luarocks" 449 defaults.local_cache = dir.path(home, ".cache", "luarocks")
438 defaults.variables.MAKE = os.getenv("MAKE") or "make" 450 defaults.variables.MAKE = os.getenv("MAKE") or "make"
439 defaults.variables.CC = os.getenv("CC") or "gcc" 451 defaults.variables.CC = os.getenv("CC") or "gcc"
440 defaults.variables.RC = os.getenv("WINDRES") or "windres" 452 defaults.variables.RC = os.getenv("WINDRES") or "windres"
@@ -668,17 +680,17 @@ function cfg.init(detected, warning)
668 local sysconfdir = os.getenv("LUAROCKS_SYSCONFDIR") or hardcoded.SYSCONFDIR 680 local sysconfdir = os.getenv("LUAROCKS_SYSCONFDIR") or hardcoded.SYSCONFDIR
669 if platforms.windows and not platforms.msys2_mingw_w64 then 681 if platforms.windows and not platforms.msys2_mingw_w64 then
670 cfg.home = os.getenv("APPDATA") or "c:" 682 cfg.home = os.getenv("APPDATA") or "c:"
671 cfg.home_tree = cfg.home.."/luarocks" 683 cfg.home_tree = dir.path(cfg.home, "luarocks")
672 cfg.sysconfdir = sysconfdir or ((os.getenv("PROGRAMFILES") or "c:") .. "/luarocks") 684 cfg.sysconfdir = sysconfdir or dir.path((os.getenv("PROGRAMFILES") or "c:"), "luarocks")
673 else 685 else
674 cfg.home = os.getenv("HOME") or "" 686 cfg.home = os.getenv("HOME") or ""
675 cfg.home_tree = cfg.home.."/.luarocks" 687 cfg.home_tree = dir.path(cfg.home, ".luarocks")
676 cfg.sysconfdir = sysconfdir or detect_sysconfdir() or "/etc/luarocks" 688 cfg.sysconfdir = sysconfdir or detect_sysconfdir() or "/etc/luarocks"
677 end 689 end
678 end 690 end
679 691
680 -- Load system configuration file 692 -- Load system configuration file
681 sys_config_file = (cfg.sysconfdir .. "/" .. config_file_name):gsub("\\", "/") 693 sys_config_file = dir.path(cfg.sysconfdir, config_file_name)
682 local sys_config_ok, err = load_config_file(cfg, platforms, sys_config_file) 694 local sys_config_ok, err = load_config_file(cfg, platforms, sys_config_file)
683 if err then 695 if err then
684 exit_ok, exit_err, exit_what = nil, err, "config" 696 exit_ok, exit_err, exit_what = nil, err, "config"
@@ -710,9 +722,9 @@ function cfg.init(detected, warning)
710 722
711 -- try XDG config home 723 -- try XDG config home
712 if platforms.unix and not home_config_ok then 724 if platforms.unix and not home_config_ok then
713 local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or cfg.home .. "/.config" 725 local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or dir.path(cfg.home, ".config")
714 cfg.homeconfdir = xdg_config_home .. "/luarocks" 726 cfg.homeconfdir = dir.path(xdg_config_home, "luarocks")
715 home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/") 727 home_config_file = dir.path(cfg.homeconfdir, config_file_name)
716 home_config_ok, err = load_config_file(cfg, platforms, home_config_file) 728 home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
717 if err then 729 if err then
718 exit_ok, exit_err, exit_what = nil, err, "config" 730 exit_ok, exit_err, exit_what = nil, err, "config"
@@ -722,7 +734,7 @@ function cfg.init(detected, warning)
722 -- try the alternative defaults if there was no environment specified file or it didn't work 734 -- try the alternative defaults if there was no environment specified file or it didn't work
723 if not home_config_ok then 735 if not home_config_ok then
724 cfg.homeconfdir = cfg.home_tree 736 cfg.homeconfdir = cfg.home_tree
725 home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/") 737 home_config_file = dir.path(cfg.homeconfdir, config_file_name)
726 home_config_ok, err = load_config_file(cfg, platforms, home_config_file) 738 home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
727 if err then 739 if err then
728 exit_ok, exit_err, exit_what = nil, err, "config" 740 exit_ok, exit_err, exit_what = nil, err, "config"
@@ -731,7 +743,7 @@ function cfg.init(detected, warning)
731 743
732 -- finally, use the project-specific config file if any 744 -- finally, use the project-specific config file if any
733 if cfg.project_dir then 745 if cfg.project_dir then
734 project_config_file = cfg.project_dir .. "/.luarocks/" .. config_file_name 746 project_config_file = dir.path(cfg.project_dir, ".luarocks", config_file_name)
735 project_config_ok, err = load_config_file(cfg, platforms, project_config_file) 747 project_config_ok, err = load_config_file(cfg, platforms, project_config_file)
736 if err then 748 if err then
737 exit_ok, exit_err, exit_what = nil, err, "config" 749 exit_ok, exit_err, exit_what = nil, err, "config"
@@ -741,7 +753,7 @@ function cfg.init(detected, warning)
741 753
742 -- backwards compatibility: 754 -- backwards compatibility:
743 if cfg.lua_interpreter and cfg.variables.LUA_BINDIR and not cfg.variables.LUA then 755 if cfg.lua_interpreter and cfg.variables.LUA_BINDIR and not cfg.variables.LUA then
744 cfg.variables.LUA = (cfg.variables.LUA_BINDIR .. "/" .. cfg.lua_interpreter):gsub("\\", "/") 756 cfg.variables.LUA = dir.path(cfg.variables.LUA_BINDIR, cfg.lua_interpreter)
745 end 757 end
746 758
747 ---------------------------------------- 759 ----------------------------------------
@@ -776,7 +788,7 @@ function cfg.init(detected, warning)
776 if platforms.windows and hardcoded.WIN_TOOLS then 788 if platforms.windows and hardcoded.WIN_TOOLS then
777 local tools = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", "WGET", } 789 local tools = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", "WGET", }
778 for _, tool in ipairs(tools) do 790 for _, tool in ipairs(tools) do
779 defaults.variables[tool] = '"' .. hardcoded.WIN_TOOLS .. "/" .. defaults.variables[tool] .. '.exe"' 791 defaults.variables[tool] = '"' .. dir.path(hardcoded.WIN_TOOLS, defaults.variables[tool] .. '.exe') .. '"'
780 end 792 end
781 else 793 else
782 defaults.fs_use_modules = true 794 defaults.fs_use_modules = true
@@ -785,9 +797,9 @@ function cfg.init(detected, warning)
785 -- if only cfg.variables.LUA is given in config files, 797 -- if only cfg.variables.LUA is given in config files,
786 -- derive LUA_BINDIR and LUA_DIR from them. 798 -- derive LUA_BINDIR and LUA_DIR from them.
787 if cfg.variables.LUA and not cfg.variables.LUA_BINDIR then 799 if cfg.variables.LUA and not cfg.variables.LUA_BINDIR then
788 cfg.variables.LUA_BINDIR = cfg.variables.LUA:match("^(.*)[/\\][^/\\]*$") 800 cfg.variables.LUA_BINDIR = cfg.variables.LUA:match("^(.*)[\\/][^\\/]*$")
789 if not cfg.variables.LUA_DIR then 801 if not cfg.variables.LUA_DIR then
790 cfg.variables.LUA_DIR = cfg.variables.LUA_BINDIR:gsub("[/\\]bin$", "") or cfg.variables.LUA_BINDIR 802 cfg.variables.LUA_DIR = cfg.variables.LUA_BINDIR:gsub("[\\/]bin$", "") or cfg.variables.LUA_BINDIR
791 end 803 end
792 end 804 end
793 805
@@ -826,13 +838,13 @@ function cfg.init(detected, warning)
826 local function make_paths_from_tree(tree) 838 local function make_paths_from_tree(tree)
827 local lua_path, lib_path, bin_path 839 local lua_path, lib_path, bin_path
828 if type(tree) == "string" then 840 if type(tree) == "string" then
829 lua_path = tree..cfg.lua_modules_path 841 lua_path = dir.path(tree, cfg.lua_modules_path)
830 lib_path = tree..cfg.lib_modules_path 842 lib_path = dir.path(tree, cfg.lib_modules_path)
831 bin_path = tree.."/bin" 843 bin_path = dir.path(tree, "bin")
832 else 844 else
833 lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path 845 lua_path = tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path)
834 lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path 846 lib_path = tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path)
835 bin_path = tree.bin_dir or tree.root.."/bin" 847 bin_path = tree.bin_dir or dir.path(tree.root, "bin")
836 end 848 end
837 return lua_path, lib_path, bin_path 849 return lua_path, lib_path, bin_path
838 end 850 end
@@ -841,9 +853,9 @@ function cfg.init(detected, warning)
841 local new_path, new_cpath, new_bin = {}, {}, {} 853 local new_path, new_cpath, new_bin = {}, {}, {}
842 local function add_tree_to_paths(tree) 854 local function add_tree_to_paths(tree)
843 local lua_path, lib_path, bin_path = make_paths_from_tree(tree) 855 local lua_path, lib_path, bin_path = make_paths_from_tree(tree)
844 table.insert(new_path, lua_path.."/?.lua") 856 table.insert(new_path, dir.path(lua_path, "?.lua"))
845 table.insert(new_path, lua_path.."/?/init.lua") 857 table.insert(new_path, dir.path(lua_path, "?", "init.lua"))
846 table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension) 858 table.insert(new_cpath, dir.path(lib_path, "?."..cfg.lib_extension))
847 table.insert(new_bin, bin_path) 859 table.insert(new_bin, bin_path)
848 end 860 end
849 if current then 861 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 = {}
4local require = nil 4local require = nil
5-------------------------------------------------------------------------------- 5--------------------------------------------------------------------------------
6 6
7local dir_sep = package.config:sub(1, 1)
8
7local function unquote(c) 9local function unquote(c)
8 local first, last = c:sub(1,1), c:sub(-1) 10 local first, last = c:sub(1,1), c:sub(-1)
9 if (first == '"' and last == '"') or 11 if (first == '"' and last == '"') or
@@ -30,7 +32,7 @@ function dir.path(...)
30 for i, c in ipairs(t) do 32 for i, c in ipairs(t) do
31 t[i] = unquote(c) 33 t[i] = unquote(c)
32 end 34 end
33 return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", "")) 35 return dir.normalize(table.concat(t, "/"))
34end 36end
35 37
36--- Split protocol and path from an URL or local pathname. 38--- Split protocol and path from an URL or local pathname.
@@ -51,8 +53,9 @@ function dir.split_url(url)
51end 53end
52 54
53--- Normalize a url or local path. 55--- Normalize a url or local path.
54-- URLs should be in the "protocol://path" format. System independent 56-- URLs should be in the "protocol://path" format.
55-- forward slashes are used, removing trailing and double slashes 57-- Removes trailing and double slashes, and '.' and '..' components.
58-- for 'file' URLs, the native system's slashes are used.
56-- @param url string: an URL or a local pathname. 59-- @param url string: an URL or a local pathname.
57-- @return string: Normalized result. 60-- @return string: Normalized result.
58function dir.normalize(name) 61function dir.normalize(name)
@@ -83,7 +86,11 @@ function dir.normalize(name)
83 else 86 else
84 pathname = drive .. table.concat(pieces, "/") 87 pathname = drive .. table.concat(pieces, "/")
85 end 88 end
86 if protocol ~= "file" then pathname = protocol .."://"..pathname end 89 if protocol ~= "file" then
90 pathname = protocol .. "://" .. pathname
91 else
92 pathname = pathname:gsub("/", dir_sep)
93 end
87 return pathname 94 return pathname
88end 95end
89 96
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 = {}
5local cfg = require("luarocks.core.cfg") 5local cfg = require("luarocks.core.cfg")
6local dir = require("luarocks.core.dir") 6local dir = require("luarocks.core.dir")
7local require = nil 7local require = nil
8
9local dir_sep = package.config:sub(1, 1)
8-------------------------------------------------------------------------------- 10--------------------------------------------------------------------------------
9 11
10function path.rocks_dir(tree) 12function path.rocks_dir(tree)
@@ -26,10 +28,10 @@ end
26-- @return string: a pathname with the same directory parts and a versioned basename. 28-- @return string: a pathname with the same directory parts and a versioned basename.
27function path.versioned_name(file, prefix, name, version) 29function path.versioned_name(file, prefix, name, version)
28 assert(type(file) == "string") 30 assert(type(file) == "string")
29 assert(type(name) == "string" and not name:match("/")) 31 assert(type(name) == "string" and not name:match(dir_sep))
30 assert(type(version) == "string") 32 assert(type(version) == "string")
31 33
32 local rest = file:sub(#prefix+1):gsub("^/*", "") 34 local rest = file:sub(#prefix+1):gsub("^" .. dir_sep .. "*", "")
33 local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_") 35 local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_")
34 return dir.path(prefix, name_version.."-"..rest) 36 return dir.path(prefix, name_version.."-"..rest)
35end 37end
@@ -57,7 +59,7 @@ function path.path_to_module(file)
57 for ext, _ in pairs(exts) do 59 for ext, _ in pairs(exts) do
58 name = file:match("(.*)%." .. ext .. "$") 60 name = file:match("(.*)%." .. ext .. "$")
59 if name then 61 if name then
60 name = name:gsub("[/\\]", ".") 62 name = name:gsub("[\\/]", ".")
61 break 63 break
62 end 64 end
63 end 65 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 = {}
4local require = nil 4local require = nil
5-------------------------------------------------------------------------------- 5--------------------------------------------------------------------------------
6 6
7local dir_sep = package.config:sub(1, 1)
8
7--- Run a process and read a its output. 9--- Run a process and read a its output.
8-- Equivalent to io.popen(cmd):read("*l"), except that it 10-- Equivalent to io.popen(cmd):read("*l"), except that it
9-- closes the fd right away. 11-- closes the fd right away.
@@ -12,7 +14,6 @@ local require = nil
12-- May be used to read more, passing, for instance, "*a". 14-- May be used to read more, passing, for instance, "*a".
13-- @return string: the output of the program. 15-- @return string: the output of the program.
14function util.popen_read(cmd, spec) 16function util.popen_read(cmd, spec)
15 local dir_sep = package.config:sub(1, 1)
16 local tmpfile = (dir_sep == "\\") 17 local tmpfile = (dir_sep == "\\")
17 and (os.getenv("TMP") .. "/luarocks-" .. tostring(math.floor(math.random() * 10000))) 18 and (os.getenv("TMP") .. "/luarocks-" .. tostring(math.floor(math.random() * 10000)))
18 or os.tmpname() 19 or os.tmpname()
@@ -165,6 +166,9 @@ end
165function util.cleanup_path(list, sep, lua_version, keep_first) 166function util.cleanup_path(list, sep, lua_version, keep_first)
166 assert(type(list) == "string") 167 assert(type(list) == "string")
167 assert(type(sep) == "string") 168 assert(type(sep) == "string")
169
170 list = list:gsub(dir_sep, "/")
171
168 local parts = util.split_string(list, sep) 172 local parts = util.split_string(list, sep)
169 local final, entries = {}, {} 173 local final, entries = {}, {}
170 local start, stop, step 174 local start, stop, step
@@ -191,7 +195,7 @@ function util.cleanup_path(list, sep, lua_version, keep_first)
191 end 195 end
192 end 196 end
193 197
194 return table.concat(final, sep) 198 return (table.concat(final, sep):gsub("/", dir_sep))
195end 199end
196 200
197-- from http://lua-users.org/wiki/SplitJoin 201-- 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
8dir.split_url = core.split_url 8dir.split_url = core.split_url
9dir.normalize = core.normalize 9dir.normalize = core.normalize
10 10
11local dir_sep = package.config:sub(1, 1)
12
11--- Strip the path off a path+filename. 13--- Strip the path off a path+filename.
12-- @param pathname string: A path+name, such as "/a/b/c" 14-- @param pathname string: A path+name, such as "/a/b/c"
13-- or "\a\b\c". 15-- or "\a\b\c".
@@ -15,8 +17,13 @@ dir.normalize = core.normalize
15function dir.base_name(pathname) 17function dir.base_name(pathname)
16 assert(type(pathname) == "string") 18 assert(type(pathname) == "string")
17 19
18 local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)") 20 local b
19 return base or pathname 21 b = pathname:gsub("[/\\]", "/") -- canonicalize to forward slashes
22 b = b:gsub("/*$", "") -- drop trailing slashes
23 b = b:match(".*[/\\]([^/\\]*)") -- match last component
24 b = b or pathname -- fallback to original if no slashes
25
26 return b
20end 27end
21 28
22--- Strip the name off a path+filename. 29--- Strip the name off a path+filename.
@@ -26,7 +33,15 @@ end
26-- no directory separators in input, "" is returned. 33-- no directory separators in input, "" is returned.
27function dir.dir_name(pathname) 34function dir.dir_name(pathname)
28 assert(type(pathname) == "string") 35 assert(type(pathname) == "string")
29 return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or "" 36
37 local d
38 d = pathname:gsub("[/\\]", "/") -- canonicalize to forward slashes
39 d = d:gsub("/*$", "") -- drop trailing slashes
40 d = d:match("(.*)[/]+[^/]*") -- match all components but the last
41 d = d or "" -- switch to "" if there's no match
42 d = d:gsub("/", dir_sep) -- decanonicalize to native slashes
43
44 return d
30end 45end
31 46
32--- Returns true if protocol does not require additional tools. 47--- 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)
133 133
134 local protocol, pathname = dir.split_url(url) 134 local protocol, pathname = dir.split_url(url)
135 if protocol == "file" then 135 if protocol == "file" then
136 local fullname = dir.normalize(fs.absolute_name(pathname)) 136 local fullname = fs.absolute_name(pathname)
137 if not fs.exists(fullname) then 137 if not fs.exists(fullname) then
138 local hint = (not pathname:match("^/")) 138 local hint = (not pathname:match("^/"))
139 and (" - note that given path in rockspec is not absolute: " .. url) 139 and (" - note that given path in rockspec is not absolute: " .. url)
@@ -141,7 +141,7 @@ function fetch.fetch_url(url, filename, cache, mirroring)
141 return nil, "Local file not found: " .. fullname .. hint 141 return nil, "Local file not found: " .. fullname .. hint
142 end 142 end
143 filename = filename or dir.base_name(pathname) 143 filename = filename or dir.base_name(pathname)
144 local dstname = dir.normalize(fs.absolute_name(dir.path(".", filename))) 144 local dstname = fs.absolute_name(dir.path(".", filename))
145 local ok, err 145 local ok, err
146 if fullname == dstname then 146 if fullname == dstname then
147 ok = true 147 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
28local patch = require("luarocks.tools.patch") 28local patch = require("luarocks.tools.patch")
29local tar = require("luarocks.tools.tar") 29local tar = require("luarocks.tools.tar")
30 30
31local dir_sep = package.config:sub(1, 1)
32
31local dir_stack = {} 33local dir_stack = {}
32 34
33--- Test is file/dir is writable. 35--- Test is file/dir is writable.
@@ -277,6 +279,11 @@ function fs_lua.system_temp_dir()
277 return os.getenv("TMPDIR") or os.getenv("TEMP") or "/tmp" 279 return os.getenv("TMPDIR") or os.getenv("TEMP") or "/tmp"
278end 280end
279 281
282local function temp_dir_pattern(name_pattern)
283 return dir.path(fs.system_temp_dir(),
284 "luarocks_" .. dir.normalize(name_pattern):gsub("[/\\]", "_") .. "-")
285end
286
280--------------------------------------------------------------------- 287---------------------------------------------------------------------
281-- LuaFileSystem functions 288-- LuaFileSystem functions
282--------------------------------------------------------------------- 289---------------------------------------------------------------------
@@ -361,12 +368,12 @@ function fs_lua.make_dir(directory)
361 path = directory:sub(1, 2) 368 path = directory:sub(1, 2)
362 directory = directory:sub(4) 369 directory = directory:sub(4)
363 else 370 else
364 if directory:match("^/") then 371 if directory:match("^" .. dir_sep) then
365 path = "" 372 path = ""
366 end 373 end
367 end 374 end
368 for d in directory:gmatch("([^/]+)/*") do 375 for d in directory:gmatch("([^" .. dir_sep .. "]+)" .. dir_sep .. "*") do
369 path = path and path .. "/" .. d or d 376 path = path and path .. dir_sep .. d or d
370 local mode = lfs.attributes(path, "mode") 377 local mode = lfs.attributes(path, "mode")
371 if not mode then 378 if not mode then
372 local ok, err = lfs.mkdir(path) 379 local ok, err = lfs.mkdir(path)
@@ -504,7 +511,8 @@ end
504-- @return boolean or (boolean, string): true on success, false on failure, 511-- @return boolean or (boolean, string): true on success, false on failure,
505-- plus an error message. 512-- plus an error message.
506function fs_lua.copy_contents(src, dest, perms) 513function fs_lua.copy_contents(src, dest, perms)
507 assert(src and dest) 514 assert(src)
515 assert(dest)
508 src = dir.normalize(src) 516 src = dir.normalize(src)
509 dest = dir.normalize(dest) 517 dest = dir.normalize(dest)
510 if not fs.is_dir(src) then 518 if not fs.is_dir(src) then
@@ -589,7 +597,7 @@ local function recursive_find(cwd, prefix, result)
589 table.insert(result, item) 597 table.insert(result, item)
590 local pathname = dir.path(cwd, file) 598 local pathname = dir.path(cwd, file)
591 if lfs.attributes(pathname, "mode") == "directory" then 599 if lfs.attributes(pathname, "mode") == "directory" then
592 recursive_find(pathname, item.."/", result) 600 recursive_find(pathname, item .. dir_sep, result)
593 end 601 end
594 end 602 end
595 end 603 end
@@ -656,9 +664,8 @@ else -- if not lfs_ok
656 664
657function fs_lua.exists(file) 665function fs_lua.exists(file)
658 assert(file) 666 assert(file)
659 file = dir.normalize(fs.absolute_name(file))
660 -- check if file exists by attempting to open it 667 -- check if file exists by attempting to open it
661 return util.exists(file) 668 return util.exists(fs.absolute_name(file))
662end 669end
663 670
664end 671end
@@ -1072,9 +1079,8 @@ if posix.mkdtemp then
1072-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure. 1079-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
1073function fs_lua.make_temp_dir(name_pattern) 1080function fs_lua.make_temp_dir(name_pattern)
1074 assert(type(name_pattern) == "string") 1081 assert(type(name_pattern) == "string")
1075 name_pattern = dir.normalize(name_pattern)
1076 1082
1077 return posix.mkdtemp(fs.system_temp_dir() .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-XXXXXX") 1083 return posix.mkdtemp(temp_dir_pattern(name_pattern) .. "-XXXXXX")
1078end 1084end
1079 1085
1080end -- if posix.mkdtemp 1086end -- if posix.mkdtemp
@@ -1085,20 +1091,21 @@ end
1085-- Other functions 1091-- Other functions
1086--------------------------------------------------------------------- 1092---------------------------------------------------------------------
1087 1093
1088if lfs_ok and not fs_lua.make_temp_dir then 1094if not fs_lua.make_temp_dir then
1089 1095
1090function fs_lua.make_temp_dir(name_pattern) 1096function fs_lua.make_temp_dir(name_pattern)
1091 assert(type(name_pattern) == "string") 1097 assert(type(name_pattern) == "string")
1092 name_pattern = dir.normalize(name_pattern)
1093
1094 local pattern = fs.system_temp_dir() .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-"
1095 1098
1096 while true do 1099 local ok, err
1097 local name = pattern .. tostring(math.random(10000000)) 1100 for _ = 1, 3 do
1098 if lfs.mkdir(name) then 1101 local name = temp_dir_pattern(name_pattern) .. tostring(math.random(10000000))
1102 ok, err = fs.make_dir(name)
1103 if ok then
1099 return name 1104 return name
1100 end 1105 end
1101 end 1106 end
1107
1108 return nil, err
1102end 1109end
1103 1110
1104end 1111end
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)
47 pathname = unquoted 47 pathname = unquoted
48 end 48 end
49 49
50 relative_to = (relative_to or fs.current_dir()):gsub("/*$", "") 50 relative_to = relative_to or fs.current_dir()
51 if pathname:sub(1,1) == "/" then 51 if pathname:sub(1,1) == "/" then
52 return pathname 52 return dir.normalize(pathname)
53 else 53 else
54 return relative_to .. "/" .. pathname 54 return dir.path(relative_to, pathname)
55 end 55 end
56end 56end
57 57
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)
133 local drive, root, rest = split_root(pathname) 133 local drive, root, rest = split_root(pathname)
134 if root:match("[\\/]$") then 134 if root:match("[\\/]$") then
135 -- It's an absolute path already. Ensure is not quoted. 135 -- It's an absolute path already. Ensure is not quoted.
136 return drive .. root .. rest 136 return dir.normalize(drive .. root .. rest)
137 else 137 else
138 -- It's a relative path, join it with base path. 138 -- It's a relative path, join it with base path.
139 -- This drops drive letter from paths like "C:foo". 139 -- This drops drive letter from paths like "C:foo".
140 return relative_to .. "/" .. rest 140 return dir.path(relative_to, rest)
141 end 141 end
142end 142end
143 143
@@ -237,7 +237,7 @@ function win32.copy_binary(filename, dest)
237 dest = dir.dir_name(dest) 237 dest = dir.dir_name(dest)
238 if base:match(exe_pattern) then 238 if base:match(exe_pattern) then
239 base = base:gsub(exe_pattern, ".lua") 239 base = base:gsub(exe_pattern, ".lua")
240 local helpname = dest.."/"..base 240 local helpname = dest.."\\"..base
241 local helper = io.open(helpname, "w") 241 local helper = io.open(helpname, "w")
242 if not helper then 242 if not helper then
243 return nil, "Could not open "..helpname.." for writing." 243 return nil, "Could not open "..helpname.." for writing."
@@ -331,23 +331,6 @@ function win32.is_writable(file)
331 return result 331 return result
332end 332end
333 333
334--- Create a temporary directory.
335-- @param name_pattern string: name pattern to use for avoiding conflicts
336-- when creating temporary directory.
337-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
338function win32.make_temp_dir(name_pattern)
339 assert(type(name_pattern) == "string")
340 name_pattern = dir.normalize(name_pattern)
341
342 local temp_dir = os.getenv("TMP") .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-" .. tostring(math.floor(math.random() * 10000))
343 local ok, err = fs.make_dir(temp_dir)
344 if ok then
345 return temp_dir
346 else
347 return nil, err
348 end
349end
350
351function win32.tmpname() 334function win32.tmpname()
352 local name = os.tmpname() 335 local name = os.tmpname()
353 local tmp = os.getenv("TMP") 336 local tmp = os.getenv("TMP")