Grey-Echo 3b69cf992e This is an important refactor of the way documentation generation works
* Installs luarocks WITH it's executable (easy to install other rocks if necessary)
* Use Lua supplied with luarocks
* Create Utils/luadocumentor.bat, which works with RELATIVE PATH ! -> Everybody can generate the doc
* Updated launch files accordingly
2017-04-05 01:26:39 +02:00

157 lines
5.2 KiB
Lua

--- Common fs operations implemented with third-party tools.
local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local cfg = require("luarocks.cfg")
local vars = cfg.variables
local dir_stack = {}
--- Obtain current directory.
-- Uses the module's internal directory stack.
-- @return string: the absolute pathname of the current directory.
function tools.current_dir()
local current = cfg.cache_pwd
if not current then
local pipe = io.popen(fs.quiet_stderr(fs.Q(vars.PWD)))
current = pipe:read("*l")
pipe:close()
cfg.cache_pwd = current
end
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
return current
end
--- Change the current directory.
-- Uses the module's internal directory stack. This does not have exact
-- semantics of chdir, as it does not handle errors the same way,
-- but works well for our purposes for now.
-- @param directory string: The directory to switch to.
-- @return boolean or (nil, string): true if successful, (nil, error message) if failed.
function tools.change_dir(directory)
assert(type(directory) == "string")
if fs.is_dir(directory) then
table.insert(dir_stack, directory)
return true
end
return nil, "directory not found: "..directory
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
function tools.change_dir_to_root()
table.insert(dir_stack, "/")
end
--- Change working directory to the previous in the directory stack.
function tools.pop_dir()
local directory = table.remove(dir_stack)
return directory ~= nil
end
--- Run the given command.
-- The command is executed in the current directory in the directory stack.
-- @param cmd string: No quoting/escaping is applied to the command.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
function tools.execute_string(cmd)
local current = fs.current_dir()
if not current then return false end
cmd = fs.command_at(current, cmd)
local code = os.execute(cmd)
if code == 0 or code == true then
return true
else
return false
end
end
--- Internal implementation function for fs.dir.
-- Yields a filename on each iteration.
-- @param at string: directory to list
-- @return nil
function tools.dir_iterator(at)
local pipe = io.popen(fs.command_at(at, fs.Q(vars.LS)))
for file in pipe:lines() do
if file ~= "." and file ~= ".." then
coroutine.yield(file)
end
end
pipe:close()
end
--- Download a remote file.
-- @param url string: URL to be fetched.
-- @param filename string or nil: this function attempts to detect the
-- resulting local filename of the remote file as the basename of the URL;
-- if that is not correct (due to a redirection, for example), the local
-- filename can be given explicitly as this second argument.
-- @return (boolean, string): true and the filename on success,
-- false and the error message on failure.
function tools.use_downloader(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
filename = fs.absolute_name(filename or dir.base_name(url))
local ok
if cfg.downloader == "wget" then
local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet "
if cfg.connection_timeout and cfg.connection_timeout > 0 then
wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 "
end
if cache then
-- --timestamping is incompatible with --output-document,
-- but that's not a problem for our use cases.
fs.change_dir(dir.dir_name(filename))
ok = fs.execute_quiet(wget_cmd.." --timestamping ", url)
fs.pop_dir()
elseif filename then
ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url)
else
ok = fs.execute_quiet(wget_cmd, url)
end
elseif cfg.downloader == "curl" then
local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent \""..cfg.user_agent.." via curl\" "
if cfg.connection_timeout and cfg.connection_timeout > 0 then
curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
end
ok = fs.execute_string(fs.quiet_stderr(curl_cmd..fs.Q(url).." > "..fs.Q(filename)))
end
if ok then
return true, filename
else
return false
end
end
local md5_cmd = {
md5sum = fs.Q(vars.MD5SUM),
openssl = fs.Q(vars.OPENSSL).." md5",
md5 = fs.Q(vars.MD5),
}
--- Get the MD5 checksum for a file.
-- @param file string: The file to be computed.
-- @return string: The MD5 checksum or nil + message
function tools.get_md5(file)
local cmd = md5_cmd[cfg.md5checker]
if not cmd then return nil, "no MD5 checker command configured" end
local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file)))
local computed = pipe:read("*a")
pipe:close()
if computed then
computed = computed:match("("..("%x"):rep(32)..")")
end
if computed then return computed end
return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
end
return tools