aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/luarocks/fs.lua19
-rw-r--r--src/luarocks/fs/lua.lua23
-rw-r--r--src/luarocks/fs/unix/tools.lua7
-rw-r--r--src/luarocks/fs/win32.lua9
-rw-r--r--src/luarocks/fs/win32/tools.lua45
5 files changed, 71 insertions, 32 deletions
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua
index 467b1943..e002c7ba 100644
--- a/src/luarocks/fs.lua
+++ b/src/luarocks/fs.lua
@@ -38,3 +38,22 @@ load_fns(fs_lua)
38local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools") 38local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools")
39if ok and fs_plat_tools then load_fns(fs_plat_tools) end 39if ok and fs_plat_tools then load_fns(fs_plat_tools) end
40 40
41-- uncomment below for further debugging than 'verbose=true' in config file
42-- code below will also catch commands outside of fs.execute()
43-- especially uses of io.popen().
44--[[
45old_exec = os.execute
46os.execute = function(cmd)
47 print("os.execute: ", cmd)
48 return old_exec(cmd)
49end
50old_popen = io.popen
51io.popen = function(one, two)
52 if two == nil then
53 print("io.popen: ", one)
54 else
55 print("io.popen: ", one, "Mode:", two)
56 end
57 return old_popen(one, two)
58end
59--]]
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index d477d88f..f9ec43ba 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -108,29 +108,33 @@ end
108-- The command is executed in the current directory in the dir stack. 108-- The command is executed in the current directory in the dir stack.
109-- @param command string: The command to be executed. No quoting/escaping 109-- @param command string: The command to be executed. No quoting/escaping
110-- is applied. 110-- is applied.
111-- @param ... Strings containing additional arguments, which are quoted. 111-- @param ... Strings containing additional arguments, which will be quoted.
112-- @return boolean: true if command succeeds (status code 0), false 112-- @return boolean: true if command succeeds (status code 0), false
113-- otherwise. 113-- otherwise.
114function execute_quiet(command, ...) 114function execute_quiet(command, ...)
115 assert(type(command) == "string") 115 assert(type(command) == "string")
116 return fs.execute_string(fs.quiet(quote_args(command, ...))) 116 if cfg.verbose then
117 return fs.execute_string(quote_args(command, ...))
118 else
119 return fs.execute_string(fs.quiet(quote_args(command, ...)))
120 end
117end 121end
118 122
119--- Check the MD5 checksum for a file. 123--- Check the MD5 checksum for a file.
120-- @param file string: The file to be checked. 124-- @param file string: The file to be checked.
121-- @param md5sum string: The string with the expected MD5 checksum. 125-- @param md5sum string: The string with the expected MD5 checksum.
122-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not 126-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false + msg if not
123-- or if it could not perform the check for any reason. 127-- or if it could not perform the check for any reason.
124function check_md5(file, md5sum) 128function check_md5(file, md5sum)
125 file = dir.normalize(file) 129 file = dir.normalize(file)
126 local computed = fs.get_md5(file) 130 local computed, msg = fs.get_md5(file)
127 if not computed then 131 if not computed then
128 return false 132 return false, msg
129 end 133 end
130 if computed:match("^"..md5sum) then 134 if computed:match("^"..md5sum) then
131 return true 135 return true
132 else 136 else
133 return false 137 return false, "Mismatch MD5 hash for file "..file
134 end 138 end
135end 139end
136 140
@@ -644,14 +648,15 @@ if md5_ok then
644 648
645--- Get the MD5 checksum for a file. 649--- Get the MD5 checksum for a file.
646-- @param file string: The file to be computed. 650-- @param file string: The file to be computed.
647-- @return string: The MD5 checksum 651-- @return string: The MD5 checksum or nil + error
648function get_md5(file) 652function get_md5(file)
649 file = fs.absolute_name(file) 653 file = fs.absolute_name(file)
650 local file = io.open(file, "rb") 654 local file = io.open(file, "rb")
651 if not file then return false end 655 if not file then return nil, "Failed to compute MD5 hash for file "..file end
652 local computed = md5.sumhexa(file:read("*a")) 656 local computed = md5.sumhexa(file:read("*a"))
653 file:close() 657 file:close()
654 return computed 658 if computed then return computed end
659 return nil, "Failed to compute MD5 hash for file "..file
655end 660end
656 661
657end 662end
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
index e3468ab4..c857b093 100644
--- a/src/luarocks/fs/unix/tools.lua
+++ b/src/luarocks/fs/unix/tools.lua
@@ -328,8 +328,11 @@ function get_md5(file)
328 local pipe = io.popen(cmd.." "..fs.absolute_name(file)) 328 local pipe = io.popen(cmd.." "..fs.absolute_name(file))
329 local computed = pipe:read("*a") 329 local computed = pipe:read("*a")
330 pipe:close() 330 pipe:close()
331 if not computed then return nil end 331 if computed then
332 return computed:match("("..("%x"):rep(32)..")") 332 computed = computed:match("("..("%x"):rep(32)..")")
333 end
334 if computed then return computed end
335 return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
333end 336end
334 337
335function get_permissions(filename) 338function get_permissions(filename)
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua
index 6f7ba140..b6ea25e4 100644
--- a/src/luarocks/fs/win32.lua
+++ b/src/luarocks/fs/win32.lua
@@ -9,6 +9,15 @@ local cfg = require("luarocks.cfg")
9local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11 11
12-- Monkey patch io.popen and os.execute to make sure quoting
13-- works as expected.
14-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html
15local _prefix = "type NUL && "
16local _popen, _execute = io.popen, os.execute
17io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
18os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
19
20
12--- Annotate command string for quiet execution. 21--- Annotate command string for quiet execution.
13-- @param cmd string: A command-line string. 22-- @param cmd string: A command-line string.
14-- @return string: The command-line, with silencing annotation. 23-- @return string: The command-line, with silencing annotation.
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
index 979aaff4..1d302288 100644
--- a/src/luarocks/fs/win32/tools.lua
+++ b/src/luarocks/fs/win32/tools.lua
@@ -112,7 +112,7 @@ end
112function make_dir(directory) 112function make_dir(directory)
113 assert(directory) 113 assert(directory)
114 directory = dir.normalize(directory) 114 directory = dir.normalize(directory)
115 fs.execute_quiet(vars.MKDIR.." -p ", directory) 115 fs.execute_quiet(fs.Q(vars.MKDIR).." -p ", directory)
116 if not fs.is_dir(directory) then 116 if not fs.is_dir(directory) then
117 return false, "failed making directory "..directory 117 return false, "failed making directory "..directory
118 end 118 end
@@ -125,7 +125,7 @@ end
125-- @param directory string: pathname of directory to remove. 125-- @param directory string: pathname of directory to remove.
126function remove_dir_if_empty(directory) 126function remove_dir_if_empty(directory)
127 assert(directory) 127 assert(directory)
128 fs.execute_quiet(vars.RMDIR, directory) 128 fs.execute_quiet(fs.Q(vars.RMDIR), directory)
129end 129end
130 130
131--- Remove a directory if it is empty. 131--- Remove a directory if it is empty.
@@ -134,7 +134,7 @@ end
134-- @param directory string: pathname of directory to remove. 134-- @param directory string: pathname of directory to remove.
135function remove_dir_tree_if_empty(directory) 135function remove_dir_tree_if_empty(directory)
136 assert(directory) 136 assert(directory)
137 fs.execute_quiet(vars.RMDIR, directory) 137 fs.execute_quiet(fs.Q(vars.RMDIR), directory)
138end 138end
139 139
140--- Copy a file. 140--- Copy a file.
@@ -145,7 +145,7 @@ end
145function copy(src, dest) 145function copy(src, dest)
146 assert(src and dest) 146 assert(src and dest)
147 if dest:match("[/\\]$") then dest = dest:sub(1, -2) end 147 if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
148 local ok = fs.execute(vars.CP, src, dest) 148 local ok = fs.execute(fs.Q(vars.CP), src, dest)
149 if ok then 149 if ok then
150 return true 150 return true
151 else 151 else
@@ -160,7 +160,7 @@ end
160-- plus an error message. 160-- plus an error message.
161function copy_contents(src, dest) 161function copy_contents(src, dest)
162 assert(src and dest) 162 assert(src and dest)
163 if fs.execute_quiet(vars.CP.." -dR "..src.."\\*.* "..fs.Q(dest)) then 163 if fs.execute_quiet(fs.Q(vars.CP).." -dR "..src.."\\*.* "..fs.Q(dest)) then
164 return true 164 return true
165 else 165 else
166 return false, "Failed copying "..src.." to "..dest 166 return false, "Failed copying "..src.." to "..dest
@@ -191,7 +191,7 @@ function list_dir(at)
191 return {} 191 return {}
192 end 192 end
193 local result = {} 193 local result = {}
194 local pipe = io.popen(command_at(at, vars.LS)) 194 local pipe = io.popen(command_at(at, fs.Q(vars.LS)))
195 for file in pipe:lines() do 195 for file in pipe:lines() do
196 table.insert(result, file) 196 table.insert(result, file)
197 end 197 end
@@ -214,7 +214,7 @@ function find(at)
214 return {} 214 return {}
215 end 215 end
216 local result = {} 216 local result = {}
217 local pipe = io.popen(command_at(at, vars.FIND.." 2> NUL")) 217 local pipe = io.popen(command_at(at, fs.Q(vars.FIND).." 2> NUL"))
218 for file in pipe:lines() do 218 for file in pipe:lines() do
219 -- Windows find is a bit different 219 -- Windows find is a bit different
220 local first_two = file:sub(1,2) 220 local first_two = file:sub(1,2)
@@ -233,7 +233,7 @@ end
233-- additional arguments. 233-- additional arguments.
234-- @return boolean: true on success, false on failure. 234-- @return boolean: true on success, false on failure.
235function zip(zipfile, ...) 235function zip(zipfile, ...)
236 return fs.execute_quiet(vars.SEVENZ.." -aoa a -tzip", zipfile, ...) 236 return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa a -tzip", zipfile, ...)
237end 237end
238 238
239--- Uncompress files from a .zip archive. 239--- Uncompress files from a .zip archive.
@@ -241,7 +241,7 @@ end
241-- @return boolean: true on success, false on failure. 241-- @return boolean: true on success, false on failure.
242function unzip(zipfile) 242function unzip(zipfile)
243 assert(zipfile) 243 assert(zipfile)
244 return fs.execute_quiet(vars.SEVENZ.." -aoa x", zipfile) 244 return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", zipfile)
245end 245end
246 246
247--- Test is pathname is a directory. 247--- Test is pathname is a directory.
@@ -257,7 +257,7 @@ end
257-- @return boolean: true if it is a regular file, false otherwise. 257-- @return boolean: true if it is a regular file, false otherwise.
258function is_file(file) 258function is_file(file)
259 assert(file) 259 assert(file)
260 return fs.execute(vars.TEST.." -f", file) 260 return fs.execute(fs.Q(vars.TEST).." -f", file)
261end 261end
262 262
263--- Download a remote file. 263--- Download a remote file.
@@ -276,7 +276,7 @@ function download(url, filename, cache)
276 276
277 local ok 277 local ok
278 if cfg.downloader == "wget" then 278 if cfg.downloader == "wget" then
279 local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet " 279 local wget_cmd = fs.Q(vars.WGET).." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet "
280 if cache then 280 if cache then
281 -- --timestamping is incompatible with --output-document, 281 -- --timestamping is incompatible with --output-document,
282 -- but that's not a problem for our use cases. 282 -- but that's not a problem for our use cases.
@@ -289,7 +289,7 @@ function download(url, filename, cache)
289 ok = fs.execute(wget_cmd..fs.Q(url).." 2> NUL 1> NUL") 289 ok = fs.execute(wget_cmd..fs.Q(url).." 2> NUL 1> NUL")
290 end 290 end
291 elseif cfg.downloader == "curl" then 291 elseif cfg.downloader == "curl" then
292 ok = fs.execute_string(vars.CURL.." -L --user-agent \""..cfg.user_agent.." via curl\" "..fs.Q(url).." 2> NUL 1> "..fs.Q(filename)) 292 ok = fs.execute_string(fs.Q(vars.CURL).." -L --user-agent \""..cfg.user_agent.." via curl\" "..fs.Q(url).." 2> NUL 1> "..fs.Q(filename))
293 end 293 end
294 if ok then 294 if ok then
295 return true, filename 295 return true, filename
@@ -302,7 +302,7 @@ end
302-- @param archive string: Filename of archive. 302-- @param archive string: Filename of archive.
303-- @return boolean : success status 303-- @return boolean : success status
304local function gunzip(archive) 304local function gunzip(archive)
305 return fs.execute_quiet(vars.SEVENZ.." -aoa x", archive) 305 return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", archive)
306end 306end
307 307
308--- Unpack an archive. 308--- Unpack an archive.
@@ -314,7 +314,7 @@ function unpack_archive(archive)
314 assert(type(archive) == "string") 314 assert(type(archive) == "string")
315 315
316 local ok 316 local ok
317 local sevenzx = vars.SEVENZ.." -aoa x" 317 local sevenzx = fs.Q(vars.SEVENZ).." -aoa x"
318 if archive:match("%.tar%.gz$") then 318 if archive:match("%.tar%.gz$") then
319 ok = gunzip(archive) 319 ok = gunzip(archive)
320 if ok then 320 if ok then
@@ -346,22 +346,25 @@ function unpack_archive(archive)
346end 346end
347 347
348local md5_cmd = { 348local md5_cmd = {
349 md5sum = vars.MD5SUM, 349 md5sum = fs.Q(vars.MD5SUM),
350 openssl = vars.OPENSSL.." md5", 350 openssl = fs.Q(vars.OPENSSL).." md5",
351 md5 = vars.MD5, 351 md5 = fs.Q(vars.MD5),
352} 352}
353 353
354--- Get the MD5 checksum for a file. 354--- Get the MD5 checksum for a file.
355-- @param file string: The file to be computed. 355-- @param file string: The file to be computed.
356-- @return string: The MD5 checksum 356-- @return string: The MD5 checksum or nil + message
357function get_md5(file) 357function get_md5(file)
358 local cmd = md5_cmd[cfg.md5checker] 358 local cmd = md5_cmd[cfg.md5checker]
359 if not cmd then return nil end 359 if not cmd then return nil end
360 local pipe = io.popen(cmd.." "..fs.absolute_name(file)) 360 local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file)))
361 local computed = pipe:read("*a") 361 local computed = pipe:read("*a")
362 pipe:close() 362 pipe:close()
363 if not computed then return nil end 363 if computed then
364 return computed:match("("..("%x"):rep(32)..")") 364 computed = computed:match("("..("%x"):rep(32)..")")
365 end
366 if computed then return computed end
367 return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
365end 368end
366 369
367--- Test for existance of a file. 370--- Test for existance of a file.