aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2010-12-21 20:33:07 -0200
committerHisham Muhammad <hisham@gobolinux.org>2010-12-21 20:33:07 -0200
commit9f6ff4c8564e721e26faa7cff1bc2e0923f809e9 (patch)
treec9101814fed2a8de573075a47d8779540aecbd16
parent3f9a19ca94f9238d5ec897d0bf2cdac8eb6d763e (diff)
downloadluarocks-9f6ff4c8564e721e26faa7cff1bc2e0923f809e9.tar.gz
luarocks-9f6ff4c8564e721e26faa7cff1bc2e0923f809e9.tar.bz2
luarocks-9f6ff4c8564e721e26faa7cff1bc2e0923f809e9.zip
Fix bug with paths causing LuaRocks to break on Windows when using LuaFileSystem.
(Bug reported by Cosmin Apreutesei)
-rw-r--r--src/luarocks/fs/lua.lua101
1 files changed, 60 insertions, 41 deletions
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index 5b3efd94..a9fca7b4 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -38,6 +38,10 @@ function Q(arg)
38 return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'" 38 return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'"
39end 39end
40 40
41local function normalize(name)
42 return name:gsub("\\", "/"):gsub("/$", "")
43end
44
41--- Test is file/dir is writable. 45--- Test is file/dir is writable.
42-- Warning: testing if a file/dir is writable does not guarantee 46-- Warning: testing if a file/dir is writable does not guarantee
43-- that it will remain writable and therefore it is no replacement 47-- that it will remain writable and therefore it is no replacement
@@ -46,9 +50,10 @@ end
46-- @return boolean: true if file exists, false otherwise. 50-- @return boolean: true if file exists, false otherwise.
47function is_writable(file) 51function is_writable(file)
48 assert(file) 52 assert(file)
53 file = normalize(file)
49 local result 54 local result
50 if fs.is_dir(file) then 55 if fs.is_dir(file) then
51 local file2 = file .. '/.tmpluarockstestwritable' 56 local file2 = dir.path(file, '.tmpluarockstestwritable')
52 local fh = io.open(file2, 'wb') 57 local fh = io.open(file2, 'wb')
53 result = fh ~= nil 58 result = fh ~= nil
54 if fh then fh:close() end 59 if fh then fh:close() end
@@ -67,8 +72,8 @@ end
67-- @return string or nil: name of temporary directory or nil on failure. 72-- @return string or nil: name of temporary directory or nil on failure.
68function make_temp_dir(name) 73function make_temp_dir(name)
69 assert(type(name) == "string") 74 assert(type(name) == "string")
75 name = normalize(name)
70 76
71 name = name:gsub("\\", "/")
72 local temp_dir = (os.getenv("TMP") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000)) 77 local temp_dir = (os.getenv("TMP") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000))
73 if fs.make_dir(temp_dir) then 78 if fs.make_dir(temp_dir) then
74 return temp_dir 79 return temp_dir
@@ -100,6 +105,7 @@ end
100-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not 105-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not
101-- or if it could not perform the check for any reason. 106-- or if it could not perform the check for any reason.
102function check_md5(file, md5sum) 107function check_md5(file, md5sum)
108 file = normalize(file)
103 local computed = fs.get_md5(file) 109 local computed = fs.get_md5(file)
104 if not computed then 110 if not computed then
105 return false 111 return false
@@ -144,6 +150,7 @@ end
144-- @param d string: The directory to switch to. 150-- @param d string: The directory to switch to.
145function change_dir(d) 151function change_dir(d)
146 table.insert(dir_stack, lfs.currentdir()) 152 table.insert(dir_stack, lfs.currentdir())
153 d = normalize(d)
147 lfs.chdir(d) 154 lfs.chdir(d)
148end 155end
149 156
@@ -175,7 +182,7 @@ end
175-- @return boolean: true on success, false on failure. 182-- @return boolean: true on success, false on failure.
176function make_dir(directory) 183function make_dir(directory)
177 assert(type(directory) == "string") 184 assert(type(directory) == "string")
178 directory = directory:gsub("\\", "/") 185 directory = normalize(directory)
179 local path = nil 186 local path = nil
180 if directory:sub(2, 2) == ":" then 187 if directory:sub(2, 2) == ":" then
181 path = directory:sub(1, 2) 188 path = directory:sub(1, 2)
@@ -205,6 +212,7 @@ end
205-- @param d string: pathname of directory to remove. 212-- @param d string: pathname of directory to remove.
206function remove_dir_if_empty(d) 213function remove_dir_if_empty(d)
207 assert(d) 214 assert(d)
215 d = normalize(d)
208 lfs.rmdir(d) 216 lfs.rmdir(d)
209end 217end
210 218
@@ -214,6 +222,7 @@ end
214-- @param d string: pathname of directory to remove. 222-- @param d string: pathname of directory to remove.
215function remove_dir_tree_if_empty(d) 223function remove_dir_tree_if_empty(d)
216 assert(d) 224 assert(d)
225 d = normalize(d)
217 for i=1,10 do 226 for i=1,10 do
218 lfs.rmdir(d) 227 lfs.rmdir(d)
219 d = dir.dir_name(d) 228 d = dir.dir_name(d)
@@ -227,6 +236,8 @@ end
227-- plus an error message. 236-- plus an error message.
228function copy(src, dest) 237function copy(src, dest)
229 assert(src and dest) 238 assert(src and dest)
239 src = normalize(src)
240 dest = normalize(dest)
230 local destmode = lfs.attributes(dest, "mode") 241 local destmode = lfs.attributes(dest, "mode")
231 if destmode == "directory" then 242 if destmode == "directory" then
232 dest = dir.path(dest, dir.base_name(src)) 243 dest = dir.path(dest, dir.base_name(src))
@@ -248,6 +259,7 @@ function copy(src, dest)
248end 259end
249 260
250--- Implementation function for recursive copy of directory contents. 261--- Implementation function for recursive copy of directory contents.
262-- Assumes paths are normalized.
251-- @param src string: Pathname of source 263-- @param src string: Pathname of source
252-- @param dest string: Pathname of destination 264-- @param dest string: Pathname of destination
253-- @return boolean or (boolean, string): true on success, false on failure 265-- @return boolean or (boolean, string): true on success, false on failure
@@ -277,6 +289,8 @@ end
277-- plus an error message. 289-- plus an error message.
278function copy_contents(src, dest) 290function copy_contents(src, dest)
279 assert(src and dest) 291 assert(src and dest)
292 src = normalize(src)
293 dest = normalize(dest)
280 assert(lfs.attributes(src, "mode") == "directory") 294 assert(lfs.attributes(src, "mode") == "directory")
281 295
282 for file in lfs.dir(src) do 296 for file in lfs.dir(src) do
@@ -291,35 +305,34 @@ function copy_contents(src, dest)
291end 305end
292 306
293--- Implementation function for recursive removal of directories. 307--- Implementation function for recursive removal of directories.
294-- @param src string: Pathname of source 308-- Assumes paths are normalized.
295-- @param dest string: Pathname of destination 309-- @param name string: Pathname of file
296-- @return boolean or (boolean, string): true on success, 310-- @return boolean or (boolean, string): true on success,
297-- or nil and an error message on failure. 311-- or nil and an error message on failure.
298local function recursive_delete(src) 312local function recursive_delete(name)
299 local srcmode = lfs.attributes(src, "mode") 313 local mode = lfs.attributes(name, "mode")
300 314
301 if srcmode == "file" then 315 if mode == "file" then
302 return os.remove(src) 316 return os.remove(name)
303 elseif srcmode == "directory" then 317 elseif mode == "directory" then
304 for file in lfs.dir(src) do 318 for file in lfs.dir(name) do
305 if file ~= "." and file ~= ".." then 319 if file ~= "." and file ~= ".." then
306 local ok, err = recursive_delete(dir.path(src, file)) 320 local ok, err = recursive_delete(dir.path(name, file))
307 if not ok then return nil, err end 321 if not ok then return nil, err end
308 end 322 end
309 end 323 end
310 local ok, err = lfs.rmdir(src) 324 local ok, err = lfs.rmdir(name)
311 if not ok then return nil, err end 325 if not ok then return nil, err end
312 end 326 end
313 return true 327 return true
314end 328end
315 329
316--- Delete a file or a directory and all its contents. 330--- Delete a file or a directory and all its contents.
317-- For safety, this only accepts absolute paths. 331-- @param name string: Pathname of source
318-- @param arg string: Pathname of source
319-- @return boolean: true on success, false on failure. 332-- @return boolean: true on success, false on failure.
320function delete(arg) 333function delete(name)
321 assert(arg) 334 name = normalize(name)
322 return recursive_delete(arg) or false 335 return recursive_delete(name) or false
323end 336end
324 337
325--- List the contents of a directory. 338--- List the contents of a directory.
@@ -332,6 +345,7 @@ function list_dir(at)
332 if not at then 345 if not at then
333 at = fs.current_dir() 346 at = fs.current_dir()
334 end 347 end
348 at = normalize(at)
335 if not fs.is_dir(at) then 349 if not fs.is_dir(at) then
336 return {} 350 return {}
337 end 351 end
@@ -345,6 +359,7 @@ function list_dir(at)
345end 359end
346 360
347--- Implementation function for recursive find. 361--- Implementation function for recursive find.
362-- Assumes paths are normalized.
348-- @param cwd string: Current working directory in recursion. 363-- @param cwd string: Current working directory in recursion.
349-- @param prefix string: Auxiliary prefix string to form pathname. 364-- @param prefix string: Auxiliary prefix string to form pathname.
350-- @param result table: Array of strings where results are collected. 365-- @param result table: Array of strings where results are collected.
@@ -371,6 +386,7 @@ function find(at)
371 if not at then 386 if not at then
372 at = fs.current_dir() 387 at = fs.current_dir()
373 end 388 end
389 at = normalize(at)
374 if not fs.is_dir(at) then 390 if not fs.is_dir(at) then
375 return {} 391 return {}
376 end 392 end
@@ -384,7 +400,8 @@ end
384-- @return boolean: true if file exists, false otherwise. 400-- @return boolean: true if file exists, false otherwise.
385function exists(file) 401function exists(file)
386 assert(file) 402 assert(file)
387 return type(lfs.attributes(file)) == "table" 403 file = normalize(file)
404 return type(file) == "table"
388end 405end
389 406
390--- Test is pathname is a directory. 407--- Test is pathname is a directory.
@@ -392,6 +409,7 @@ end
392-- @return boolean: true if it is a directory, false otherwise. 409-- @return boolean: true if it is a directory, false otherwise.
393function is_dir(file) 410function is_dir(file)
394 assert(file) 411 assert(file)
412 file = normalize(file)
395 return lfs.attributes(file, "mode") == "directory" 413 return lfs.attributes(file, "mode") == "directory"
396end 414end
397 415
@@ -400,10 +418,12 @@ end
400-- @return boolean: true if it is a file, false otherwise. 418-- @return boolean: true if it is a file, false otherwise.
401function is_file(file) 419function is_file(file)
402 assert(file) 420 assert(file)
421 file = normalize(file)
403 return lfs.attributes(file, "mode") == "file" 422 return lfs.attributes(file, "mode") == "file"
404end 423end
405 424
406function set_time(file, time) 425function set_time(file, time)
426 file = normalize(file)
407 return lfs.touch(file, time) 427 return lfs.touch(file, time)
408end 428end
409 429
@@ -426,27 +446,27 @@ if unzip_ok then
426-- @param zipfile string: pathname of .zip archive to be extracted. 446-- @param zipfile string: pathname of .zip archive to be extracted.
427-- @return boolean: true on success, false on failure. 447-- @return boolean: true on success, false on failure.
428function unzip(zipfile) 448function unzip(zipfile)
429 local zipfile, err = luazip.open(zipfile) 449 local zipfile, err = luazip.open(zipfile)
430 if not zipfile then return nil, err end 450 if not zipfile then return nil, err end
431 local files = zipfile:files() 451 local files = zipfile:files()
432 local file = files() 452 local file = files()
433 repeat 453 repeat
434 if file.filename:sub(#file.filename) == "/" then 454 if file.filename:sub(#file.filename) == "/" then
435 fs.make_dir(dir.path(fs.current_dir(), file.filename)) 455 fs.make_dir(dir.path(fs.current_dir(), file.filename))
436 else 456 else
437 local rf, err = zipfile:open(file.filename) 457 local rf, err = zipfile:open(file.filename)
438 if not rf then zipfile:close(); return nil, err end 458 if not rf then zipfile:close(); return nil, err end
439 local contents = rf:read("*a") 459 local contents = rf:read("*a")
440 rf:close() 460 rf:close()
441 local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb") 461 local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb")
442 if not wf then zipfile:close(); return nil, err end 462 if not wf then zipfile:close(); return nil, err end
443 wf:write(contents) 463 wf:write(contents)
444 wf:close() 464 wf:close()
445 end 465 end
446 file = files() 466 file = files()
447 until not file 467 until not file
448 zipfile:close() 468 zipfile:close()
449 return true 469 return true
450end 470end
451 471
452end 472end
@@ -457,7 +477,6 @@ end
457 477
458if socket_ok then 478if socket_ok then
459 479
460
461local ltn12 = require("ltn12") 480local ltn12 = require("ltn12")
462 481
463--- Download a remote file. 482--- Download a remote file.