aboutsummaryrefslogtreecommitdiff
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
parent79bd1739d8ca004ddd0b2fa5e24da4a6f4b776fa (diff)
downloadluarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.tar.gz
luarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.tar.bz2
luarocks-2c4ff5240bf298fec07749f5984de2f08b8736ec.zip
fix: better normalization for paths and slashes
Fixes #1195.
-rw-r--r--spec/build_spec.lua3
-rw-r--r--spec/dir_spec.lua27
-rw-r--r--spec/fs_spec.lua31
-rw-r--r--spec/path_spec.lua15
-rw-r--r--spec/quick/config.q4
-rw-r--r--spec/quick/list.q4
-rw-r--r--spec/remove_spec.lua3
-rw-r--r--spec/util/quick.lua106
-rw-r--r--spec/util/test_env.lua398
-rw-r--r--spec/util_spec.lua59
-rw-r--r--spec/which_spec.lua9
-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
23 files changed, 489 insertions, 384 deletions
diff --git a/spec/build_spec.lua b/spec/build_spec.lua
index 5e78aa4f..0a270ec4 100644
--- a/spec/build_spec.lua
+++ b/spec/build_spec.lua
@@ -5,6 +5,7 @@ local run = test_env.run
5local testing_paths = test_env.testing_paths 5local testing_paths = test_env.testing_paths
6local write_file = test_env.write_file 6local write_file = test_env.write_file
7local git_repo = require("spec.util.git_repo") 7local git_repo = require("spec.util.git_repo")
8local P = test_env.P
8 9
9test_env.unload_luarocks() 10test_env.unload_luarocks()
10local cfg = require("luarocks.core.cfg") 11local cfg = require("luarocks.core.cfg")
@@ -661,7 +662,7 @@ describe("LuaRocks build #unit", function()
661 write_file("bin/binfile", "", finally) 662 write_file("bin/binfile", "", finally)
662 663
663 local _, install, copy_directories = build_builtin.autodetect_modules({}, {}, {}) 664 local _, install, copy_directories = build_builtin.autodetect_modules({}, {}, {})
664 assert.same(install, { bin = { "bin/binfile" } }) 665 assert.same(install, { bin = { P"bin/binfile" } })
665 assert.same(copy_directories, { "doc", "docs", "samples", "tests" }) 666 assert.same(copy_directories, { "doc", "docs", "samples", "tests" })
666 667
667 lfs.rmdir("doc") 668 lfs.rmdir("doc")
diff --git a/spec/dir_spec.lua b/spec/dir_spec.lua
index f6ef172e..b5dadda8 100644
--- a/spec/dir_spec.lua
+++ b/spec/dir_spec.lua
@@ -1,5 +1,6 @@
1local test_env = require("spec.util.test_env") 1local test_env = require("spec.util.test_env")
2local testing_paths = test_env.testing_paths 2local testing_paths = test_env.testing_paths
3local P = test_env.P
3 4
4test_env.unload_luarocks() 5test_env.unload_luarocks()
5test_env.setup_specs() 6test_env.setup_specs()
@@ -45,26 +46,26 @@ describe("luarocks.dir #unit", function()
45 46
46 describe("dir.normalize", function() 47 describe("dir.normalize", function()
47 it("converts backslashes and removes trailing slashes", function() 48 it("converts backslashes and removes trailing slashes", function()
48 assert.are.same("/foo/ovo", dir.normalize("\\foo\\ovo\\")) 49 assert.are.same(P"/foo/ovo", dir.normalize("\\foo\\ovo\\"))
49 assert.are.same("c:/some/dir", dir.normalize("c:\\..\\some\\foo\\..\\dir")) 50 assert.are.same(P"c:/some/dir", dir.normalize("c:\\..\\some\\foo\\..\\dir"))
50 assert.are.same("http://example.com/foo/ovo", dir.normalize("http://example.com/foo\\ovo\\")) 51 assert.are.same("http://example.com/foo/ovo", dir.normalize("http://example.com/foo\\ovo\\"))
51 end) 52 end)
52 it("strips unneeded /../ and /./", function() 53 it("strips unneeded /../ and /./", function()
53 assert.are.same("/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) 54 assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt"))
54 assert.are.same("/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) 55 assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt"))
55 assert.are.same("/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./some/subdir/../..")) 56 assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./some/subdir/../.."))
56 assert.are.same("/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./.")) 57 assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./."))
57 end) 58 end)
58 it("respects relative paths", function() 59 it("respects relative paths", function()
59 assert.are.same(".", dir.normalize(".")) 60 assert.are.same(P".", dir.normalize("."))
60 assert.are.same("boo", dir.normalize("./boo")) 61 assert.are.same(P"boo", dir.normalize("./boo"))
61 assert.are.same("/boo", dir.normalize("/./boo")) 62 assert.are.same(P"/boo", dir.normalize("/./boo"))
62 assert.are.same("../../../../boo", dir.normalize("../../../hello/world/../../../boo")) 63 assert.are.same(P"../../../../boo", dir.normalize("../../../hello/world/../../../boo"))
63 end) 64 end)
64 it("respects root directory", function() 65 it("respects root directory", function()
65 assert.are.same("/", dir.normalize("/")) 66 assert.are.same(P"/", dir.normalize("/"))
66 assert.are.same("/", dir.normalize("/////")) 67 assert.are.same(P"/", dir.normalize("/////"))
67 assert.are.same("/", dir.normalize("/a/b/.././../c/./../../")) 68 assert.are.same(P"/", dir.normalize("/a/b/.././../c/./../../"))
68 end) 69 end)
69 end) 70 end)
70 71
diff --git a/spec/fs_spec.lua b/spec/fs_spec.lua
index cd6e5c13..aea86af3 100644
--- a/spec/fs_spec.lua
+++ b/spec/fs_spec.lua
@@ -11,6 +11,7 @@ local posix_ok = pcall(require, "posix")
11local testing_paths = test_env.testing_paths 11local testing_paths = test_env.testing_paths
12local get_tmp_path = test_env.get_tmp_path 12local get_tmp_path = test_env.get_tmp_path
13local write_file = test_env.write_file 13local write_file = test_env.write_file
14local P = test_env.P
14 15
15-- A chdir that works in both full and minimal mode, setting 16-- A chdir that works in both full and minimal mode, setting
16-- both the real process current dir and the LuaRocks internal stack in minimal mode 17-- both the real process current dir and the LuaRocks internal stack in minimal mode
@@ -92,33 +93,33 @@ describe("luarocks.fs #unit", function()
92 describe("fs.absolute_name", function() 93 describe("fs.absolute_name", function()
93 it("unchanged if already absolute", function() 94 it("unchanged if already absolute", function()
94 if is_win then 95 if is_win then
95 assert.are.same("c:\\foo\\bar", fs.absolute_name("\"c:\\foo\\bar\"")) 96 assert.are.same(P"c:\\foo\\bar", fs.absolute_name("\"c:\\foo\\bar\""))
96 assert.are.same("c:\\foo\\bar", fs.absolute_name("c:\\foo\\bar")) 97 assert.are.same(P"c:\\foo\\bar", fs.absolute_name("c:\\foo\\bar"))
97 assert.are.same("d:\\foo\\bar", fs.absolute_name("d:\\foo\\bar")) 98 assert.are.same(P"d:\\foo\\bar", fs.absolute_name("d:\\foo\\bar"))
98 assert.are.same("\\foo\\bar", fs.absolute_name("\\foo\\bar")) 99 assert.are.same(P"\\foo\\bar", fs.absolute_name("\\foo\\bar"))
99 else 100 else
100 assert.are.same("/foo/bar", fs.absolute_name("/foo/bar")) 101 assert.are.same(P"/foo/bar", fs.absolute_name("/foo/bar"))
101 end 102 end
102 end) 103 end)
103 104
104 it("converts to absolute if relative", function() 105 it("converts to absolute if relative", function()
105 local cur = fs.current_dir() 106 local cur = fs.current_dir()
106 if is_win then 107 if is_win then
107 assert.are.same(cur .. "/foo\\bar", fs.absolute_name("\"foo\\bar\"")) 108 assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("\"foo\\bar\""))
108 assert.are.same(cur .. "/foo\\bar", fs.absolute_name("foo\\bar")) 109 assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("foo\\bar"))
109 else 110 else
110 assert.are.same(cur .. "/foo/bar", fs.absolute_name("foo/bar")) 111 assert.are.same(P(cur .. "/foo/bar"), fs.absolute_name("foo/bar"))
111 end 112 end
112 end) 113 end)
113 114
114 it("converts a relative to specified base if given", function() 115 it("converts a relative to specified base if given", function()
115 if is_win then 116 if is_win then
116 assert.are.same("c:\\bla/foo\\bar", fs.absolute_name("\"foo\\bar\"", "c:\\bla")) 117 assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("\"foo\\bar\"", "c:\\bla"))
117 assert.are.same("c:\\bla/foo\\bar", fs.absolute_name("foo\\bar", "c:\\bla")) 118 assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo/bar", "c:\\bla"))
118 assert.are.same("c:\\bla/foo\\bar", fs.absolute_name("foo\\bar", "c:\\bla\\")) 119 assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo\\bar", "c:\\bla\\"))
119 else 120 else
120 assert.are.same("/bla/foo/bar", fs.absolute_name("foo/bar", "/bla")) 121 assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla"))
121 assert.are.same("/bla/foo/bar", fs.absolute_name("foo/bar", "/bla/")) 122 assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla/"))
122 end 123 end
123 end) 124 end)
124 end) 125 end)
@@ -619,9 +620,9 @@ describe("luarocks.fs #unit", function()
619 assert.truthy(fs.change_dir_to_root()) 620 assert.truthy(fs.change_dir_to_root())
620 if is_win then 621 if is_win then
621 local curr_dir = fs.current_dir() 622 local curr_dir = fs.current_dir()
622 assert.truthy(curr_dir == "C:\\" or curr_dir == "/") 623 assert.truthy(curr_dir == "C:\\" or curr_dir == P"/")
623 else 624 else
624 assert.same("/", fs.current_dir()) 625 assert.same(P"/", fs.current_dir())
625 end 626 end
626 end) 627 end)
627 628
diff --git a/spec/path_spec.lua b/spec/path_spec.lua
index 9b2a2854..ba2ecdde 100644
--- a/spec/path_spec.lua
+++ b/spec/path_spec.lua
@@ -57,19 +57,4 @@ describe("luarocks path #integration", function()
57 it("--tree", function() 57 it("--tree", function()
58 assert.is_true(run.luarocks_bool("path --tree=lua_modules")) 58 assert.is_true(run.luarocks_bool("path --tree=lua_modules"))
59 end) 59 end)
60
61 it("--project-tree", function()
62 local path1 = "/share/lua/5%." .. test_env.lua_version:sub(3, 3) .. "/%?%.lua"
63 local path2 = "/share/lua/5%." .. test_env.lua_version:sub(3, 3) .. "/%?/init%.lua"
64
65 local path = run.luarocks("path --project-tree=foo")
66 assert.truthy(path:find("foo" .. path1))
67 assert.truthy(path:find("foo" .. path2))
68
69 path = run.luarocks("path --project-tree=foo --tree=bar")
70 assert.falsy(path:find("foo" .. path1))
71 assert.falsy(path:find("foo" .. path2))
72 assert.truthy(path:find("bar" .. path1))
73 assert.truthy(path:find("bar" .. path2))
74 end)
75end) 60end)
diff --git a/spec/quick/config.q b/spec/quick/config.q
index ec338f98..3150a9ce 100644
--- a/spec/quick/config.q
+++ b/spec/quick/config.q
@@ -12,6 +12,6 @@ RUN: luarocks config --system-config
12 12
13STDOUT: 13STDOUT:
14-------------------------------------------------------------------------------- 14--------------------------------------------------------------------------------
15%{testing_lrprefix}/etc/luarocks/config-%{LUA_VERSION}.lua 15%{path(%{testing_lrprefix}/etc/luarocks/config-%{LUA_VERSION}.lua)}
16-------------------------------------------------------------------------------- 16--------------------------------------------------------------------------------
17#TODO: ^^^ %{path()} 17
diff --git a/spec/quick/list.q b/spec/quick/list.q
index 7cbdee43..fbb3f557 100644
--- a/spec/quick/list.q
+++ b/spec/quick/list.q
@@ -5,6 +5,6 @@ RUN: luarocks --tree=%{path(/some/invalid/tree)} list
5 5
6STDOUT: 6STDOUT:
7-------------------------------------------------------------------------------- 7--------------------------------------------------------------------------------
8Rocks installed for Lua %{lua_version} in /some/invalid/tree 8Rocks installed for Lua %{lua_version} in %{path(/some/invalid/tree)}
9-------------------------------------------------------------------------------- 9--------------------------------------------------------------------------------
10#TODO: ^^^ %{path()} 10
diff --git a/spec/remove_spec.lua b/spec/remove_spec.lua
index a67db591..ddeb0644 100644
--- a/spec/remove_spec.lua
+++ b/spec/remove_spec.lua
@@ -4,6 +4,7 @@ local run = test_env.run
4local testing_paths = test_env.testing_paths 4local testing_paths = test_env.testing_paths
5local env_variables = test_env.env_variables 5local env_variables = test_env.env_variables
6local V = test_env.V 6local V = test_env.V
7local P = test_env.P
7 8
8test_env.unload_luarocks() 9test_env.unload_luarocks()
9 10
@@ -86,7 +87,7 @@ describe("luarocks remove #integration", function()
86 end) 87 end)
87 88
88 it("restores old versions", function() 89 it("restores old versions", function()
89 local libdir = testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION 90 local libdir = P(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION)
90 91
91 assert.is_true(run.luarocks_bool("install luafilesystem ${LUAFILESYSTEM_OLD_V}")) 92 assert.is_true(run.luarocks_bool("install luafilesystem ${LUAFILESYSTEM_OLD_V}"))
92 assert.is.truthy(lfs.attributes(libdir.."/lfs."..test_env.lib_extension)) 93 assert.is.truthy(lfs.attributes(libdir.."/lfs."..test_env.lib_extension))
diff --git a/spec/util/quick.lua b/spec/util/quick.lua
index c8bfb61a..1fcf2b36 100644
--- a/spec/util/quick.lua
+++ b/spec/util/quick.lua
@@ -37,7 +37,7 @@ local function is_hr(line)
37end 37end
38 38
39local function parse(filename) 39local function parse(filename)
40 local fd = assert(io.open(filename, "r")) 40 local fd = assert(io.open(filename, "rb"))
41 local input = assert(fd:read("*a")) 41 local input = assert(fd:read("*a"))
42 fd:close() 42 fd:close()
43 43
@@ -67,11 +67,27 @@ local function parse(filename)
67 os.exit(1) 67 os.exit(1)
68 end 68 end
69 69
70 local function bool_arg(cmd, cur_block, field, arg) 70 local function bool_arg(cmd, cur, field, arg)
71 if arg ~= "true" and arg ~= "false" then 71 if arg ~= "true" and arg ~= "false" then
72 fail(cmd .. " argument must be 'true' or 'false'") 72 fail(cmd .. " argument must be 'true' or 'false'")
73 end 73 end
74 cur_block[field] = (arg == "true") 74 cur[field] = (arg == "true")
75 end
76
77 local function block_start_arg(cmd, cur, field)
78 if not cur or cur.op ~= "RUN" then
79 fail(cmd .. " must be given in the context of a RUN")
80 end
81 if cur[field] then
82 fail(cmd .. " was already declared")
83 end
84
85 cur[field] = {
86 data = {}
87 }
88 cur_block = cur[field]
89 cur_block_name = cmd
90 table.insert(stack, "block start")
75 end 91 end
76 92
77 local test_env = require("spec.util.test_env") 93 local test_env = require("spec.util.test_env")
@@ -109,7 +125,11 @@ local function parse(filename)
109 end)) 125 end))
110 end 126 end
111 127
112 for line in input:gmatch("[^\n]*") do 128 if input:sub(#input, #input) ~= "\n" then
129 input = input .. "\n"
130 end
131
132 for line in input:gmatch("([^\r\n]*)\r?\n?") do
113 cur_line = cur_line + 1 133 cur_line = cur_line + 1
114 134
115 local state = stack[#stack] 135 local state = stack[#stack]
@@ -182,34 +202,20 @@ local function parse(filename)
182 202
183 cur_op.exit = code 203 cur_op.exit = code
184 cur_op.exit_line = cur_line 204 cur_op.exit_line = cur_line
185 elseif cmd == "STDERR" then 205 elseif cmd == "VERBOSE" then
186 if not cur_op or cur_op.op ~= "RUN" then 206 if not cur_op or cur_op.op ~= "RUN" then
187 fail("STDERR must be given in the context of a RUN") 207 fail("VERBOSE must be given in the context of a RUN")
188 end
189 if cur_op.stderr then
190 fail("STDERR was already declared")
191 end 208 end
192 209
193 cur_op.stderr = { 210 bool_arg("VERBOSE", cur_op, "verbose", arg)
194 data = {} 211 elseif cmd == "STDERR" then
195 } 212 block_start_arg("STDERR", cur_op, "stderr")
196 cur_block = cur_op.stderr 213 elseif cmd == "NOT_STDERR" then
197 cur_block_name = "STDERR" 214 block_start_arg("NOT_STDERR", cur_op, "not_stderr")
198 table.insert(stack, "block start")
199 elseif cmd == "STDOUT" then 215 elseif cmd == "STDOUT" then
200 if not cur_op or cur_op.op ~= "RUN" then 216 block_start_arg("STDOUT", cur_op, "stdout")
201 fail("STDOUT must be given in the context of a RUN") 217 elseif cmd == "NOT_STDOUT" then
202 end 218 block_start_arg("NOT_STDOUT", cur_op, "not_stdout")
203 if cur_op.stdout then
204 fail("STDOUT was already declared")
205 end
206
207 cur_op.stdout = {
208 data = {}
209 }
210 cur_block = cur_op.stdout
211 cur_block_name = "STDOUT"
212 table.insert(stack, "block start")
213 elseif cmd == "TEST" then 219 elseif cmd == "TEST" then
214 table.remove(stack) 220 table.remove(stack)
215 start_test(arg) 221 start_test(arg)
@@ -298,7 +304,7 @@ function quick.compile(filename, env)
298 write([=[ end ]=]) 304 write([=[ end ]=])
299 for _, op in ipairs(t.ops) do 305 for _, op in ipairs(t.ops) do
300 if op.op == "FILE" then 306 if op.op == "FILE" then
301 write([=[ test_env.write_file(handle_tmpdir("]=], op.name, [=["), handle_tmpdir([=====[ ]=]) 307 write(([=[ test_env.write_file(handle_tmpdir(%q), handle_tmpdir([=====[ ]=]):format(op.name))
302 for _, line in ipairs(op.data) do 308 for _, line in ipairs(op.data) do
303 write(line) 309 write(line)
304 end 310 end
@@ -324,7 +330,7 @@ function quick.compile(filename, env)
324 write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs)) 330 write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs))
325 write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=]) 331 write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=])
326 332
327 write([=[ local fd_stderr = assert(io.open("stderr.txt", "r")) ]=]) 333 write([=[ local fd_stderr = assert(io.open("stderr.txt", "rb")) ]=])
328 write([=[ local stderr_data = fd_stderr:read("*a") ]=]) 334 write([=[ local stderr_data = fd_stderr:read("*a") ]=])
329 write([=[ fd_stderr:close() ]=]) 335 write([=[ fd_stderr:close() ]=])
330 336
@@ -332,23 +338,46 @@ function quick.compile(filename, env)
332 write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line)) 338 write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line))
333 write([=[ end ]=]) 339 write([=[ end ]=])
334 340
335 if op.stdout then 341 if op.stdout or op.not_stdout or op.verbose then
336 write([=[ local fd_stdout = assert(io.open("stdout.txt", "r")) ]=]) 342 write([=[ local fd_stdout = assert(io.open("stdout.txt", "rb")) ]=])
337 write([=[ local stdout_data = fd_stdout:read("*a") ]=]) 343 write([=[ local stdout_data = fd_stdout:read("*a") ]=])
338 write([=[ fd_stdout:close() ]=]) 344 write([=[ fd_stdout:close() ]=])
345 end
346
347 if op.verbose then
348 write([=[ print() ]=])
349 write([=[ print("STDOUT: --" .. ("-"):rep(70)) ]=])
350 write([=[ print(stdout_data) ]=])
351 write([=[ print("STDERR: --" .. ("-"):rep(70)) ]=])
352 write([=[ print(stderr_data) ]=])
353 write([=[ print(("-"):rep(80)) ]=])
354 write([=[ print() ]=])
355 end
339 356
357 if op.stdout then
340 write([=[ do ]=]) 358 write([=[ do ]=])
341 write([=[ local block_at = 1 ]=]) 359 write([=[ local block_at = 1 ]=])
342 write([=[ local s, e, line ]=]) 360 write([=[ local s, e, line ]=])
343 for i, line in ipairs(op.stdout.data) do 361 for i, line in ipairs(op.stdout.data) do
344 write(([=[ line = %q ]=]):format(line)) 362 write(([=[ line = %q ]=]):format(line))
345 write(([=[ s, e = string.find(stdout_data, line, block_at, true) ]=])) 363 write(([=[ s, e = string.find(stdout_data, line, 1, true) ]=]))
346 write(([=[ assert(s, error_message(%d, "STDOUT did not match: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) 364 write(([=[ assert(s, error_message(%d, "STDOUT did not match: " .. line, stdout_data)) ]=]):format(op.stdout.start + i))
347 write(([=[ block_at = e + 1 ]=]):format(i)) 365 write(([=[ block_at = e + 1 ]=]):format(i))
348 end 366 end
349 write([=[ end ]=]) 367 write([=[ end ]=])
350 end 368 end
351 369
370 if op.not_stdout then
371 write([=[ do ]=])
372 write([=[ local line ]=])
373 for i, line in ipairs(op.not_stdout.data) do
374 write(([=[ line = %q ]=]):format(line))
375 write(([=[ s = string.find(stdout_data, line, 1, true) ]=]))
376 write(([=[ assert(not s, error_message(%d, "NOT_STDOUT did match unwanted output: " .. line, stdout_data)) ]=]):format(op.stdout.start + i))
377 end
378 write([=[ end ]=])
379 end
380
352 if op.stderr then 381 if op.stderr then
353 write([=[ do ]=]) 382 write([=[ do ]=])
354 write([=[ local block_at = 1 ]=]) 383 write([=[ local block_at = 1 ]=])
@@ -362,6 +391,17 @@ function quick.compile(filename, env)
362 write([=[ end ]=]) 391 write([=[ end ]=])
363 end 392 end
364 393
394 if op.not_stderr then
395 write([=[ do ]=])
396 write([=[ local line ]=])
397 for i, line in ipairs(op.not_stderr.data) do
398 write(([=[ line = %q ]=]):format(line))
399 write(([=[ s = string.find(stderr_data, line, block_at, true) ]=]))
400 write(([=[ assert(not s, error_message(%d, "NOT_STDERR did match unwanted output: " .. line, stderr_data)) ]=]):format(op.stderr.start + i))
401 end
402 write([=[ end ]=])
403 end
404
365 if op.exit then 405 if op.exit then
366 write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit)) 406 write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit))
367 end 407 end
diff --git a/spec/util/test_env.lua b/spec/util/test_env.lua
index dcda6311..41787cb7 100644
--- a/spec/util/test_env.lua
+++ b/spec/util/test_env.lua
@@ -37,6 +37,19 @@ local function title(str)
37 print(("-"):rep(#str)) 37 print(("-"):rep(#str))
38end 38end
39 39
40local dir_sep = package.config:sub(1, 1)
41local function P(p)
42 return (p:gsub("/", dir_sep))
43end
44
45local function dir_path(...)
46 return P((table.concat({ ... }, "/"):gsub("\\", "/"):gsub("/+", "/")))
47end
48
49local function C(...)
50 return table.concat({...}, " ")
51end
52
40--- Quote argument for shell processing. Fixes paths on Windows. 53--- Quote argument for shell processing. Fixes paths on Windows.
41-- Adds double quotes and escapes. Based on function in fs/win32.lua. 54-- Adds double quotes and escapes. Based on function in fs/win32.lua.
42-- @param arg string: Unquoted argument. 55-- @param arg string: Unquoted argument.
@@ -46,7 +59,7 @@ local function Q(arg)
46 local drive_letter = "[%.a-zA-Z]?:?[\\/]" 59 local drive_letter = "[%.a-zA-Z]?:?[\\/]"
47 -- Quote DIR for Windows 60 -- Quote DIR for Windows
48 if arg:match("^"..drive_letter) then 61 if arg:match("^"..drive_letter) then
49 arg = arg:gsub("/", "\\") 62 arg = P(arg)
50 end 63 end
51 64
52 if arg == "\\" then 65 if arg == "\\" then
@@ -72,7 +85,7 @@ local function V(str)
72 elseif suffix == "v" then 85 elseif suffix == "v" then
73 return v 86 return v
74 elseif suffix == "r" then 87 elseif suffix == "r" then
75 return v 88 return r
76 else 89 else
77 print("Test error: invalid suffix " .. suffix .. " in variable " .. name) 90 print("Test error: invalid suffix " .. suffix .. " in variable " .. name)
78 os.exit(1) 91 os.exit(1)
@@ -87,6 +100,14 @@ local function V(str)
87 end)) 100 end))
88end 101end
89 102
103local function tool(name)
104 if test_env.TEST_TARGET_OS == "windows" then
105 return Q(dir_path(test_env.testing_paths.win_tools, name .. ".exe"))
106 else
107 return name
108 end
109end
110
90local os_remove = os.remove 111local os_remove = os.remove
91os.remove = function(f) -- luacheck: ignore 112os.remove = function(f) -- luacheck: ignore
92 return os_remove(V(f)) 113 return os_remove(V(f))
@@ -131,8 +152,18 @@ function test_env.copy(source, destination)
131 source = V(source) 152 source = V(source)
132 destination = V(destination) 153 destination = V(destination)
133 154
134 local r_source, err = io.open(source, "r") 155 local r_source, r_destination, err
135 local r_destination, err = io.open(destination, "w") 156 r_source, err = io.open(source, "r")
157 if err then
158 print(debug.traceback())
159 os.exit(1)
160 end
161
162 r_destination, err = io.open(destination, "w")
163 if err then
164 print(debug.traceback())
165 os.exit(1)
166 end
136 167
137 while true do 168 while true do
138 local block = r_source:read(8192) 169 local block = r_source:read(8192)
@@ -147,7 +178,7 @@ end
147function test_env.get_tmp_path() 178function test_env.get_tmp_path()
148 local path = os.tmpname() 179 local path = os.tmpname()
149 if test_env.TEST_TARGET_OS == "windows" and not path:find(":") then 180 if test_env.TEST_TARGET_OS == "windows" and not path:find(":") then
150 path = os.getenv("TEMP") .. path 181 path = dir_path(os.getenv("TEMP"), path)
151 end 182 end
152 os.remove(path) 183 os.remove(path)
153 return path 184 return path
@@ -234,8 +265,8 @@ local function execute_bool(command, print_command, env_variables)
234 local redirect_filename 265 local redirect_filename
235 local redirect = "" 266 local redirect = ""
236 if print_command ~= nil then 267 if print_command ~= nil then
237 redirect_filename = test_env.testing_paths.luarocks_tmp.."/output.txt" 268 redirect_filename = dir_path(test_env.testing_paths.luarocks_tmp, "output.txt")
238 redirect = " > "..redirect_filename 269 redirect = " > " .. redirect_filename
239 os.remove(redirect_filename) 270 os.remove(redirect_filename)
240 end 271 end
241 local ok = test_env.execute(command .. redirect) 272 local ok = test_env.execute(command .. redirect)
@@ -312,7 +343,7 @@ function test_env.set_args()
312 if not test_env.TEST_TARGET_OS then 343 if not test_env.TEST_TARGET_OS then
313 title("OS CHECK") 344 title("OS CHECK")
314 345
315 if package.config:sub(1,1) == "\\" then 346 if dir_sep == "\\" then
316 test_env.TEST_TARGET_OS = "windows" 347 test_env.TEST_TARGET_OS = "windows"
317 if test_env.APPVEYOR then 348 if test_env.APPVEYOR then
318 test_env.OPENSSL_INCDIR = "C:\\OpenSSL-v111-Win32\\include" 349 test_env.OPENSSL_INCDIR = "C:\\OpenSSL-v111-Win32\\include"
@@ -348,7 +379,8 @@ function test_env.set_args()
348 379
349 test_env.openssl_dirs = "" 380 test_env.openssl_dirs = ""
350 if test_env.OPENSSL_INCDIR then 381 if test_env.OPENSSL_INCDIR then
351 test_env.openssl_dirs = "OPENSSL_INCDIR=" .. test_env.OPENSSL_INCDIR .. " OPENSSL_LIBDIR=" .. test_env.OPENSSL_LIBDIR 382 test_env.openssl_dirs = C("OPENSSL_INCDIR=" .. test_env.OPENSSL_INCDIR,
383 "OPENSSL_LIBDIR=" .. test_env.OPENSSL_LIBDIR)
352 end 384 end
353 385
354 return true 386 return true
@@ -358,12 +390,8 @@ function test_env.copy_dir(source_path, target_path)
358 source_path = V(source_path) 390 source_path = V(source_path)
359 target_path = V(target_path) 391 target_path = V(target_path)
360 392
361 local testing_paths = test_env.testing_paths 393 local flag = test_env.TEST_TARGET_OS == "windows" and "-R" or "-a"
362 if test_env.TEST_TARGET_OS == "windows" then 394 os.execute(C(tool("cp"), flag, dir_path(source_path, "."), target_path))
363 execute_bool(testing_paths.win_tools .. "/cp -R ".. source_path .. "/. " .. target_path)
364 else
365 execute_bool("cp -a ".. source_path .. "/. " .. target_path)
366 end
367end 395end
368 396
369--- Remove directory recursively 397--- Remove directory recursively
@@ -374,7 +402,7 @@ function test_env.remove_dir(path)
374 if exists(path) then 402 if exists(path) then
375 for file in lfs.dir(path) do 403 for file in lfs.dir(path) do
376 if file ~= "." and file ~= ".." then 404 if file ~= "." and file ~= ".." then
377 local full_path = path..'/'..file 405 local full_path = dir_path(path, file)
378 406
379 if lfs.attributes(full_path, "mode") == "directory" then 407 if lfs.attributes(full_path, "mode") == "directory" then
380 test_env.remove_dir(full_path) 408 test_env.remove_dir(full_path)
@@ -396,7 +424,7 @@ function test_env.remove_subdirs(path, pattern)
396 if exists(path) then 424 if exists(path) then
397 for file in lfs.dir(path) do 425 for file in lfs.dir(path) do
398 if file ~= "." and file ~= ".." then 426 if file ~= "." and file ~= ".." then
399 local full_path = path..'/'..file 427 local full_path = dir_path(path, file)
400 428
401 if lfs.attributes(full_path, "mode") == "directory" and file:find(pattern) then 429 if lfs.attributes(full_path, "mode") == "directory" and file:find(pattern) then
402 test_env.remove_dir(full_path) 430 test_env.remove_dir(full_path)
@@ -418,7 +446,7 @@ function test_env.remove_files(path, pattern)
418 for file in lfs.dir(path) do 446 for file in lfs.dir(path) do
419 if file ~= "." and file ~= ".." then 447 if file ~= "." and file ~= ".." then
420 if file:find(pattern) then 448 if file:find(pattern) then
421 if os.remove(path .. "/" .. file) then 449 if os.remove(dir_path(path, file)) then
422 result_check = true 450 result_check = true
423 end 451 end
424 end 452 end
@@ -442,27 +470,21 @@ local function download_rocks(urls, save_path)
442 url = V(url) 470 url = V(url)
443 471
444 if url:match("^spec/fixtures") then 472 if url:match("^spec/fixtures") then
445 table.insert(fixtures, (url:gsub("^spec/fixtures", test_env.testing_paths.fixtures_dir))) 473 table.insert(fixtures, P(url:gsub("^spec/fixtures", test_env.testing_paths.fixtures_dir)))
446 else 474 else
447 -- check if already downloaded 475 -- check if already downloaded
448 if not exists(save_path .. "/" .. url) then 476 if not exists(dir_path(save_path, url)) then
449 table.insert(to_download, ((luarocks_repo .. url):gsub("org//", "org/"))) 477 table.insert(to_download, ((luarocks_repo .. url):gsub("org//", "org/")))
450 end 478 end
451 end 479 end
452 end 480 end
453 481
454 if #fixtures > 0 then 482 if #fixtures > 0 then
455 os.execute("cp " .. table.concat(fixtures, " ") .. " " .. save_path) 483 os.execute(C(tool("cp"), table.concat(fixtures, " "), save_path))
456 end 484 end
457 485
458 if #to_download > 0 then 486 if #to_download > 0 then
459 local cmd 487 local ok = execute_bool(C(tool("wget"), "--no-check-certificate -cP", save_path, table.concat(to_download, " ")))
460 if test_env.TEST_TARGET_OS == "windows" then
461 cmd = test_env.testing_paths.win_tools .. "/wget --no-check-certificate -cP " .. save_path
462 else
463 cmd = "wget -cP " .. save_path
464 end
465 local ok = execute_bool(cmd.." "..table.concat(to_download, " "))
466 if not ok then 488 if not ok then
467 os.exit(1) 489 os.exit(1)
468 end 490 end
@@ -492,12 +514,13 @@ end
492-- @return md5sum string: md5sum of directory 514-- @return md5sum string: md5sum of directory
493local function hash_environment(path) 515local function hash_environment(path)
494 if test_env.TEST_TARGET_OS == "linux" then 516 if test_env.TEST_TARGET_OS == "linux" then
495 return execute_output("cd " .. path .. " && find . -printf \"%s %p\n\"") 517 return execute_output(C("cd", path, "&& find . -printf \"%s %p\n\" | md5sum"))
496 elseif test_env.TEST_TARGET_OS == "osx" then 518 elseif test_env.TEST_TARGET_OS == "osx" then
497 return execute_output("find " .. path .. " -type f -exec stat -f \"%z %N\" {} \\; | md5") 519 return execute_output(C("find", path, "-type f -exec stat -f \"%z %N\" {} \\; | md5"))
498 elseif test_env.TEST_TARGET_OS == "windows" then 520 elseif test_env.TEST_TARGET_OS == "windows" then
499 return execute_output("\"" .. Q(test_env.testing_paths.win_tools .. "/find") .. " " .. Q(path) 521 return execute_output(
500 .. " -printf \"%s %p\"\" > temp_sum.txt && certUtil -hashfile temp_sum.txt && del temp_sum.txt") 522 "\"" .. C(tool("find"), Q(path), "-printf", "\"%s %p\"") .. "\"" ..
523 " > temp_sum.txt && certUtil -hashfile temp_sum.txt && del temp_sum.txt")
501 end 524 end
502end 525end
503 526
@@ -505,29 +528,44 @@ end
505-- @param testing_paths table: table with paths to testing directory 528-- @param testing_paths table: table with paths to testing directory
506-- @return env_variables table: table with created environment variables 529-- @return env_variables table: table with created environment variables
507local function create_env(testing_paths) 530local function create_env(testing_paths)
508 local luaversion_short = _VERSION:gsub("Lua ", "") 531 local lua_v = _VERSION:gsub("Lua ", "")
532 local testrun_dir = test_env.testing_paths.testrun_dir
533 local lrprefix = testing_paths.testing_lrprefix
534 local tree = testing_paths.testing_tree
535 local sys_tree = testing_paths.testing_sys_tree
509 536
510 if test_env.LUAJIT_V then 537 if test_env.LUAJIT_V then
511 luaversion_short="5.1" 538 lua_v="5.1"
512 end 539 end
513 540
514 local env_variables = {} 541 local env_variables = {}
515 env_variables.GNUPGHOME = testing_paths.gpg_dir 542 env_variables.GNUPGHOME = testing_paths.gpg_dir
516 env_variables.LUA_VERSION = luaversion_short 543 env_variables.LUA_VERSION = lua_v
517 env_variables.LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config.lua" 544 env_variables.LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua")
545
546 local lua_path = {}
518 if test_env.TEST_TARGET_OS == "windows" then 547 if test_env.TEST_TARGET_OS == "windows" then
519 env_variables.LUA_PATH = testing_paths.testing_lrprefix .. "\\lua\\?.lua;" 548 table.insert(lua_path, dir_path(lrprefix, "lua", "?.lua"))
520 else 549 else
521 env_variables.LUA_PATH = testing_paths.testing_lrprefix .. "/share/lua/" .. luaversion_short .. "/?.lua;" 550 table.insert(lua_path, dir_path(lrprefix, "share", "lua", lua_v, "?.lua"))
522 end 551 end
523 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;" 552 table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?.lua"))
524 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;" 553 table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?", "init.lua"))
525 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;" 554 table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?.lua"))
526 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;" 555 table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?", "init.lua"))
527 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.src_dir .. "/?.lua;" 556 table.insert(lua_path, dir_path(testing_paths.src_dir, "?.lua"))
528 env_variables.LUA_CPATH = testing_paths.testing_tree .. "/lib/lua/" .. luaversion_short .. "/?." .. test_env.lib_extension .. ";" 557 env_variables.LUA_PATH = table.concat(lua_path, ";") .. ";"
529 .. testing_paths.testing_sys_tree .. "/lib/lua/" .. luaversion_short .. "/?." .. test_env.lib_extension .. ";" 558
530 env_variables.PATH = os.getenv("PATH") .. ";" .. testing_paths.testing_tree .. "/bin;" .. testing_paths.testing_sys_tree .. "/bin;" 559 local lua_cpath = {}
560 local lib_pattern = "?." .. test_env.lib_extension
561 table.insert(lua_cpath, dir_path(tree, "lib", "lua", lua_v, lib_pattern))
562 table.insert(lua_cpath, dir_path(sys_tree, "lib", "lua", lua_v, lib_pattern))
563 env_variables.LUA_CPATH = table.concat(lua_cpath, ";") .. ";"
564
565 local path = { os.getenv("PATH") }
566 table.insert(path, dir_path(tree, "bin"))
567 table.insert(path, dir_path(sys_tree, "bin"))
568 env_variables.PATH = table.concat(path, test_env.TARGET_OS == "windows" and ";" or ":")
531 569
532 return env_variables 570 return env_variables
533end 571end
@@ -544,16 +582,19 @@ local function create_md5sums(testing_paths)
544end 582end
545 583
546local function make_run_function(cmd_name, exec_function, with_coverage, do_print) 584local function make_run_function(cmd_name, exec_function, with_coverage, do_print)
547 local cmd_prefix = Q(test_env.testing_paths.lua) .. " " 585 local cmd_prefix = Q(test_env.testing_paths.lua)
586 local testrun_dir = test_env.testing_paths.testrun_dir
548 587
549 if with_coverage then 588 if with_coverage then
550 cmd_prefix = cmd_prefix .. "-e \"require('luacov.runner')('" .. test_env.testing_paths.testrun_dir .. "/luacov.config')\" " 589 cmd_prefix = C(cmd_prefix, "-e", "\"require('luacov.runner')([[" .. testrun_dir .. "/luacov.config]])\"")
551 end 590 end
552 591
553 if cmd_name then 592 if cmd_name then
554 cmd_prefix = cmd_prefix .. test_env.testing_paths.src_dir .. "/bin/" .. cmd_name .. " " 593 cmd_prefix = C(cmd_prefix, dir_path(test_env.testing_paths.src_dir, "bin", cmd_name))
555 end 594 end
556 595
596 cmd_prefix = P(cmd_prefix)
597
557 return function(cmd, new_vars) 598 return function(cmd, new_vars)
558 cmd = V(cmd) 599 cmd = V(cmd)
559 local temp_vars = {} 600 local temp_vars = {}
@@ -565,34 +606,34 @@ local function make_run_function(cmd_name, exec_function, with_coverage, do_prin
565 temp_vars[k] = v 606 temp_vars[k] = v
566 end 607 end
567 end 608 end
568 return exec_function(cmd_prefix .. cmd, do_print, temp_vars) 609 return exec_function(C(cmd_prefix, cmd), do_print, temp_vars)
569 end 610 end
570end 611end
571 612
572local function make_run_functions() 613local function make_run_functions()
573 return { 614 local fns = {}
574 lua = make_run_function(nil, execute_output, true, true), 615
575 lua_bool = make_run_function(nil, execute_bool, true, true), 616 local cmds = {
576 luarocks = make_run_function("luarocks", execute_output, true, true), 617 ["lua"] = nil,
577 luarocks_bool = make_run_function("luarocks", execute_bool, true, true), 618 ["luarocks"] = "luarocks",
578 luarocks_noprint = make_run_function("luarocks", execute_bool, true, false), 619 ["luarocks_admin"] = "luarocks-admin",
579 luarocks_nocov = make_run_function("luarocks", execute_bool, false, true),
580 luarocks_noprint_nocov = make_run_function("luarocks", execute_bool, false, false),
581 luarocks_admin = make_run_function("luarocks-admin", execute_output, true, true),
582 luarocks_admin_bool = make_run_function("luarocks-admin", execute_bool, true, true),
583 luarocks_admin_nocov = make_run_function("luarocks-admin", execute_bool, false, false)
584 } 620 }
621
622 for _, name in ipairs({"lua", "luarocks", "luarocks_admin"}) do
623 fns[name] = make_run_function(cmds[name], execute_output, true, true)
624 fns[name .. "_bool"] = make_run_function(cmds[name], execute_bool, true, true)
625 fns[name .. "_nocov"] = make_run_function(cmds[name], execute_bool, false, true)
626 fns[name .. "_noprint_nocov"] = make_run_function(cmds[name], execute_bool, false, false)
627 end
628
629 return fns
585end 630end
586 631
587local function move_file(src, dst) 632local function move_file(src, dst)
588 if test_env.TEST_TARGET_OS == "windows" then 633 local ok = execute_bool(C(tool("mv"), P(src), P(dst)))
589 execute_bool(test_env.testing_paths.win_tools .. "/mv " .. src .. " " .. dst) 634 if not ok then
590 else 635 print(debug.traceback())
591 local ok = execute_bool("mv " .. src .. " " .. dst) 636 os.exit(1)
592 if not ok then
593 print(debug.traceback())
594 os.exit(1)
595 end
596 end 637 end
597end 638end
598 639
@@ -610,13 +651,15 @@ local function build_environment(rocks, env_variables)
610 lfs.mkdir(testing_paths.testing_tree) 651 lfs.mkdir(testing_paths.testing_tree)
611 lfs.mkdir(testing_paths.testing_sys_tree) 652 lfs.mkdir(testing_paths.testing_sys_tree)
612 653
613 test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_server)) 654 test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server)))
614 test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_cache)) 655 test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_cache)))
615 656
616 for _, rock in ipairs(rocks) do 657 for _, rock in ipairs(rocks) do
617 if not test_env.run.luarocks_nocov(test_env.quiet("install --only-server=" .. testing_paths.testing_cache .. " --tree=" .. testing_paths.testing_sys_tree .. " " .. Q(rock), env_variables)) then 658 local only_server = "--only-server=" .. testing_paths.testing_cache
618 assert(test_env.run.luarocks_nocov("build --tree=" .. Q(testing_paths.testing_sys_tree) .. " " .. Q(rock), env_variables)) 659 local tree = "--tree=" .. testing_paths.testing_sys_tree
619 assert(test_env.run.luarocks_nocov("pack --tree=" .. Q(testing_paths.testing_sys_tree) .. " " .. Q(rock), env_variables)) 660 if not test_env.run.luarocks_nocov(test_env.quiet(C("install", only_server, tree, Q(rock)), env_variables)) then
661 assert(test_env.run.luarocks_nocov(C("build", tree, Q(rock)), env_variables))
662 assert(test_env.run.luarocks_nocov(C("pack", tree, Q(rock)), env_variables))
620 move_file(rock .. "-*.rock", testing_paths.testing_cache) 663 move_file(rock .. "-*.rock", testing_paths.testing_cache)
621 end 664 end
622 end 665 end
@@ -641,16 +684,6 @@ local function reset_environment(testing_paths, md5sums)
641 end 684 end
642end 685end
643 686
644local function found_interpreter(testing_paths, luadir, lua_bindir)
645 local location = lua_bindir .. "/" .. testing_paths.lua_exe
646 if exists(location) then
647 testing_paths.lua_bindir = lua_bindir
648 testing_paths.luadir = luadir
649 testing_paths.lua = location
650 return true
651 end
652end
653
654local function find_lua() 687local function find_lua()
655 -- (1) LUA is a full path 688 -- (1) LUA is a full path
656 if test_env.LUA and test_env.LUA:match("[/\\]") then 689 if test_env.LUA and test_env.LUA:match("[/\\]") then
@@ -671,22 +704,22 @@ local function find_lua()
671 if test_env.LUA_DIR then 704 if test_env.LUA_DIR then
672 705
673 local luadir = test_env.LUA_DIR 706 local luadir = test_env.LUA_DIR
674 local lua_bindir = exists(luadir .. "/bin") 707 local lua_bindir = exists(dir_path(luadir, "bin"))
675 and luadir .. "/bin" 708 and dir_path(luadir, "bin")
676 or luadir 709 or luadir
677 local lua = lua_bindir .. "/" .. lua_exe 710 local lua = dir_path(lua_bindir, lua_exe)
678 711
679 return lua_bindir, luadir, lua 712 return lua_bindir, luadir, lua
680 end 713 end
681 714
682 -- (2.2) LUA_DIR was not given, try some default paths 715 -- (2.2) LUA_DIR was not given, try some default paths
683 local try_dirs = (test_env.TEST_TARGET_OS == "windows") 716 local try_dirs = (test_env.TEST_TARGET_OS == "windows")
684 and { os.getenv("ProgramFiles(x86)").."/LuaRocks" } 717 and { os.getenv("ProgramFiles(x86)").."\\LuaRocks" }
685 or { "/usr/local", "/usr" } 718 or { "/usr/local", "/usr" }
686 719
687 for _, luadir in ipairs(try_dirs) do 720 for _, luadir in ipairs(try_dirs) do
688 for _, lua_bindir in ipairs({ luadir, luadir .. "/bin" }) do 721 for _, lua_bindir in ipairs({ luadir, dir_path(luadir, "bin") }) do
689 local lua = lua_bindir .. "/" .. lua_exe 722 local lua = dir_path(lua_bindir, lua_exe)
690 if exists(lua) then 723 if exists(lua) then
691 return lua_bindir, luadir, lua 724 return lua_bindir, luadir, lua
692 end 725 end
@@ -694,50 +727,47 @@ local function find_lua()
694 end 727 end
695end 728end
696 729
697local function create_paths(luaversion_full) 730local function create_testing_paths(suffix)
698 731 local paths = {}
699 local testing_paths = {}
700 732
701 testing_paths.lua_bindir, testing_paths.luadir, testing_paths.lua = find_lua() 733 paths.lua_bindir, paths.luadir, paths.lua = find_lua()
702 if (not testing_paths.lua) or (not exists(testing_paths.lua)) then 734 if (not paths.lua) or (not exists(paths.lua)) then
703 error("Lua interpreter not found! Run `busted -Xhelper help` for options") 735 error("Lua interpreter not found! Run `busted -Xhelper help` for options")
704 end 736 end
705 737
706 local base_dir = lfs.currentdir() 738 local base_dir = lfs.currentdir()
739 paths.src_dir = dir_path(base_dir, "src")
740 paths.spec_dir = dir_path(base_dir, "spec")
741 paths.util_dir = dir_path(base_dir, "spec", "util")
742 paths.fixtures_dir = dir_path(base_dir, "spec", "fixtures")
743 paths.fixtures_repo_dir = dir_path(base_dir, "spec", "fixtures", "a_repo")
744 paths.gpg_dir = dir_path(base_dir, "spec", "fixtures", "gpg")
745
746 local testrun_dir = dir_path(base_dir, "testrun")
747 paths.testrun_dir = testrun_dir
748 paths.testing_lrprefix = dir_path(testrun_dir, "testing_lrprefix-" .. suffix)
749 paths.testing_tree = dir_path(testrun_dir, "testing-" .. suffix)
750 paths.testing_tree_copy = dir_path(testrun_dir, "testing_copy-" .. suffix)
751 paths.testing_sys_tree = dir_path(testrun_dir, "testing_sys-" .. suffix)
752 paths.testing_sys_tree_copy = dir_path(testrun_dir, "testing_sys_copy-" .. suffix)
753 paths.testing_cache = dir_path(testrun_dir, "testing_cache-" .. suffix)
754 paths.testing_server = dir_path(testrun_dir, "testing_server-" .. suffix)
755
756 local rocks_v = "rocks-" .. test_env.lua_version
757 paths.testing_rocks = dir_path(paths.testing_tree, "lib", "luarocks", rocks_v)
758 paths.testing_sys_rocks = dir_path(paths.testing_sys_tree, "lib", "luarocks", rocks_v)
707 759
708 if test_env.TEST_TARGET_OS == "windows" then 760 if test_env.TEST_TARGET_OS == "windows" then
709 base_dir = base_dir:gsub("\\","/") 761 paths.luarocks_tmp = os.getenv("TEMP")
710 end
711
712 testing_paths.fixtures_dir = base_dir .. "/spec/fixtures"
713 testing_paths.gpg_dir = testing_paths.fixtures_dir .. "/gpg"
714 testing_paths.fixtures_repo_dir = base_dir .. "/spec/fixtures/a_repo"
715 testing_paths.util_dir = base_dir .. "/spec/util"
716 testing_paths.testrun_dir = base_dir .. "/testrun"
717 testing_paths.src_dir = base_dir .. "/src"
718 testing_paths.spec_dir = base_dir .. "/spec"
719 testing_paths.testing_lrprefix = testing_paths.testrun_dir .. "/testing_lrprefix-" .. luaversion_full
720 testing_paths.testing_tree = testing_paths.testrun_dir .. "/testing-" .. luaversion_full
721 testing_paths.testing_tree_copy = testing_paths.testrun_dir .. "/testing_copy-" .. luaversion_full
722 testing_paths.testing_sys_tree = testing_paths.testrun_dir .. "/testing_sys-" .. luaversion_full
723 testing_paths.testing_sys_tree_copy = testing_paths.testrun_dir .. "/testing_sys_copy-" .. luaversion_full
724 testing_paths.testing_cache = testing_paths.testrun_dir .. "/testing_cache-" .. luaversion_full
725 testing_paths.testing_server = testing_paths.testrun_dir .. "/testing_server-" .. luaversion_full
726
727 testing_paths.testing_rocks = testing_paths.testing_tree .. "/lib/luarocks/rocks-" .. test_env.lua_version
728 testing_paths.testing_sys_rocks = testing_paths.testing_sys_tree .. "/lib/luarocks/rocks-" .. test_env.lua_version
729
730 if test_env.TEST_TARGET_OS == "windows" then
731 testing_paths.luarocks_tmp = os.getenv("TEMP")
732 else 762 else
733 testing_paths.luarocks_tmp = "/tmp/luarocks_testing" 763 paths.luarocks_tmp = "/tmp/luarocks_testing"
734 end 764 end
735 765
736 if test_env.TEST_TARGET_OS == "windows" then 766 if test_env.TEST_TARGET_OS == "windows" then
737 testing_paths.win_tools = base_dir .. "/win32/tools" 767 paths.win_tools = dir_path(base_dir, "win32", "tools")
738 end 768 end
739 769
740 return testing_paths 770 return paths
741end 771end
742 772
743--- Helper function to unload luarocks modules from global table package.loaded 773--- Helper function to unload luarocks modules from global table package.loaded
@@ -748,7 +778,7 @@ function test_env.unload_luarocks()
748 package.loaded[modname] = nil 778 package.loaded[modname] = nil
749 end 779 end
750 end 780 end
751 local src_pattern = test_env.testing_paths.src_dir .. "/?.lua" 781 local src_pattern = dir_path(test_env.testing_paths.src_dir, "?.lua")
752 if not package.path:find(src_pattern, 1, true) then 782 if not package.path:find(src_pattern, 1, true) then
753 package.path = src_pattern .. ";" .. package.path 783 package.path = src_pattern .. ";" .. package.path
754 end 784 end
@@ -760,16 +790,19 @@ local function get_luarocks_platform(variables)
760 "cfg.init();" .. 790 "cfg.init();" ..
761 "print(cfg.arch)" .. 791 "print(cfg.arch)" ..
762 "\"" 792 "\""
763 local cmd = test_env.testing_paths.lua .. " -e " .. print_arch_script 793 local cmd = C(test_env.testing_paths.lua, "-e", print_arch_script)
764 return execute_output(cmd, false, variables) 794 return execute_output(cmd, false, variables)
765end 795end
766 796
767--- Function for initial setup of environment, variables, md5sums for spec files 797--- Function for initial setup of environment, variables, md5sums for spec files
768function test_env.setup_specs(extra_rocks) 798function test_env.setup_specs(extra_rocks)
799 local testrun_dir = test_env.testing_paths.testrun_dir
800 local variables = test_env.env_variables
801
769 -- if global variable about successful creation of testing environment doesn't exist, build environment 802 -- if global variable about successful creation of testing environment doesn't exist, build environment
770 if not test_env.setup_done then 803 if not test_env.setup_done then
771 if test_env.CI then 804 if test_env.CI then
772 if not exists(os.getenv("HOME") .. "/.ssh/id_rsa.pub") then 805 if not exists(os.getenv("HOME"), ".ssh/id_rsa.pub") then
773 execute_bool("ssh-keygen -t rsa -P \"\" -f ~/.ssh/id_rsa") 806 execute_bool("ssh-keygen -t rsa -P \"\" -f ~/.ssh/id_rsa")
774 execute_bool("cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys") 807 execute_bool("cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys")
775 execute_bool("chmod og-wx ~/.ssh/authorized_keys") 808 execute_bool("chmod og-wx ~/.ssh/authorized_keys")
@@ -783,8 +816,8 @@ function test_env.setup_specs(extra_rocks)
783 require("spec.util.git_repo") 816 require("spec.util.git_repo")
784 require("spec.util.quick") 817 require("spec.util.quick")
785 818
786 package.path = test_env.env_variables.LUA_PATH 819 package.path = variables.LUA_PATH
787 package.cpath = test_env.env_variables.LUA_CPATH 820 package.cpath = variables.LUA_CPATH
788 821
789 test_env.platform = get_luarocks_platform(test_env.env_variables) 822 test_env.platform = get_luarocks_platform(test_env.env_variables)
790 test_env.wrapper_extension = test_env.TEST_TARGET_OS == "windows" and ".bat" or "" 823 test_env.wrapper_extension = test_env.TEST_TARGET_OS == "windows" and ".bat" or ""
@@ -801,10 +834,10 @@ function test_env.setup_specs(extra_rocks)
801 end 834 end
802 835
803 if test_env.RESET_ENV then 836 if test_env.RESET_ENV then
804 reset_environment(test_env.testing_paths, test_env.md5sums, test_env.env_variables) 837 reset_environment(test_env.testing_paths, test_env.md5sums, variables)
805 end 838 end
806 839
807 lfs.chdir(test_env.testing_paths.testrun_dir) 840 lfs.chdir(testrun_dir)
808end 841end
809 842
810--- Test if required rock is installed and if not, install it. 843--- Test if required rock is installed and if not, install it.
@@ -829,7 +862,11 @@ end
829-- replace %{key} in given string with value. 862-- replace %{key} in given string with value.
830local function substitute(str, replacements) 863local function substitute(str, replacements)
831 return (str:gsub("%%%b{}", function(marker) 864 return (str:gsub("%%%b{}", function(marker)
832 return replacements[marker:sub(3, -2)] 865 local r = replacements[marker:sub(3, -2)]
866 if r then
867 r = r:gsub("\\", "\\\\")
868 end
869 return r
833 end)) 870 end))
834end 871end
835 872
@@ -837,6 +874,8 @@ end
837--- Create configs for luacov and several versions of Luarocks 874--- Create configs for luacov and several versions of Luarocks
838-- configs needed for some tests. 875-- configs needed for some tests.
839local function create_configs() 876local function create_configs()
877 local testrun_dir = test_env.testing_paths.testrun_dir
878
840 -- testing_config.lua 879 -- testing_config.lua
841 -- testing_config_show_downloads.lua 880 -- testing_config_show_downloads.lua
842 -- testing_config_no_downloader.lua 881 -- testing_config_no_downloader.lua
@@ -857,17 +896,17 @@ local function create_configs()
857 }, 896 },
858 } 897 }
859 ]], { 898 ]], {
860 user = os.getenv("USER"), 899 user = "testuser",
861 testing_sys_tree = test_env.testing_paths.testing_sys_tree, 900 testing_sys_tree = test_env.testing_paths.testing_sys_tree,
862 testing_tree = test_env.testing_paths.testing_tree, 901 testing_tree = test_env.testing_paths.testing_tree,
863 testing_server = test_env.testing_paths.testing_server, 902 testing_server = test_env.testing_paths.testing_server,
864 testing_cache = test_env.testing_paths.testing_cache 903 testing_cache = test_env.testing_paths.testing_cache
865 }) 904 })
866 905
867 test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config.lua", config_content .. " \nweb_browser = \"true\"") 906 test_env.write_file(dir_path(testrun_dir, "testing_config.lua"), config_content .. " \nweb_browser = \"true\"")
868 test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_show_downloads.lua", config_content 907 test_env.write_file(dir_path(testrun_dir, "testing_config_show_downloads.lua"), config_content
869 .. "show_downloads = true \n rocks_servers={\"http://luarocks.org/repositories/rocks\"}") 908 .. "show_downloads = true \n rocks_servers={\"http://luarocks.org/repositories/rocks\"}")
870 test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_no_downloader.lua", config_content 909 test_env.write_file(dir_path(testrun_dir, "testing_config_no_downloader.lua"), config_content
871 .. "variables = { WGET = 'invalid', CURL = 'invalid' }") 910 .. "variables = { WGET = 'invalid', CURL = 'invalid' }")
872 911
873 -- testing_config_sftp.lua 912 -- testing_config_sftp.lua
@@ -885,32 +924,35 @@ local function create_configs()
885 }, 924 },
886 } 925 }
887 ]], { 926 ]], {
888 user = os.getenv("USER"), 927 user = "testuser",
889 testing_sys_tree = test_env.testing_paths.testing_sys_tree, 928 testing_sys_tree = test_env.testing_paths.testing_sys_tree,
890 testing_tree = test_env.testing_paths.testing_tree, 929 testing_tree = test_env.testing_paths.testing_tree,
891 testing_cache = test_env.testing_paths.testing_cache 930 testing_cache = test_env.testing_paths.testing_cache
892 }) 931 })
893 932
894 test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_sftp.lua", config_content) 933 test_env.write_file(dir_path(testrun_dir, "testing_config_sftp.lua"), config_content)
895 934
896 -- luacov.config 935 -- luacov.config
897 config_content = substitute([[ 936 config_content = substitute([[
898 return { 937 return {
899 statsfile = "%{testrun_dir}/luacov.stats.out", 938 statsfile = "%{statsfile}",
900 reportfile = "%{testrun_dir}/luacov.report.out", 939 reportfile = "%{reportfile}",
901 modules = { 940 modules = {
902 ["luarocks"] = "src/bin/luarocks", 941 ["luarocks"] = "%{luarocks_path}",
903 ["luarocks-admin"] = "src/bin/luarocks-admin", 942 ["luarocks-admin"] = "%{luarocks_admin_path}",
904 ["luarocks.*"] = "src", 943 ["luarocks.*"] = "src",
905 ["luarocks.*.*"] = "src", 944 ["luarocks.*.*"] = "src",
906 ["luarocks.*.*.*"] = "src" 945 ["luarocks.*.*.*"] = "src"
907 } 946 }
908 } 947 }
909 ]], { 948 ]], {
910 testrun_dir = test_env.testing_paths.testrun_dir 949 statsfile = dir_path(testrun_dir, "luacov.stats.out"),
950 reportfile = dir_path(testrun_dir, "luacov.report.out"),
951 luarocks_path = dir_path("src", "bin", "luarocks"),
952 luarocks_admin_path = dir_path("src", "bin", "luarocks-admin"),
911 }) 953 })
912 954
913 test_env.write_file(test_env.testing_paths.testrun_dir .. "/luacov.config", config_content) 955 test_env.write_file(dir_path(testrun_dir, "luacov.config"), config_content)
914 956
915 config_content = [[ 957 config_content = [[
916 -- Config file of mock LuaRocks.org site for tests 958 -- Config file of mock LuaRocks.org site for tests
@@ -920,18 +962,20 @@ local function create_configs()
920 api_version = "1", 962 api_version = "1",
921 } 963 }
922 ]] 964 ]]
923 test_env.write_file(test_env.testing_paths.testrun_dir .. "/luarocks_site.lua", config_content) 965 test_env.write_file(dir_path(testrun_dir, "luarocks_site.lua"), config_content)
924end 966end
925 967
926--- Remove testing directories. 968--- Remove testing directories.
927local function clean() 969local function clean()
970 local testrun_dir = test_env.testing_paths.testrun_dir
971
928 print("Cleaning testing directory...") 972 print("Cleaning testing directory...")
929 test_env.remove_dir(test_env.testing_paths.luarocks_tmp) 973 test_env.remove_dir(test_env.testing_paths.luarocks_tmp)
930 test_env.remove_subdirs(test_env.testing_paths.testrun_dir, "testing[_%-]") 974 test_env.remove_subdirs(testrun_dir, "testing[_%-]")
931 test_env.remove_files(test_env.testing_paths.testrun_dir, "testing_") 975 test_env.remove_files(testrun_dir, "testing_")
932 test_env.remove_files(test_env.testing_paths.testrun_dir, "luacov") 976 test_env.remove_files(testrun_dir, "luacov")
933 test_env.remove_files(test_env.testing_paths.testrun_dir, "upload_config") 977 test_env.remove_files(testrun_dir, "upload_config")
934 test_env.remove_files(test_env.testing_paths.testrun_dir, "luarocks_site") 978 test_env.remove_files(testrun_dir, "luarocks_site")
935 print("Cleaning done!") 979 print("Cleaning done!")
936end 980end
937 981
@@ -942,7 +986,7 @@ local function setup_luarocks()
942 986
943 local lines = { 987 local lines = {
944 "return {", 988 "return {",
945 ("SYSCONFDIR = %q,"):format(testing_paths.testing_lrprefix .. "/etc/luarocks"), 989 ("SYSCONFDIR = %q,"):format(dir_path(testing_paths.testing_lrprefix, "etc/luarocks")),
946 ("LUA_DIR = %q,"):format(testing_paths.luadir), 990 ("LUA_DIR = %q,"):format(testing_paths.luadir),
947 ("LUA_BINDIR = %q,"):format(testing_paths.lua_bindir), 991 ("LUA_BINDIR = %q,"):format(testing_paths.lua_bindir),
948 ("LUA = %q,"):format(testing_paths.lua), 992 ("LUA = %q,"):format(testing_paths.lua),
@@ -965,33 +1009,33 @@ local function setup_luarocks()
965end 1009end
966 1010
967local function mock_api_call(path) 1011local function mock_api_call(path)
968 if test_env.TEST_TARGET_OS == "windows" then 1012 test_env.execute(C(tool("wget"), "--quiet --timeout=5 --tries=1 localhost:8080" .. path))
969 return test_env.execute(Q(test_env.testing_paths.win_tools .. "/wget") .. " --quiet --timeout=5 --tries=1 localhost:8080" .. path)
970 else
971 return test_env.execute("curl -s localhost:8080" .. path)
972 end
973end 1013end
974 1014
975function test_env.mock_server_init() 1015function test_env.mock_server_init()
976 local testing_paths = test_env.testing_paths 1016 local testing_paths = test_env.testing_paths
977 assert(test_env.need_rock("restserver-xavante")) 1017 assert(test_env.need_rock("restserver-xavante"))
978 1018
979 if test_env.TEST_TARGET_OS == "windows" then 1019 local lua = Q(testing_paths.lua)
980 os.execute(test_env.execute_helper("start /b \"\" " .. Q(testing_paths.lua) .. " " .. Q(testing_paths.util_dir .. "/mock-server.lua") .. " " .. Q(testing_paths.fixtures_dir), true, test_env.env_variables)) 1020 local mock_server = Q(dir_path(testing_paths.util_dir, "mock-server.lua"))
981 else 1021 local fixtures_dir = Q(testing_paths.fixtures_dir)
982 os.execute(test_env.execute_helper(testing_paths.lua .. " " .. testing_paths.util_dir .. "/mock-server.lua " .. testing_paths.fixtures_dir .. " &", true, test_env.env_variables)) 1022
983 end 1023 local cmd = C(lua, mock_server, fixtures_dir)
1024
1025 local bg_cmd = test_env.TEST_TARGET_OS == "windows"
1026 and C("start", "/b", "\"\"", cmd)
1027 or C(cmd, "&")
1028
1029 os.execute(test_env.execute_helper(bg_cmd, true, test_env.env_variables))
984 1030
985 for _ = 1, 10 do 1031 for _ = 1, 10 do
986 if mock_api_call("/api/tool_version") then 1032 if mock_api_call("/api/tool_version") then
987 break 1033 break
988 end 1034 end
989 1035
990 if test_env.TEST_TARGET_OS == "windows" then 1036 os.execute(test_env.TEST_TARGET_OS == "windows"
991 os.execute("timeout 1 > NUL") 1037 and "timeout 1 > NUL"
992 else 1038 or "sleep 1")
993 os.execute("sleep 1")
994 end
995 end 1039 end
996 1040
997end 1041end
@@ -1000,9 +1044,9 @@ function test_env.mock_server_done()
1000 mock_api_call("/shutdown") 1044 mock_api_call("/shutdown")
1001end 1045end
1002 1046
1003local function find_binary_rock(src_rock, dir) 1047local function find_binary_rock(src_rock, dirname)
1004 local patt = src_rock:gsub("([.-])", "%%%1"):gsub("src", ".*[^s][^r][^c]") 1048 local patt = src_rock:gsub("([.-])", "%%%1"):gsub("src", ".*[^s][^r][^c]")
1005 for name in lfs.dir(dir) do 1049 for name in lfs.dir(dirname) do
1006 if name:match(patt) then 1050 if name:match(patt) then
1007 return true 1051 return true
1008 end 1052 end
@@ -1034,14 +1078,18 @@ local function prepare_mock_server_binary_rocks()
1034 rock = V(rock) 1078 rock = V(rock)
1035 local rockname = rock:gsub("%-[^-]+%-%d+%.[%a.]+$", "") 1079 local rockname = rock:gsub("%-[^-]+%-%d+%.[%a.]+$", "")
1036 if not find_binary_rock(rock, testing_paths.testing_server) then 1080 if not find_binary_rock(rock, testing_paths.testing_server) then
1037 test_env.run.luarocks_nocov("build " .. Q(testing_paths.testing_server .. "/" .. rock) .. " --tree=" .. testing_paths.testing_cache) 1081 local rockpath = dir_path(testing_paths.testing_server, rock)
1038 test_env.run.luarocks_nocov("pack " .. rockname .. " --tree=" .. testing_paths.testing_cache) 1082 local tree = "--tree=" .. testing_paths.testing_cache
1083
1084 test_env.run.luarocks_nocov(C("build", Q(rockpath), tree))
1085 test_env.run.luarocks_nocov(C("pack", rockname, tree))
1086
1039 move_file(rockname .. "-*.rock", testing_paths.testing_server) 1087 move_file(rockname .. "-*.rock", testing_paths.testing_server)
1040 make_manifest = true 1088 make_manifest = true
1041 end 1089 end
1042 end 1090 end
1043 if make_manifest then 1091 if make_manifest then
1044 test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_server)) 1092 test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server)))
1045 end 1093 end
1046end 1094end
1047 1095
@@ -1049,13 +1097,14 @@ end
1049-- Main function to create config files and testing environment 1097-- Main function to create config files and testing environment
1050function test_env.main() 1098function test_env.main()
1051 local testing_paths = test_env.testing_paths 1099 local testing_paths = test_env.testing_paths
1100 local testrun_dir = test_env.testing_paths.testrun_dir
1052 1101
1053 if test_env.TEST_ENV_CLEAN then 1102 if test_env.TEST_ENV_CLEAN then
1054 clean() 1103 clean()
1055 end 1104 end
1056 1105
1057 lfs.mkdir(testing_paths.testrun_dir) 1106 lfs.mkdir(testrun_dir)
1058 test_env.write_file(testing_paths.testrun_dir .. "/.luarocks-no-project", "") 1107 test_env.write_file(dir_path(testrun_dir, ".luarocks-no-project"), "")
1059 lfs.mkdir(testing_paths.testing_cache) 1108 lfs.mkdir(testing_paths.testing_cache)
1060 lfs.mkdir(testing_paths.luarocks_tmp) 1109 lfs.mkdir(testing_paths.luarocks_tmp)
1061 1110
@@ -1068,7 +1117,7 @@ function test_env.main()
1068 local urls = {} -- names of rock and rockspec files to be downloaded 1117 local urls = {} -- names of rock and rockspec files to be downloaded
1069 1118
1070 local env_vars = { 1119 local env_vars = {
1071 LUAROCKS_CONFIG = test_env.testing_paths.testrun_dir .. "/testing_config.lua" 1120 LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua")
1072 } 1121 }
1073 1122
1074 if test_env.TYPE_TEST_ENV == "full" then 1123 if test_env.TYPE_TEST_ENV == "full" then
@@ -1088,8 +1137,8 @@ function test_env.main()
1088 table.insert(urls, "/luaposix-${LUAPOSIX}.src.rock") 1137 table.insert(urls, "/luaposix-${LUAPOSIX}.src.rock")
1089 table.insert(rocks, "luaposix") 1138 table.insert(rocks, "luaposix")
1090 end 1139 end
1091 assert(test_env.run.luarocks_nocov("config variables.OPENSSL_INCDIR " .. Q(test_env.OPENSSL_INCDIR), env_vars)) 1140 assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_INCDIR", Q(test_env.OPENSSL_INCDIR)), env_vars))
1092 assert(test_env.run.luarocks_nocov("config variables.OPENSSL_LIBDIR " .. Q(test_env.OPENSSL_LIBDIR), env_vars)) 1141 assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_LIBDIR", Q(test_env.OPENSSL_LIBDIR)), env_vars))
1093 end 1142 end
1094 1143
1095 -- luacov is needed for both minimal or full environment 1144 -- luacov is needed for both minimal or full environment
@@ -1111,12 +1160,13 @@ end
1111 1160
1112test_env.set_lua_version() 1161test_env.set_lua_version()
1113test_env.set_args() 1162test_env.set_args()
1114test_env.testing_paths = create_paths(test_env.LUA_V or test_env.LUAJIT_V) 1163test_env.testing_paths = create_testing_paths(test_env.LUA_V or test_env.LUAJIT_V)
1115test_env.env_variables = create_env(test_env.testing_paths) 1164test_env.env_variables = create_env(test_env.testing_paths)
1116test_env.run = make_run_functions() 1165test_env.run = make_run_functions()
1117test_env.exists = exists 1166test_env.exists = exists
1118test_env.V = V 1167test_env.V = V
1119test_env.Q = Q 1168test_env.Q = Q
1169test_env.P = P
1120test_env.platform = get_luarocks_platform(test_env.env_variables) 1170test_env.platform = get_luarocks_platform(test_env.env_variables)
1121 1171
1122return test_env 1172return test_env
diff --git a/spec/util_spec.lua b/spec/util_spec.lua
index 0c2d620e..abc0da57 100644
--- a/spec/util_spec.lua
+++ b/spec/util_spec.lua
@@ -2,6 +2,7 @@ local test_env = require("spec.util.test_env")
2local lfs = require("lfs") 2local lfs = require("lfs")
3local run = test_env.run 3local run = test_env.run
4local testing_paths = test_env.testing_paths 4local testing_paths = test_env.testing_paths
5local P = test_env.P
5 6
6describe("Basic tests #integration", function() 7describe("Basic tests #integration", function()
7 8
@@ -182,34 +183,34 @@ describe("luarocks.util #unit", function()
182 end) 183 end)
183 184
184 describe("core.util.cleanup_path", function() 185 describe("core.util.cleanup_path", function()
185 it("does not change order of existing items of prepended path", function() 186 it("does not change order of existing items of prepended path", function()
186 local sys_path = '/usr/local/bin;/usr/bin' 187 local sys_path = P'/usr/local/bin;/usr/bin'
187 local lr_path = '/home/user/.luarocks/bin;/usr/bin' 188 local lr_path = P'/home/user/.luarocks/bin;/usr/bin'
188 local path = lr_path .. ';' .. sys_path 189 local path = lr_path .. ';' .. sys_path
189 190
190 local result = core_util.cleanup_path(path, ';', '5.3', false) 191 local result = core_util.cleanup_path(path, ';', '5.3', false)
191 assert.are.equal('/home/user/.luarocks/bin;/usr/local/bin;/usr/bin', result) 192 assert.are.equal(P'/home/user/.luarocks/bin;/usr/local/bin;/usr/bin', result)
192 end) 193 end)
193 194
194 it("does not change order of existing items of appended path", function() 195 it("does not change order of existing items of appended path", function()
195 local sys_path = '/usr/local/bin;/usr/bin' 196 local sys_path = P'/usr/local/bin;/usr/bin'
196 local lr_path = '/home/user/.luarocks/bin;/usr/bin' 197 local lr_path = P'/home/user/.luarocks/bin;/usr/bin'
197 local path = sys_path .. ';' .. lr_path 198 local path = sys_path .. ';' .. lr_path
198 199
199 local result = core_util.cleanup_path(path, ';', '5.3', true) 200 local result = core_util.cleanup_path(path, ';', '5.3', true)
200 assert.are.equal('/usr/local/bin;/usr/bin;/home/user/.luarocks/bin', result) 201 assert.are.equal(P'/usr/local/bin;/usr/bin;/home/user/.luarocks/bin', result)
201 end) 202 end)
202 203
203 it("rewrites versions that do not match the provided version", function() 204 it("rewrites versions that do not match the provided version", function()
204 local expected = 'a/b/lua/5.3/?.lua;a/b/c/lua/5.3/?.lua' 205 local expected = P'a/b/lua/5.3/?.lua;a/b/c/lua/5.3/?.lua'
205 local result = core_util.cleanup_path('a/b/lua/5.2/?.lua;a/b/c/lua/5.3/?.lua', ';', '5.3') 206 local result = core_util.cleanup_path(P'a/b/lua/5.2/?.lua;a/b/c/lua/5.3/?.lua', ';', '5.3')
206 assert.are.equal(expected, result) 207 assert.are.equal(expected, result)
207 end) 208 end)
208 209
209 it("does not rewrite versions for which the provided version is a substring", function() 210 it("does not rewrite versions for which the provided version is a substring", function()
210 local expected = 'a/b/lua/5.3/?.lua;a/b/c/lua/5.3.4/?.lua' 211 local expected = P'a/b/lua/5.3/?.lua;a/b/c/lua/5.3.4/?.lua'
211 local result = core_util.cleanup_path('a/b/lua/5.2/?.lua;a/b/c/lua/5.3.4/?.lua', ';', '5.3') 212 local result = core_util.cleanup_path(P'a/b/lua/5.2/?.lua;a/b/c/lua/5.3.4/?.lua', ';', '5.3')
212 assert.are.equal(expected, result) 213 assert.are.equal(expected, result)
213 end) 214 end)
214 end) 215 end)
215end) 216end)
diff --git a/spec/which_spec.lua b/spec/which_spec.lua
index d6e07eb7..9ccb1040 100644
--- a/spec/which_spec.lua
+++ b/spec/which_spec.lua
@@ -1,10 +1,6 @@
1local test_env = require("spec.util.test_env") 1local test_env = require("spec.util.test_env")
2local lfs = require("lfs")
3local run = test_env.run 2local run = test_env.run
4local testing_paths = test_env.testing_paths 3local P = test_env.P
5local env_variables = test_env.env_variables
6local write_file = test_env.write_file
7local hardcoded
8 4
9test_env.unload_luarocks() 5test_env.unload_luarocks()
10 6
@@ -17,7 +13,6 @@ describe("luarocks which #integration", function()
17 setup(function() 13 setup(function()
18 test_env.setup_specs(extra_rocks) 14 test_env.setup_specs(extra_rocks)
19 test_env.unload_luarocks() -- need to be required here, because hardcoded is created after first loading of specs 15 test_env.unload_luarocks() -- need to be required here, because hardcoded is created after first loading of specs
20 hardcoded = require("luarocks.core.hardcoded")
21 end) 16 end)
22 17
23 it("fails on missing arguments", function() 18 it("fails on missing arguments", function()
@@ -28,7 +23,7 @@ describe("luarocks which #integration", function()
28 it("finds modules found in package.path", function() 23 it("finds modules found in package.path", function()
29 assert.is_true(run.luarocks_bool("install say 1.2")) 24 assert.is_true(run.luarocks_bool("install say 1.2"))
30 local output = run.luarocks("which say") 25 local output = run.luarocks("which say")
31 assert.match("say/init.lua", output, 1, true) 26 assert.match(P"say/init.lua", output, 1, true)
32 assert.match("provided by say 1.2-1", output, 1, true) 27 assert.match("provided by say 1.2-1", output, 1, true)
33 end) 28 end)
34 29
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")