diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2010-12-21 20:33:07 -0200 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2010-12-21 20:33:07 -0200 |
| commit | 9f6ff4c8564e721e26faa7cff1bc2e0923f809e9 (patch) | |
| tree | c9101814fed2a8de573075a47d8779540aecbd16 /src | |
| parent | 3f9a19ca94f9238d5ec897d0bf2cdac8eb6d763e (diff) | |
| download | luarocks-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)
Diffstat (limited to 'src')
| -rw-r--r-- | src/luarocks/fs/lua.lua | 101 |
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("'", "'\\''") .. "'" |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | local function normalize(name) | ||
| 42 | return name:gsub("\\", "/"):gsub("/$", "") | ||
| 43 | end | ||
| 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. |
| 47 | function is_writable(file) | 51 | function 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. |
| 68 | function make_temp_dir(name) | 73 | function 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. |
| 102 | function check_md5(file, md5sum) | 107 | function 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. |
| 145 | function change_dir(d) | 151 | function 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) |
| 148 | end | 155 | end |
| 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. |
| 176 | function make_dir(directory) | 183 | function 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. |
| 206 | function remove_dir_if_empty(d) | 213 | function remove_dir_if_empty(d) |
| 207 | assert(d) | 214 | assert(d) |
| 215 | d = normalize(d) | ||
| 208 | lfs.rmdir(d) | 216 | lfs.rmdir(d) |
| 209 | end | 217 | end |
| 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. |
| 215 | function remove_dir_tree_if_empty(d) | 223 | function 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. |
| 228 | function copy(src, dest) | 237 | function 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) | |||
| 248 | end | 259 | end |
| 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. |
| 278 | function copy_contents(src, dest) | 290 | function 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) | |||
| 291 | end | 305 | end |
| 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. |
| 298 | local function recursive_delete(src) | 312 | local 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 |
| 314 | end | 328 | end |
| 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. |
| 320 | function delete(arg) | 333 | function delete(name) |
| 321 | assert(arg) | 334 | name = normalize(name) |
| 322 | return recursive_delete(arg) or false | 335 | return recursive_delete(name) or false |
| 323 | end | 336 | end |
| 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) | |||
| 345 | end | 359 | end |
| 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. |
| 385 | function exists(file) | 401 | function exists(file) |
| 386 | assert(file) | 402 | assert(file) |
| 387 | return type(lfs.attributes(file)) == "table" | 403 | file = normalize(file) |
| 404 | return type(file) == "table" | ||
| 388 | end | 405 | end |
| 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. |
| 393 | function is_dir(file) | 410 | function 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" |
| 396 | end | 414 | end |
| 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. |
| 401 | function is_file(file) | 419 | function 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" |
| 404 | end | 423 | end |
| 405 | 424 | ||
| 406 | function set_time(file, time) | 425 | function set_time(file, time) |
| 426 | file = normalize(file) | ||
| 407 | return lfs.touch(file, time) | 427 | return lfs.touch(file, time) |
| 408 | end | 428 | end |
| 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. |
| 428 | function unzip(zipfile) | 448 | function 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 |
| 450 | end | 470 | end |
| 451 | 471 | ||
| 452 | end | 472 | end |
| @@ -457,7 +477,6 @@ end | |||
| 457 | 477 | ||
| 458 | if socket_ok then | 478 | if socket_ok then |
| 459 | 479 | ||
| 460 | |||
| 461 | local ltn12 = require("ltn12") | 480 | local ltn12 = require("ltn12") |
| 462 | 481 | ||
| 463 | --- Download a remote file. | 482 | --- Download a remote file. |
