# HG changeset patch
# User HackBot
# Date 1355523867 0
# Node ID d137f631bad536d9cfd5749894490ff5546951bb
# Parent ff65dfb632633924692b7d4a515de05945309540
(cd luabuild/luarocks-2.0.12; make install)
diff -r ff65dfb63263 -r d137f631bad5 bin/luarocks
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/luarocks Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,26 @@
+#!/hackenv/bin/lua
+package.path = [[/hackenv/share/lua/5.2//?.lua;/hackenv/share/lua/5.2//?/init.lua;]]..package.path
+
+local command_line = require("luarocks.command_line")
+
+program_name = "luarocks"
+program_description = "LuaRocks main command-line interface"
+
+commands = {}
+commands.help = require("luarocks.help")
+commands.pack = require("luarocks.pack")
+commands.unpack = require("luarocks.unpack")
+commands.build = require("luarocks.build")
+commands.install = require("luarocks.install")
+commands.search = require("luarocks.search")
+commands.list = require("luarocks.list")
+commands.remove = require("luarocks.remove")
+commands.make = require("luarocks.make")
+commands.download = require("luarocks.download")
+commands.path = require("luarocks.path")
+commands.show = require("luarocks.show")
+commands.new_version = require("luarocks.new_version")
+commands.lint = require("luarocks.lint")
+commands.purge = require("luarocks.purge")
+
+command_line.run_command(...)
diff -r ff65dfb63263 -r d137f631bad5 bin/luarocks-admin
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/luarocks-admin Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,18 @@
+#!/hackenv/bin/lua
+package.path = [[/hackenv/share/lua/5.2//?.lua;/hackenv/share/lua/5.2//?/init.lua;]]..package.path
+
+local command_line = require("luarocks.command_line")
+
+program_name = "luarocks-admin"
+program_description = "LuaRocks repository administration interface"
+
+commands = {
+}
+
+commands.help = require("luarocks.help")
+commands.make_manifest = require("luarocks.make_manifest")
+commands.add = require("luarocks.add")
+commands.remove = require("luarocks.admin_remove")
+commands.refresh_cache = require("luarocks.refresh_cache")
+
+command_line.run_command(...)
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/add.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/add.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,108 @@
+
+--- Module implementing the luarocks-admin "add" command.
+-- Adds a rock or rockspec to a rocks server.
+module("luarocks.add", package.seeall)
+
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local fetch = require("luarocks.fetch")
+local dir = require("luarocks.dir")
+local manif = require("luarocks.manif")
+local index = require("luarocks.index")
+local fs = require("luarocks.fs")
+local cache = require("luarocks.cache")
+
+help_summary = "Add a rock or rockspec to a rocks server."
+help_arguments = "[--server=] [--no-refresh] {|...}"
+help = [[
+Arguments are local files, which may be rockspecs or rocks.
+The flag --server indicates which server to use.
+If not given, the default server set in the upload_server variable
+from the configuration file is used instead.
+The flag --no-refresh indicates the local cache should not be refreshed
+prior to generation of the updated manifest.
+]]
+
+local function add_files_to_server(refresh, rockfiles, server, upload_server)
+ assert(type(refresh) == "boolean" or not refresh)
+ assert(type(rockfiles) == "table")
+ assert(type(server) == "string")
+ assert(type(upload_server) == "table" or not upload_server)
+
+ local download_url, login_url = cache.get_server_urls(server, upload_server)
+ local at = fs.current_dir()
+ local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
+
+ local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
+ if not local_cache then
+ return nil, protocol
+ end
+ if protocol == "file" then
+ return nil, "Server "..server.." is not recognized, check your configuration."
+ end
+
+ if not login_url then
+ login_url = protocol.."://"..server_path
+ end
+
+ fs.change_dir(at)
+
+ local files = {}
+ for i, rockfile in ipairs(rockfiles) do
+ if fs.exists(rockfile) then
+ util.printout("Copying file "..rockfile.." to "..local_cache.."...")
+ local absolute = fs.absolute_name(rockfile)
+ fs.copy(absolute, local_cache)
+ table.insert(files, dir.base_name(absolute))
+ else
+ util.printerr("File "..rockfile.." not found")
+ end
+ end
+ if #files == 0 then
+ return nil, "No files found"
+ end
+
+ fs.change_dir(local_cache)
+
+ util.printout("Updating manifest...")
+ manif.make_manifest(local_cache, "one")
+ util.printout("Updating index.html...")
+ index.make_index(local_cache)
+
+ local login_info = ""
+ if user then login_info = " -u "..user end
+ if password then login_info = login_info..":"..password end
+ if not login_url:match("/$") then
+ login_url = login_url .. "/"
+ end
+
+ -- TODO abstract away explicit 'curl' call
+
+ local cmd
+ if protocol == "rsync" then
+ local srv, path = server_path:match("([^/]+)(/.+)")
+ cmd = cfg.variables.RSYNC.." --exclude=.git -Oavz -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
+ elseif upload_server and upload_server.sftp then
+ local part1, part2 = upload_server.sftp:match("^([^/]*)/(.*)$")
+ cmd = cfg.variables.SCP.." manifest index.html "..table.concat(files, " ").." "..user.."@"..part1..":/"..part2
+ else
+ cmd = cfg.variables.CURL.." "..login_info.." -T '{manifest,index.html,"..table.concat(files, ",").."}' "..login_url
+ end
+
+ util.printout(cmd)
+ fs.execute(cmd)
+
+ return true
+end
+
+function run(...)
+ local files = { util.parse_flags(...) }
+ local flags = table.remove(files, 1)
+ if #files < 1 then
+ return nil, "Argument missing, see help."
+ end
+ local server, server_table = cache.get_upload_server(flags["server"])
+ if not server then return nil, server_table end
+ return add_files_to_server(not flags["no-refresh"], files, server, server_table)
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/admin_remove.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/admin_remove.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,87 @@
+
+--- Module implementing the luarocks-admin "remove" command.
+-- Removes a rock or rockspec from a rocks server.
+module("luarocks.admin_remove", package.seeall)
+
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local fetch = require("luarocks.fetch")
+local dir = require("luarocks.dir")
+local manif = require("luarocks.manif")
+local index = require("luarocks.index")
+local fs = require("luarocks.fs")
+local cache = require("luarocks.cache")
+
+help_summary = "Remove a rock or rockspec from a rocks server."
+help_arguments = "[--from=] [--no-refresh] {|...}"
+help = [[
+Arguments are local files, which may be rockspecs or rocks.
+The flag --from indicates which server to use.
+If not given, the default server set in the upload_server variable
+from the configuration file is used instead.
+The flag --no-refresh indicates the local cache should not be refreshed
+prior to generation of the updated manifest.
+]]
+
+local function remove_files_from_server(refresh, rockfiles, server, upload_server)
+ assert(type(refresh) == "boolean" or not refresh)
+ assert(type(rockfiles) == "table")
+ assert(type(server) == "string")
+ assert(type(upload_server) == "table" or not upload_server)
+
+ local download_url, login_url = cache.get_server_urls(server, upload_server)
+ local at = fs.current_dir()
+ local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
+
+ local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
+ if not local_cache then
+ return nil, protocol
+ end
+ if protocol ~= "rsync" then
+ return nil, "This command requires 'rsync', check your configuration."
+ end
+
+ fs.change_dir(at)
+
+ local nr_files = 0
+ for i, rockfile in ipairs(rockfiles) do
+ local basename = dir.base_name(rockfile)
+ local file = dir.path(local_cache, basename)
+ util.printout("Removing file "..file.."...")
+ if fs.delete(file) then
+ nr_files = nr_files + 1
+ else
+ util.printerr("Failed removing "..file)
+ end
+ end
+ if nr_files == 0 then
+ return nil, "No files removed."
+ end
+
+ fs.change_dir(local_cache)
+
+ util.printout("Updating manifest...")
+ manif.make_manifest(local_cache, "one")
+ util.printout("Updating index.html...")
+ index.make_index(local_cache)
+
+ local srv, path = server_path:match("([^/]+)(/.+)")
+ local cmd = "rsync -Oavz --delete -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
+
+ util.printout(cmd)
+ fs.execute(cmd)
+
+ return true
+end
+
+function run(...)
+ local files = { util.parse_flags(...) }
+ local flags = table.remove(files, 1)
+ if #files < 1 then
+ return nil, "Argument missing, see help."
+ end
+ local server, server_table = cache.get_upload_server(flags["server"])
+ if not server then return nil, server_table end
+ return remove_files_from_server(not flags["no-refresh"], files, server, server_table)
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/build.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,335 @@
+
+--- Module implementing the LuaRocks "build" command.
+-- Builds a rock, compiling its C parts if any.
+module("luarocks.build", package.seeall)
+
+local pack = require("luarocks.pack")
+local path = require("luarocks.path")
+local util = require("luarocks.util")
+local repos = require("luarocks.repos")
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local deps = require("luarocks.deps")
+local manif = require("luarocks.manif")
+local cfg = require("luarocks.cfg")
+
+help_summary = "Build/compile a rock."
+help_arguments = "[--pack-binary-rock] {|| []}"
+help = [[
+Build and install a rock, compiling its C parts if any.
+Argument may be a rockspec file, a source rock file
+or the name of a rock to be fetched from a repository.
+
+If --pack-binary-rock is passed, the rock is not installed;
+instead, a .rock file with the contents of compilation is produced
+in the current directory.
+]]
+
+--- Install files to a given location.
+-- Takes a table where the array part is a list of filenames to be copied.
+-- In the hash part, other keys, if is_module_path is set, are identifiers
+-- in Lua module format, to indicate which subdirectory the file should be
+-- copied to. For example, install_files({["foo.bar"] = "src/bar.lua"}, "boo")
+-- will copy src/bar.lua to boo/foo.
+-- @param files table or nil: A table containing a list of files to copy in
+-- the format described above. If nil is passed, this function is a no-op.
+-- Directories should be delimited by forward slashes as in internet URLs.
+-- @param location string: The base directory files should be copied to.
+-- @param is_module_path boolean: True if string keys in files should be
+-- interpreted as dotted module paths.
+-- @return boolean or (nil, string): True if succeeded or
+-- nil and an error message.
+local function install_files(files, location, is_module_path)
+ assert(type(files) == "table" or not files)
+ assert(type(location) == "string")
+ if files then
+ for k, file in pairs(files) do
+ local dest = location
+ if type(k) == "string" then
+ if is_module_path then
+ dest = dir.path(location, path.module_to_path(k))
+ fs.make_dir(dest)
+ else
+ dest = dir.path(location, dir.dir_name(k))
+ fs.make_dir(dest)
+ dest = dir.path(dest, dir.base_name(k))
+ end
+ else
+ fs.make_dir(dest)
+ end
+ local ok = fs.copy(dir.path(file), dest)
+ if not ok then
+ return nil, "Failed copying "..file
+ end
+ end
+ end
+ return true
+end
+
+--- Write to the current directory the contents of a table,
+-- where each key is a file name and its value is the file content.
+-- @param files table: The table of files to be written.
+local function extract_from_rockspec(files)
+ for name, content in pairs(files) do
+ local fd = io.open(dir.path(fs.current_dir(), name), "w+")
+ fd:write(content)
+ fd:close()
+ end
+end
+
+--- Applies patches inlined in the build.patches section
+-- and extracts files inlined in the build.extra_files section
+-- of a rockspec.
+-- @param rockspec table: A rockspec table.
+-- @return boolean or (nil, string): True if succeeded or
+-- nil and an error message.
+function apply_patches(rockspec)
+ assert(type(rockspec) == "table")
+
+ local build = rockspec.build
+ if build.extra_files then
+ extract_from_rockspec(build.extra_files)
+ end
+ if build.patches then
+ extract_from_rockspec(build.patches)
+ for patch, patchdata in util.sortedpairs(build.patches) do
+ util.printout("Applying patch "..patch.."...")
+ local ok, err = fs.apply_patch(tostring(patch), patchdata)
+ if not ok then
+ return nil, "Failed applying patch "..patch
+ end
+ end
+ end
+ return true
+end
+
+--- Build and install a rock given a rockspec.
+-- @param rockspec_file string: local or remote filename of a rockspec.
+-- @param need_to_fetch boolean: true if sources need to be fetched,
+-- false if the rockspec was obtained from inside a source rock.
+-- @param minimal_mode boolean: true if there's no need to fetch,
+-- unpack or change dir (this is used by "luarocks make"). Implies
+-- need_to_fetch = false.
+-- @param deps_mode: string: Which trees to check dependencies for:
+-- "none", "one", "order" or "all".
+-- @return boolean or (nil, string, [string]): True if succeeded or
+-- nil and an error message followed by an error code.
+function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
+ assert(type(rockspec_file) == "string")
+ assert(type(need_to_fetch) == "boolean")
+
+ local rockspec, err, errcode = fetch.load_rockspec(rockspec_file)
+ if err then
+ return nil, err, errcode
+ elseif not rockspec.build then
+ return nil, "Rockspec error: build table not specified"
+ elseif not rockspec.build.type then
+ return nil, "Rockspec error: build type not specified"
+ end
+
+ if deps_mode == "none" then
+ util.printerr("Warning: skipping dependency checks.")
+ else
+ local ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
+ if err then
+ return nil, err, errcode
+ end
+ end
+
+ ok, err, errcode = deps.check_external_deps(rockspec, "build")
+ if err then
+ return nil, err, errcode
+ end
+
+ local name, version = rockspec.name, rockspec.version
+ if repos.is_installed(name, version) then
+ repos.delete_version(name, version)
+ end
+
+ if not minimal_mode then
+ local _, source_dir
+ if need_to_fetch then
+ ok, source_dir, errcode = fetch.fetch_sources(rockspec, true)
+ if not ok then
+ return nil, source_dir, errcode
+ end
+ fs.change_dir(source_dir)
+ elseif rockspec.source.file then
+ local ok, err = fs.unpack_archive(rockspec.source.file)
+ if not ok then
+ return nil, err
+ end
+ end
+ fs.change_dir(rockspec.source.dir)
+ end
+
+ local dirs = {
+ lua = { name = path.lua_dir(name, version), is_module_path = true },
+ lib = { name = path.lib_dir(name, version), is_module_path = true },
+ conf = { name = path.conf_dir(name, version), is_module_path = false },
+ bin = { name = path.bin_dir(name, version), is_module_path = false },
+ }
+
+ for _, d in pairs(dirs) do
+ fs.make_dir(d.name)
+ end
+ local rollback = util.schedule_function(function()
+ fs.delete(path.install_dir(name, version))
+ fs.remove_dir_if_empty(path.versions_dir(name))
+ end)
+
+ local build = rockspec.build
+
+ if not minimal_mode then
+ ok, err = apply_patches(rockspec)
+ if err then
+ return nil, err
+ end
+ end
+
+ if build.type ~= "none" then
+
+ -- Temporary compatibility
+ if build.type == "module" then
+ util.printout("Do not use 'module' as a build type. Use 'builtin' instead.")
+ build.type = "builtin"
+ end
+
+ local build_type
+ ok, build_type = pcall(require, "luarocks.build." .. build.type)
+ if not ok or not type(build_type) == "table" then
+ return nil, "Failed initializing build back-end for build type '"..build.type.."': "..build_type
+ end
+
+ ok, err = build_type.run(rockspec)
+ if not ok then
+ return nil, "Build error: " .. err
+ end
+ end
+
+ if build.install then
+ for id, install_dir in pairs(dirs) do
+ ok, err = install_files(build.install[id], install_dir.name, install_dir.is_module_path)
+ if not ok then
+ return nil, err
+ end
+ end
+ end
+
+ local copy_directories = build.copy_directories or {"doc"}
+
+ for _, copy_dir in pairs(copy_directories) do
+ if fs.is_dir(copy_dir) then
+ local dest = dir.path(path.install_dir(name, version), copy_dir)
+ fs.make_dir(dest)
+ fs.copy_contents(copy_dir, dest)
+ else
+ util.warning("Directory '"..copy_dir.."' not found")
+ end
+ end
+
+ for _, d in pairs(dirs) do
+ fs.remove_dir_if_empty(d.name)
+ end
+
+ fs.pop_dir()
+
+ fs.copy(rockspec.local_filename, path.rockspec_file(name, version))
+ if need_to_fetch then
+ fs.pop_dir()
+ end
+
+ ok, err = manif.make_rock_manifest(name, version)
+ if err then return nil, err end
+
+ ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec))
+ if err then return nil, err end
+
+ util.remove_scheduled_function(rollback)
+ rollback = util.schedule_function(function()
+ repos.delete_version(name, version)
+ end)
+
+ ok, err = repos.run_hook(rockspec, "post_install")
+ if err then return nil, err end
+
+ ok, err = manif.update_manifest(name, version, nil, deps_mode)
+ if err then return nil, err end
+
+ local license = ""
+ if rockspec.description and rockspec.description.license then
+ license = ("(license: "..rockspec.description.license..")")
+ end
+
+ local root_dir = path.root_dir(cfg.rocks_dir)
+ util.printout()
+ util.printout(name.." "..version.." is now built and installed in "..root_dir.." "..license)
+
+ util.remove_scheduled_function(rollback)
+ return true
+end
+
+--- Build and install a rock.
+-- @param rock_file string: local or remote filename of a rock.
+-- @param need_to_fetch boolean: true if sources need to be fetched,
+-- false if the rockspec was obtained from inside a source rock.
+-- @param deps_mode: string: Which trees to check dependencies for:
+-- "none", "one", "order" or "all".
+-- @return boolean or (nil, string, [string]): True if build was successful,
+-- or false and an error message and an optional error code.
+function build_rock(rock_file, need_to_fetch, deps_mode)
+ assert(type(rock_file) == "string")
+ assert(type(need_to_fetch) == "boolean")
+
+ local unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file)
+ if not unpack_dir then
+ return nil, err, errcode
+ end
+ local rockspec_file = path.rockspec_name_from_rock(rock_file)
+ fs.change_dir(unpack_dir)
+ local ok, err, errcode = build_rockspec(rockspec_file, need_to_fetch, false, deps_mode)
+ fs.pop_dir()
+ return ok, err, errcode
+end
+
+local function do_build(name, version, deps_mode)
+ if name:match("%.rockspec$") then
+ return build_rockspec(name, true, false, deps_mode)
+ elseif name:match("%.src%.rock$") then
+ return build_rock(name, false, deps_mode)
+ elseif name:match("%.all%.rock$") then
+ local install = require("luarocks.install")
+ return install.install_binary_rock(name, deps_mode)
+ elseif name:match("%.rock$") then
+ return build_rock(name, true, deps_mode)
+ elseif not name:match(dir.separator) then
+ local search = require("luarocks.search")
+ return search.act_on_src_or_rockspec(run, name:lower(), version, deps.deps_mode_to_flag(deps_mode))
+ end
+ return nil, "Don't know what to do with "..name
+end
+
+--- Driver function for "build" command.
+-- @param name string: A local or remote rockspec or rock file.
+-- If a package name is given, forwards the request to "search" and,
+-- if returned a result, installs the matching rock.
+-- @param version string: When passing a package name, a version number may
+-- also be given.
+-- @return boolean or (nil, string): True if build was successful; nil and an
+-- error message otherwise.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+ if type(name) ~= "string" then
+ return nil, "Argument missing, see help."
+ end
+ assert(type(version) == "string" or not version)
+
+ if flags["pack-binary-rock"] then
+ return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags))
+ else
+ local ok, err = fs.check_command_permissions(flags)
+ if not ok then return nil, err end
+ return do_build(name, version, deps.get_deps_mode(flags))
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/build/builtin.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build/builtin.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,252 @@
+
+--- A builtin build system: back-end to provide a portable way of building C-based Lua modules.
+module("luarocks.build.builtin", package.seeall)
+
+local fs = require("luarocks.fs")
+local path = require("luarocks.path")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+
+--- Run a command displaying its execution on standard output.
+-- @return boolean: true if command succeeds (status code 0), false
+-- otherwise.
+local function execute(...)
+ io.stdout:write(table.concat({...}, " ").."\n")
+ return fs.execute(...)
+end
+
+--- Makes an RC file with an embedded Lua script, for building .exes on Windows
+-- @return nil if could open files, error otherwise
+local function make_rc(luafilename, rcfilename)
+ local rcfile = io.open(rcfilename, "w")
+ if not rcfile then
+ error("Could not open "..rcfilename.." for writing.")
+ end
+ rcfile:write("STRINGTABLE\r\nBEGIN\r\n")
+
+ local i = 1
+ for line in io.lines(luafilename) do
+ if not line:match("^#!") then
+ rcfile:write(i .. " \"")
+ line = line:gsub("\\", "\\\\"):gsub('"', '""'):gsub("[\r\n]+", "")
+ rcfile:write(line .. "\\r\\n\"\r\n")
+ i = i + 1
+ end
+ end
+
+ rcfile:write("END\r\n")
+
+ rcfile:close()
+end
+
+--- Driver function for the builtin build back-end.
+-- @param rockspec table: the loaded rockspec.
+-- @return boolean or (nil, string): true if no errors ocurred,
+-- nil and an error message otherwise.
+function run(rockspec)
+ assert(type(rockspec) == "table")
+ local compile_object, compile_library, compile_wrapper_binary
+
+ local build = rockspec.build
+ local variables = rockspec.variables
+
+ local function add_flags(extras, flag, flags)
+ if flags then
+ if type(flags) ~= "table" then
+ flags = { tostring(flags) }
+ end
+ util.variable_substitutions(flags, variables)
+ for _, v in ipairs(flags) do
+ table.insert(extras, flag:format(v))
+ end
+ end
+ end
+
+ if cfg.is_platform("mingw32") then
+ compile_object = function(object, source, defines, incdirs)
+ local extras = {}
+ add_flags(extras, "-D%s", defines)
+ add_flags(extras, "-I%s", incdirs)
+ return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
+ end
+ compile_library = function(library, objects, libraries, libdirs, name)
+ local extras = { unpack(objects) }
+ add_flags(extras, "-L%s", libdirs)
+ add_flags(extras, "%s.lib", libraries)
+ extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB)
+ extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80")
+ local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
+ return ok
+ end
+ compile_wrapper_binary = function(fullname, name)
+ local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
+ local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
+ local rcname = basename..".rc"
+ local resname = basename..".o"
+ local wrapname = basename..".exe"
+ make_rc(fullname, fullbasename..".rc")
+ local ok = execute(variables.RC, "-o", resname, rcname)
+ if not ok then return ok end
+ ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER,
+ dir.path(variables.LUA_LIBDIR, variables.LUALIB), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32")
+ return ok, wrapname
+ end
+ elseif cfg.is_platform("win32") then
+ compile_object = function(object, source, defines, incdirs)
+ local extras = {}
+ add_flags(extras, "-D%s", defines)
+ add_flags(extras, "-I%s", incdirs)
+ return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
+ end
+ compile_library = function(library, objects, libraries, libdirs, name)
+ local extras = { unpack(objects) }
+ add_flags(extras, "-libpath:%s", libdirs)
+ add_flags(extras, "%s.lib", libraries)
+ local basename = dir.base_name(library):gsub(".[^.]*$", "")
+ local deffile = basename .. ".def"
+ local def = io.open(dir.path(fs.current_dir(), deffile), "w+")
+ def:write("EXPORTS\n")
+ def:write("luaopen_"..name:gsub("%.", "_").."\n")
+ def:close()
+ local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras))
+ local manifestfile = basename..".dll.manifest"
+ if ok and fs.exists(manifestfile) then
+ ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2")
+ end
+ return ok
+ end
+ compile_wrapper_binary = function(fullname, name)
+ local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
+ local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
+ local rcname = basename..".rc"
+ local resname = basename..".res"
+ local wrapname = basename..".exe"
+ make_rc(fullname, fullbasename..".rc")
+ local ok = execute(variables.RC, "-r", "-fo"..resname, rcname)
+ if not ok then return ok end
+ ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER,
+ dir.path(variables.LUA_LIBDIR, variables.LUALIB), "user32.lib")
+ local manifestfile = wrapname..".manifest"
+ if ok and fs.exists(manifestfile) then
+ ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1")
+ end
+ return ok, wrapname
+ end
+ else
+ compile_object = function(object, source, defines, incdirs)
+ local extras = {}
+ add_flags(extras, "-D%s", defines)
+ add_flags(extras, "-I%s", incdirs)
+ return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras))
+ end
+ compile_library = function (library, objects, libraries, libdirs)
+ local extras = { unpack(objects) }
+ add_flags(extras, "-L%s", libdirs)
+ if cfg.gcc_rpath then
+ add_flags(extras, "-Wl,-rpath,%s:", libdirs)
+ end
+ add_flags(extras, "-l%s", libraries)
+ if cfg.is_platform("cygwin") then
+ add_flags(extras, "-l%s", {"lua"})
+ end
+ return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras))
+ end
+ compile_wrapper_binary = function(fullname, name) return true, name end
+ end
+
+ local ok = true
+ local err = "Build error"
+ local built_modules = {}
+ local luadir = path.lua_dir(rockspec.name, rockspec.version)
+ local libdir = path.lib_dir(rockspec.name, rockspec.version)
+ local docdir = path.doc_dir(rockspec.name, rockspec.version)
+ -- On Windows, compiles an .exe for each Lua file in build.install.bin, and
+ -- replaces the filename with the .exe name. Strips the .lua extension if it exists,
+ -- otherwise just appends .exe to the name
+ if build.install and build.install.bin then
+ for i, name in ipairs(build.install.bin) do
+ local fullname = dir.path(fs.current_dir(), name)
+ local match = name:match("%.lua$")
+ local basename = name:gsub("%.lua$", "")
+ local file
+ if not match then
+ file = io.open(fullname)
+ end
+ if match or (file and file:read():match("#!.*lua.*")) then
+ ok, name = compile_wrapper_binary(fullname, name)
+ if ok then
+ build.install.bin[i] = name
+ else
+ if file then file:close() end
+ return nil, "Build error in wrapper binaries"
+ end
+ end
+ if file then file:close() end
+ end
+ end
+ for name, info in pairs(build.modules) do
+ local moddir = path.module_to_path(name)
+ if type(info) == "string" then
+ local ext = info:match(".([^.]+)$")
+ if ext == "lua" then
+ if info:match("init%.lua$") and not name:match("%.init$") then
+ moddir = path.module_to_path(name..".init")
+ end
+ local dest = dir.path(luadir, moddir)
+ built_modules[info] = dest
+ else
+ info = {info}
+ end
+ end
+ if type(info) == "table" then
+ local objects = {}
+ local sources = info.sources
+ if info[1] then sources = info end
+ if type(sources) == "string" then sources = {sources} end
+ for _, source in ipairs(sources) do
+ local object = source:gsub(".[^.]*$", "."..cfg.obj_extension)
+ if not object then
+ object = source.."."..cfg.obj_extension
+ end
+ ok = compile_object(object, source, info.defines, info.incdirs)
+ if not ok then
+ err = "Failed compiling object "..object
+ break
+ end
+ table.insert(objects, object)
+ end
+ if not ok then break end
+ local module_name = dir.path(moddir, name:match("([^.]*)$").."."..cfg.lib_extension):gsub("//", "/")
+ if moddir ~= "" then
+ fs.make_dir(moddir)
+ end
+ local dest = dir.path(libdir, moddir)
+ built_modules[module_name] = dest
+ ok = compile_library(module_name, objects, info.libraries, info.libdirs, name)
+ if not ok then
+ err = "Failed compiling module "..module_name
+ break
+ end
+ end
+ end
+ for name, dest in pairs(built_modules) do
+ fs.make_dir(dest)
+ ok = fs.copy(name, dest)
+ if not ok then
+ err = "Failed installing "..name.." in "..dest
+ break
+ end
+ end
+ if ok then
+ if fs.is_dir("lua") then
+ ok = fs.copy_contents("lua", luadir)
+ if not ok then err = "Failed copying contents of 'lua' directory." end
+ end
+ end
+ if ok then
+ return true
+ else
+ return nil, err
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/build/cmake.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build/cmake.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,58 @@
+
+--- Build back-end for CMake-based modules.
+module("luarocks.build.cmake", package.seeall)
+
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+
+--- Driver function for the "cmake" build back-end.
+-- @param rockspec table: the loaded rockspec.
+-- @return boolean or (nil, string): true if no errors ocurred,
+-- nil and an error message otherwise.
+function run(rockspec)
+ assert(type(rockspec) == "table")
+ local build = rockspec.build
+ local variables = build.variables or {}
+
+ -- Pass Env variables
+ variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH")
+ variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH")
+ variables.CMAKE_INCLUDE_PATH=os.getenv("CMAKE_INCLUDE_PATH")
+
+ util.variable_substitutions(variables, rockspec.variables)
+
+ if not fs.execute_string(fs.quiet(rockspec.variables.CMAKE.." --help")) then
+ return nil, "'"..rockspec.variables.CMAKE.."' program not found. Is cmake installed? You may want to edit variables.CMAKE"
+ end
+
+ -- If inline cmake is present create CMakeLists.txt from it.
+ if type(build.cmake) == "string" then
+ local cmake = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w"))
+ cmake:write(build.cmake)
+ cmake:close()
+ end
+
+
+ -- Execute cmake with variables.
+ local args = ""
+ if cfg.cmake_generator then
+ args = args .. ' -G"'..cfg.cmake_generator.. '"'
+ end
+ for k,v in pairs(variables) do
+ args = args .. ' -D' ..k.. '="' ..v.. '"'
+ end
+
+ if not fs.execute_string(rockspec.variables.CMAKE.." . " ..args) then
+ return nil, "Failed cmake."
+ end
+
+ if not fs.execute_string(rockspec.variables.MAKE.." -fMakefile") then
+ return nil, "Failed building."
+ end
+
+ if not fs.execute_string(rockspec.variables.MAKE.." -fMakefile install") then
+ return nil, "Failed installing."
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/build/command.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build/command.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,32 @@
+
+--- Build back-end for raw listing of commands in rockspec files.
+module("luarocks.build.command", package.seeall)
+
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+
+--- Driver function for the "command" build back-end.
+-- @param rockspec table: the loaded rockspec.
+-- @return boolean or (nil, string): true if no errors ocurred,
+-- nil and an error message otherwise.
+function run(rockspec)
+ assert(type(rockspec) == "table")
+
+ local build = rockspec.build
+
+ util.variable_substitutions(build, rockspec.variables)
+
+ if build.build_command then
+ util.printout(build.build_command)
+ if not fs.execute(build.build_command) then
+ return nil, "Failed building."
+ end
+ end
+ if build.install_command then
+ util.printout(build.install_command)
+ if not fs.execute(build.install_command) then
+ return nil, "Failed installing."
+ end
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/build/make.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/build/make.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,92 @@
+
+--- Build back-end for using Makefile-based packages.
+module("luarocks.build.make", package.seeall)
+
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+
+--- Call "make" with given target and variables
+-- @param make_cmd string: the make command to be used (typically
+-- configured through variables.MAKE in the config files, or
+-- the appropriate platform-specific default).
+-- @param pass boolean: If true, run make; if false, do nothing.
+-- @param target string: The make target; an empty string indicates
+-- the default target.
+-- @param variables table: A table containing string-string key-value
+-- pairs representing variable assignments to be passed to make.
+-- @return boolean: false if any errors occurred, true otherwise.
+local function make_pass(make_cmd, pass, target, variables)
+ assert(type(pass) == "boolean")
+ assert(type(target) == "string")
+ assert(type(variables) == "table")
+
+ local assignments = {}
+ for k,v in pairs(variables) do
+ table.insert(assignments, k.."="..v)
+ end
+ if pass then
+ return fs.execute(make_cmd.." "..target, unpack(assignments))
+ else
+ return true
+ end
+end
+
+--- Driver function for the "make" build back-end.
+-- @param rockspec table: the loaded rockspec.
+-- @return boolean or (nil, string): true if no errors ocurred,
+-- nil and an error message otherwise.
+function run(rockspec)
+ assert(type(rockspec) == "table")
+
+ local build = rockspec.build
+
+ if build.build_pass == nil then build.build_pass = true end
+ if build.install_pass == nil then build.install_pass = true end
+ build.build_variables = build.build_variables or {}
+ build.install_variables = build.install_variables or {}
+ build.build_target = build.build_target or ""
+ build.install_target = build.install_target or "install"
+ local makefile = build.makefile or cfg.makefile
+ if makefile then
+ -- Assumes all make's accept -f. True for POSIX make, GNU make and Microsoft nmake.
+ build.build_target = "-f "..makefile.." "..build.build_target
+ build.install_target = "-f "..makefile.." "..build.install_target
+ end
+
+ if build.variables then
+ for var, val in pairs(build.variables) do
+ build.build_variables[var] = val
+ build.install_variables[var] = val
+ end
+ end
+
+ util.warn_if_not_used(build.build_variables, { CFLAGS=true }, "variable %s was not passed in build_variables")
+
+ util.variable_substitutions(build.build_variables, rockspec.variables)
+ util.variable_substitutions(build.install_variables, rockspec.variables)
+
+ local auto_variables = { "CC" }
+
+ for _, variable in pairs(auto_variables) do
+ if not build.build_variables[variable] then
+ build.build_variables[variable] = rockspec.variables[variable]
+ end
+ if not build.install_variables[variable] then
+ build.install_variables[variable] = rockspec.variables[variable]
+ end
+ end
+
+ -- backwards compatibility
+ local make_cmd = cfg.make or rockspec.variables.MAKE
+
+ local ok = make_pass(make_cmd, build.build_pass, build.build_target, build.build_variables)
+ if not ok then
+ return nil, "Failed building."
+ end
+ ok = make_pass(make_cmd, build.install_pass, build.install_target, build.install_variables)
+ if not ok then
+ return nil, "Failed installing."
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/cache.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/cache.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,85 @@
+
+--- Module handling the LuaRocks local cache.
+-- Adds a rock or rockspec to a rocks server.
+module("luarocks.cache", package.seeall)
+
+local fs = require("luarocks.fs")
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+function get_upload_server(server)
+ if not server then server = cfg.upload_server end
+ if not server then
+ return nil, "No server specified and no default configured with upload_server."
+ end
+ return server, cfg.upload_servers and cfg.upload_servers[server]
+end
+
+function get_server_urls(server, upload_server)
+ local download_url = server
+ local login_url = nil
+ if upload_server then
+ if upload_server.rsync then download_url = "rsync://"..upload_server.rsync
+ elseif upload_server.http then download_url = "http://"..upload_server.http
+ elseif upload_server.ftp then download_url = "ftp://"..upload_server.ftp
+ end
+
+ if upload_server.ftp then login_url = "ftp://"..upload_server.ftp
+ elseif upload_server.sftp then login_url = "sftp://"..upload_server.sftp
+ end
+ end
+ return download_url, login_url
+end
+
+function split_server_url(server, url, user, password)
+ local protocol, server_path = dir.split_url(url)
+ if server_path:match("@") then
+ local credentials
+ credentials, server_path = server_path:match("([^@]*)@(.*)")
+ if credentials:match(":") then
+ user, password = credentials:match("([^:]*):(.*)")
+ else
+ user = credentials
+ end
+ end
+ local local_cache
+ if cfg.local_cache then
+ local_cache = cfg.local_cache .. "/" .. server
+ end
+ return local_cache, protocol, server_path, user, password
+end
+
+function refresh_local_cache(server, url, user, password)
+ local local_cache, protocol, server_path, user, password = split_server_url(server, url, user, password)
+
+ fs.make_dir(cfg.local_cache)
+
+ local tmp_cache = false
+ if not local_cache then
+ local_cache = fs.make_temp_dir("local_cache")
+ tmp_cache = true
+ end
+ local ok = fs.make_dir(local_cache)
+ if not ok then
+ return nil, "Failed creating local cache dir."
+ end
+ fs.change_dir(local_cache)
+ util.printout("Refreshing cache "..local_cache.."...")
+
+ -- TODO abstract away explicit 'wget' call
+ local ok = false
+ if protocol == "rsync" then
+ local srv, path = server_path:match("([^/]+)(/.+)")
+ ok = fs.execute(cfg.variables.RSYNC.." -avz -e ssh "..user.."@"..srv..":"..path.."/ "..local_cache.."/")
+ else
+ local login_info = ""
+ if user then login_info = " --user="..user end
+ if password then login_info = login_info .. " --password="..password end
+ ok = fs.execute(cfg.variables.WGET.." --no-cache -q -m -np -nd "..protocol.."://"..server_path..login_info)
+ end
+ if not ok then
+ return nil, "Failed downloading cache."
+ end
+ return local_cache, protocol, server_path, user, password
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/cfg.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/cfg.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,454 @@
+--- Configuration for LuaRocks.
+-- Tries to load the user's configuration file and
+-- defines defaults for unset values. See the
+-- config
+-- file format documentation for details.
+--
+-- End-users shouldn't edit this file. They can override any defaults
+-- set in this file using their system-wide $LUAROCKS_SYSCONFIG file
+-- (see luarocks.site_config) or their user-specific configuration file
+-- (~/.luarocks/config.lua on Unix or %APPDATA%/luarocks/config.lua on
+-- Windows).
+
+local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION =
+ rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION
+
+module("luarocks.cfg")
+
+-- Load site-local global configurations
+local ok, site_config = pcall(require, "luarocks.site_config")
+if not ok then
+ io.stderr:write("Site-local luarocks/site_config.lua file not found. Incomplete installation?\n")
+ site_config = {}
+end
+
+_M.site_config = site_config
+
+lua_version = _VERSION:sub(5)
+program_version = "2.0.12"
+
+local persist = require("luarocks.persist")
+
+local popen_ok, popen_result = pcall(io.popen, "")
+if popen_ok then
+ if popen_result then
+ popen_result:close()
+ end
+else
+ io.stderr:write("Your version of Lua does not support io.popen,\n")
+ io.stderr:write("which is required by LuaRocks. Please check your Lua installation.\n")
+ os.exit(1)
+end
+
+-- System detection:
+
+local detected = {}
+local system,proc
+
+-- A proper installation of LuaRocks will hardcode the system
+-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M,
+-- so that this detection does not run every time. When it is
+-- performed, we use the Unix way to identify the system,
+-- even on Windows (assuming UnxUtils or Cygwin).
+system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
+proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l")
+if proc:match("i[%d]86") then
+ proc = "x86"
+elseif proc:match("amd64") or proc:match("x86_64") then
+ proc = "x86_64"
+elseif proc:match("Power Macintosh") then
+ proc = "powerpc"
+end
+
+if system == "FreeBSD" then
+ detected.unix = true
+ detected.freebsd = true
+ detected.bsd = true
+elseif system == "OpenBSD" then
+ detected.unix = true
+ detected.openbsd = true
+ detected.bsd = true
+elseif system == "NetBSD" then
+ detected.unix = true
+ detected.netbsd = true
+ detected.bsd = true
+elseif system == "Darwin" then
+ detected.unix = true
+ detected.macosx = true
+ detected.bsd = true
+elseif system == "Linux" then
+ detected.unix = true
+ detected.linux = true
+elseif system == "SunOS" then
+ detected.unix = true
+ detected.solaris = true
+elseif system and system:match("^CYGWIN") then
+ detected.unix = true
+ detected.cygwin = true
+elseif system and system:match("^Windows") then
+ detected.windows = true
+elseif system and system:match("^MINGW") then
+ detected.windows = true
+ detected.mingw32 = true
+else
+ detected.unix = true
+ -- Fall back to Unix in unknown systems.
+end
+
+-- Path configuration:
+
+local version_suffix = lua_version:gsub ("%.", "_")
+local sys_config_file, home_config_file
+local sys_config_ok, home_config_ok = false, false
+sys_config_file = site_config["LUAROCKS_SYSCONFIG_" .. version_suffix] or site_config.LUAROCKS_SYSCONFIG
+if detected.windows then
+ home = os.getenv("APPDATA") or "c:"
+ sys_config_file = sys_config_file or "c:/luarocks/config.lua"
+ home_config_file = home.."/luarocks/config.lua"
+ home_tree = home.."/luarocks/"
+else
+ home = os.getenv("HOME") or ""
+ sys_config_file = sys_config_file or "/etc/luarocks/config.lua"
+ home_config_file = home.."/.luarocks/config.lua"
+ home_tree = home.."/.luarocks/"
+end
+
+variables = {}
+rocks_trees = {}
+
+local ok, err = persist.load_into_table(sys_config_file, _M)
+if ok then
+ sys_config_ok = true
+else -- nil or false
+ sys_config_ok = ok
+ if err and ok == nil then
+ io.stderr:write(err.."\n")
+ end
+end
+
+if not site_config.LUAROCKS_FORCE_CONFIG then
+ home_config_file = os.getenv("LUAROCKS_CONFIG_" .. version_suffix) or os.getenv("LUAROCKS_CONFIG") or home_config_file
+ local home_overrides, err = persist.load_into_table(home_config_file, { home = home })
+ if home_overrides then
+ home_config_ok = true
+ local util = require("luarocks.util")
+ if home_overrides.rocks_trees then
+ _M.rocks_trees = nil
+ end
+ if home_overrides.rocks_servers then
+ _M.rocks_servers = nil
+ end
+ util.deep_merge(_M, home_overrides)
+ else -- nil or false
+ home_config_ok = home_overrides
+ if err and home_config_ok == nil then
+ io.stderr:write(err.."\n")
+ end
+ end
+end
+
+if not next(rocks_trees) then
+ if home_tree then
+ table.insert(rocks_trees, home_tree)
+ end
+ if site_config.LUAROCKS_ROCKS_TREE then
+ table.insert(rocks_trees, site_config.LUAROCKS_ROCKS_TREE)
+ end
+end
+
+-- Configure defaults:
+
+local root = rocks_trees[#rocks_trees]
+local defaults = {
+
+ local_by_default = false,
+ use_extensions = false,
+ accept_unknown_fields = false,
+ fs_use_modules = true,
+ deps_mode = "one",
+
+ lua_modules_path = "/share/lua/"..lua_version,
+ lib_modules_path = "/lib/lua/"..lua_version,
+
+ arch = "unknown",
+ lib_extension = "unknown",
+ obj_extension = "unknown",
+
+ rocks_servers = {
+ {
+ "http://www.luarocks.org/repositories/rocks",
+ "http://luarocks.giga.puc-rio.br/",
+ "http://luafr.org/luarocks/rocks",
+ "http://liblua.so/luarocks/repositories/rocks",
+ "http://luarocks.logiceditor.com/rocks",
+ }
+ },
+
+ lua_extension = "lua",
+ lua_interpreter = site_config.LUA_INTERPRETER or "lua",
+ downloader = site_config.LUAROCKS_DOWNLOADER or "wget",
+ md5checker = site_config.LUAROCKS_MD5CHECKER or "md5sum",
+
+ variables = {
+ MAKE = "make",
+ CC = "cc",
+ LD = "ld",
+
+ CVS = "cvs",
+ GIT = "git",
+ SSCM = "sscm",
+ SVN = "svn",
+ HG = "hg",
+
+ RSYNC = "rsync",
+ WGET = "wget",
+ SCP = "scp",
+ CURL = "curl",
+
+ PWD = "pwd",
+ MKDIR = "mkdir",
+ RMDIR = "rmdir",
+ CP = "cp",
+ LS = "ls",
+ RM = "rm",
+ FIND = "find",
+ TEST = "test",
+ CHMOD = "chmod",
+ PATCH = "patch",
+
+ ZIP = "zip",
+ UNZIP = "unzip",
+ GUNZIP = "gunzip",
+ BUNZIP2 = "bunzip2",
+ TAR = "tar",
+
+ MD5SUM = "md5sum",
+ OPENSSL = "openssl",
+ MD5 = "md5",
+ STAT = "stat",
+
+ CMAKE = "cmake",
+ SEVENZ = "7z",
+
+ STATFLAG = "-c '%a'",
+ },
+
+ external_deps_subdirs = {
+ bin = "bin",
+ lib = "lib",
+ include = "include"
+ },
+ runtime_external_deps_subdirs = {
+ bin = "bin",
+ lib = "lib",
+ include = "include"
+ },
+}
+
+if detected.windows then
+ home_config_file = home_config_file:gsub("\\","/")
+ defaults.fs_use_modules = false
+ defaults.arch = "win32-"..proc
+ defaults.platforms = {"win32", "windows" }
+ defaults.lib_extension = "dll"
+ defaults.external_lib_extension = "dll"
+ defaults.obj_extension = "obj"
+ defaults.external_deps_dirs = { "c:/external/" }
+ defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/bin"
+ defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/include"
+ defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/lib"
+ defaults.cmake_generator = "MinGW Makefiles"
+ defaults.makefile = "Makefile.win"
+ defaults.variables.MAKE = "nmake"
+ defaults.variables.CC = "cl"
+ defaults.variables.RC = "rc"
+ defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.obj"
+ defaults.variables.LD = "link"
+ defaults.variables.MT = "mt"
+ defaults.variables.LUALIB = "lua"..lua_version..".lib"
+ defaults.variables.CFLAGS = "/MD /O2"
+ defaults.variables.LIBFLAG = "/dll"
+ defaults.variables.LUALIB = "lua"..lua_version..".lib"
+ defaults.external_deps_patterns = {
+ bin = { "?.exe", "?.bat" },
+ lib = { "?.lib", "?.dll", "lib?.dll" },
+ include = { "?.h" }
+ }
+ defaults.runtime_external_deps_patterns = {
+ bin = { "?.exe", "?.bat" },
+ lib = { "?.dll", "lib?.dll" },
+ include = { "?.h" }
+ }
+ defaults.export_path = "SET PATH=%s"
+ defaults.export_path_separator = ";"
+ defaults.export_lua_path = "SET LUA_PATH=%s"
+ defaults.export_lua_cpath = "SET LUA_CPATH=%s"
+ defaults.local_cache = home.."/cache/luarocks"
+end
+
+if detected.mingw32 then
+ defaults.platforms = { "win32", "mingw32" }
+ defaults.obj_extension = "o"
+ defaults.cmake_generator = "MinGW Makefiles"
+ defaults.variables.MAKE = "mingw32-make"
+ defaults.variables.CC = "mingw32-gcc"
+ defaults.variables.RC = "windres"
+ defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.o"
+ defaults.variables.LD = "mingw32-gcc"
+ defaults.variables.CFLAGS = "-O2"
+ defaults.variables.LIBFLAG = "-shared"
+end
+
+if detected.unix then
+ defaults.lib_extension = "so"
+ defaults.external_lib_extension = "so"
+ defaults.obj_extension = "o"
+ defaults.external_deps_dirs = { "/usr/local", "/usr" }
+ defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR or "/usr/local/bin"
+ defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR or "/usr/local/include"
+ defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib"
+ defaults.variables.CFLAGS = "-O2"
+ defaults.cmake_generator = "Unix Makefiles"
+ defaults.platforms = { "unix" }
+ defaults.variables.CC = "gcc"
+ defaults.variables.LD = "gcc"
+ defaults.gcc_rpath = true
+ defaults.variables.LIBFLAG = "-shared"
+ defaults.external_deps_patterns = {
+ bin = { "?" },
+ lib = { "lib?.a", "lib?.so", "lib?.so.*" },
+ include = { "?.h" }
+ }
+ defaults.runtime_external_deps_patterns = {
+ bin = { "?" },
+ lib = { "lib?.so", "lib?.so.*" },
+ include = { "?.h" }
+ }
+ defaults.export_path = "export PATH='%s'"
+ defaults.export_path_separator = ":"
+ defaults.export_lua_path = "export LUA_PATH='%s'"
+ defaults.export_lua_cpath = "export LUA_CPATH='%s'"
+ defaults.local_cache = home.."/.cache/luarocks"
+ if not defaults.variables.CFLAGS:match("-fPIC") then
+ defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
+ end
+end
+
+if detected.cygwin then
+ defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
+ defaults.arch = "cygwin-"..proc
+ defaults.platforms = {"unix", "cygwin"}
+ defaults.cmake_generator = "Unix Makefiles"
+ defaults.variables.CC = "echo -llua | xargs gcc"
+ defaults.variables.LD = "echo -llua | xargs gcc"
+ defaults.variables.LIBFLAG = "-shared"
+end
+
+if detected.bsd then
+ defaults.variables.MAKE = "gmake"
+ defaults.variables.STATFLAG = "-f '%OLp'"
+end
+
+if detected.macosx then
+ defaults.external_lib_extension = "dylib"
+ defaults.arch = "macosx-"..proc
+ defaults.platforms = {"unix", "bsd", "macosx"}
+ defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
+ defaults.variables.STATFLAG = "-f '%A'"
+ local version = io.popen("sw_vers -productVersion"):read("*l")
+ version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3
+ if version >= 5 then
+ version = 5
+ else
+ defaults.gcc_rpath = false
+ end
+ defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc"
+ defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc"
+end
+
+if detected.linux then
+ defaults.arch = "linux-"..proc
+ defaults.platforms = {"unix", "linux"}
+end
+
+if detected.freebsd then
+ defaults.arch = "freebsd-"..proc
+ defaults.platforms = {"unix", "bsd", "freebsd"}
+end
+
+if detected.openbsd then
+ defaults.arch = "openbsd-"..proc
+ defaults.platforms = {"unix", "bsd", "openbsd"}
+end
+
+if detected.netbsd then
+ defaults.arch = "netbsd-"..proc
+ defaults.platforms = {"unix", "bsd", "netbsd"}
+end
+
+if detected.solaris then
+ defaults.arch = "solaris-"..proc
+ defaults.platforms = {"unix", "solaris"}
+ defaults.variables.MAKE = "gmake"
+end
+
+-- Expose some more values detected by LuaRocks for use by rockspec authors.
+defaults.variables.LIB_EXTENSION = defaults.lib_extension
+defaults.variables.OBJ_EXTENSION = defaults.obj_extension
+defaults.variables.LUAROCKS_PREFIX = site_config.LUAROCKS_PREFIX
+defaults.variables.LUA = site_config.LUA_DIR_SET and (defaults.variables.LUA_BINDIR.."/"..defaults.lua_interpreter) or defaults.lua_interpreter
+
+-- Use defaults:
+
+-- Populate values from 'defaults.variables' in 'variables' if they were not
+-- already set by user.
+if not _M.variables then
+ _M.variables = {}
+end
+for k,v in pairs(defaults.variables) do
+ if not _M.variables[k] then
+ _M.variables[k] = v
+ end
+end
+
+-- For values not set in the config file, use values from the 'defaults' table.
+local cfg_mt = {
+ __index = function(t, k)
+ local default = defaults[k]
+ if default then
+ rawset(t, k, default)
+ end
+ return default
+ end
+}
+setmetatable(_M, cfg_mt)
+
+for _,tree in ipairs(rocks_trees) do
+ if type(tree) == "string" then
+ package.path = tree..lua_modules_path.."/?.lua;"..tree..lua_modules_path.."/?/init.lua;"..package.path
+ package.cpath = tree..lib_modules_path.."/?."..lib_extension..";"..package.cpath
+ else
+ package.path = (tree.lua_dir or tree.root..lua_modules_path).."/?.lua;"..
+ (tree.lua_dir or tree.root..lua_modules_path).."/?/init.lua;"..package.path
+ package.cpath = (tree.lib_dir or tree.root..lib_modules_path).."/?."..lib_extension..";"..package.cpath
+ end
+end
+
+function which_config()
+ return sys_config_file, sys_config_ok, home_config_file, home_config_ok
+end
+
+user_agent = "LuaRocks/"..program_version.." "..arch
+
+--- Check if platform was detected
+-- @param query string: The platform name to check.
+-- @return boolean: true if LuaRocks is currently running on queried platform.
+function is_platform(query)
+ assert(type(query) == "string")
+
+ for _, platform in ipairs(platforms) do
+ if platform == query then
+ return true
+ end
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/command_line.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/command_line.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,166 @@
+
+--- Functions for command-line scripts.
+module("luarocks.command_line", package.seeall)
+
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local path = require("luarocks.path")
+local dir = require("luarocks.dir")
+local deps = require("luarocks.deps")
+
+--- Display an error message and exit.
+-- @param message string: The error message.
+local function die(message)
+ assert(type(message) == "string")
+
+ local ok, err = pcall(util.run_scheduled_functions)
+ if not ok then
+ util.printerr("\nLuaRocks "..cfg.program_version.." internal bug (please report at luarocks-developers@lists.sourceforge.net):\n"..err)
+ end
+ util.printerr("\nError: "..message)
+ os.exit(1)
+end
+
+--- Main command-line processor.
+-- Parses input arguments and calls the appropriate driver function
+-- to execute the action requested on the command-line, forwarding
+-- to it any additional arguments passed by the user.
+-- Uses the global table "commands", which contains
+-- the loaded modules representing commands.
+-- @param ... string: Arguments given on the command-line.
+function run_command(...)
+ local args = {...}
+ local cmdline_vars = {}
+ for i = #args, 1, -1 do
+ local arg = args[i]
+ if arg:match("^[^-][^=]*=") then
+ local var, val = arg:match("^([A-Z_][A-Z0-9_]*)=(.*)")
+ if val then
+ cmdline_vars[var] = val
+ table.remove(args, i)
+ else
+ die("Invalid assignment: "..arg)
+ end
+ end
+ end
+ local nonflags = { util.parse_flags(unpack(args)) }
+ local flags = table.remove(nonflags, 1)
+
+ if flags["from"] then flags["server"] = flags["from"] end
+ if flags["only-from"] then flags["only-server"] = flags["only-from"] end
+ if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end
+ if flags["to"] then flags["tree"] = flags["to"] end
+ if flags["nodeps"] then
+ flags["deps-mode"] = "none"
+ table.insert(args, "--deps-mode=none")
+ end
+
+ cfg.flags = flags
+
+ local command
+
+ if flags["version"] then
+ util.printout(program_name.." "..cfg.program_version)
+ util.printout(program_description)
+ util.printout()
+ os.exit(0)
+ elseif flags["help"] or #nonflags == 0 then
+ command = "help"
+ args = nonflags
+ else
+ command = nonflags[1]
+ for i, arg in ipairs(args) do
+ if arg == command then
+ table.remove(args, i)
+ break
+ end
+ end
+ end
+ command = command:gsub("-", "_")
+
+ if flags["extensions"] then
+ cfg.use_extensions = true
+ local type_check = require("luarocks.type_check")
+ type_check.load_extensions()
+ end
+
+ if cfg.local_by_default then
+ flags["local"] = true
+ end
+
+ if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then
+ die("Invalid entry for --deps-mode.")
+ end
+
+ if flags["tree"] then
+ if flags["tree"] == true or flags["tree"] == "" then
+ die("Argument error: use --tree=")
+ end
+ local fs = require("luarocks.fs")
+ local root_dir = fs.absolute_name(flags["tree"])
+ path.use_tree(root_dir)
+ elseif flags["local"] then
+ path.use_tree(cfg.home_tree)
+ else
+ local trees = cfg.rocks_trees
+ path.use_tree(trees[#trees])
+ end
+
+ if type(cfg.root_dir) == "string" then
+ cfg.root_dir = cfg.root_dir:gsub("/+$", "")
+ else
+ cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "")
+ end
+ cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
+ cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
+ cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "")
+ cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
+
+ cfg.variables.ROCKS_TREE = cfg.rocks_dir
+ cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
+
+ if flags["server"] then
+ if flags["server"] == true then
+ die("Argument error: use --server=")
+ end
+ local protocol, path = dir.split_url(flags["server"])
+ table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
+ end
+
+ if flags["only-server"] then
+ if flags["only-server"] == true then
+ die("Argument error: use --only-server=")
+ end
+ cfg.rocks_servers = { flags["only-server"] }
+ end
+
+ if flags["only-sources"] then
+ cfg.only_sources_from = flags["only-sources"]
+ end
+
+ if command ~= "help" then
+ for k, v in pairs(cmdline_vars) do
+ cfg.variables[k] = v
+ end
+ end
+
+ if commands[command] then
+ -- TODO the interface of run should be modified, to receive the
+ -- flags table and the (possibly unpacked) nonflags arguments.
+ -- This would remove redundant parsing of arguments.
+ -- I'm not changing this now to avoid messing with the run()
+ -- interface, which I know some people use (even though
+ -- I never published it as a public API...)
+ local xp, ok, err = xpcall(function() return commands[command].run(unpack(args)) end, function(err)
+ die(debug.traceback("LuaRocks "..cfg.program_version
+ .." bug (please report at luarocks-developers@lists.sourceforge.net).\n"
+ ..err, 2))
+ end)
+ if xp and (not ok) then
+ die(err)
+ end
+ else
+ die("Unknown command: "..command)
+ end
+ util.run_scheduled_functions()
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/deps.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/deps.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,706 @@
+
+--- Dependency handling functions.
+-- Dependencies are represented in LuaRocks through strings with
+-- a package name followed by a comma-separated list of constraints.
+-- Each constraint consists of an operator and a version number.
+-- In this string format, version numbers are represented as
+-- naturally as possible, like they are used by upstream projects
+-- (e.g. "2.0beta3"). Internally, LuaRocks converts them to a purely
+-- numeric representation, allowing comparison following some
+-- "common sense" heuristics. The precise specification of the
+-- comparison criteria is the source code of this module, but the
+-- test/test_deps.lua file included with LuaRocks provides some
+-- insights on what these criteria are.
+module("luarocks.deps", package.seeall)
+
+local cfg = require("luarocks.cfg")
+local manif_core = require("luarocks.manif_core")
+local path = require("luarocks.path")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+local operators = {
+ ["=="] = "==",
+ ["~="] = "~=",
+ [">"] = ">",
+ ["<"] = "<",
+ [">="] = ">=",
+ ["<="] = "<=",
+ ["~>"] = "~>",
+ -- plus some convenience translations
+ [""] = "==",
+ ["="] = "==",
+ ["!="] = "~="
+}
+
+local deltas = {
+ scm = 1000,
+ cvs = 1000,
+ rc = -1000,
+ pre = -10000,
+ beta = -100000,
+ alpha = -1000000
+}
+
+local version_mt = {
+ --- Equality comparison for versions.
+ -- All version numbers must be equal.
+ -- If both versions have revision numbers, they must be equal;
+ -- otherwise the revision number is ignored.
+ -- @param v1 table: version table to compare.
+ -- @param v2 table: version table to compare.
+ -- @return boolean: true if they are considered equivalent.
+ __eq = function(v1, v2)
+ if #v1 ~= #v2 then
+ return false
+ end
+ for i = 1, #v1 do
+ if v1[i] ~= v2[i] then
+ return false
+ end
+ end
+ if v1.revision and v2.revision then
+ return (v1.revision == v2.revision)
+ end
+ return true
+ end,
+ --- Size comparison for versions.
+ -- All version numbers are compared.
+ -- If both versions have revision numbers, they are compared;
+ -- otherwise the revision number is ignored.
+ -- @param v1 table: version table to compare.
+ -- @param v2 table: version table to compare.
+ -- @return boolean: true if v1 is considered lower than v2.
+ __lt = function(v1, v2)
+ for i = 1, math.max(#v1, #v2) do
+ local v1i, v2i = v1[i] or 0, v2[i] or 0
+ if v1i ~= v2i then
+ return (v1i < v2i)
+ end
+ end
+ if v1.revision and v2.revision then
+ return (v1.revision < v2.revision)
+ end
+ return false
+ end
+}
+
+local version_cache = {}
+setmetatable(version_cache, {
+ __mode = "kv"
+})
+
+--- Parse a version string, converting to table format.
+-- A version table contains all components of the version string
+-- converted to numeric format, stored in the array part of the table.
+-- If the version contains a revision, it is stored numerically
+-- in the 'revision' field. The original string representation of
+-- the string is preserved in the 'string' field.
+-- Returned version tables use a metatable
+-- allowing later comparison through relational operators.
+-- @param vstring string: A version number in string format.
+-- @return table or nil: A version table or nil
+-- if the input string contains invalid characters.
+function parse_version(vstring)
+ if not vstring then return nil end
+ assert(type(vstring) == "string")
+
+ local cached = version_cache[vstring]
+ if cached then
+ return cached
+ end
+
+ local version = {}
+ local i = 1
+
+ local function add_token(number)
+ version[i] = version[i] and version[i] + number/100000 or number
+ i = i + 1
+ end
+
+ -- trim leading and trailing spaces
+ vstring = vstring:match("^%s*(.*)%s*$")
+ version.string = vstring
+ -- store revision separately if any
+ local main, revision = vstring:match("(.*)%-(%d+)$")
+ if revision then
+ vstring = main
+ version.revision = tonumber(revision)
+ end
+ while #vstring > 0 do
+ -- extract a number
+ local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)")
+ if token then
+ add_token(tonumber(token))
+ else
+ -- extract a word
+ token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)")
+ if not token then
+ util.printerr("Warning: version number '"..vstring.."' could not be parsed.")
+ version[i] = 0
+ break
+ end
+ local last = #version
+ version[i] = deltas[token] or (token:byte() / 1000)
+ end
+ vstring = rest
+ end
+ setmetatable(version, version_mt)
+ version_cache[vstring] = version
+ return version
+end
+
+--- Utility function to compare version numbers given as strings.
+-- @param a string: one version.
+-- @param b string: another version.
+-- @return boolean: True if a > b.
+function compare_versions(a, b)
+ return parse_version(a) > parse_version(b)
+end
+
+--- Consumes a constraint from a string, converting it to table format.
+-- For example, a string ">= 1.0, > 2.0" is converted to a table in the
+-- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
+-- back to the caller.
+-- @param input string: A list of constraints in string format.
+-- @return (table, string) or nil: A table representing the same
+-- constraints and the string with the unused input, or nil if the
+-- input string is invalid.
+local function parse_constraint(input)
+ assert(type(input) == "string")
+
+ local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
+ op = operators[op]
+ version = parse_version(version)
+ if not op or not version then return nil end
+ return { op = op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest
+end
+
+--- Convert a list of constraints from string to table format.
+-- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
+-- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
+-- Version tables use a metatable allowing later comparison through
+-- relational operators.
+-- @param input string: A list of constraints in string format.
+-- @return table or nil: A table representing the same constraints,
+-- or nil if the input string is invalid.
+function parse_constraints(input)
+ assert(type(input) == "string")
+
+ local constraints, constraint = {}, nil
+ while #input > 0 do
+ constraint, input = parse_constraint(input)
+ if constraint then
+ table.insert(constraints, constraint)
+ else
+ return nil
+ end
+ end
+ return constraints
+end
+
+--- Convert a dependency from string to table format.
+-- For example, a string "foo >= 1.0, < 2.0"
+-- is converted to a table in the format
+-- {name = "foo", constraints = {{op = ">=", version={1,0}},
+-- {op = "<", version={2,0}}}}. Version tables use a metatable
+-- allowing later comparison through relational operators.
+-- @param dep string: A dependency in string format
+-- as entered in rockspec files.
+-- @return table or nil: A table representing the same dependency relation,
+-- or nil if the input string is invalid.
+function parse_dep(dep)
+ assert(type(dep) == "string")
+
+ local name, rest = dep:match("^%s*([a-zA-Z][a-zA-Z0-9%.%-%_]*)%s*(.*)")
+ if not name then return nil end
+ local constraints = parse_constraints(rest)
+ if not constraints then return nil end
+ return { name = name, constraints = constraints }
+end
+
+--- Convert a version table to a string.
+-- @param v table: The version table
+-- @param internal boolean or nil: Whether to display versions in their
+-- internal representation format or how they were specified.
+-- @return string: The dependency information pretty-printed as a string.
+function show_version(v, internal)
+ assert(type(v) == "table")
+ assert(type(internal) == "boolean" or not internal)
+
+ return (internal
+ and table.concat(v, ":")..(v.revision and tostring(v.revision) or "")
+ or v.string)
+end
+
+--- Convert a dependency in table format to a string.
+-- @param dep table: The dependency in table format
+-- @param internal boolean or nil: Whether to display versions in their
+-- internal representation format or how they were specified.
+-- @return string: The dependency information pretty-printed as a string.
+function show_dep(dep, internal)
+ assert(type(dep) == "table")
+ assert(type(internal) == "boolean" or not internal)
+
+ local pretty = {}
+ for _, c in ipairs(dep.constraints) do
+ table.insert(pretty, c.op .. " " .. show_version(c.version, internal))
+ end
+ return dep.name.." "..table.concat(pretty, ", ")
+end
+
+--- A more lenient check for equivalence between versions.
+-- This returns true if the requested components of a version
+-- match and ignore the ones that were not given. For example,
+-- when requesting "2", then "2", "2.1", "2.3.5-9"... all match.
+-- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2"
+-- doesn't.
+-- @param version string or table: Version to be tested; may be
+-- in string format or already parsed into a table.
+-- @param requested string or table: Version requested; may be
+-- in string format or already parsed into a table.
+-- @return boolean: True if the tested version matches the requested
+-- version, false otherwise.
+local function partial_match(version, requested)
+ assert(type(version) == "string" or type(version) == "table")
+ assert(type(requested) == "string" or type(version) == "table")
+
+ if type(version) ~= "table" then version = parse_version(version) end
+ if type(requested) ~= "table" then requested = parse_version(requested) end
+ if not version or not requested then return false end
+
+ for i, ri in ipairs(requested) do
+ local vi = version[i] or 0
+ if ri ~= vi then return false end
+ end
+ if requested.revision then
+ return requested.revision == version.revision
+ end
+ return true
+end
+
+--- Check if a version satisfies a set of constraints.
+-- @param version table: A version in table format
+-- @param constraints table: An array of constraints in table format.
+-- @return boolean: True if version satisfies all constraints,
+-- false otherwise.
+function match_constraints(version, constraints)
+ assert(type(version) == "table")
+ assert(type(constraints) == "table")
+ local ok = true
+ setmetatable(version, version_mt)
+ for _, constr in pairs(constraints) do
+ local constr_version = constr.version
+ setmetatable(constr.version, version_mt)
+ if constr.op == "==" then ok = version == constr_version
+ elseif constr.op == "~=" then ok = version ~= constr_version
+ elseif constr.op == ">" then ok = version > constr_version
+ elseif constr.op == "<" then ok = version < constr_version
+ elseif constr.op == ">=" then ok = version >= constr_version
+ elseif constr.op == "<=" then ok = version <= constr_version
+ elseif constr.op == "~>" then ok = partial_match(version, constr_version)
+ end
+ if not ok then break end
+ end
+ return ok
+end
+
+--- Attempt to match a dependency to an installed rock.
+-- @param dep table: A dependency parsed in table format.
+-- @param blacklist table: Versions that can't be accepted. Table where keys
+-- are program versions and values are 'true'.
+-- @return table or nil: A table containing fields 'name' and 'version'
+-- representing an installed rock which matches the given dependency,
+-- or nil if it could not be matched.
+local function match_dep(dep, blacklist, deps_mode)
+ assert(type(dep) == "table")
+
+ local versions
+ if dep.name == "lua" then
+ versions = { cfg.lua_version }
+ else
+ versions = manif_core.get_versions(dep.name, deps_mode)
+ end
+ if not versions then
+ return nil
+ end
+ if blacklist then
+ local i = 1
+ while versions[i] do
+ if blacklist[versions[i]] then
+ table.remove(versions, i)
+ else
+ i = i + 1
+ end
+ end
+ end
+ local candidates = {}
+ for _, vstring in ipairs(versions) do
+ local version = parse_version(vstring)
+ if match_constraints(version, dep.constraints) then
+ table.insert(candidates, version)
+ end
+ end
+ if #candidates == 0 then
+ return nil
+ else
+ table.sort(candidates)
+ return {
+ name = dep.name,
+ version = candidates[#candidates].string
+ }
+ end
+end
+
+--- Attempt to match dependencies of a rockspec to installed rocks.
+-- @param rockspec table: The rockspec loaded as a table.
+-- @param blacklist table or nil: Program versions to not use as valid matches.
+-- Table where keys are program names and values are tables where keys
+-- are program versions and values are 'true'.
+-- @return table, table: A table where keys are dependencies parsed
+-- in table format and values are tables containing fields 'name' and
+-- version' representing matches, and a table of missing dependencies
+-- parsed as tables.
+function match_deps(rockspec, blacklist, deps_mode)
+ assert(type(rockspec) == "table")
+ assert(type(blacklist) == "table" or not blacklist)
+ local matched, missing, no_upgrade = {}, {}, {}
+
+ for _, dep in ipairs(rockspec.dependencies) do
+ local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode)
+ if found then
+ if dep.name ~= "lua" then
+ matched[dep] = found
+ end
+ else
+ if dep.constraints[1] and dep.constraints[1].no_upgrade then
+ no_upgrade[dep.name] = dep
+ else
+ missing[dep.name] = dep
+ end
+ end
+ end
+ return matched, missing, no_upgrade
+end
+
+--- Return a set of values of a table.
+-- @param tbl table: The input table.
+-- @return table: The array of keys.
+local function values_set(tbl)
+ local set = {}
+ for _, v in pairs(tbl) do
+ set[v] = true
+ end
+ return set
+end
+
+--- Check dependencies of a rock and attempt to install any missing ones.
+-- Packages are installed using the LuaRocks "install" command.
+-- Aborts the program if a dependency could not be fulfilled.
+-- @param rockspec table: A rockspec in table format.
+-- @return boolean or (nil, string, [string]): True if no errors occurred, or
+-- nil and an error message if any test failed, followed by an optional
+-- error code.
+function fulfill_dependencies(rockspec, deps_mode)
+
+ local search = require("luarocks.search")
+ local install = require("luarocks.install")
+
+ if rockspec.supported_platforms then
+ if not platforms_set then
+ platforms_set = values_set(cfg.platforms)
+ end
+ local supported = nil
+ for _, plat in pairs(rockspec.supported_platforms) do
+ local neg, plat = plat:match("^(!?)(.*)")
+ if neg == "!" then
+ if platforms_set[plat] then
+ return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms."
+ end
+ else
+ if platforms_set[plat] then
+ supported = true
+ else
+ if supported == nil then
+ supported = false
+ end
+ end
+ end
+ end
+ if supported == false then
+ local plats = table.concat(cfg.platforms, ", ")
+ return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms."
+ end
+ end
+
+ local matched, missing, no_upgrade = match_deps(rockspec, nil, deps_mode)
+
+ if next(no_upgrade) then
+ util.printerr("Missing dependencies for "..rockspec.name.." "..rockspec.version..":")
+ for _, dep in pairs(no_upgrade) do
+ util.printerr(show_dep(dep))
+ end
+ if next(missing) then
+ for _, dep in pairs(missing) do
+ util.printerr(show_dep(dep))
+ end
+ end
+ util.printerr()
+ for _, dep in pairs(no_upgrade) do
+ util.printerr("This version of "..rockspec.name.." is designed for use with")
+ util.printerr(show_dep(dep)..", but is configured to avoid upgrading it")
+ util.printerr("automatically. Please upgrade "..dep.name.." with")
+ util.printerr(" luarocks install "..dep.name)
+ util.printerr("or choose an older version of "..rockspec.name.." with")
+ util.printerr(" luarocks search "..rockspec.name)
+ end
+ return nil, "Failed matching dependencies."
+ end
+
+ if next(missing) then
+ util.printerr()
+ util.printerr("Missing dependencies for "..rockspec.name..":")
+ for _, dep in pairs(missing) do
+ util.printerr(show_dep(dep))
+ end
+ util.printerr()
+
+ for _, dep in pairs(missing) do
+ -- Double-check in case dependency was filled during recursion.
+ if not match_dep(dep, nil, deps_mode) then
+ local rock = search.find_suitable_rock(dep)
+ if not rock then
+ return nil, "Could not satisfy dependency: "..show_dep(dep)
+ end
+ local ok, err, errcode = install.run(rock)
+ if not ok then
+ return nil, "Failed installing dependency: "..rock.." - "..err, errcode
+ end
+ end
+ end
+ end
+ return true
+end
+
+--- If filename matches a pattern, return the capture.
+-- For example, given "libfoo.so" and "lib?.so" is a pattern,
+-- returns "foo" (which can then be used to build names
+-- based on other patterns.
+-- @param file string: a filename
+-- @param pattern string: a pattern, where ? is to be matched by the filename.
+-- @return string The pattern, if found, or nil.
+local function deconstruct_pattern(file, pattern)
+ local depattern = "^"..(pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")).."$"
+ return (file:match(depattern))
+end
+
+--- Construct all possible patterns for a name and add to the files array.
+-- Run through the patterns array replacing all occurrences of "?"
+-- with the given file name and store them in the files array.
+-- @param file string A raw name (e.g. "foo")
+-- @param array of string An array of patterns with "?" as the wildcard
+-- (e.g. {"?.so", "lib?.so"})
+-- @param files The array of constructed names
+local function add_all_patterns(file, patterns, files)
+ for _, pattern in ipairs(patterns) do
+ table.insert(files, (pattern:gsub("?", file)))
+ end
+end
+
+--- Set up path-related variables for external dependencies.
+-- For each key in the external_dependencies table in the
+-- rockspec file, four variables are created: _DIR, _BINDIR,
+-- _INCDIR and _LIBDIR. These are not overwritten
+-- if already set (e.g. by the LuaRocks config file or through the
+-- command-line). Values in the external_dependencies table
+-- are tables that may contain a "header" or a "library" field,
+-- with filenames to be tested for existence.
+-- @param rockspec table: The rockspec table.
+-- @param mode string: if "build" is given, checks all files;
+-- if "install" is given, do not scan for headers.
+-- @return boolean or (nil, string): True if no errors occurred, or
+-- nil and an error message if any test failed.
+function check_external_deps(rockspec, mode)
+ assert(type(rockspec) == "table")
+
+ local fs = require("luarocks.fs")
+
+ local vars = rockspec.variables
+ local patterns = cfg.external_deps_patterns
+ local subdirs = cfg.external_deps_subdirs
+ if mode == "install" then
+ patterns = cfg.runtime_external_deps_patterns
+ subdirs = cfg.runtime_external_deps_subdirs
+ end
+ if rockspec.external_dependencies then
+ for name, files in pairs(rockspec.external_dependencies) do
+ local ok = true
+ local failed_file = nil
+ local failed_dirname = nil
+ for _, extdir in ipairs(cfg.external_deps_dirs) do
+ ok = true
+ local prefix = vars[name.."_DIR"]
+ local dirs = {
+ BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin },
+ INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include },
+ LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib }
+ }
+ if mode == "install" then
+ dirs.INCDIR = nil
+ end
+ if not prefix then
+ prefix = extdir
+ end
+ if type(prefix) == "table" then
+ if prefix.bin then
+ dirs.BINDIR.subdir = prefix.bin
+ end
+ if prefix.include then
+ if dirs.INCDIR then
+ dirs.INCDIR.subdir = prefix.include
+ end
+ end
+ if prefix.lib then
+ dirs.LIBDIR.subdir = prefix.lib
+ end
+ prefix = prefix.prefix
+ end
+ for dirname, dirdata in pairs(dirs) do
+ dirdata.dir = vars[name.."_"..dirname] or dir.path(prefix, dirdata.subdir)
+ local file = files[dirdata.testfile]
+ if file then
+ local files = {}
+ if not file:match("%.") then
+ add_all_patterns(file, dirdata.pattern, files)
+ else
+ for _, pattern in ipairs(dirdata.pattern) do
+ local matched = deconstruct_pattern(file, pattern)
+ if matched then
+ add_all_patterns(matched, dirdata.pattern, files)
+ end
+ end
+ table.insert(files, file)
+ end
+ local found = false
+ failed_file = nil
+ for _, f in pairs(files) do
+ -- small convenience hack
+ if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
+ f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
+ end
+ if f:match("%*") then
+ local replaced = f:gsub("%.", "%%."):gsub("%*", ".*")
+ for _, entry in ipairs(fs.list_dir(dirdata.dir)) do
+ if entry:match(replaced) then
+ found = true
+ break
+ end
+ end
+ else
+ found = fs.is_file(dir.path(dirdata.dir, f))
+ end
+ if found then
+ break
+ else
+ if failed_file then
+ failed_file = failed_file .. ", or " .. f
+ else
+ failed_file = f
+ end
+ end
+ end
+ if not found then
+ ok = false
+ failed_dirname = dirname
+ break
+ end
+ end
+ end
+ if ok then
+ for dirname, dirdata in pairs(dirs) do
+ vars[name.."_"..dirname] = dirdata.dir
+ end
+ vars[name.."_DIR"] = prefix
+ break
+ end
+ end
+ if not ok then
+ return nil, "Could not find expected file "..failed_file.." for "..name.." -- you may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_dirname.." to the luarocks command. Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local", "dependency"
+ end
+ end
+ end
+ return true
+end
+
+--- Recursively scan dependencies, to build a transitive closure of all
+-- dependent packages.
+-- @param results table: The results table being built.
+-- @param missing table: The table of missing dependencies being recursively built.
+-- @param manifest table: The manifest table containing dependencies.
+-- @param name string: Package name.
+-- @param version string: Package version.
+-- @return (table, table): The results and a table of missing dependencies.
+function scan_deps(results, missing, manifest, name, version, deps_mode)
+ assert(type(results) == "table")
+ assert(type(missing) == "table")
+ assert(type(manifest) == "table")
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ local fetch = require("luarocks.fetch")
+
+ local err
+ if results[name] then
+ return results, missing
+ end
+ if not manifest.dependencies then manifest.dependencies = {} end
+ local dependencies = manifest.dependencies
+ if not dependencies[name] then dependencies[name] = {} end
+ local dependencies_name = dependencies[name]
+ local deplist = dependencies_name[version]
+ local rockspec, err
+ if not deplist then
+ rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version))
+ if err then
+ missing[name.." "..version] = err
+ return results, missing
+ end
+ dependencies_name[version] = rockspec.dependencies
+ else
+ rockspec = { dependencies = deplist }
+ end
+ local matched, failures = match_deps(rockspec, nil, deps_mode)
+ for _, match in pairs(matched) do
+ results, missing = scan_deps(results, missing, manifest, match.name, match.version, deps_mode)
+ end
+ if next(failures) then
+ for _, failure in pairs(failures) do
+ missing[show_dep(failure)] = "failed"
+ end
+ end
+ results[name] = version
+ return results, missing
+end
+
+local valid_deps_modes = {
+ one = true,
+ order = true,
+ all = true,
+ none = true,
+}
+
+function check_deps_mode_flag(flag)
+ return valid_deps_modes[flag]
+end
+
+function get_deps_mode(flags)
+ if flags["deps-mode"] then
+ return flags["deps-mode"]
+ else
+ return cfg.deps_mode
+ end
+end
+
+function deps_mode_to_flag(deps_mode)
+ return "--deps-mode="..deps_mode
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/dir.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/dir.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,70 @@
+
+--- Generic utilities for handling pathnames.
+module("luarocks.dir", package.seeall)
+
+separator = "/"
+
+--- Strip the path off a path+filename.
+-- @param pathname string: A path+name, such as "/a/b/c"
+-- or "\a\b\c".
+-- @return string: The filename without its path, such as "c".
+function base_name(pathname)
+ assert(type(pathname) == "string")
+
+ local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)")
+ return base or pathname
+end
+
+--- Strip the name off a path+filename.
+-- @param pathname string: A path+name, such as "/a/b/c".
+-- @return string: The filename without its path, such as "/a/b/".
+-- For entries such as "/a/b/", "/a/" is returned. If there are
+-- no directory separators in input, "" is returned.
+function dir_name(pathname)
+ assert(type(pathname) == "string")
+
+ return (pathname:gsub("/*$", ""):match("(.*/)[^/]*")) or ""
+end
+
+--- Describe a path in a cross-platform way.
+-- Use this function to avoid platform-specific directory
+-- separators in other modules. Removes trailing slashes from
+-- each component given, to avoid repeated separators.
+-- Separators inside strings are kept, to handle URLs containing
+-- protocols.
+-- @param ... strings representing directories
+-- @return string: a string with a platform-specific representation
+-- of the path.
+function path(...)
+ local items = {...}
+ local i = 1
+ while items[i] do
+ items[i] = items[i]:gsub("(.+)/+$", "%1")
+ if items[i] == "" then
+ table.remove(items, i)
+ else
+ i = i + 1
+ end
+ end
+ return (table.concat(items, "/"):gsub("(.+)/+$", "%1"))
+end
+
+--- Split protocol and path from an URL or local pathname.
+-- URLs should be in the "protocol://path" format.
+-- For local pathnames, "file" is returned as the protocol.
+-- @param url string: an URL or a local pathname.
+-- @return string, string: the protocol, and the pathname without the protocol.
+function split_url(url)
+ assert(type(url) == "string")
+
+ local protocol, pathname = url:match("^([^:]*)://(.*)")
+ if not protocol then
+ protocol = "file"
+ pathname = url
+ end
+ return protocol, pathname
+end
+
+function normalize(name)
+ return name:gsub("\\", "/"):gsub("(.)/*$", "%1")
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/download.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/download.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,88 @@
+
+--- Module implementing the luarocks "download" command.
+-- Download a rock from the repository.
+module("luarocks.download", package.seeall)
+
+local util = require("luarocks.util")
+local path = require("luarocks.path")
+local fetch = require("luarocks.fetch")
+local search = require("luarocks.search")
+
+help_summary = "Download a specific rock file from a rocks server."
+help_arguments = "[--all] [--arch= | --source | --rockspec] [ []]"
+
+help = [[
+--all Download all files if there are multiple matches.
+--source Download .src.rock if available.
+--rockspec Download .rockspec if available.
+--arch= Download rock for a specific architecture.
+]]
+
+function download(arch, name, version, all)
+ local results, err
+ local query = search.make_query(name, version)
+ if arch then query.arch = arch end
+ if all then
+ if name == "" then query.exact_name = false end
+ results = search.search_repos(query)
+ else
+ results, err = search.find_suitable_rock(query)
+ end
+ if type(results) == "string" then
+ local file = fetch.fetch_url(results)
+ return file
+ elseif type(results) == "table" and next(results) then
+ if all then
+ local all_ok = true
+ local any_err = ""
+ for name, result in pairs(results) do
+ for version, versions in pairs(result) do
+ for _,items in pairs(versions) do
+ local filename = path.make_url(items.repo, name, version, items.arch)
+ local ok, err = fetch.fetch_url(filename)
+ if not ok then
+ all_ok = false
+ any_err = any_err .. "\n" .. err
+ end
+ end
+ end
+ end
+ return all_ok, any_err
+ else
+ util.printerr("Multiple search results were returned.")
+ util.title("Search results:")
+ search.print_results(results)
+ return nil, "Please narrow your query or use --all."
+ end
+ end
+ return nil, "Could not find a result named "..name..(version and " "..version or "").."."
+end
+
+--- Driver function for the "download" command.
+-- @param name string: a rock name.
+-- @param version string or nil: if the name of a package is given, a
+-- version may also be passed.
+-- @return boolean or (nil, string): true if successful or nil followed
+-- by an error message.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+
+ assert(type(version) == "string" or not version)
+ if type(name) ~= "string" and not flags["all"] then
+ return nil, "Argument missing, see help."
+ end
+ if not name then name, version = "", "" end
+
+ local arch
+
+ if flags["source"] then
+ arch = "src"
+ elseif flags["rockspec"] then
+ arch = "rockspec"
+ elseif flags["arch"] then
+ arch = flags["arch"]
+ end
+
+ local dl, err = download(arch, name, version, flags["all"])
+ return dl and true, err
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,321 @@
+
+--- Functions related to fetching and loading local and remote files.
+module("luarocks.fetch", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local type_check = require("luarocks.type_check")
+local path = require("luarocks.path")
+local deps = require("luarocks.deps")
+local persist = require("luarocks.persist")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+
+--- Fetch a local or remote file.
+-- Make a remote or local URL/pathname local, fetching the file if necessary.
+-- Other "fetch" and "load" functions use this function to obtain files.
+-- If a local pathname is given, it is returned as a result.
+-- @param url string: a local pathname or a remote URL.
+-- @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 string or (nil, string, [string]): the absolute local pathname for the
+-- fetched file, or nil and a message in case of errors, followed by
+-- an optional error code.
+function fetch_url(url, filename)
+ assert(type(url) == "string")
+ assert(type(filename) == "string" or not filename)
+
+ local protocol, pathname = dir.split_url(url)
+ if protocol == "file" then
+ return fs.absolute_name(pathname)
+ elseif protocol == "http" or protocol == "ftp" or protocol == "https" then
+ local ok, err = fs.download(url, filename)
+ if not ok then
+ return nil, "Failed downloading "..url..(err and " - "..err or ""), "network"
+ end
+ return dir.path(fs.current_dir(), filename or dir.base_name(url))
+ else
+ return nil, "Unsupported protocol "..protocol
+ end
+end
+
+--- For remote URLs, create a temporary directory and download URL inside it.
+-- This temporary directory will be deleted on program termination.
+-- For local URLs, just return the local pathname and its directory.
+-- @param url string: URL to be downloaded
+-- @param tmpname string: name pattern to use for avoiding conflicts
+-- when creating temporary directory.
+-- @param filename string or nil: local filename of URL to be downloaded,
+-- in case it can't be inferred from the URL.
+-- @return (string, string) or (nil, string, [string]): absolute local pathname of
+-- the fetched file and temporary directory name; or nil and an error message
+-- followed by an optional error code
+function fetch_url_at_temp_dir(url, tmpname, filename)
+ assert(type(url) == "string")
+ assert(type(tmpname) == "string")
+ assert(type(filename) == "string" or not filename)
+ filename = filename or dir.base_name(url)
+
+ local protocol, pathname = dir.split_url(url)
+ if protocol == "file" then
+ if fs.exists(pathname) then
+ return pathname, dir.dir_name(fs.absolute_name(pathname))
+ else
+ return nil, "File not found: "..pathname
+ end
+ else
+ local temp_dir = fs.make_temp_dir(tmpname)
+ if not temp_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, temp_dir)
+ fs.change_dir(temp_dir)
+ local file, err, errcode = fetch_url(url, filename)
+ fs.pop_dir()
+ if not file then
+ return nil, "Error fetching file: "..err, errcode
+ end
+ return file, temp_dir
+ end
+end
+
+--- Obtain a rock and unpack it.
+-- If a directory is not given, a temporary directory will be created,
+-- which will be deleted on program termination.
+-- @param rock_file string: URL or filename of the rock.
+-- @param dest string or nil: if given, directory will be used as
+-- a permanent destination.
+-- @return string or (nil, string, [string]): the directory containing the contents
+-- of the unpacked rock.
+function fetch_and_unpack_rock(rock_file, dest)
+ assert(type(rock_file) == "string")
+ assert(type(dest) == "string" or not dest)
+
+ local name = dir.base_name(rock_file):match("(.*)%.[^.]*%.rock")
+
+ local rock_file, err, errcode = fetch_url_at_temp_dir(rock_file,"luarocks-rock-"..name)
+ if not rock_file then
+ return nil, "Could not fetch rock file: " .. err, errcode
+ end
+
+ rock_file = fs.absolute_name(rock_file)
+ local unpack_dir
+ if dest then
+ unpack_dir = dest
+ fs.make_dir(unpack_dir)
+ else
+ unpack_dir = fs.make_temp_dir(name)
+ end
+ if not dest then
+ util.schedule_function(fs.delete, unpack_dir)
+ end
+ fs.change_dir(unpack_dir)
+ local ok = fs.unzip(rock_file)
+ if not ok then
+ return nil, "Failed unpacking rock file: " .. rock_file
+ end
+ fs.pop_dir()
+ return unpack_dir
+end
+
+--- Back-end function that actually loads the local rockspec.
+-- Performs some validation and postprocessing of the rockspec contents.
+-- @param filename string: The local filename of the rockspec file.
+-- @return table or (nil, string): A table representing the rockspec
+-- or nil followed by an error message.
+function load_local_rockspec(filename)
+ assert(type(filename) == "string")
+ filename = fs.absolute_name(filename)
+ local rockspec, err = persist.load_into_table(filename)
+ if not rockspec then
+ return nil, "Could not load rockspec file "..filename.." ("..err..")"
+ end
+
+ local ok, err = type_check.type_check_rockspec(rockspec)
+ if not ok then
+ return nil, filename..": "..err
+ end
+
+ if rockspec.rockspec_format then
+ if deps.compare_versions(rockspec.rockspec_format, type_check.rockspec_format) then
+ return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks."
+ end
+ end
+
+ util.platform_overrides(rockspec.build)
+ util.platform_overrides(rockspec.dependencies)
+ util.platform_overrides(rockspec.external_dependencies)
+ util.platform_overrides(rockspec.source)
+ util.platform_overrides(rockspec.hooks)
+
+ local basename = dir.base_name(filename)
+ if basename == "rockspec" then
+ rockspec.name = rockspec.package:lower()
+ else
+ rockspec.name = basename:match("(.*)-[^-]*-[0-9]*")
+ if not rockspec.name then
+ return nil, "Expected filename in format 'name-version-revision.rockspec'."
+ end
+ end
+
+ local protocol, pathname = dir.split_url(rockspec.source.url)
+ if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
+ rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
+ end
+ rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
+
+ -- Temporary compatibility
+ if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
+ if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end
+
+ local name_version = rockspec.package:lower() .. "-" .. rockspec.version
+ if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then
+ return nil, "Inconsistency between rockspec filename ("..basename..") and its contents ("..name_version..".rockspec)."
+ end
+
+ rockspec.local_filename = filename
+ local filebase = rockspec.source.file or rockspec.source.url
+ local base = dir.base_name(filebase)
+ base = base:gsub("%.[^.]*$", ""):gsub("%.tar$", "")
+ rockspec.source.dir = rockspec.source.dir
+ or rockspec.source.module
+ or ((filebase:match(".lua$") or filebase:match(".c$")) and ".")
+ or base
+ if rockspec.dependencies then
+ for i = 1, #rockspec.dependencies do
+ local parsed = deps.parse_dep(rockspec.dependencies[i])
+ if not parsed then
+ return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."'"
+ end
+ rockspec.dependencies[i] = parsed
+ end
+ else
+ rockspec.dependencies = {}
+ end
+ local ok, err = path.configure_paths(rockspec)
+ if err then
+ return nil, "Error verifying paths: "..err
+ end
+
+ return rockspec
+end
+
+--- Load a local or remote rockspec into a table.
+-- This is the entry point for the LuaRocks tools.
+-- Only the LuaRocks runtime loader should use
+-- load_local_rockspec directly.
+-- @param filename string: Local or remote filename of a rockspec.
+-- @param location string or nil: Where to download. If not given,
+-- a temporary dir is created.
+-- @return table or (nil, string, [string]): A table representing the rockspec
+-- or nil followed by an error message and optional error code.
+function load_rockspec(filename, location)
+ assert(type(filename) == "string")
+
+ local name
+ local basename = dir.base_name(filename)
+ if basename == "rockspec" then
+ name = "rockspec"
+ else
+ name = basename:match("(.*)%.rockspec")
+ if not name and not basename == "rockspec" then
+ return nil, "Filename '"..filename.."' does not look like a rockspec."
+ end
+ end
+
+ local err, errcode
+ if location then
+ fs.change_dir(location)
+ filename, err = fetch_url(filename)
+ fs.pop_dir()
+ else
+ filename, err, errcode = fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name)
+ end
+ if not filename then
+ return nil, err, errcode
+ end
+
+ return load_local_rockspec(filename)
+end
+
+--- Download sources for building a rock using the basic URL downloader.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Whether to extract the sources from
+-- the fetched source tarball or not.
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string, [string]): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message and optional error code.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(extract) == "boolean")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local url = rockspec.source.url
+ local name = rockspec.name.."-"..rockspec.version
+ local filename = rockspec.source.file
+ local source_file, store_dir, err, errcode
+ if dest_dir then
+ fs.change_dir(dest_dir)
+ source_file, err, errcode = fetch_url(url, filename)
+ fs.pop_dir()
+ store_dir = dest_dir
+ else
+ source_file, store_dir, errcode = fetch_url_at_temp_dir(url, "luarocks-source-"..name, filename)
+ end
+ if not source_file then
+ return nil, err or store_dir, errcode
+ end
+ if rockspec.source.md5 then
+ if not fs.check_md5(source_file, rockspec.source.md5) then
+ return nil, "MD5 check for "..filename.." has failed."
+ end
+ end
+ if extract then
+ fs.change_dir(store_dir)
+ fs.unpack_archive(rockspec.source.file)
+ if not fs.exists(rockspec.source.dir) then
+ return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file
+ end
+ fs.pop_dir()
+ end
+ return source_file, store_dir
+end
+
+--- Download sources for building a rock, calling the appropriate protocol method.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: When downloading compressed formats, whether to extract
+-- the sources from the fetched archive or not.
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function fetch_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(extract) == "boolean")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local protocol = rockspec.source.protocol
+ local ok, proto
+ if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
+ proto = require("luarocks.fetch")
+ else
+ ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_"))
+ if not ok then
+ return nil, "Unknown protocol "..protocol
+ end
+ end
+
+ if cfg.only_sources_from
+ and rockspec.source.pathname
+ and #rockspec.source.pathname > 0 then
+ if #cfg.only_sources_from == 0 then
+ return nil, "Can't download "..rockspec.source.url.." -- download from remote servers disabled"
+ elseif rockspec.source.pathname:find(cfg.only_sources_from, 1, true) ~= 1 then
+ return nil, "Can't download "..rockspec.source.url.." -- only downloading from "..cfg.only_sources_from
+ end
+ end
+ return proto.get_sources(rockspec, extract, dest_dir)
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/cvs.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/cvs.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,44 @@
+
+--- Fetch back-end for retrieving sources from CVS.
+module("luarocks.fetch.cvs", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+--- Download sources for building a rock, using CVS.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local name_version = rockspec.name .. "-" .. rockspec.version
+ local module = rockspec.source.module or dir.base_name(rockspec.source.url)
+ local command = {rockspec.variables.CVS, "-d"..rockspec.source.pathname, "export", module}
+ if rockspec.source.tag then
+ table.insert(command, 4, "-r")
+ table.insert(command, 5, rockspec.source.tag)
+ end
+ local store_dir
+ if not dest_dir then
+ store_dir = fs.make_temp_dir(name_version)
+ if not store_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, store_dir)
+ else
+ store_dir = dest_dir
+ end
+ fs.change_dir(store_dir)
+ if not fs.execute(unpack(command)) then
+ return nil, "Failed fetching files from CVS."
+ end
+ fs.pop_dir()
+ return module, store_dir
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/git.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/git.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,81 @@
+
+--- Fetch back-end for retrieving sources from GIT.
+module("luarocks.fetch.git", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+--- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We
+-- need to know this in order to build the appropriate command; if we can't
+-- clone by tag then we'll have to issue a subsequent command to check out the
+-- given tag.
+-- @return boolean: Whether Git can clone by tag.
+local function git_can_clone_by_tag()
+ local version_string = io.popen('git --version'):read()
+ local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)')
+ major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0
+ local value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10)))
+ git_can_clone_by_tag = function() return value end
+ return git_can_clone_by_tag()
+end
+
+--- Download sources for building a rock, using git.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local git_cmd = rockspec.variables.GIT
+ local name_version = rockspec.name .. "-" .. rockspec.version
+ local module = dir.base_name(rockspec.source.url)
+ -- Strip off .git from base name if present
+ module = module:gsub("%.git$", "")
+
+ local store_dir
+ if not dest_dir then
+ store_dir = fs.make_temp_dir(name_version)
+ if not store_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, store_dir)
+ else
+ store_dir = dest_dir
+ end
+ store_dir = fs.absolute_name(store_dir)
+ fs.change_dir(store_dir)
+
+ local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module}
+ local tag_or_branch = rockspec.source.tag or rockspec.source.branch
+ -- If the tag or branch is explicitly set to "master" in the rockspec, then
+ -- we can avoid passing it to Git since it's the default.
+ if tag_or_branch == "master" then tag_or_branch = nil end
+ if tag_or_branch then
+ if git_can_clone_by_tag() then
+ -- The argument to `--branch` can actually be a branch or a tag as of
+ -- Git 1.7.10.
+ table.insert(command, 4, "--branch=" .. tag_or_branch)
+ end
+ end
+ if not fs.execute(unpack(command)) then
+ return nil, "Failed cloning git repository."
+ end
+ fs.change_dir(module)
+ if tag_or_branch and not git_can_clone_by_tag() then
+ local checkout_command = {git_cmd, "checkout", tag_or_branch}
+ if not fs.execute(unpack(checkout_command)) then
+ return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.'
+ end
+ end
+
+ fs.delete(dir.path(store_dir, module, ".git"))
+ fs.delete(dir.path(store_dir, module, ".gitignore"))
+ fs.pop_dir()
+ fs.pop_dir()
+ return module, store_dir
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/git_file.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/git_file.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,17 @@
+
+--- Fetch back-end for retrieving sources from local Git repositories.
+module("luarocks.fetch.git_file", package.seeall)
+
+local git = require("luarocks.fetch.git")
+
+--- Fetch sources for building a rock from a local Git repository.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ rockspec.source.url = rockspec.source.url:gsub("^git.file://", "")
+ return git.get_sources(rockspec, extract, dest_dir)
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/hg.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/hg.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,54 @@
+
+--- Fetch back-end for retrieving sources from HG.
+module("luarocks.fetch.hg", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+--- Download sources for building a rock, using hg.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local hg_cmd = rockspec.variables.HG
+ local name_version = rockspec.name .. "-" .. rockspec.version
+ -- Strip off special hg:// protocol type
+ local url = rockspec.source.url:gsub("^hg://", "")
+
+ local module = dir.base_name(url)
+
+ local command = {hg_cmd, "clone", url, module}
+ local tag_or_branch = rockspec.source.tag or rockspec.source.branch
+ if tag_or_branch then
+ command = {hg_cmd, "clone", "--rev", url, module}
+ end
+ local store_dir
+ if not dest_dir then
+ store_dir = fs.make_temp_dir(name_version)
+ if not store_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, store_dir)
+ else
+ store_dir = dest_dir
+ end
+ fs.change_dir(store_dir)
+ if not fs.execute(unpack(command)) then
+ return nil, "Failed cloning hg repository."
+ end
+ fs.change_dir(module)
+
+ fs.delete(dir.path(store_dir, module, ".hg"))
+ fs.delete(dir.path(store_dir, module, ".hgignore"))
+ fs.pop_dir()
+ fs.pop_dir()
+ return module, store_dir
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/sscm.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/sscm.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,42 @@
+
+--- Fetch back-end for retrieving sources from Surround SCM Server
+module("luarocks.fetch.sscm", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+
+--- Download sources via Surround SCM Server for building a rock.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local sscm_cmd = rockspec.variables.SSCM
+ local module = rockspec.source.module or dir.base_name(rockspec.source.url)
+ local branch, repository = string.match(rockspec.source.pathname, "^([^/]*)/(.*)")
+ if not branch or not repository then
+ return nil, "Error retrieving branch and repository from rockspec."
+ end
+ -- Search for working directory.
+ local working_dir
+ local tmp = io.popen(string.format(sscm_cmd..[[ property "/" -d -b%s -p%s]], branch, repository))
+ for line in tmp:lines() do
+ --%c because a chr(13) comes in the end.
+ working_dir = string.match(line, "Working directory:[%s]*(.*)%c$")
+ if working_dir then break end
+ end
+ tmp:close()
+ if not working_dir then
+ return nil, "Error retrieving working directory from SSCM."
+ end
+ if not fs.execute(sscm_cmd, "get", "*", "-e" , "-r", "-b"..branch, "-p"..repository, "-tmodify", "-wreplace") then
+ return nil, "Failed fetching files from SSCM."
+ end
+ -- FIXME: This function does not honor the dest_dir parameter.
+ return module, working_dir
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fetch/svn.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fetch/svn.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,53 @@
+
+--- Fetch back-end for retrieving sources from Subversion.
+module("luarocks.fetch.svn", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+--- Download sources for building a rock, using Subversion.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function get_sources(rockspec, extract, dest_dir)
+ assert(type(rockspec) == "table")
+ assert(type(dest_dir) == "string" or not dest_dir)
+
+ local svn_cmd = rockspec.variables.SVN
+ local name_version = rockspec.name .. "-" .. rockspec.version
+ local module = rockspec.source.module or dir.base_name(rockspec.source.url)
+ local url = rockspec.source.url:gsub("^svn://", "")
+ local command = {svn_cmd, "checkout", url, module}
+ if rockspec.source.tag then
+ table.insert(command, 5, "-r")
+ table.insert(command, 6, rockspec.source.tag)
+ end
+ local store_dir
+ if not dest_dir then
+ store_dir = fs.make_temp_dir(name_version)
+ if not store_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, store_dir)
+ else
+ store_dir = dest_dir
+ end
+ fs.change_dir(store_dir)
+ if not fs.execute(unpack(command)) then
+ return nil, "Failed fetching files from Subversion."
+ end
+ fs.change_dir(module)
+ for _, d in ipairs(fs.find(".")) do
+ if dir.base_name(d) == ".svn" then
+ fs.delete(dir.path(store_dir, module, d))
+ end
+ end
+ fs.pop_dir()
+ fs.pop_dir()
+ return module, store_dir
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,40 @@
+
+--- Proxy module for filesystem and platform abstractions.
+-- All code using "fs" code should require "luarocks.fs",
+-- and not the various platform-specific implementations.
+-- However, see the documentation of the implementation
+-- for the API reference.
+
+local pairs = pairs
+
+module("luarocks.fs", package.seeall)
+
+local cfg = require("luarocks.cfg")
+
+local function load_fns(fs_table)
+ for name, fn in pairs(fs_table) do
+ if not _M[name] then
+ _M[name] = fn
+ end
+ end
+end
+
+-- Load platform-specific functions
+local loaded_platform = nil
+for _, platform in ipairs(cfg.platforms) do
+ local ok, fs_plat = pcall(require, "luarocks.fs."..platform)
+ if ok and fs_plat then
+ loaded_platform = platform
+ load_fns(fs_plat)
+ break
+ end
+end
+
+-- Load platform-independent pure-Lua functionality
+local fs_lua = require("luarocks.fs.lua")
+load_fns(fs_lua)
+
+-- Load platform-specific fallbacks for missing Lua modules
+local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools")
+if ok and fs_plat_tools then load_fns(fs_plat_tools) end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs/lua.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs/lua.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,697 @@
+
+--- Native Lua implementation of filesystem and platform abstractions,
+-- using LuaFileSystem, LZLib, MD5 and LuaCurl.
+module("luarocks.fs.lua", package.seeall)
+
+local fs = require("luarocks.fs")
+
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+local path = require("luarocks.path")
+
+local socket_ok, zip_ok, unzip_ok, lfs_ok, md5_ok, posix_ok, _
+local http, ftp, lrzip, luazip, lfs, md5, posix
+
+if cfg.fs_use_modules then
+ socket_ok, http = pcall(require, "socket.http")
+ _, ftp = pcall(require, "socket.ftp")
+ zip_ok, lrzip = pcall(require, "luarocks.tools.zip")
+ unzip_ok, luazip = pcall(require, "zip"); _G.zip = nil
+ lfs_ok, lfs = pcall(require, "lfs")
+ md5_ok, md5 = pcall(require, "md5")
+ posix_ok, posix = pcall(require, "posix")
+end
+
+local patch = require("luarocks.tools.patch")
+
+local dir_stack = {}
+
+math.randomseed(os.time())
+
+dir_separator = "/"
+
+--- Quote argument for shell processing.
+-- Adds single quotes and escapes.
+-- @param arg string: Unquoted argument.
+-- @return string: Quoted argument.
+function Q(arg)
+ assert(type(arg) == "string")
+
+ -- FIXME Unix-specific
+ return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'"
+end
+
+--- Test is file/dir is writable.
+-- Warning: testing if a file/dir is writable does not guarantee
+-- that it will remain writable and therefore it is no replacement
+-- for checking the result of subsequent operations.
+-- @param file string: filename to test
+-- @return boolean: true if file exists, false otherwise.
+function is_writable(file)
+ assert(file)
+ file = dir.normalize(file)
+ local result
+ if fs.is_dir(file) then
+ local file2 = dir.path(file, '.tmpluarockstestwritable')
+ local fh = io.open(file2, 'wb')
+ result = fh ~= nil
+ if fh then fh:close() end
+ os.remove(file2)
+ else
+ local fh = io.open(file, 'r+b')
+ result = fh ~= nil
+ if fh then fh:close() end
+ end
+ return result
+end
+
+--- Create a temporary directory.
+-- @param name string: name pattern to use for avoiding conflicts
+-- when creating temporary directory.
+-- @return string or nil: name of temporary directory or nil on failure.
+function make_temp_dir(name)
+ assert(type(name) == "string")
+ name = dir.normalize(name)
+
+ local temp_dir = (os.getenv("TMP") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000))
+ if fs.make_dir(temp_dir) then
+ return temp_dir
+ else
+ return nil
+ end
+end
+
+--- Run the given command, quoting its arguments.
+-- The command is executed in the current directory in the dir stack.
+-- @param command string: The command to be executed. No quoting/escaping
+-- is applied.
+-- @param ... Strings containing additional arguments, which are quoted.
+-- @return boolean: true if command succeeds (status code 0), false
+-- otherwise.
+function execute(command, ...)
+ assert(type(command) == "string")
+
+ for _, arg in ipairs({...}) do
+ assert(type(arg) == "string")
+ command = command .. " " .. fs.Q(arg)
+ end
+ return fs.execute_string(command)
+end
+
+--- Check the MD5 checksum for a file.
+-- @param file string: The file to be checked.
+-- @param md5sum string: The string with the expected MD5 checksum.
+-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not
+-- or if it could not perform the check for any reason.
+function check_md5(file, md5sum)
+ file = dir.normalize(file)
+ local computed = fs.get_md5(file)
+ if not computed then
+ return false
+ end
+ if computed:match("^"..md5sum) then
+ return true
+ else
+ return false
+ end
+end
+
+---------------------------------------------------------------------
+-- LuaFileSystem functions
+---------------------------------------------------------------------
+
+if lfs_ok then
+
+--- Run the given command.
+-- The command is executed in the current directory in the dir stack.
+-- @param cmd string: No quoting/escaping is applied to the command.
+-- @return boolean: true if command succeeds (status code 0), false
+-- otherwise.
+function execute_string(cmd)
+ local code = os.execute(cmd)
+ if code == 0 or code == true then
+ return true
+ else
+ return false
+ end
+end
+
+--- Obtain current directory.
+-- Uses the module's internal dir stack.
+-- @return string: the absolute pathname of the current directory.
+function current_dir()
+ return lfs.currentdir()
+end
+
+--- Change the current directory.
+-- Uses the module's internal dir 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 d string: The directory to switch to.
+function change_dir(d)
+ table.insert(dir_stack, lfs.currentdir())
+ d = dir.normalize(d)
+ lfs.chdir(d)
+end
+
+--- Change directory to root.
+-- Allows leaving a directory (e.g. for deleting it) in
+-- a crossplatform way.
+function change_dir_to_root()
+ table.insert(dir_stack, lfs.currentdir())
+ lfs.chdir("/") -- works on Windows too
+end
+
+--- Change working directory to the previous in the dir stack.
+-- @return true if a pop ocurred, false if the stack was empty.
+function pop_dir()
+ local d = table.remove(dir_stack)
+ if d then
+ lfs.chdir(d)
+ return true
+ else
+ return false
+ end
+end
+
+--- Create a directory if it does not already exist.
+-- If any of the higher levels in the path name does not exist
+-- too, they are created as well.
+-- @param directory string: pathname of directory to create.
+-- @return boolean: true on success, false on failure.
+function make_dir(directory)
+ assert(type(directory) == "string")
+ directory = dir.normalize(directory)
+ local path = nil
+ if directory:sub(2, 2) == ":" then
+ path = directory:sub(1, 2)
+ directory = directory:sub(4)
+ else
+ if directory:match("^/") then
+ path = ""
+ end
+ end
+ for d in directory:gmatch("([^"..dir.separator.."]+)"..dir.separator.."*") do
+ path = path and path .. dir.separator .. d or d
+ local mode = lfs.attributes(path, "mode")
+ if not mode then
+ if not lfs.mkdir(path) then
+ return false
+ end
+ elseif mode ~= "directory" then
+ return false
+ end
+ end
+ return true
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param d string: pathname of directory to remove.
+function remove_dir_if_empty(d)
+ assert(d)
+ d = dir.normalize(d)
+ lfs.rmdir(d)
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param d string: pathname of directory to remove.
+function remove_dir_tree_if_empty(d)
+ assert(d)
+ d = dir.normalize(d)
+ for i=1,10 do
+ lfs.rmdir(d)
+ d = dir.dir_name(d)
+ end
+end
+
+--- Copy a file.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @param perms string or nil: Permissions for destination file,
+-- or nil to use the source filename permissions
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy(src, dest, perms)
+ assert(src and dest)
+ src = dir.normalize(src)
+ dest = dir.normalize(dest)
+ local destmode = lfs.attributes(dest, "mode")
+ if destmode == "directory" then
+ dest = dir.path(dest, dir.base_name(src))
+ end
+ if not perms then perms = fs.get_permissions(src) end
+ local src_h, err = io.open(src, "rb")
+ if not src_h then return nil, err end
+ local dest_h, err = io.open(dest, "w+b")
+ if not dest_h then src_h:close() return nil, err end
+ while true do
+ local block = src_h:read(8192)
+ if not block then break end
+ dest_h:write(block)
+ end
+ src_h:close()
+ dest_h:close()
+ fs.chmod(dest, perms)
+ return true
+end
+
+--- Implementation function for recursive copy of directory contents.
+-- Assumes paths are normalized.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure
+local function recursive_copy(src, dest)
+ local srcmode = lfs.attributes(src, "mode")
+
+ if srcmode == "file" then
+ local ok = fs.copy(src, dest)
+ if not ok then return false end
+ elseif srcmode == "directory" then
+ local subdir = dir.path(dest, dir.base_name(src))
+ fs.make_dir(subdir)
+ for file in lfs.dir(src) do
+ if file ~= "." and file ~= ".." then
+ local ok = recursive_copy(dir.path(src, file), subdir)
+ if not ok then return false end
+ end
+ end
+ end
+ return true
+end
+
+--- Recursively copy the contents of a directory.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy_contents(src, dest)
+ assert(src and dest)
+ src = dir.normalize(src)
+ dest = dir.normalize(dest)
+ assert(lfs.attributes(src, "mode") == "directory")
+
+ for file in lfs.dir(src) do
+ if file ~= "." and file ~= ".." then
+ local ok = recursive_copy(dir.path(src, file), dest)
+ if not ok then
+ return false, "Failed copying "..src.." to "..dest
+ end
+ end
+ end
+ return true
+end
+
+--- Implementation function for recursive removal of directories.
+-- Assumes paths are normalized.
+-- @param name string: Pathname of file
+-- @return boolean or (boolean, string): true on success,
+-- or nil and an error message on failure.
+local function recursive_delete(name)
+ local mode = lfs.attributes(name, "mode")
+
+ if mode == "file" then
+ return os.remove(name)
+ elseif mode == "directory" then
+ for file in lfs.dir(name) do
+ if file ~= "." and file ~= ".." then
+ local ok, err = recursive_delete(dir.path(name, file))
+ if not ok then return nil, err end
+ end
+ end
+ local ok, err = lfs.rmdir(name)
+ if not ok then return nil, err end
+ end
+ return true
+end
+
+--- Delete a file or a directory and all its contents.
+-- @param name string: Pathname of source
+-- @return boolean: true on success, false on failure.
+function delete(name)
+ name = dir.normalize(name)
+ return recursive_delete(name) or false
+end
+
+--- List the contents of a directory.
+-- @param at string or nil: directory to list (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function list_dir(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ at = dir.normalize(at)
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ for file in lfs.dir(at) do
+ if file ~= "." and file ~= ".." then
+ table.insert(result, file)
+ end
+ end
+ return result
+end
+
+--- Implementation function for recursive find.
+-- Assumes paths are normalized.
+-- @param cwd string: Current working directory in recursion.
+-- @param prefix string: Auxiliary prefix string to form pathname.
+-- @param result table: Array of strings where results are collected.
+local function recursive_find(cwd, prefix, result)
+ for file in lfs.dir(cwd) do
+ if file ~= "." and file ~= ".." then
+ local item = prefix .. file
+ table.insert(result, item)
+ local pathname = dir.path(cwd, file)
+ if lfs.attributes(pathname, "mode") == "directory" then
+ recursive_find(pathname, item..dir_separator, result)
+ end
+ end
+ end
+end
+
+--- Recursively scan the contents of a directory.
+-- @param at string or nil: directory to scan (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function find(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ at = dir.normalize(at)
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ recursive_find(at, "", result)
+ return result
+end
+
+--- Test for existance of a file.
+-- @param file string: filename to test
+-- @return boolean: true if file exists, false otherwise.
+function exists(file)
+ assert(file)
+ file = dir.normalize(file)
+ return type(lfs.attributes(file)) == "table"
+end
+
+--- Test is pathname is a directory.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a directory, false otherwise.
+function is_dir(file)
+ assert(file)
+ file = dir.normalize(file)
+ return lfs.attributes(file, "mode") == "directory"
+end
+
+--- Test is pathname is a regular file.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a file, false otherwise.
+function is_file(file)
+ assert(file)
+ file = dir.normalize(file)
+ return lfs.attributes(file, "mode") == "file"
+end
+
+function set_time(file, time)
+ file = dir.normalize(file)
+ return lfs.touch(file, time)
+end
+
+end
+
+---------------------------------------------------------------------
+-- LuaZip functions
+---------------------------------------------------------------------
+
+if zip_ok then
+
+function zip(zipfile, ...)
+ return lrzip.zip(zipfile, ...)
+end
+
+end
+
+if unzip_ok then
+--- Uncompress files from a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be extracted.
+-- @return boolean: true on success, false on failure.
+function unzip(zipfile)
+ local zipfile, err = luazip.open(zipfile)
+ if not zipfile then return nil, err end
+ local files = zipfile:files()
+ local file = files()
+ repeat
+ if file.filename:sub(#file.filename) == "/" then
+ fs.make_dir(dir.path(fs.current_dir(), file.filename))
+ else
+ local rf, err = zipfile:open(file.filename)
+ if not rf then zipfile:close(); return nil, err end
+ local contents = rf:read("*a")
+ rf:close()
+ local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb")
+ if not wf then zipfile:close(); return nil, err end
+ wf:write(contents)
+ wf:close()
+ end
+ file = files()
+ until not file
+ zipfile:close()
+ return true
+end
+
+end
+
+---------------------------------------------------------------------
+-- LuaSocket functions
+---------------------------------------------------------------------
+
+if socket_ok then
+
+local ltn12 = require("ltn12")
+local luasec_ok, https = pcall(require, "ssl.https")
+local redirect_protocols = {
+ http = http,
+ https = luasec_ok and https,
+}
+
+local function http_request(url, http, loop_control)
+ local result = {}
+
+ local proxy = cfg.proxy
+ if type(proxy) ~= "string" then proxy = nil end
+ -- LuaSocket's http.request crashes when given URLs missing the scheme part.
+ if proxy and not proxy:find("://") then
+ proxy = "http://" .. proxy
+ end
+
+ local res, status, headers, err = http.request {
+ url = url,
+ proxy = proxy,
+ redirect = false,
+ sink = ltn12.sink.table(result),
+ headers = {
+ ["user-agent"] = cfg.user_agent.." via LuaSocket"
+ },
+ }
+ if not res then
+ return nil, status
+ elseif status == 301 or status == 302 then
+ local location = headers.location
+ if location then
+ local protocol, rest = dir.split_url(location)
+ if redirect_protocols[protocol] then
+ if not loop_control then
+ loop_control = {}
+ elseif loop_control[location] then
+ return nil, "Redirection loop -- broken URL?"
+ end
+ loop_control[url] = true
+ return http_request(location, redirect_protocols[protocol], loop_control)
+ else
+ return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support."
+ end
+ end
+ return nil, err
+ elseif status ~= 200 then
+ return nil, err
+ else
+ return table.concat(result)
+ end
+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: true on success, false on failure.
+function download(url, filename)
+ assert(type(url) == "string")
+ assert(type(filename) == "string" or not filename)
+
+ filename = dir.path(fs.current_dir(), filename or dir.base_name(url))
+
+ local content, err
+ if util.starts_with(url, "http:") then
+ content, err = http_request(url, http)
+ elseif util.starts_with(url, "ftp:") then
+ content, err = ftp.get(url)
+ elseif util.starts_with(url, "https:") then
+ if luasec_ok then
+ content, err = http_request(url, https)
+ else
+ err = "Unsupported protocol - install luasec to get HTTPS support."
+ end
+ else
+ err = "Unsupported protocol"
+ end
+ if not content then
+ return false, tostring(err)
+ end
+ local file = io.open(filename, "wb")
+ if not file then return false end
+ file:write(content)
+ file:close()
+ return true
+end
+
+end
+---------------------------------------------------------------------
+-- MD5 functions
+---------------------------------------------------------------------
+
+if md5_ok then
+
+--- Get the MD5 checksum for a file.
+-- @param file string: The file to be computed.
+-- @return string: The MD5 checksum
+function get_md5(file)
+ file = fs.absolute_name(file)
+ local file = io.open(file, "rb")
+ if not file then return false end
+ local computed = md5.sumhexa(file:read("*a"))
+ file:close()
+ return computed
+end
+
+end
+
+---------------------------------------------------------------------
+-- POSIX functions
+---------------------------------------------------------------------
+
+if posix_ok then
+
+local octal_to_rwx = {
+ ["0"] = "---",
+ ["1"] = "--x",
+ ["2"] = "-w-",
+ ["3"] = "-wx",
+ ["4"] = "r--",
+ ["5"] = "r-x",
+ ["6"] = "rw-",
+ ["7"] = "rwx",
+}
+
+function chmod(file, mode)
+ -- LuaPosix (as of 5.1.15) does not support octal notation...
+ if mode:sub(1,1) == "0" then
+ local new_mode = {}
+ for c in mode:sub(2):gmatch(".") do
+ table.insert(new_mode, octal_to_rwx[c])
+ end
+ mode = table.concat(new_mode)
+ end
+ local err = posix.chmod(file, mode)
+ return err == 0
+end
+
+function get_permissions(file)
+ return posix.stat(file, "mode")
+end
+
+end
+
+---------------------------------------------------------------------
+-- Other functions
+---------------------------------------------------------------------
+
+--- Apply a patch.
+-- @param patchname string: The filename of the patch.
+-- @param patchdata string or nil: The actual patch as a string.
+function apply_patch(patchname, patchdata)
+ local p, all_ok = patch.read_patch(patchname, patchdata)
+ if not all_ok then
+ return nil, "Failed reading patch "..patchname
+ end
+ if p then
+ return patch.apply_patch(p, 1)
+ end
+end
+
+--- Move a file.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function move(src, dest)
+ assert(src and dest)
+ if fs.exists(dest) and not fs.is_dir(dest) then
+ return false, "File already exists: "..dest
+ end
+ local ok, err = fs.copy(src, dest)
+ if not ok then
+ return false, err
+ end
+ ok = fs.delete(src)
+ if not ok then
+ return false, "Failed move: could not delete "..src.." after copy."
+ end
+ return true
+end
+
+--- Check if user has write permissions for the command.
+-- Assumes the configuration variables under cfg have been previously set up.
+-- @param flags table: the flags table passed to run() drivers.
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function check_command_permissions(flags)
+ local root_dir = path.root_dir(cfg.rocks_dir)
+ local ok = true
+ local err = ""
+ for _, dir in ipairs { cfg.rocks_dir, root_dir } do
+ if fs.exists(dir) and not fs.is_writable(dir) then
+ ok = false
+ err = "Your user does not have write permissions in " .. dir
+ break
+ end
+ end
+ local root_parent = dir.dir_name(root_dir)
+ if ok and not fs.exists(root_dir) and not fs.is_writable(root_parent) then
+ ok = false
+ err = root_dir.." does not exist and your user does not have write permissions in " .. root_parent
+ end
+ if ok then
+ return true
+ else
+ if flags["local"] then
+ err = err .. " \n-- please check your permissions."
+ else
+ err = err .. " \n-- you may want to run as a privileged user or use your local tree with --local."
+ end
+ return nil, err
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs/unix.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs/unix.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,109 @@
+
+--- Unix implementation of filesystem and platform abstractions.
+
+local assert, type, table, io, package, math, os, ipairs =
+ assert, type, table, io, package, math, os, ipairs
+
+module("luarocks.fs.unix", package.seeall)
+
+local fs = require("luarocks.fs")
+
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+
+math.randomseed(os.time())
+
+--- Annotate command string for quiet execution.
+-- @param cmd string: A command-line string.
+-- @return string: The command-line, with silencing annotation.
+function quiet(cmd)
+ return cmd.." 1> /dev/null 2> /dev/null"
+end
+
+--- Return an absolute pathname from a potentially relative one.
+-- @param pathname string: pathname to convert.
+-- @param relative_to string or nil: path to prepend when making
+-- pathname absolute, or the current dir in the dir stack if
+-- not given.
+-- @return string: The pathname converted to absolute.
+function absolute_name(pathname, relative_to)
+ assert(type(pathname) == "string")
+ assert(type(relative_to) == "string" or not relative_to)
+
+ relative_to = relative_to or fs.current_dir()
+ if pathname:sub(1,1) == "/" then
+ return pathname
+ else
+ return relative_to .. "/" .. pathname
+ end
+end
+
+--- Create a wrapper to make a script executable from the command-line.
+-- @param file string: Pathname of script to be made executable.
+-- @param dest string: Directory where to put the wrapper.
+-- @return boolean or (nil, string): True if succeeded, or nil and
+-- an error message.
+function wrap_script(file, dest)
+ assert(type(file) == "string")
+ assert(type(dest) == "string")
+
+ local base = dir.base_name(file)
+ local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
+ local wrapper = io.open(wrapname, "w")
+ if not wrapper then
+ return nil, "Could not open "..wrapname.." for writing."
+ end
+ wrapper:write("#!/bin/sh\n\n")
+ wrapper:write('LUA_PATH="'..package.path..';$LUA_PATH"\n')
+ wrapper:write('LUA_CPATH="'..package.cpath..';$LUA_CPATH"\n')
+ wrapper:write('export LUA_PATH LUA_CPATH\n')
+ wrapper:write('exec "'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader "'..file..'" "$@"\n')
+ wrapper:close()
+ if fs.chmod(wrapname, "0755") then
+ return true
+ else
+ return nil, "Could not make "..wrapname.." executable."
+ end
+end
+
+--- Check if a file (typically inside path.bin_dir) is an actual binary
+-- or a Lua wrapper.
+-- @param filename string: the file name with full path.
+-- @return boolean: returns true if file is an actual binary
+-- (or if it couldn't check) or false if it is a Lua wrapper.
+function is_actual_binary(filename)
+ if filename:match("%.lua$") then
+ return false
+ end
+ local file = io.open(filename)
+ if not file then
+ return true
+ end
+ local first = file:read(2)
+ file:close()
+ if not first then
+ util.printerr("Warning: could not read "..filename)
+ return true
+ end
+ return first ~= "#!"
+end
+
+function copy_binary(filename, dest)
+ return fs.copy(filename, dest, "0755")
+end
+
+--- Move a file on top of the other.
+-- The new file ceases to exist under its original name,
+-- and takes over the name of the old file.
+-- On Unix this is done through a single rename operation.
+-- @param old_file The name of the original file,
+-- which will be the new name of new_file.
+-- @param new_file The name of the new file,
+-- which will replace old_file.
+-- @return boolean or (nil, string): True if succeeded, or nil and
+-- an error message.
+function replace_file(old_file, new_file)
+ return os.rename(new_file, old_file)
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs/unix/tools.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs/unix/tools.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,318 @@
+
+--- fs operations implemented with third-party tools for Unix platform abstractions.
+module("luarocks.fs.unix.tools", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local cfg = require("luarocks.cfg")
+
+local dir_stack = {}
+
+local vars = cfg.variables
+
+local function command_at(directory, cmd)
+ return "cd " .. fs.Q(directory) .. " && " .. cmd
+end
+
+--- Obtain current directory.
+-- Uses the module's internal directory stack.
+-- @return string: the absolute pathname of the current directory.
+function current_dir()
+ local pipe = io.popen(vars.PWD)
+ local current = pipe:read("*l")
+ pipe:close()
+ for _, directory in ipairs(dir_stack) do
+ current = fs.absolute_name(directory, current)
+ end
+ return current
+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 execute_string(cmd)
+ local code = os.execute(command_at(fs.current_dir(), cmd))
+ if code == 0 or code == true then
+ return true
+ else
+ return false
+ end
+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.
+function change_dir(directory)
+ assert(type(directory) == "string")
+ table.insert(dir_stack, directory)
+end
+
+--- Change directory to root.
+-- Allows leaving a directory (e.g. for deleting it) in
+-- a crossplatform way.
+function change_dir_to_root()
+ table.insert(dir_stack, "/")
+end
+
+--- Change working directory to the previous in the directory stack.
+function pop_dir()
+ local directory = table.remove(dir_stack)
+ return directory ~= nil
+end
+
+--- Create a directory if it does not already exist.
+-- If any of the higher levels in the path name does not exist
+-- too, they are created as well.
+-- @param directory string: pathname of directory to create.
+-- @return boolean: true on success, false on failure.
+function make_dir(directory)
+ assert(directory)
+ return fs.execute(vars.MKDIR.." -p", directory)
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param directory string: pathname of directory to remove.
+function remove_dir_if_empty(directory)
+ assert(directory)
+ fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param directory string: pathname of directory to remove.
+function remove_dir_tree_if_empty(directory)
+ assert(directory)
+ fs.execute_string(fs.quiet(vars.RMDIR.." -p "..fs.Q(directory)))
+end
+
+--- Copy a file.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @param perm string or nil: Permissions for destination file,
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy(src, dest, perm)
+ assert(src and dest)
+ if fs.execute(vars.CP, src, dest) then
+ if perm then
+ if fs.is_dir(dest) then
+ dest = dir.path(dest, dir.base_name(src))
+ end
+ if fs.chmod(dest, perm) then
+ return true
+ else
+ return false, "Failed setting permissions of "..dest
+ end
+ end
+ return true
+ else
+ return false, "Failed copying "..src.." to "..dest
+ end
+end
+
+--- Recursively copy the contents of a directory.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy_contents(src, dest)
+ assert(src and dest)
+ if fs.execute_string(fs.quiet(vars.CP.." -pPR "..fs.Q(src).."/* "..fs.Q(dest))) then
+ return true
+ else
+ return false, "Failed copying "..src.." to "..dest
+ end
+end
+--- Delete a file or a directory and all its contents.
+-- For safety, this only accepts absolute paths.
+-- @param arg string: Pathname of source
+-- @return boolean: true on success, false on failure.
+function delete(arg)
+ assert(arg)
+ assert(arg:sub(1,1) == "/")
+ return fs.execute_string(fs.quiet(vars.RM.." -rf " .. fs.Q(arg)))
+end
+
+--- List the contents of a directory.
+-- @param at string or nil: directory to list (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function list_dir(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ local pipe = io.popen(command_at(at, vars.LS))
+ for file in pipe:lines() do
+ table.insert(result, file)
+ end
+ pipe:close()
+ return result
+end
+
+--- Recursively scan the contents of a directory.
+-- @param at string or nil: directory to scan (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function find(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ local pipe = io.popen(command_at(at, vars.FIND.." * 2>/dev/null"))
+ for file in pipe:lines() do
+ table.insert(result, file)
+ end
+ pipe:close()
+ return result
+end
+
+--- Compress files in a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be created.
+-- @param ... Filenames to be stored in the archive are given as
+-- additional arguments.
+-- @return boolean: true on success, false on failure.
+function zip(zipfile, ...)
+ return fs.execute(vars.ZIP.." -r", zipfile, ...)
+end
+
+--- Uncompress files from a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be extracted.
+-- @return boolean: true on success, false on failure.
+function unzip(zipfile)
+ assert(zipfile)
+ return fs.execute(vars.UNZIP, zipfile)
+end
+
+--- Test is file/directory exists
+-- @param file string: filename to test
+-- @return boolean: true if file exists, false otherwise.
+function exists(file)
+ assert(file)
+ return fs.execute(vars.TEST, "-e", file)
+end
+
+--- Test is pathname is a directory.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a directory, false otherwise.
+function is_dir(file)
+ assert(file)
+ return fs.execute(vars.TEST, "-d", file)
+end
+
+--- Test is pathname is a regular file.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a regular file, false otherwise.
+function is_file(file)
+ assert(file)
+ return fs.execute(vars.TEST, "-f", file)
+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: true on success, false on failure.
+function download(url, filename)
+ assert(type(url) == "string")
+ assert(type(filename) == "string" or not filename)
+
+ if cfg.downloader == "wget" then
+ local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet --continue "
+ if filename then
+ return fs.execute(wget_cmd.." --output-document ", filename, url)
+ else
+ return fs.execute(wget_cmd, url)
+ end
+ elseif cfg.downloader == "curl" then
+ filename = filename or dir.base_name(url)
+ return fs.execute_string(vars.CURL.." -L --user-agent '"..cfg.user_agent.." via curl' "..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename))
+ end
+end
+
+function chmod(pathname, mode)
+ if mode then
+ return fs.execute(vars.CHMOD, mode, pathname)
+ else
+ return false
+ end
+end
+
+--- Apply a patch.
+-- @param patchname string: The filename of the patch.
+function apply_patch(patchname)
+ return fs.execute(vars.PATCH.." -p1 -f -i ", patchname)
+end
+
+--- Unpack an archive.
+-- Extract the contents of an archive, detecting its format by
+-- filename extension.
+-- @param archive string: Filename of archive.
+-- @return boolean or (boolean, string): true on success, false and an error message on failure.
+function unpack_archive(archive)
+ assert(type(archive) == "string")
+
+ local ok
+ if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then
+ ok = fs.execute_string(vars.GUNZIP.." -c "..archive.."|"..vars.TAR.." -xf -")
+ elseif archive:match("%.tar%.bz2$") then
+ ok = fs.execute_string(vars.BUNZIP2.." -c "..archive.."|tar -xf -")
+ elseif archive:match("%.zip$") then
+ ok = fs.execute(vars.UNZIP, archive)
+ elseif archive:match("%.lua$") or archive:match("%.c$") then
+ -- Ignore .lua and .c files; they don't need to be extracted.
+ return true
+ else
+ local ext = archive:match(".*(%..*)")
+ return false, "Unrecognized filename extension "..(ext or "")
+ end
+ if not ok then
+ return false, "Failed extracting "..archive
+ end
+ return true
+end
+
+local md5_cmd = {
+ md5sum = vars.MD5SUM,
+ openssl = vars.OPENSSL.." md5",
+ md5 = vars.MD5,
+}
+
+--- Get the MD5 checksum for a file.
+-- @param file string: The file to be computed.
+-- @return string: The MD5 checksum
+function get_md5(file)
+ local cmd = md5_cmd[cfg.md5checker]
+ if not cmd then return nil end
+ local pipe = io.popen(cmd.." "..fs.absolute_name(file))
+ local computed = pipe:read("*a")
+ pipe:close()
+ if not computed then return nil end
+ return computed:match("("..("%x"):rep(32)..")")
+end
+
+function get_permissions(filename)
+ local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename))
+ local ret = pipe:read("*l")
+ pipe:close()
+ return ret
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs/win32.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs/win32.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,131 @@
+--- Windows implementation of filesystem and platform abstractions.
+-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
+-- used by this module.
+module("luarocks.fs.win32", package.seeall)
+
+local fs = require("luarocks.fs")
+
+local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
+
+--- Annotate command string for quiet execution.
+-- @param cmd string: A command-line string.
+-- @return string: The command-line, with silencing annotation.
+function quiet(cmd)
+ return cmd.." 2> NUL 1> NUL"
+end
+
+--- Quote argument for shell processing. Fixes paths on Windows.
+-- Adds single quotes and escapes.
+-- @param arg string: Unquoted argument.
+-- @return string: Quoted argument.
+function Q(arg)
+ assert(type(arg) == "string")
+ -- Quote DIR for Windows
+ if arg:match("^[%.a-zA-Z]?:?[\\/]") then
+ return '"' .. arg:gsub("/", "\\"):gsub('"', '\\"') .. '"'
+ end
+ -- URLs and anything else
+ return '"' .. arg:gsub('"', '\\"') .. '"'
+end
+
+--- Return an absolute pathname from a potentially relative one.
+-- @param pathname string: pathname to convert.
+-- @param relative_to string or nil: path to prepend when making
+-- pathname absolute, or the current dir in the dir stack if
+-- not given.
+-- @return string: The pathname converted to absolute.
+function absolute_name(pathname, relative_to)
+ assert(type(pathname) == "string")
+ assert(type(relative_to) == "string" or not relative_to)
+
+ relative_to = relative_to or fs.current_dir()
+ -- FIXME I'm not sure this first \\ should be there at all.
+ -- What are the Windows rules for drive letters?
+ if pathname:match("^[\\.a-zA-Z]?:?[\\/]") then
+ return pathname
+ else
+ return relative_to .. "/" .. pathname
+ end
+end
+
+--- Create a wrapper to make a script executable from the command-line.
+-- @param file string: Pathname of script to be made executable.
+-- @param dest string: Directory where to put the wrapper.
+-- @return boolean or (nil, string): True if succeeded, or nil and
+-- an error message.
+function wrap_script(file, dest)
+ assert(type(file) == "string")
+ assert(type(dest) == "string")
+
+ local base = dir.base_name(file)
+ local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
+ wrapname = wrapname..".bat"
+ local wrapper = io.open(wrapname, "w")
+ if not wrapper then
+ return nil, "Could not open "..wrapname.." for writing."
+ end
+ wrapper:write("@echo off\n")
+ wrapper:write("setlocal\n")
+ wrapper:write('set LUA_PATH='..package.path..";%LUA_PATH%\n")
+ wrapper:write('set LUA_CPATH='..package.cpath..";%LUA_CPATH%\n")
+ wrapper:write('"'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader "'..file..'" %*\n')
+ wrapper:write("endlocal\n")
+ wrapper:close()
+ return true
+end
+
+function is_actual_binary(name)
+ name = name:lower()
+ if name:match("%.bat$") or name:match("%.exe$") then
+ return true
+ end
+ return false
+end
+
+function copy_binary(filename, dest)
+ local ok, err = fs.copy(filename, dest)
+ if not ok then
+ return nil, err
+ end
+ local exe_pattern = "%.[Ee][Xx][Ee]$"
+ local base = dir.base_name(filename)
+ local dest = dir.dir_name(dest)
+ if base:match(exe_pattern) then
+ base = base:gsub(exe_pattern, ".lua")
+ local helpname = dest.."/"..base
+ local helper = io.open(helpname, "w")
+ if not helper then
+ return nil, "Could not open "..helpname.." for writing."
+ end
+ helper:write('package.path=\"'..package.path:gsub("\\","\\\\")..';\"..package.path\n')
+ helper:write('package.cpath=\"'..package.path:gsub("\\","\\\\")..';\"..package.cpath\n')
+ helper:close()
+ end
+ return true
+end
+
+function chmod(filename, mode)
+ return true
+end
+
+function get_permissions(filename)
+ return ""
+end
+
+--- Move a file on top of the other.
+-- The new file ceases to exist under its original name,
+-- and takes over the name of the old file.
+-- On Windows this is done by removing the original file and
+-- renaming the new file to its original name.
+-- @param old_file The name of the original file,
+-- which will be the new name of new_file.
+-- @param new_file The name of the new file,
+-- which will replace old_file.
+-- @return boolean or (nil, string): True if succeeded, or nil and
+-- an error message.
+function replace_file(old_file, new_file)
+ os.remove(old_file)
+ return os.rename(new_file, old_file)
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/fs/win32/tools.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/fs/win32/tools.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,333 @@
+
+--- fs operations implemented with third-party tools for Windows platform abstractions.
+-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
+-- used by this module.
+module("luarocks.fs.win32.tools", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local cfg = require("luarocks.cfg")
+
+local dir_stack = {}
+
+local vars = cfg.variables
+
+--- Strip the last extension of a filename.
+-- Example: "foo.tar.gz" becomes "foo.tar".
+-- If filename has no dots, returns it unchanged.
+-- @param filename string: The file name to strip.
+-- @return string: The stripped name.
+local function strip_extension(filename)
+ assert(type(filename) == "string")
+
+ return (filename:gsub("%.[^.]+$", "")) or filename
+end
+
+local function command_at(directory, cmd)
+ local drive = directory:match("^([A-Za-z]:)")
+ cmd = "cd " .. fs.Q(directory) .. " & " .. cmd
+ if drive then
+ cmd = drive .. " & " .. cmd
+ end
+ return cmd
+end
+
+--- Obtain current directory.
+-- Uses the module's internal directory stack.
+-- @return string: the absolute pathname of the current directory.
+function current_dir()
+ local pipe = io.popen(vars.PWD)
+ local current = pipe:read("*l")
+ pipe:close()
+ for _, directory in ipairs(dir_stack) do
+ current = fs.absolute_name(directory, current)
+ end
+ return current
+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 execute_string(cmd)
+ local code = os.execute(command_at(fs.current_dir(), cmd))
+ if code == 0 or code == true then
+ return true
+ else
+ return false
+ end
+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.
+function change_dir(directory)
+ assert(type(directory) == "string")
+ table.insert(dir_stack, directory)
+end
+
+--- Change directory to root.
+-- Allows leaving a directory (e.g. for deleting it) in
+-- a crossplatform way.
+function change_dir_to_root()
+ table.insert(dir_stack, "/")
+end
+
+--- Change working directory to the previous in the directory stack.
+function pop_dir()
+ local directory = table.remove(dir_stack)
+ return directory ~= nil
+end
+
+--- Create a directory if it does not already exist.
+-- If any of the higher levels in the path name does not exist
+-- too, they are created as well.
+-- @param directory string: pathname of directory to create.
+-- @return boolean: true on success, false on failure.
+function make_dir(directory)
+ assert(directory)
+ fs.execute(fs.quiet(vars.MKDIR.." "..fs.Q(directory)))
+ return 1
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param directory string: pathname of directory to remove.
+function remove_dir_if_empty(directory)
+ assert(directory)
+ fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+end
+
+--- Remove a directory if it is empty.
+-- Does not return errors (for example, if directory is not empty or
+-- if already does not exist)
+-- @param directory string: pathname of directory to remove.
+function remove_dir_tree_if_empty(directory)
+ assert(directory)
+ fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+end
+
+--- Copy a file.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy(src, dest)
+ assert(src and dest)
+ if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
+ if fs.execute(vars.CP, src, dest) then
+ return true
+ else
+ return false, "Failed copying "..src.." to "..dest
+ end
+end
+
+--- Recursively copy the contents of a directory.
+-- @param src string: Pathname of source
+-- @param dest string: Pathname of destination
+-- @return boolean or (boolean, string): true on success, false on failure,
+-- plus an error message.
+function copy_contents(src, dest)
+ assert(src and dest)
+ if fs.execute_string(fs.quiet(vars.CP.." -a "..src.."\\*.* "..fs.Q(dest))) then
+ return true
+ else
+ return false, "Failed copying "..src.." to "..dest
+ end
+end
+
+--- Delete a file or a directory and all its contents.
+-- For safety, this only accepts absolute paths.
+-- @param arg string: Pathname of source
+-- @return boolean: true on success, false on failure.
+function delete(arg)
+ assert(arg)
+ assert(arg:match("^[\a-zA-Z]?:?[\\/]"))
+ fs.execute(vars.CHMOD.." a+rw -R ", arg)
+ return fs.execute_string(fs.quiet(vars.RM.." -rf " .. fs.Q(arg)))
+end
+
+--- List the contents of a directory.
+-- @param at string or nil: directory to list (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function list_dir(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ local pipe = io.popen(command_at(at, vars.LS))
+ for file in pipe:lines() do
+ table.insert(result, file)
+ end
+ pipe:close()
+
+ return result
+end
+
+--- Recursively scan the contents of a directory.
+-- @param at string or nil: directory to scan (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory. Paths are returned with forward slashes.
+function find(at)
+ assert(type(at) == "string" or not at)
+ if not at then
+ at = fs.current_dir()
+ end
+ if not fs.is_dir(at) then
+ return {}
+ end
+ local result = {}
+ local pipe = io.popen(command_at(at, vars.FIND.." 2> NUL"))
+ for file in pipe:lines() do
+ -- Windows find is a bit different
+ local first_two = file:sub(1,2)
+ if first_two == ".\\" or first_two == "./" then file=file:sub(3) end
+ if file ~= "." then
+ table.insert(result, (file:gsub("\\", "/")))
+ end
+ end
+ pipe:close()
+ return result
+end
+
+--- Compress files in a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be created.
+-- @param ... Filenames to be stored in the archive are given as
+-- additional arguments.
+-- @return boolean: true on success, false on failure.
+function zip(zipfile, ...)
+ return fs.execute(vars.SEVENZ.." a -tzip", zipfile, ...)
+end
+
+--- Uncompress files from a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be extracted.
+-- @return boolean: true on success, false on failure.
+function unzip(zipfile)
+ assert(zipfile)
+ return fs.execute(vars.SEVENZ.." x", zipfile)
+end
+
+--- Test is pathname is a directory.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a directory, false otherwise.
+function is_dir(file)
+ assert(file)
+ return fs.execute(fs.quiet(vars.TEST.." -d " .. fs.Q(file)))
+end
+
+--- Test is pathname is a regular file.
+-- @param file string: pathname to test
+-- @return boolean: true if it is a regular file, false otherwise.
+function is_file(file)
+ assert(file)
+ return fs.execute(vars.TEST.." -f", file)
+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: true on success, false on failure.
+function download(url, filename)
+ assert(type(url) == "string")
+ assert(type(filename) == "string" or not filename)
+
+ if cfg.downloader == "wget" then
+ local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet --continue "
+ if filename then
+ return fs.execute(wget_cmd.." --output-document ", filename, url)
+ else
+ return fs.execute(wget_cmd, url)
+ end
+ elseif cfg.downloader == "curl" then
+ filename = filename or dir.base_name(url)
+ return fs.execute_string(vars.CURL.." -L --user-agent \""..cfg.user_agent.." via curl\" "..fs.Q(url).." 2> NUL 1> "..fs.Q(filename))
+ end
+end
+
+--- Uncompress gzip file.
+-- @param archive string: Filename of archive.
+-- @return boolean : success status
+local function gunzip(archive)
+ return fs.execute(vars.SEVENZ.." x", archive)
+end
+
+--- Unpack an archive.
+-- Extract the contents of an archive, detecting its format by
+-- filename extension.
+-- @param archive string: Filename of archive.
+-- @return boolean or (boolean, string): true on success, false and an error message on failure.
+function unpack_archive(archive)
+ assert(type(archive) == "string")
+
+ local ok
+ local sevenzx = vars.SEVENZ.." x"
+ if archive:match("%.tar%.gz$") then
+ ok = gunzip(archive)
+ if ok then
+ ok = fs.execute(sevenzx, strip_extension(archive))
+ end
+ elseif archive:match("%.tgz$") then
+ ok = gunzip(archive)
+ if ok then
+ ok = fs.execute(sevenzx, strip_extension(archive)..".tar")
+ end
+ elseif archive:match("%.tar%.bz2$") then
+ ok = fs.execute(sevenzx, archive)
+ if ok then
+ ok = fs.execute(sevenzx, strip_extension(archive))
+ end
+ elseif archive:match("%.zip$") then
+ ok = fs.execute(sevenzx, archive)
+ elseif archive:match("%.lua$") or archive:match("%.c$") then
+ -- Ignore .lua and .c files; they don't need to be extracted.
+ return true
+ else
+ local ext = archive:match(".*(%..*)")
+ return false, "Unrecognized filename extension "..(ext or "")
+ end
+ if not ok then
+ return false, "Failed extracting "..archive
+ end
+ return true
+end
+
+local md5_cmd = {
+ md5sum = vars.MD5SUM,
+ openssl = vars.OPENSSL.." md5",
+ md5 = vars.MD5,
+}
+
+--- Get the MD5 checksum for a file.
+-- @param file string: The file to be computed.
+-- @return string: The MD5 checksum
+function get_md5(file)
+ local cmd = md5_cmd[cfg.md5checker]
+ if not cmd then return nil end
+ local pipe = io.popen(cmd.." "..fs.absolute_name(file))
+ local computed = pipe:read("*a")
+ pipe:close()
+ if not computed then return nil end
+ return computed:match("("..("%x"):rep(32)..")")
+end
+
+--- Test for existance of a file.
+-- @param file string: filename to test
+-- @return boolean: true if file exists, false otherwise.
+function exists(file)
+ assert(file)
+ return fs.execute(fs.quiet("if not exist " .. fs.Q(file) .. " invalidcommandname"))
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/help.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/help.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,101 @@
+
+--- Module implementing the LuaRocks "help" command.
+-- This is a generic help display module, which
+-- uses a global table called "commands" to find commands
+-- to show help for; each command should be represented by a
+-- table containing "help" and "help_summary" fields.
+module("luarocks.help", package.seeall)
+
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+
+help_summary = "Help on commands. Type '"..program_name.." help ' for more."
+
+help_arguments = "[]"
+help = [[
+ is the command to show help for.
+]]
+
+local function print_banner()
+ util.printout("\nLuaRocks "..cfg.program_version..", a module deployment system for Lua")
+end
+
+local function print_section(section)
+ util.printout("\n"..section)
+end
+
+local function get_status(status)
+ if status then
+ return "ok"
+ elseif status == false then
+ return "not found"
+ else
+ return "failed"
+ end
+end
+
+--- Driver function for the "help" command.
+-- @param command string or nil: command to show help for; if not
+-- given, help summaries for all commands are shown.
+-- @return boolean or (nil, string): true if there were no errors
+-- or nil and an error message if an invalid command was requested.
+function run(...)
+ local flags, command = util.parse_flags(...)
+
+ if not command then
+ local sys_file, sys_ok, home_file, home_ok = cfg.which_config()
+ print_banner()
+ print_section("NAME")
+ util.printout("\t"..program_name..[[ - ]]..program_description)
+ print_section("SYNOPSIS")
+ util.printout("\t"..program_name..[[ [--from= | --only-from=] [--to=] [VAR=VALUE]... [] ]])
+ print_section("GENERAL OPTIONS")
+ util.printout([[
+ These apply to all commands, as appropriate:
+
+ --server= Fetch rocks/rockspecs from this server
+ (takes priority over config file)
+ --only-server= Fetch rocks/rockspecs from this server only
+ (overrides any entries in the config file)
+ --only-sources= Restrict downloads to paths matching the
+ given URL.
+ --tree= Which tree to operate on.
+ --local Use the tree in the user's home directory.]])
+ print_section("VARIABLES")
+ util.printout([[
+ Variables from the "variables" table of the configuration file
+ can be overriden with VAR=VALUE assignments.]])
+ print_section("COMMANDS")
+ local names = {}
+ for name, command in pairs(commands) do
+ table.insert(names, name)
+ end
+ table.sort(names)
+ for _, name in ipairs(names) do
+ local command = commands[name]
+ util.printout("", name)
+ util.printout("\t", command.help_summary)
+ end
+ print_section("CONFIGURATION")
+ util.printout([[
+ System configuration file: ]]..sys_file .. " (" .. get_status(sys_ok) ..[[)
+ User configuration file: ]]..home_file .. " (" .. get_status(home_ok) ..")\n")
+ else
+ command = command:gsub("-", "_")
+ if commands[command] then
+ local arguments = commands[command].help_arguments or ""
+ print_banner()
+ print_section("NAME")
+ util.printout("\t"..program_name.." "..command.." - "..commands[command].help_summary)
+ print_section("SYNOPSIS")
+ util.printout("\t"..program_name.." "..command.." "..arguments)
+ print_section("DESCRIPTION")
+ util.printout("",(commands[command].help:gsub("\n","\n\t"):gsub("\n\t$","")))
+ print_section("SEE ALSO")
+ util.printout("","'luarocks help' for general options and configuration.\n")
+ else
+ return nil, "Unknown command '"..command.."'"
+ end
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/index.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/index.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,172 @@
+
+--- Module which builds the index.html page to be used in rocks servers.
+module("luarocks.index", package.seeall)
+
+local util = require("luarocks.util")
+local fs = require("luarocks.fs")
+local deps = require("luarocks.deps")
+local persist = require("luarocks.persist")
+local dir = require("luarocks.dir")
+local manif = require("luarocks.manif")
+
+local ext_url_target = ' target="_blank"'
+
+local index_header = [[
+
+
+
+Available rocks
+
+
+
+
+Available rocks
+
+Lua modules available from this location for use with LuaRocks:
+
+
+]]
+
+local index_package_start = [[
+
+ $package - $summary
+ $detailed
+$externaldependencies
+latest sources $homepage | License: $license
+
|
+
+]]
+
+local index_package_end = [[
+ |
+ |
+]]
+
+local index_footer = [[
+
+
+manifest file
+
+
+
+]]
+
+function format_external_dependencies(rockspec)
+ if rockspec.external_dependencies then
+ local deplist = {}
+ local listed_set = {}
+ local plats = nil
+ for name, desc in util.sortedpairs(rockspec.external_dependencies) do
+ if name ~= "platforms" then
+ table.insert(deplist, name:lower())
+ listed_set[name] = true
+ else
+ plats = desc
+ end
+ end
+ if plats then
+ for plat, entries in util.sortedpairs(plats) do
+ for name, desc in util.sortedpairs(entries) do
+ if not listed_set[name] then
+ table.insert(deplist, name:lower() .. " (on "..plat..")")
+ end
+ end
+ end
+ end
+ return 'External dependencies: ' .. table.concat(deplist, ', ').. '
'
+ else
+ return ""
+ end
+end
+
+function make_index(repo)
+ if not fs.is_dir(repo) then
+ return nil, "Cannot access repository at "..repo
+ end
+ local manifest = manif.load_manifest(repo)
+ local out = io.open(dir.path(repo, "index.html"), "w")
+
+ out:write(index_header)
+ for package, version_list in util.sortedpairs(manifest.repository) do
+ local latest_rockspec = nil
+ local output = index_package_start
+ for version, data in util.sortedpairs(version_list, deps.compare_versions) do
+ local versions = {}
+ output = output..version..': '
+ table.sort(data, function(a,b) return a.arch < b.arch end)
+ for _, item in ipairs(data) do
+ local link = ''..item.arch..''
+ if item.arch == 'rockspec' then
+ local rs = ("%s-%s.rockspec"):format(package, version)
+ if not latest_rockspec then latest_rockspec = rs end
+ link = link:gsub("$url", rs)
+ else
+ link = link:gsub("$url", ("%s-%s.%s.rock"):format(package, version, item.arch))
+ end
+ table.insert(versions, link)
+ end
+ output = output .. table.concat(versions, ', ') .. '
'
+ end
+ output = output .. index_package_end
+ if latest_rockspec then
+ local rockspec = persist.load_into_table(dir.path(repo, latest_rockspec))
+ local descript = rockspec.description or {}
+ local vars = {
+ anchor = package,
+ package = rockspec.package,
+ original = rockspec.source.url,
+ summary = descript.summary or "",
+ detailed = descript.detailed or "",
+ license = descript.license or "N/A",
+ homepage = descript.homepage and ('| project homepage') or "",
+ externaldependencies = format_external_dependencies(rockspec)
+ }
+ vars.detailed = vars.detailed:gsub("\n\n", "
"):gsub("%s+", " ")
+ vars.detailed = vars.detailed:gsub("(https?://[a-zA-Z0-9%.%%-_%+%[%]=%?&/$@;:]+)", '%1')
+ output = output:gsub("$(%w+)", vars)
+ else
+ output = output:gsub("$anchor", package)
+ output = output:gsub("$package", package)
+ output = output:gsub("$(%w+)", "")
+ end
+ out:write(output)
+ end
+ out:write(index_footer)
+ out:close()
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/install.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/install.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,150 @@
+
+--- Module implementing the LuaRocks "install" command.
+-- Installs binary rocks.
+module("luarocks.install", package.seeall)
+
+local path = require("luarocks.path")
+local repos = require("luarocks.repos")
+local fetch = require("luarocks.fetch")
+local util = require("luarocks.util")
+local fs = require("luarocks.fs")
+local deps = require("luarocks.deps")
+local manif = require("luarocks.manif")
+local cfg = require("luarocks.cfg")
+
+help_summary = "Install a rock."
+
+help_arguments = "{| []}"
+
+help = [[
+Argument may be the name of a rock to be fetched from a repository
+or a filename of a locally available rock.
+]]
+
+--- Install a binary rock.
+-- @param rock_file string: local or remote filename of a rock.
+-- @param deps_mode: string: Which trees to check dependencies for:
+-- "none", "one", "order" or "all".
+-- @return boolean or (nil, string, [string]): True if succeeded or
+-- nil and an error message and an optional error code.
+function install_binary_rock(rock_file, deps_mode)
+ assert(type(rock_file) == "string")
+
+ local name, version, arch = path.parse_name(rock_file)
+ if not name then
+ return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
+ end
+
+ if arch ~= "all" and arch ~= cfg.arch then
+ return nil, "Incompatible architecture "..arch, "arch"
+ end
+ if repos.is_installed(name, version) then
+ repos.delete_version(name, version)
+ end
+
+ local rollback = util.schedule_function(function()
+ fs.delete(path.install_dir(name, version))
+ fs.remove_dir_if_empty(path.versions_dir(name))
+ end)
+
+ local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version))
+ if not ok then return nil, err, errcode end
+
+ local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
+ if err then
+ return nil, "Failed loading rockspec for installed package: "..err, errcode
+ end
+
+ if deps_mode == "none" then
+ util.printerr("Warning: skipping dependency checks.")
+ else
+ ok, err, errcode = deps.check_external_deps(rockspec, "install")
+ if err then return nil, err, errcode end
+ end
+
+ -- For compatibility with .rock files built with LuaRocks 1
+ if not fs.exists(path.rock_manifest_file(name, version)) then
+ ok, err = manif.make_rock_manifest(name, version)
+ if err then return nil, err end
+ end
+
+ if deps_mode ~= "none" then
+ ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
+ if err then return nil, err, errcode end
+ end
+
+ local wrap_bin_scripts = true
+ if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
+ wrap_bin_scripts = false
+ end
+
+ ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec))
+ if err then return nil, err end
+
+ util.remove_scheduled_function(rollback)
+ rollback = util.schedule_function(function()
+ repos.delete_version(name, version)
+ end)
+
+ ok, err = repos.run_hook(rockspec, "post_install")
+ if err then return nil, err end
+
+ ok, err = manif.update_manifest(name, version, nil, deps_mode)
+ if err then return nil, err end
+
+ local license = ""
+ if rockspec.description.license then
+ license = ("(license: "..rockspec.description.license..")")
+ end
+
+ local root_dir = path.root_dir(cfg.rocks_dir)
+ util.printout()
+ util.printout(name.." "..version.." is now installed in "..root_dir.." "..license)
+
+ util.remove_scheduled_function(rollback)
+ return true
+end
+
+--- Driver function for the "install" command.
+-- @param name string: name of a binary rock. If an URL or pathname
+-- to a binary rock is given, fetches and installs it. If a rockspec or a
+-- source rock is given, forwards the request to the "build" command.
+-- If a package name is given, forwards the request to "search" and,
+-- if returned a result, installs the matching rock.
+-- @param version string: When passing a package name, a version number
+-- may also be given.
+-- @return boolean or (nil, string): True if installation was
+-- successful, nil and an error message otherwise.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+ if type(name) ~= "string" then
+ return nil, "Argument missing, see help."
+ end
+
+ local ok, err = fs.check_command_permissions(flags)
+ if not ok then return nil, err end
+
+ if name:match("%.rockspec$") or name:match("%.src%.rock$") then
+ util.printout("Using "..name.."... switching to 'build' mode")
+ local build = require("luarocks.build")
+ return build.run(name, deps.get_deps_mode(flags), flags["local"] and "--local")
+ elseif name:match("%.rock$") then
+ return install_binary_rock(name, deps.get_deps_mode(flags))
+ else
+ local search = require("luarocks.search")
+ local results, err = search.find_suitable_rock(search.make_query(name:lower(), version))
+ if err then
+ return nil, err
+ elseif type(results) == "string" then
+ local url = results
+ util.printout("Installing "..url.."...")
+ return run(url)
+ else
+ util.printout()
+ util.printerr("Could not determine which rock to install.")
+ util.title("Search results:")
+ search.print_results(results)
+ return nil, (next(results) and "Please narrow your query." or "No results found.")
+ end
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/lint.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/lint.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,41 @@
+
+--- Module implementing the LuaRocks "lint" command.
+-- Utility function that checks syntax of the rockspec.
+module("luarocks.lint", package.seeall)
+
+local util = require("luarocks.util")
+local download = require("luarocks.download")
+local fetch = require("luarocks.fetch")
+
+help_summary = "Check syntax of a rockspec."
+help_arguments = ""
+help = [[
+This is a utility function that checks the syntax of a rockspec.
+
+It returns success or failure if the text of a rockspec is
+syntactically correct.
+]]
+
+function run(...)
+ local flags, input = util.parse_flags(...)
+
+ if not input then
+ return nil, "Argument missing, see help."
+ end
+
+ local filename = input
+ if not input:match(".rockspec$") then
+ local err
+ filename, err = download.download("rockspec", input)
+ if not filename then
+ return nil, err
+ end
+ end
+
+ local rs, err = fetch.load_local_rockspec(filename)
+ if not rs then
+ return nil, "Failed loading rockspec: "..err
+ end
+
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/list.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/list.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,38 @@
+
+--- Module implementing the LuaRocks "list" command.
+-- Lists currently installed rocks.
+module("luarocks.list", package.seeall)
+
+local search = require("luarocks.search")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local path = require("luarocks.path")
+
+help_summary = "Lists currently installed rocks."
+help_arguments = "[--porcelain] "
+help = [[
+ is a substring of a rock name to filter by.
+
+--porcelain Produce machine-friendly output.
+]]
+
+--- Driver function for "list" command.
+-- @param filter string or nil: A substring of a rock name to filter by.
+-- @param version string or nil: a version may also be passed.
+-- @return boolean: True if succeeded, nil on errors.
+function run(...)
+ local flags, filter, version = util.parse_flags(...)
+ local results = {}
+ local query = search.make_query(filter and filter:lower() or "", version)
+ query.exact_name = false
+ local trees = cfg.rocks_trees
+ if flags["tree"] then
+ trees = { flags["tree"] }
+ end
+ for _, tree in ipairs(trees) do
+ search.manifest_search(results, path.rocks_dir(tree), query)
+ end
+ util.title("Installed rocks:", flags["porcelain"])
+ search.print_results(results, flags["porcelain"])
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/loader.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/loader.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,212 @@
+
+--- A module which installs a Lua package loader that is LuaRocks-aware.
+-- This loader uses dependency information from the LuaRocks tree to load
+-- correct versions of modules. It does this by constructing a "context"
+-- table in the environment, which records which versions of packages were
+-- used to load previous modules, so that the loader chooses versions
+-- that are declared to be compatible with the ones loaded earlier.
+local global_env = _G
+local package, require, ipairs, pairs, table, type, next, unpack =
+ package, require, ipairs, pairs, table, type, next, unpack
+
+module("luarocks.loader")
+
+local path = require("luarocks.path")
+local manif_core = require("luarocks.manif_core")
+local deps = require("luarocks.deps")
+local cfg = require("luarocks.cfg")
+
+context = {}
+
+-- Contains a table when rocks trees are loaded,
+-- or 'false' to indicate rocks trees failed to load.
+-- 'nil' indicates rocks trees were not attempted to be loaded yet.
+rocks_trees = nil
+
+local function load_rocks_trees()
+ local any_ok = false
+ local trees = {}
+ for _, tree in ipairs(cfg.rocks_trees) do
+ local manifest, err = manif_core.load_local_manifest(path.rocks_dir(tree))
+ if manifest then
+ any_ok = true
+ table.insert(trees, {tree=tree, manifest=manifest})
+ end
+ end
+ if not any_ok then
+ rocks_trees = false
+ return false
+ end
+ rocks_trees = trees
+ return true
+end
+
+--- Process the dependencies of a package to determine its dependency
+-- chain for loading modules.
+-- @param name string: The name of an installed rock.
+-- @param version string: The version of the rock, in string format
+function add_context(name, version)
+ -- assert(type(name) == "string")
+ -- assert(type(version) == "string")
+
+ if context[name] then
+ return
+ end
+ context[name] = version
+
+ if not rocks_trees and not load_rocks_trees() then
+ return nil
+ end
+
+ local providers = {}
+ for _, tree in ipairs(rocks_trees) do
+ local manifest = tree.manifest
+
+ local pkgdeps
+ if manifest.dependencies and manifest.dependencies[name] then
+ pkgdeps = manifest.dependencies[name][version]
+ end
+ if not pkgdeps then
+ return nil
+ end
+ for _, dep in ipairs(pkgdeps) do
+ local pkg, constraints = dep.name, dep.constraints
+
+ for _, tree in ipairs(rocks_trees) do
+ local entries = tree.manifest.repository[pkg]
+ if entries then
+ for version, pkgs in pairs(entries) do
+ if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
+ add_context(pkg, version)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+--- Internal sorting function.
+-- @param a table: A provider table.
+-- @param b table: Another provider table.
+-- @return boolean: True if the version of a is greater than that of b.
+local function sort_versions(a,b)
+ return a.version > b.version
+end
+
+--- Request module to be loaded through other loaders,
+-- once the proper name of the module has been determined.
+-- For example, in case the module "socket.core" has been requested
+-- to the LuaRocks loader and it determined based on context that
+-- the version 2.0.2 needs to be loaded and it is not the current
+-- version, the module requested for the other loaders will be
+-- "socket.core_2_0_2".
+-- @param module The module name requested by the user, such as "socket.core"
+-- @param name The rock name, such as "luasocket"
+-- @param version The rock version, such as "2.0.2-1"
+-- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2".
+-- @return table or (nil, string): The module table as returned by some other loader,
+-- or nil followed by an error message if no other loader managed to load the module.
+local function call_other_loaders(module, name, version, module_name)
+ for i, loader in pairs(package.loaders) do
+ if loader ~= luarocks_loader then
+ local results = { loader(module_name) }
+ if type(results[1]) == "function" then
+ return unpack(results)
+ end
+ end
+ end
+ return "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
+end
+
+--- Search for a module in the rocks trees
+-- @param module string: module name (eg. "socket.core")
+-- @param filter_module_name function(string, string, string, string, number):
+-- a function that takes the module name (eg "socket.core"), the rock name
+-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree
+-- (eg "/usr/local"), and the numeric index of the matching entry, so the
+-- filter function can know if the matching module was the first entry or not.
+-- @return string, string, string: name of the rock containing the module
+-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
+-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
+-- stored versioned).
+local function select_module(module, filter_module_name)
+ --assert(type(module) == "string")
+ --assert(type(filter_module_name) == "function")
+
+ if not rocks_trees and not load_rocks_trees() then
+ return nil
+ end
+
+ local providers = {}
+ for _, tree in ipairs(rocks_trees) do
+ local entries = tree.manifest.modules[module]
+ if entries then
+ for i, entry in ipairs(entries) do
+ local name, version = entry:match("^([^/]*)/(.*)$")
+ local module_name = tree.manifest.repository[name][version][1].modules[module]
+ if type(module_name) ~= "string" then
+ error("Invalid format in manifest file (invalid data for "..tostring(name).." "..tostring(version)..")")
+ end
+ module_name = filter_module_name(module_name, name, version, tree.tree, i)
+ if context[name] == version then
+ return name, version, module_name
+ end
+ version = deps.parse_version(version)
+ table.insert(providers, {name = name, version = version, module_name = module_name})
+ end
+ end
+ end
+
+ if next(providers) then
+ table.sort(providers, sort_versions)
+ local first = providers[1]
+ return first.name, first.version.string, first.module_name
+ end
+end
+
+--- Search for a module
+-- @param module string: module name (eg. "socket.core")
+-- @return string, string, string: name of the rock containing the module
+-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
+-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
+-- stored versioned).
+local function pick_module(module)
+ return
+ select_module(module, function(module_name, name, version, tree, i)
+ if i > 1 then
+ module_name = path.versioned_name(module_name, "", name, version)
+ end
+ module_name = path.path_to_module(module_name)
+ return module_name
+ end)
+end
+
+--- Return the pathname of the file that would be loaded for a module.
+-- @param module string: module name (eg. "socket.core")
+-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
+function which(module)
+ local name, version, module_name = select_module(module, path.which_i)
+ return module_name
+end
+
+--- Package loader for LuaRocks support.
+-- A module is searched in installed rocks that match the
+-- current LuaRocks context. If module is not part of the
+-- context, or if a context has not yet been set, the module
+-- in the package with the highest version is used.
+-- @param module string: The module name, like in plain require().
+-- @return table: The module table (typically), like in plain
+-- require(). See require()
+-- in the Lua reference manual for details.
+function luarocks_loader(module)
+ local name, version, module_name = pick_module(module)
+ if not name then
+ return "No LuaRocks module found for "..module
+ else
+ add_context(name, version)
+ return call_other_loaders(module, name, version, module_name)
+ end
+end
+
+table.insert(global_env.package.loaders, 1, luarocks_loader)
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/make.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/make.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,72 @@
+
+--- Module implementing the LuaRocks "make" command.
+-- Builds sources in the current directory, but unlike "build",
+-- it does not fetch sources, etc., assuming everything is
+-- available in the current directory.
+module("luarocks.make", package.seeall)
+
+local build = require("luarocks.build")
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local fetch = require("luarocks.fetch")
+local pack = require("luarocks.pack")
+local deps = require("luarocks.deps")
+
+help_summary = "Compile package in current directory using a rockspec."
+help_arguments = "[--pack-binary-rock] []"
+help = [[
+Builds sources in the current directory, but unlike "build",
+it does not fetch sources, etc., assuming everything is
+available in the current directory. If no argument is given,
+look for a rockspec in the current directory. If more than one
+is found, you must specify which to use, through the command-line.
+
+This command is useful as a tool for debugging rockspecs.
+To install rocks, you'll normally want to use the "install" and
+"build" commands. See the help on those for details.
+
+If --pack-binary-rock is passed, the rock is not installed;
+instead, a .rock file with the contents of compilation is produced
+in the current directory.
+]]
+
+--- Driver function for "make" command.
+-- @param name string: A local rockspec.
+-- @return boolean or (nil, string): True if build was successful; nil and an
+-- error message otherwise.
+function run(...)
+ local flags, rockspec = util.parse_flags(...)
+ assert(type(rockspec) == "string" or not rockspec)
+
+ if not rockspec then
+ local files = fs.list_dir(fs.current_dir())
+ for _, file in pairs(files) do
+ if file:match("rockspec$") then
+ if rockspec then
+ return nil, "Please specify which rockspec file to use."
+ else
+ rockspec = file
+ end
+ end
+ end
+ if not rockspec then
+ return nil, "Argument missing: please specify a rockspec to use on current directory."
+ end
+ end
+ if not rockspec:match("rockspec$") then
+ return nil, "Invalid argument: 'make' takes a rockspec as a parameter. See help."
+ end
+
+ if flags["pack-binary-rock"] then
+ local rspec, err, errcode = fetch.load_rockspec(rockspec)
+ if not rspec then
+ return nil, err
+ end
+ return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, deps.get_deps_mode(flags))
+ else
+ local ok, err = fs.check_command_permissions(flags)
+ if not ok then return nil, err end
+ return build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags))
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/make_manifest.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/make_manifest.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,37 @@
+
+--- Module implementing the luarocks-admin "make_manifest" command.
+-- Compile a manifest file for a repository.
+module("luarocks.make_manifest", package.seeall)
+
+local manif = require("luarocks.manif")
+local index = require("luarocks.index")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local deps = require("luarocks.deps")
+
+help_summary = "Compile a manifest file for a repository."
+
+help = [[
+, if given, is a local repository pathname.
+]]
+
+--- Driver function for "make_manifest" command.
+-- @param repo string or nil: Pathname of a local repository. If not given,
+-- the default local repository configured as cfg.rocks_dir is used.
+-- @return boolean or (nil, string): True if manifest was generated,
+-- or nil and an error message.
+function run(...)
+ local flags, repo = util.parse_flags(...)
+
+ assert(type(repo) == "string" or not repo)
+ repo = repo or cfg.rocks_dir
+
+ util.printout("Making manifest for "..repo)
+
+ local ok, err = manif.make_manifest(repo, deps.get_deps_mode(flags))
+ if ok then
+ util.printout("Generating index.html for "..repo)
+ index.make_index(repo)
+ end
+ return ok, err
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/manif.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/manif.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,374 @@
+
+--- Module for handling manifest files and tables.
+-- Manifest files describe the contents of a LuaRocks tree or server.
+-- They are loaded into manifest tables, which are then used for
+-- performing searches, matching dependencies, etc.
+module("luarocks.manif", package.seeall)
+
+local manif_core = require("luarocks.manif_core")
+local persist = require("luarocks.persist")
+local fetch = require("luarocks.fetch")
+local dir = require("luarocks.dir")
+local fs = require("luarocks.fs")
+local search = require("luarocks.search")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local path = require("luarocks.path")
+local repos = require("luarocks.repos")
+local deps = require("luarocks.deps")
+
+rock_manifest_cache = {}
+
+--- Commit a table to disk in given local path.
+-- @param where string: The directory where the table should be saved.
+-- @param name string: The filename.
+-- @param tbl table: The table to be saved.
+-- @return boolean or (nil, string): true if successful, or nil and a
+-- message in case of errors.
+local function save_table(where, name, tbl)
+ assert(type(where) == "string")
+ assert(type(name) == "string")
+ assert(type(tbl) == "table")
+
+ local filename = dir.path(where, name)
+ local ok, err = persist.save_from_table(filename..".tmp", tbl)
+ if ok then
+ ok, err = fs.replace_file(filename, filename..".tmp")
+ end
+ return ok, err
+end
+
+function load_rock_manifest(name, version, root)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ local name_version = name.."/"..version
+ if rock_manifest_cache[name_version] then
+ return rock_manifest_cache[name_version].rock_manifest
+ end
+ local pathname = path.rock_manifest_file(name, version, root)
+ local rock_manifest = persist.load_into_table(pathname)
+ if not rock_manifest then return nil end
+ rock_manifest_cache[name_version] = rock_manifest
+ return rock_manifest.rock_manifest
+end
+
+function make_rock_manifest(name, version)
+ local install_dir = path.install_dir(name, version)
+ local rock_manifest = path.rock_manifest_file(name, version)
+ local tree = {}
+ for _, file in ipairs(fs.find(install_dir)) do
+ local full_path = dir.path(install_dir, file)
+ local walk = tree
+ local last
+ local last_name
+ for name in file:gmatch("[^/]+") do
+ local next = walk[name]
+ if not next then
+ next = {}
+ walk[name] = next
+ end
+ last = walk
+ last_name = name
+ walk = next
+ end
+ if fs.is_file(full_path) then
+ last[last_name] = fs.get_md5(full_path)
+ end
+ end
+ local rock_manifest = { rock_manifest=tree }
+ rock_manifest_cache[name.."/"..version] = rock_manifest
+ save_table(install_dir, "rock_manifest", rock_manifest )
+end
+
+--- Load a local or remote manifest describing a repository.
+-- All functions that use manifest tables assume they were obtained
+-- through either this function or load_local_manifest.
+-- @param repo_url string: URL or pathname for the repository.
+-- @return table or (nil, string, [string]): A table representing the manifest,
+-- or nil followed by an error message and an optional error code.
+function load_manifest(repo_url)
+ assert(type(repo_url) == "string")
+
+ if manif_core.manifest_cache[repo_url] then
+ return manif_core.manifest_cache[repo_url]
+ end
+
+ local protocol, pathname = dir.split_url(repo_url)
+ if protocol == "file" then
+ pathname = dir.path(pathname, "manifest")
+ else
+ local url = dir.path(repo_url, "manifest")
+ local name = repo_url:gsub("[/:]","_")
+ local file, err, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-manifest-"..name)
+ if not file then
+ return nil, "Failed fetching manifest for "..repo_url..(err and " - "..err or ""), errcode
+ end
+ pathname = file
+ end
+ return manif_core.manifest_loader(pathname, repo_url)
+end
+
+--- Output a table listing items of a package.
+-- @param itemsfn function: a function for obtaining items of a package.
+-- pkg and version will be passed to it; it should return a table with
+-- items as keys.
+-- @param pkg string: package name
+-- @param version string: package version
+-- @param tbl table: the package matching table: keys should be item names
+-- and values arrays of strings with packages names in "name/version" format.
+local function store_package_items(itemsfn, pkg, version, tbl)
+ assert(type(itemsfn) == "function")
+ assert(type(pkg) == "string")
+ assert(type(version) == "string")
+ assert(type(tbl) == "table")
+
+ local pkg_version = pkg.."/"..version
+ local result = {}
+
+ for item, path in pairs(itemsfn(pkg, version)) do
+ result[item] = path
+ if not tbl[item] then
+ tbl[item] = {}
+ end
+ table.insert(tbl[item], pkg_version)
+ end
+ return result
+end
+
+--- Sort function for ordering rock identifiers in a manifest's
+-- modules table. Rocks are ordered alphabetically by name, and then
+-- by version which greater first.
+-- @param a string: Version to compare.
+-- @param b string: Version to compare.
+-- @return boolean: The comparison result, according to the
+-- rule outlined above.
+local function sort_pkgs(a, b)
+ assert(type(a) == "string")
+ assert(type(b) == "string")
+
+ local na, va = a:match("(.*)/(.*)$")
+ local nb, vb = b:match("(.*)/(.*)$")
+
+ return (na == nb) and deps.compare_versions(va, vb) or na < nb
+end
+
+--- Sort items of a package matching table by version number (higher versions first).
+-- @param tbl table: the package matching table: keys should be strings
+-- and values arrays of strings with packages names in "name/version" format.
+local function sort_package_matching_table(tbl)
+ assert(type(tbl) == "table")
+
+ if next(tbl) then
+ for item, pkgs in pairs(tbl) do
+ if #pkgs > 1 then
+ table.sort(pkgs, sort_pkgs)
+ -- Remove duplicates from the sorted array.
+ local prev = nil
+ local i = 1
+ while pkgs[i] do
+ local curr = pkgs[i]
+ if curr == prev then
+ table.remove(pkgs, i)
+ else
+ prev = curr
+ i = i + 1
+ end
+ end
+ end
+ end
+ end
+end
+
+--- Process the dependencies of a manifest table to determine its dependency
+-- chains for loading modules. The manifest dependencies information is filled
+-- and any dependency inconsistencies or missing dependencies are reported to
+-- standard error.
+-- @param manifest table: a manifest table.
+local function update_dependencies(manifest, deps_mode)
+ assert(type(manifest) == "table")
+ assert(type(deps_mode) == "string")
+
+ for pkg, versions in pairs(manifest.repository) do
+ for version, repositories in pairs(versions) do
+ local current = pkg.." "..version
+ for _, repo in ipairs(repositories) do
+ if repo.arch == "installed" then
+ local missing
+ repo.dependencies, missing = deps.scan_deps({}, {}, manifest, pkg, version, deps_mode)
+ repo.dependencies[pkg] = nil
+ if missing then
+ for miss, err in pairs(missing) do
+ if miss == current then
+ util.printerr("Tree inconsistency detected: "..current.." has no rockspec. "..err)
+ else
+ util.printerr("Missing dependency for "..pkg.." "..version..": "..miss)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+--- Store search results in a manifest table.
+-- @param results table: The search results as returned by search.disk_search.
+-- @param manifest table: A manifest table (must contain repository, modules, commands tables).
+-- It will be altered to include the search results.
+-- @return boolean or (nil, string): true in case of success, or nil followed by an error message.
+local function store_results(results, manifest, deps_mode)
+ assert(type(results) == "table")
+ assert(type(manifest) == "table")
+ assert(type(deps_mode) == "string")
+
+ for name, versions in pairs(results) do
+ local pkgtable = manifest.repository[name] or {}
+ for version, entries in pairs(versions) do
+ local versiontable = {}
+ for _, entry in ipairs(entries) do
+ local entrytable = {}
+ entrytable.arch = entry.arch
+ if entry.arch == "installed" then
+ local rock_manifest = load_rock_manifest(name, version)
+ if not rock_manifest then
+ return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
+ end
+ entrytable.modules = store_package_items(repos.package_modules, name, version, manifest.modules)
+ entrytable.commands = store_package_items(repos.package_commands, name, version, manifest.commands)
+ end
+ table.insert(versiontable, entrytable)
+ end
+ pkgtable[version] = versiontable
+ end
+ manifest.repository[name] = pkgtable
+ end
+ update_dependencies(manifest, deps_mode)
+ sort_package_matching_table(manifest.modules)
+ sort_package_matching_table(manifest.commands)
+ return true
+end
+
+--- Scan a LuaRocks repository and output a manifest file.
+-- A file called 'manifest' will be written in the root of the given
+-- repository directory.
+-- @param repo A local repository directory.
+-- @return boolean or (nil, string): True if manifest was generated,
+-- or nil and an error message.
+function make_manifest(repo, deps_mode)
+ assert(type(repo) == "string")
+ assert(type(deps_mode) == "string")
+
+ if deps_mode == "none" then deps_mode = cfg.deps_mode end
+
+ if not fs.is_dir(repo) then
+ return nil, "Cannot access repository at "..repo
+ end
+
+ local query = search.make_query("")
+ query.exact_name = false
+ query.arch = "any"
+ local results = search.disk_search(repo, query)
+ local manifest = { repository = {}, modules = {}, commands = {} }
+ manif_core.manifest_cache[repo] = manifest
+
+ local ok, err = store_results(results, manifest, deps_mode)
+ if not ok then return nil, err end
+
+ return save_table(repo, "manifest", manifest)
+end
+
+--- Load a manifest file from a local repository and add to the repository
+-- information with regard to the given name and version.
+-- A file called 'manifest' will be written in the root of the given
+-- repository directory.
+-- @param name string: Name of a package from the repository.
+-- @param version string: Version of a package from the repository.
+-- @param repo string or nil: Pathname of a local repository. If not given,
+-- the default local repository configured as cfg.rocks_dir is used.
+-- @return boolean or (nil, string): True if manifest was generated,
+-- or nil and an error message.
+function update_manifest(name, version, repo, deps_mode)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ repo = path.rocks_dir(repo or cfg.root_dir)
+ assert(type(deps_mode) == "string")
+
+ if deps_mode == "none" then deps_mode = cfg.deps_mode end
+
+ util.printout("Updating manifest for "..repo)
+
+ local manifest, err = load_manifest(repo)
+ if not manifest then
+ util.printerr("No existing manifest. Attempting to rebuild...")
+ local ok, err = make_manifest(repo, deps_mode)
+ if not ok then
+ return nil, err
+ end
+ manifest, err = load_manifest(repo)
+ if not manifest then
+ return nil, err
+ end
+ end
+
+ local results = {[name] = {[version] = {{arch = "installed", repo = repo}}}}
+
+ local ok, err = store_results(results, manifest, deps_mode)
+ if not ok then return nil, err end
+
+ return save_table(repo, "manifest", manifest)
+end
+
+local function find_providers(file, root)
+ assert(type(file) == "string")
+ root = root or cfg.root_dir
+
+ local manifest, err = manif_core.load_local_manifest(path.rocks_dir(root))
+ if not manifest then
+ return nil, err .. " -- corrupted local rocks tree?"
+ end
+ local deploy_bin = path.deploy_bin_dir(root)
+ local deploy_lua = path.deploy_lua_dir(root)
+ local deploy_lib = path.deploy_lib_dir(root)
+ local key, manifest_tbl
+
+ if util.starts_with(file, deploy_lua) then
+ manifest_tbl = manifest.modules
+ key = path.path_to_module(file:sub(#deploy_lua+1):gsub("\\", "/"))
+ elseif util.starts_with(file, deploy_lib) then
+ manifest_tbl = manifest.modules
+ key = path.path_to_module(file:sub(#deploy_lib+1):gsub("\\", "/"))
+ elseif util.starts_with(file, deploy_bin) then
+ manifest_tbl = manifest.commands
+ key = file:sub(#deploy_bin+1):gsub("^[\\/]*", "")
+ else
+ assert(false, "Assertion failed: '"..file.."' is not a deployed file.")
+ end
+
+ local providers = manifest_tbl[key]
+ if not providers then
+ return nil, "untracked"
+ end
+ return providers
+end
+
+--- Given a path of a deployed file, figure out which rock name and version
+-- correspond to it in the tree manifest.
+-- @param file string: The full path of a deployed file.
+-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used.
+-- @return string, string: name and version of the provider rock.
+function find_current_provider(file, root)
+ local providers, err = find_providers(file, root)
+ if not providers then return nil, err end
+ return providers[1]:match("([^/]*)/([^/]*)")
+end
+
+function find_next_provider(file, root)
+ local providers, err = find_providers(file, root)
+ if not providers then return nil, err end
+ if providers[2] then
+ return providers[2]:match("([^/]*)/([^/]*)")
+ else
+ return nil
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/manif_core.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/manif_core.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,79 @@
+
+--- Core functions for querying manifest files.
+-- This module requires no specific 'fs' functionality.
+module("luarocks.manif_core", package.seeall)
+
+local persist = require("luarocks.persist")
+local type_check = require("luarocks.type_check")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local path = require("luarocks.path")
+
+manifest_cache = {}
+
+--- Back-end function that actually loads the manifest
+-- and stores it in the manifest cache.
+-- @param file string: The local filename of the manifest file.
+-- @param repo_url string: The repository identifier.
+-- @param quick boolean: If given, skips type checking.
+function manifest_loader(file, repo_url, quick)
+ local manifest, err = persist.load_into_table(file)
+ if not manifest then
+ return nil, "Failed loading manifest for "..repo_url..": "..err
+ end
+ if not quick then
+ local ok, err = type_check.type_check_manifest(manifest)
+ if not ok then
+ return nil, "Error checking manifest: "..err
+ end
+ end
+
+ manifest_cache[repo_url] = manifest
+ return manifest
+end
+
+--- Load a local manifest describing a repository.
+-- All functions that use manifest tables assume they were obtained
+-- through either this function or load_manifest.
+-- @param repo_url string: URL or pathname for the repository.
+-- @return table or (nil, string): A table representing the manifest,
+-- or nil followed by an error message.
+function load_local_manifest(repo_url)
+ assert(type(repo_url) == "string")
+
+ if manifest_cache[repo_url] then
+ return manifest_cache[repo_url]
+ end
+
+ local pathname = dir.path(repo_url, "manifest")
+
+ return manifest_loader(pathname, repo_url, true)
+end
+
+--- Get all versions of a package listed in a manifest file.
+-- @param name string: a package name.
+-- @param deps_mode string: "one", to use only the currently
+-- configured tree; "order" to select trees based on order
+-- (use the current tree and all trees below it on the list)
+-- or "all", to use all trees.
+-- @return table: An array of strings listing installed
+-- versions of a package.
+function get_versions(name, deps_mode)
+ assert(type(name) == "string")
+ assert(type(deps_mode) == "string")
+
+ local manifest = {}
+ path.map_trees(deps_mode, function(tree)
+ local loaded = load_local_manifest(path.rocks_dir(tree))
+ if loaded then
+ util.deep_merge(manifest, loaded)
+ end
+ end)
+
+ local item = next(manifest) and manifest.repository[name]
+ if item then
+ return util.keys(item)
+ end
+ return {}
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/new_version.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/new_version.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,141 @@
+
+--- Module implementing the LuaRocks "new_version" command.
+-- Utility function that writes a new rockspec, updating data from a previous one.
+module("luarocks.new_version", package.seeall)
+
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local download = require("luarocks.download")
+local fetch = require("luarocks.fetch")
+local persist = require("luarocks.persist")
+local dir = require("luarocks.dir")
+local fs = require("luarocks.fs")
+
+help_summary = "Auto-write a rockspec for a new version of a rock."
+help_arguments = "{|} [] []"
+help = [[
+This is a utility function that writes a new rockspec, updating data
+from a previous one.
+
+If a package name is given, it downloads the latest rockspec from the
+default server. If a rockspec is given, it uses it instead.
+
+If the version number is not given, it only increments the revision
+number of the given (or downloaded) rockspec.
+
+If a URL is given, it replaces the one from the old rockspec with the
+given URL. If a URL is not given and a new version is given, it tries
+to guess the new URL by replacing occurrences of the version number
+in the URL or tag. It also tries to download the new URL to determine
+the new MD5 checksum.
+
+WARNING: it writes the new rockspec to the current directory,
+overwriting the file if it already exists.
+]]
+
+local order = {"rockspec_format", "package", "version",
+ { "source", { "url", "tag", "branch", "md5" } },
+ { "description", {"summary", "detailed", "homepage", "license" } },
+ "supported_platforms", "dependencies", "external_dependencies",
+ { "build", {"type", "modules", "copy_directories", "platforms"} },
+ "hooks"}
+
+local function try_replace(tbl, field, old, new)
+ if not tbl[field] then
+ return false
+ end
+ local old_field = tbl[field]
+ local new_field = tbl[field]:gsub(old, new)
+ if new_field ~= old_field then
+ util.printout("Guessing new '"..field.."' field as "..new_field)
+ tbl[field] = new_field
+ return true
+ end
+ return false
+end
+
+local function check_url_and_update_md5(out_rs, out_name)
+ out_rs.source.md5 = nil
+ local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_name)
+ if file then
+ util.printout("File successfully downloaded. Updating MD5 checksum...")
+ out_rs.source.md5 = fs.get_md5(file)
+ else
+ util.printerr("Warning: invalid URL - "..temp_dir)
+ end
+end
+
+function run(...)
+ local flags, input, version, url = util.parse_flags(...)
+ if not input then
+ return nil, "Missing arguments: expected program or rockspec. See help."
+ end
+ assert(type(input) == "string")
+
+ local filename = input
+ if not input:match(".rockspec$") then
+ local err
+ filename, err = download.download("rockspec", input)
+ if not filename then
+ return nil, err
+ end
+ end
+
+ local valid_rs, err = fetch.load_rockspec(filename)
+ if not valid_rs then
+ return nil, err
+ end
+
+ local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$")
+ local new_ver, new_rev
+
+ if version then
+ new_ver, new_rev = version:match("(.*)%-(%d+)$")
+ new_rev = tonumber(new_rev)
+ if not new_rev then
+ new_ver = version
+ new_rev = 1
+ end
+ else
+ new_ver = old_ver
+ new_rev = tonumber(old_rev) + 1
+ end
+
+
+ local out_rs = persist.load_into_table(filename)
+ local out_name = out_rs.package:lower()
+ out_rs.version = new_ver.."-"..new_rev
+ if url then
+ out_rs.source.url = url
+ check_url_and_update_md5(out_rs, out_name)
+ else
+ if new_ver ~= old_ver then
+ local ok = try_replace(out_rs.source, "url", old_ver, new_ver)
+ if ok then
+ check_url_and_update_md5(out_rs, out_name)
+ else
+ ok = try_replace(out_rs.source, "tag", old_ver, new_ver)
+ if not ok then
+ return nil, "Failed to determine the location of the new version."
+ end
+ end
+ end
+ end
+
+ if out_rs.build and out_rs.build.type == "module" then
+ out_rs.build.type = "builtin"
+ end
+
+ local out_filename = out_name.."-"..new_ver.."-"..new_rev..".rockspec"
+
+ persist.save_from_table(out_filename, out_rs, order)
+
+ util.printout("Wrote "..out_filename)
+
+ local valid_out_rs, err = fetch.load_local_rockspec(out_filename)
+ if not valid_out_rs then
+ return nil, "Failed loading generated rockspec: "..err
+ end
+
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/pack.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/pack.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,205 @@
+
+--- Module implementing the LuaRocks "pack" command.
+-- Creates a rock, packing sources or binaries.
+module("luarocks.pack", package.seeall)
+
+local path = require("luarocks.path")
+local repos = require("luarocks.repos")
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local dir = require("luarocks.dir")
+local manif = require("luarocks.manif")
+local search = require("luarocks.search")
+
+help_summary = "Create a rock, packing sources or binaries."
+help_arguments = "{| []}"
+help = [[
+Argument may be a rockspec file, for creating a source rock,
+or the name of an installed package, for creating a binary rock.
+In the latter case, the app version may be given as a second
+argument.
+]]
+
+--- Create a source rock.
+-- Packages a rockspec and its required source files in a rock
+-- file with the .src.rock extension, which can later be built and
+-- installed with the "build" command.
+-- @param rockspec_file string: An URL or pathname for a rockspec file.
+-- @return string or (nil, string): The filename of the resulting
+-- .src.rock file; or nil and an error message.
+local function pack_source_rock(rockspec_file)
+ assert(type(rockspec_file) == "string")
+
+ local rockspec, err = fetch.load_rockspec(rockspec_file)
+ if err then
+ return nil, "Error loading rockspec: "..err
+ end
+ rockspec_file = rockspec.local_filename
+
+ local name_version = rockspec.name .. "-" .. rockspec.version
+ local rock_file = fs.absolute_name(name_version .. ".src.rock")
+
+ local source_file, source_dir = fetch.fetch_sources(rockspec, false)
+ if not source_file then
+ return nil, source_dir
+ end
+ fs.change_dir(source_dir)
+
+ fs.delete(rock_file)
+ fs.copy(rockspec_file, source_dir)
+ if not fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file)) then
+ return nil, "Failed packing "..rock_file
+ end
+ fs.pop_dir()
+
+ return rock_file
+end
+
+local function copy_back_files(name, version, file_tree, deploy_dir, pack_dir)
+ fs.make_dir(pack_dir)
+ for file, sub in pairs(file_tree) do
+ local source = dir.path(deploy_dir, file)
+ local target = dir.path(pack_dir, file)
+ if type(sub) == "table" then
+ local ok, err = copy_back_files(name, version, sub, source, target)
+ else
+ local versioned = path.versioned_name(source, deploy_dir, name, version)
+ if fs.exists(versioned) then
+ fs.copy(versioned, target)
+ else
+ fs.copy(source, target)
+ end
+ end
+ end
+ return true
+end
+
+-- @param name string: Name of package to pack.
+-- @param version string or nil: A version number may also be passed.
+-- @return string or (nil, string): The filename of the resulting
+-- .src.rock file; or nil and an error message.
+local function do_pack_binary_rock(name, version)
+ assert(type(name) == "string")
+ assert(type(version) == "string" or not version)
+
+ local query = search.make_query(name, version)
+ query.exact_name = true
+ local results = {}
+
+ search.manifest_search(results, cfg.rocks_dir, query)
+
+ if not next(results) then
+ return nil, "'"..name.."' does not seem to be an installed rock."
+ end
+
+ local versions = results[name]
+
+ if not version then
+ local first = next(versions)
+ if next(versions, first) then
+ return nil, "Please specify which version of '"..name.."' to pack."
+ end
+ version = first
+ end
+ if not version:match("[^-]+%-%d+") then
+ return nil, "Expected version "..version.." in version-revision format."
+ end
+
+ local info = versions[version][1]
+
+ local root = path.root_dir(info.repo)
+ local prefix = path.install_dir(name, version, root)
+
+ if not fs.exists(prefix) then
+ return nil, "'"..name.." "..version.."' does not seem to be an installed rock."
+ end
+
+ local rock_manifest = manif.load_rock_manifest(name, version, root)
+ if not rock_manifest then
+ return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
+ end
+
+ local name_version = name .. "-" .. version
+ local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock")
+
+ local temp_dir = fs.make_temp_dir("pack")
+ fs.copy_contents(prefix, temp_dir)
+
+ local is_binary = false
+ if rock_manifest.lib then
+ copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"))
+ is_binary = true
+ end
+ if rock_manifest.lua then
+ copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(root), dir.path(temp_dir, "lua"))
+ end
+
+ fs.change_dir(temp_dir)
+ if not is_binary and not repos.has_binaries(name, version) then
+ rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
+ end
+ fs.delete(rock_file)
+ if not fs.zip(rock_file, unpack(fs.list_dir())) then
+ return nil, "Failed packing "..rock_file
+ end
+ fs.pop_dir()
+ fs.delete(temp_dir)
+ return rock_file
+end
+
+function pack_binary_rock(name, version, cmd, ...)
+
+ -- The --pack-binary-rock option for "luarocks build" basically performs
+ -- "luarocks build" on a temporary tree and then "luarocks pack". The
+ -- alternative would require refactoring parts of luarocks.build and
+ -- luarocks.pack, which would save a few file operations: the idea would be
+ -- to shave off the final deploy steps from the build phase and the initial
+ -- collect steps from the pack phase.
+
+ local temp_dir = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
+ if not temp_dir then
+ return nil, "Failed creating temporary directory."
+ end
+ util.schedule_function(fs.delete, temp_dir)
+
+ path.use_tree(temp_dir)
+ local ok, err = cmd(...)
+ if not ok then
+ return nil, err
+ end
+ local rname, rversion = path.parse_name(name)
+ if not rname then
+ rname, rversion = name, version
+ end
+ return do_pack_binary_rock(rname, rversion)
+end
+
+--- Driver function for the "pack" command.
+-- @param arg string: may be a rockspec file, for creating a source rock,
+-- or the name of an installed package, for creating a binary rock.
+-- @param version string or nil: if the name of a package is given, a
+-- version may also be passed.
+-- @return boolean or (nil, string): true if successful or nil followed
+-- by an error message.
+function run(...)
+ local flags, arg, version = util.parse_flags(...)
+ assert(type(version) == "string" or not version)
+ if type(arg) ~= "string" then
+ return nil, "Argument missing, see help."
+ end
+
+ local file, err
+ if arg:match(".*%.rockspec") then
+ file, err = pack_source_rock(arg)
+ else
+ file, err = do_pack_binary_rock(arg, version)
+ end
+ if err then
+ return nil, err
+ else
+ util.printout("Packed: "..file)
+ return true
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/path.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/path.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,388 @@
+
+--- LuaRocks-specific path handling functions.
+-- All paths are configured in this module, making it a single
+-- point where the layout of the local installation is defined in LuaRocks.
+module("luarocks.path", package.seeall)
+
+local dir = require("luarocks.dir")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local deps = require("luarocks.deps")
+
+help_summary = "Return the currently configured package path."
+help_arguments = ""
+help = [[
+Returns the package path currently configured for this installation
+of LuaRocks, formatted as shell commands to update LUA_PATH and
+LUA_CPATH. (On Unix systems, you may run: eval `luarocks path`)
+]]
+
+--- Infer rockspec filename from a rock filename.
+-- @param rock_name string: Pathname of a rock file.
+-- @return string: Filename of the rockspec, without path.
+function rockspec_name_from_rock(rock_name)
+ assert(type(rock_name) == "string")
+ local base_name = dir.base_name(rock_name)
+ return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec"
+end
+
+function rocks_dir(tree)
+ if type(tree) == "string" then
+ return dir.path(tree, "lib", "luarocks", "rocks")
+ else
+ assert(type(tree) == "table")
+ return tree.rocks_dir or dir.path(tree.root, "lib", "luarocks", "rocks")
+ end
+end
+
+function root_dir(rocks_dir)
+ assert(type(rocks_dir) == "string")
+
+ local suffix = dir.path("lib", "luarocks")
+ return rocks_dir:match("(.*)" .. suffix .. ".*$")
+end
+
+function deploy_bin_dir(tree)
+ if type(tree) == "string" then
+ return dir.path(tree, "bin")
+ else
+ assert(type(tree) == "table")
+ return tree.bin_dir or dir.path(tree.root, "bin")
+ end
+end
+
+function deploy_lua_dir(tree)
+ if type(tree) == "string" then
+ return dir.path(tree, cfg.lua_modules_path)
+ else
+ assert(type(tree) == "table")
+ return tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path)
+ end
+end
+
+function deploy_lib_dir(tree)
+ if type(tree) == "string" then
+ return dir.path(tree, cfg.lib_modules_path)
+ else
+ assert(type(tree) == "table")
+ return tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path)
+ end
+end
+
+function manifest_file(tree)
+ if type(tree) == "string" then
+ return dir.path(tree, "lib", "luarocks", "rocks", "manifest")
+ else
+ assert(type(tree) == "table")
+ return (tree.rocks_dir and dir.path(tree.rocks_dir, "manifest")) or dir.path(tree.root, "lib", "luarocks", "rocks", "manifest")
+ end
+end
+
+--- Get the directory for all versions of a package in a tree.
+-- @param name string: The package name.
+-- @return string: The resulting path -- does not guarantee that
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- the package (and by extension, the path) exists.
+function versions_dir(name, tree)
+ assert(type(name) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name)
+end
+
+--- Get the local installation directory (prefix) for a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function install_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version)
+end
+
+--- Get the local filename of the rockspec of an installed rock.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the file) exists.
+function rockspec_file(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, name.."-"..version..".rockspec")
+end
+
+--- Get the local filename of the rock_manifest file of an installed rock.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the file) exists.
+function rock_manifest_file(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "rock_manifest")
+end
+
+--- Get the local installation directory for C libraries of a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function lib_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "lib")
+end
+
+--- Get the local installation directory for Lua modules of a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function lua_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "lua")
+end
+
+--- Get the local installation directory for documentation of a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function doc_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "doc")
+end
+
+--- Get the local installation directory for configuration files of a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function conf_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "conf")
+end
+
+--- Get the local installation directory for command-line scripts
+-- of a package.
+-- @param name string: The package name.
+-- @param version string: The package version.
+-- @param tree string or nil: If given, specifies the local tree to use.
+-- @return string: The resulting path -- does not guarantee that
+-- the package (and by extension, the path) exists.
+function bin_dir(name, version, tree)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ tree = tree or cfg.root_dir
+ return dir.path(rocks_dir(tree), name, version, "bin")
+end
+
+--- Extract name, version and arch of a rock filename,
+-- or name, version and "rockspec" from a rockspec name.
+-- @param file_name string: pathname of a rock or rockspec
+-- @return (string, string, string) or nil: name, version and arch
+-- or nil if name could not be parsed
+function parse_name(file_name)
+ assert(type(file_name) == "string")
+ if file_name:match("%.rock$") then
+ return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.([^.]+)%.rock$")
+ else
+ return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.(rockspec)")
+ end
+end
+
+--- Make a rockspec or rock URL.
+-- @param pathname string: Base URL or pathname.
+-- @param name string: Package name.
+-- @param version string: Package version.
+-- @param arch string: Architecture identifier, or "rockspec" or "installed".
+-- @return string: A URL or pathname following LuaRocks naming conventions.
+function make_url(pathname, name, version, arch)
+ assert(type(pathname) == "string")
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ assert(type(arch) == "string")
+
+ local filename = name.."-"..version
+ if arch == "installed" then
+ filename = dir.path(name, version, filename..".rockspec")
+ elseif arch == "rockspec" then
+ filename = filename..".rockspec"
+ else
+ filename = filename.."."..arch..".rock"
+ end
+ return dir.path(pathname, filename)
+end
+
+--- Convert a pathname to a module identifier.
+-- In Unix, for example, a path "foo/bar/baz.lua" is converted to
+-- "foo.bar.baz"; "bla/init.lua" returns "bla"; "foo.so" returns "foo".
+-- @param file string: Pathname of module
+-- @return string: The module identifier, or nil if given path is
+-- not a conformant module path (the function does not check if the
+-- path actually exists).
+function path_to_module(file)
+ assert(type(file) == "string")
+
+ local name = file:match("(.*)%."..cfg.lua_extension.."$")
+ if name then
+ name = name:gsub(dir.separator, ".")
+ local init = name:match("(.*)%.init$")
+ if init then
+ name = init
+ end
+ else
+ name = file:match("(.*)%."..cfg.lib_extension.."$")
+ if name then
+ name = name:gsub(dir.separator, ".")
+ end
+ end
+ if not name then name = file end
+ name = name:gsub("^%.+", ""):gsub("%.+$", "")
+ return name
+end
+
+--- Obtain the directory name where a module should be stored.
+-- For example, on Unix, "foo.bar.baz" will return "foo/bar".
+-- @param mod string: A module name in Lua dot-separated format.
+-- @return string: A directory name using the platform's separator.
+function module_to_path(mod)
+ assert(type(mod) == "string")
+ return (mod:gsub("[^.]*$", ""):gsub("%.", dir.separator))
+end
+
+--- Set up path-related variables for a given rock.
+-- Create a "variables" table in the rockspec table, containing
+-- adjusted variables according to the configuration file.
+-- @param rockspec table: The rockspec table.
+function configure_paths(rockspec)
+ assert(type(rockspec) == "table")
+ local vars = {}
+ for k,v in pairs(cfg.variables) do
+ vars[k] = v
+ end
+ local name, version = rockspec.name, rockspec.version
+ vars.PREFIX = install_dir(name, version)
+ vars.LUADIR = lua_dir(name, version)
+ vars.LIBDIR = lib_dir(name, version)
+ vars.CONFDIR = conf_dir(name, version)
+ vars.BINDIR = bin_dir(name, version)
+ vars.DOCDIR = doc_dir(name, version)
+ rockspec.variables = vars
+end
+
+function versioned_name(file, prefix, name, version)
+ assert(type(file) == "string")
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ local rest = file:sub(#prefix+1):gsub("^/*", "")
+ local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_")
+ return dir.path(prefix, name_version.."-"..rest)
+end
+
+function use_tree(tree)
+ cfg.root_dir = tree
+ cfg.rocks_dir = rocks_dir(tree)
+ cfg.deploy_bin_dir = deploy_bin_dir(tree)
+ cfg.deploy_lua_dir = deploy_lua_dir(tree)
+ cfg.deploy_lib_dir = deploy_lib_dir(tree)
+end
+
+function map_trees(deps_mode, fn, ...)
+ local result = {}
+ if deps_mode == "one" then
+ table.insert(result, (fn(cfg.root_dir, ...)) or 0)
+ elseif deps_mode == "all" or deps_mode == "order" then
+ local use = false
+ if deps_mode == "all" then
+ use = true
+ end
+ for _, tree in ipairs(cfg.rocks_trees) do
+ if dir.normalize(tree) == dir.normalize(cfg.root_dir) then
+ use = true
+ end
+ if use then
+ table.insert(result, (fn(tree, ...)) or 0)
+ end
+ end
+ end
+ return result
+end
+
+--- Return the pathname of the file that would be loaded for a module, indexed.
+-- @param module_name string: module name (eg. "socket.core")
+-- @param name string: name of the package (eg. "luasocket")
+-- @param version string: version number (eg. "2.0.2-1")
+-- @param tree string: repository path (eg. "/usr/local")
+-- @param i number: the index, 1 if version is the current default, > 1 otherwise.
+-- This is done this way for use by select_module in luarocks.loader.
+-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
+function which_i(module_name, name, version, tree, i)
+ local deploy_dir
+ if module_name:match("%.lua$") then
+ deploy_dir = deploy_lua_dir(tree)
+ module_name = dir.path(deploy_dir, module_name)
+ else
+ deploy_dir = deploy_lib_dir(tree)
+ module_name = dir.path(deploy_dir, module_name)
+ end
+ if i > 1 then
+ module_name = versioned_name(module_name, deploy_dir, name, version)
+ end
+ return module_name
+end
+
+--- Return the pathname of the file that would be loaded for a module,
+-- returning the versioned pathname if given version is not the default version
+-- in the given manifest.
+-- @param module_name string: module name (eg. "socket.core")
+-- @param name string: name of the package (eg. "luasocket")
+-- @param version string: version number (eg. "2.0.2-1")
+-- @param tree string: repository path (eg. "/usr/local")
+-- @param manifest table: the manifest table for the tree.
+-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
+function which(module_name, filename, name, version, tree, manifest)
+ local versions = manifest.modules[module_name]
+ assert(versions)
+ for i, name_version in ipairs(versions) do
+ if name_version == name.."/"..version then
+ return which_i(filename, name, version, tree, i):gsub("//", "/")
+ end
+ end
+ assert(false)
+end
+
+--- Driver function for "path" command.
+-- @return boolean This function always succeeds.
+function run(...)
+ local flags = util.parse_flags(...)
+ local deps_mode = deps.get_deps_mode(flags)
+
+ util.printout(cfg.export_lua_path:format(util.remove_path_dupes(package.path, ';')))
+ util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(package.cpath, ';')))
+ if flags["bin"] then
+ local bin_dirs = map_trees(deps_mode, deploy_bin_dir)
+ table.insert(bin_dirs, 1, os.getenv("PATH"))
+ util.printout(cfg.export_path:format(util.remove_path_dupes(table.concat(bin_dirs, cfg.export_path_separator), cfg.export_path_separator)))
+ end
+ return true
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/persist.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/persist.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,173 @@
+
+--- Utility module for loading files into tables and
+-- saving tables into files.
+-- Implemented separately to avoid interdependencies,
+-- as it is used in the bootstrapping stage of the cfg module.
+module("luarocks.persist", package.seeall)
+
+local util = require("luarocks.util")
+
+--- Load a Lua file containing assignments, storing them in a table.
+-- The global environment is not propagated to the loaded file.
+-- @param filename string: the name of the file.
+-- @param tbl table or nil: if given, this table is used to store
+-- loaded values.
+-- @return table or (nil, string): a table with the file's assignments
+-- as fields, or nil and a message in case of errors.
+function load_into_table(filename, tbl)
+ assert(type(filename) == "string")
+ assert(type(tbl) == "table" or not tbl)
+
+ local result, chunk, ran, err
+ local result = tbl or {}
+ if setfenv then -- Lua 5.1
+ chunk, err = loadfile(filename)
+ if chunk then
+ setfenv(chunk, result)
+ ran, err = pcall(chunk)
+ end
+ else -- Lua 5.2
+ chunk, err = loadfile(filename, "t", result)
+ if chunk then
+ ran, err = pcall(chunk)
+ end
+ end
+
+ if not chunk then
+ if err:sub(1,5) ~= filename:sub(1,5) then
+ return false, err
+ end
+ return nil, "Error loading file: "..err
+ end
+ if not ran then
+ return nil, "Error running file: "..err
+ end
+ return result
+end
+
+local write_table
+
+--- Write a value as Lua code, invoking write_table.
+-- This function handles only numbers, strings and tables
+-- are keys (tables are handled recursively).
+-- @param out userdata: a file object, open for writing.
+-- @param v: the value to be written.
+-- @param level number: the indentation level
+-- @param sub_order table: optional prioritization table
+-- @see write_table
+local function write_value(out, v, level, sub_order)
+ if type(v) == "table" then
+ write_table(out, v, level + 1, sub_order)
+ elseif type(v) == "string" then
+ if v:match("\n") then
+ local open, close = "[[", "]]"
+ local equals = 0
+ while v:find(open,1,true) or v:find(close,1,true) do
+ equals = equals + 1
+ local eqs = ("="):rep(equals)
+ open, close = "["..eqs.."[", "]"..eqs.."]"
+ end
+ out:write(open.."\n"..v..close)
+ else
+ out:write("\""..v:gsub("\"", "\\\"").."\"")
+ end
+ else
+ out:write(tostring(v))
+ end
+end
+
+--- Write a table as Lua code representing a table to disk
+-- (that is, in curly brackets notation).
+-- This function handles only numbers, strings and tables
+-- are keys (tables are handled recursively).
+-- @param out userdata: a file object, open for writing.
+-- @param tbl table: the table to be written.
+-- @param level number: the indentation level
+-- @param field_order table: optional prioritization table
+write_table = function(out, tbl, level, field_order)
+ out:write("{")
+ local sep = "\n"
+ local indentation = " "
+ local indent = true
+ local i = 1
+ for k, v, sub_order in util.sortedpairs(tbl, field_order) do
+ out:write(sep)
+ if indent then
+ for n = 1,level do out:write(indentation) end
+ end
+ sep = ",\n"
+ indent = true
+ if type(k) == "number" then
+ if k ~= i then
+ out:write("["..tostring(k).."]=")
+ else
+ i = i + 1
+ end
+ indent = false
+ sep = ", "
+ elseif type(k) == "table" then
+ out:write("[")
+ write_table(out, k, level + 1)
+ out:write("] = ")
+ else
+ if k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
+ out:write(k.." = ")
+ else
+ out:write("['"..k:gsub("'", "\\'").."'] = ")
+ end
+ end
+ write_value(out, v, level, sub_order)
+ end
+ if sep ~= "\n" then
+ out:write("\n")
+ for n = 1,level-1 do out:write(indentation) end
+ end
+ out:write("}")
+end
+
+--- Writes a table to an io-like object.
+-- @param out userdata: a file object, open for writing.
+-- @param tbl table: the table to be written.
+-- @param field_order table: optional prioritization table
+-- @return userdata The file object originally passed in as the `out` parameter.
+local function write_table(out, tbl, field_order)
+ for k, v, sub_order in util.sortedpairs(tbl, field_order) do
+ out:write(k.." = ")
+ write_value(out, v, 0, sub_order)
+ out:write("\n")
+ end
+ return out
+end
+
+--- Save the contents of a table to a string.
+-- Each element of the table is saved as a global assignment.
+-- Only numbers, strings and tables (containing numbers, strings
+-- or other recursively processed tables) are supported.
+-- @param tbl table: the table containing the data to be written
+-- @param field_order table: an optional array indicating the order of top-level fields.
+-- @return string
+function save_from_table_to_string(tbl, field_order)
+ local out = {buffer = {}}
+ function out:write(data) table.insert(self.buffer, data) end
+ write_table(out, tbl, field_order)
+ return table.concat(out.buffer)
+end
+
+--- Save the contents of a table in a file.
+-- Each element of the table is saved as a global assignment.
+-- Only numbers, strings and tables (containing numbers, strings
+-- or other recursively processed tables) are supported.
+-- @param filename string: the output filename
+-- @param tbl table: the table containing the data to be written
+-- @param field_order table: an optional array indicating the order of top-level fields.
+-- @return boolean or (nil, string): true if successful, or nil and a
+-- message in case of errors.
+function save_from_table(filename, tbl, field_order)
+ local out = io.open(filename, "w")
+ if not out then
+ return nil, "Cannot create file at "..filename
+ end
+ write_table(out, tbl, field_order)
+ out:close()
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/purge.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/purge.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,48 @@
+
+--- Module implementing the LuaRocks "purge" command.
+-- Remove all rocks from a given tree.
+module("luarocks.purge", package.seeall)
+
+local util = require("luarocks.util")
+local fs = require("luarocks.fs")
+local path = require("luarocks.path")
+local search = require("luarocks.search")
+local deps = require("luarocks.deps")
+local repos = require("luarocks.repos")
+local manif = require("luarocks.manif")
+local cfg = require("luarocks.cfg")
+
+help_summary = "Remove all installed rocks from a tree."
+help_arguments = "--tree="
+help = [[
+This command removes all rocks from a given tree.
+
+The --tree argument is mandatory: luarocks purge does not
+assume a default tree.
+]]
+
+function run(...)
+ local flags = util.parse_flags(...)
+
+ local tree = flags["tree"]
+
+ if type(tree) ~= "string" then
+ return nil, "The --tree argument is mandatory, see help."
+ end
+
+ local results = {}
+ local query = search.make_query("")
+ query.exact_name = false
+ search.manifest_search(results, path.rocks_dir(tree), query)
+
+ for package, versions in util.sortedpairs(results) do
+ for version, repositories in util.sortedpairs(versions, function(a,b) return deps.compare_versions(b,a) end) do
+ util.printout("Removing "..package.." "..version.."...")
+ local ok, err = repos.delete_version(package, version, true)
+ if not ok then
+ util.printerr(err)
+ end
+ end
+ end
+ return manif.make_manifest(cfg.rocks_dir, "one")
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/refresh_cache.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/refresh_cache.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,30 @@
+
+--- Module implementing the luarocks-admin "refresh_cache" command.
+module("luarocks.refresh_cache", package.seeall)
+
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local cache = require("luarocks.cache")
+
+help_summary = "Refresh local cache of a remote rocks server."
+help_arguments = "[--from=]"
+help = [[
+The flag --from indicates which server to use.
+If not given, the default server set in the upload_server variable
+from the configuration file is used instead.
+]]
+
+function run(...)
+ local flags = util.parse_flags(...)
+ local server, upload_server = cache.get_upload_server(flags["server"])
+ if not server then return nil, upload_server end
+ local download_url = cache.get_server_urls(server, upload_server)
+
+ local ok, err = cache.refresh_local_cache(server, download_url, cfg.upload_user, cfg.upload_password)
+ if not ok then
+ return nil, err
+ else
+ return true
+ end
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/remove.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/remove.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,137 @@
+
+--- Module implementing the LuaRocks "remove" command.
+-- Uninstalls rocks.
+module("luarocks.remove", package.seeall)
+
+local search = require("luarocks.search")
+local deps = require("luarocks.deps")
+local fetch = require("luarocks.fetch")
+local repos = require("luarocks.repos")
+local path = require("luarocks.path")
+local util = require("luarocks.util")
+local cfg = require("luarocks.cfg")
+local manif = require("luarocks.manif")
+local fs = require("luarocks.fs")
+
+help_summary = "Uninstall a rock."
+help_arguments = "[--force] []"
+help = [[
+Argument is the name of a rock to be uninstalled.
+If a version is not given, try to remove all versions at once.
+Will only perform the removal if it does not break dependencies.
+To override this check and force the removal, use --force.
+]]
+
+--- Obtain a list of packages that depend on the given set of packages
+-- (where all packages of the set are versions of one program).
+-- @param name string: the name of a program
+-- @param versions array of string: the versions to be deleted.
+-- @return array of string: an empty table if no packages depend on any
+-- of the given list, or an array of strings in "name/version" format.
+local function check_dependents(name, versions, deps_mode)
+ local dependents = {}
+ local blacklist = {}
+ blacklist[name] = {}
+ for version, _ in pairs(versions) do
+ blacklist[name][version] = true
+ end
+ local local_rocks = {}
+ local query_all = search.make_query("")
+ query_all.exact_name = false
+ search.manifest_search(local_rocks, cfg.rocks_dir, query_all)
+ local_rocks[name] = nil
+ for rock_name, rock_versions in pairs(local_rocks) do
+ for rock_version, _ in pairs(rock_versions) do
+ local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version))
+ if rockspec then
+ local _, missing = deps.match_deps(rockspec, blacklist, deps_mode)
+ if missing[name] then
+ table.insert(dependents, { name = rock_name, version = rock_version })
+ end
+ end
+ end
+ end
+ return dependents
+end
+
+--- Delete given versions of a program.
+-- @param name string: the name of a program
+-- @param versions array of string: the versions to be deleted.
+-- @return boolean or (nil, string): true on success or nil and an error message.
+local function delete_versions(name, versions)
+
+ for version, _ in pairs(versions) do
+ util.printout("Removing "..name.." "..version.."...")
+ local ok, err = repos.delete_version(name, version)
+ if not ok then return nil, err end
+ end
+
+ return true
+end
+
+--- Driver function for the "remove" command.
+-- @param name string: name of a rock. If a version is given, refer to
+-- a specific version; otherwise, try to remove all versions.
+-- @param version string: When passing a package name, a version number
+-- may also be given.
+-- @return boolean or (nil, string): True if removal was
+-- successful, nil and an error message otherwise.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+
+ if type(name) ~= "string" then
+ return nil, "Argument missing, see help."
+ end
+
+ local deps_mode = flags["deps-mode"] or cfg.deps_mode
+
+ local ok, err = fs.check_command_permissions(flags)
+ if not ok then return nil, err end
+
+ local results = {}
+ search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
+
+ local versions = results[name]
+ if not versions then
+ return nil, "Could not find rock '"..name..(version and " "..version or "").."' in local tree."
+ else
+ local version = next(versions)
+ local second = next(versions, version)
+
+ util.printout("Checking stability of dependencies on the absence of")
+ util.printout(name.." "..table.concat(util.keys(versions), ", ").."...")
+ util.printout()
+
+ local dependents = check_dependents(name, versions, deps_mode)
+
+ if #dependents == 0 or flags["force"] then
+ if #dependents > 0 then
+ util.printerr("The following packages may be broken by this forced removal:")
+ for _, dependent in ipairs(dependents) do
+ util.printerr(dependent.name.." "..dependent.version)
+ end
+ util.printerr()
+ end
+ local ok, err = delete_versions(name, versions)
+ if not ok then return nil, err end
+ ok, err = manif.make_manifest(cfg.rocks_dir, deps_mode)
+ if not ok then return nil, err end
+ else
+ if not second then
+ util.printerr("Will not remove "..name.." "..version..".")
+ util.printerr("Removing it would break dependencies for: ")
+ else
+ util.printerr("Will not remove all versions of "..name..".")
+ util.printerr("Removing them would break dependencies for: ")
+ end
+ for _, dependent in ipairs(dependents) do
+ util.printerr(dependent.name.." "..dependent.version)
+ end
+ util.printerr()
+ util.printerr("Use --force to force removal (warning: this may break modules).")
+ return nil, "Failed removing."
+ end
+ end
+ util.printout("Removal successful.")
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/repos.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/repos.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,303 @@
+
+--- Functions for managing the repository on disk.
+module("luarocks.repos", package.seeall)
+
+local fs = require("luarocks.fs")
+local path = require("luarocks.path")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local dir = require("luarocks.dir")
+local manif = require("luarocks.manif")
+local deps = require("luarocks.deps")
+
+--- Get all installed versions of a package.
+-- @param name string: a package name.
+-- @return table or nil: An array of strings listing installed
+-- versions of a package, or nil if none is available.
+local function get_installed_versions(name)
+ assert(type(name) == "string")
+
+ local dirs = fs.list_dir(path.versions_dir(name))
+ return (dirs and #dirs > 0) and dirs or nil
+end
+
+--- Check if a package exists in a local repository.
+-- Version numbers are compared as exact string comparison.
+-- @param name string: name of package
+-- @param version string: package version in string format
+-- @return boolean: true if a package is installed,
+-- false otherwise.
+function is_installed(name, version)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ return fs.is_dir(path.install_dir(name, version))
+end
+
+local function recurse_rock_manifest_tree(file_tree, action)
+ assert(type(file_tree) == "table")
+ assert(type(action) == "function")
+ local function do_recurse_rock_manifest_tree(tree, parent_path, parent_module)
+
+ for file, sub in pairs(tree) do
+ if type(sub) == "table" then
+ local ok, err = do_recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".")
+ if not ok then return nil, err end
+ else
+ local ok, err = action(parent_path, parent_module, file)
+ if not ok then return nil, err end
+ end
+ end
+ return true
+ end
+ return do_recurse_rock_manifest_tree(file_tree, "", "")
+end
+
+local function store_package_data(result, name, file_tree)
+ if not file_tree then return end
+ return recurse_rock_manifest_tree(file_tree,
+ function(parent_path, parent_module, file)
+ local pathname = parent_path..file
+ result[path.path_to_module(pathname)] = pathname
+ return true
+ end
+ )
+end
+
+--- Obtain a list of modules within an installed package.
+-- @param package string: The package name; for example "luasocket"
+-- @param version string: The exact version number including revision;
+-- for example "2.0.1-1".
+-- @return table: A table of modules where keys are module identifiers
+-- in "foo.bar" format and values are pathnames in architecture-dependent
+-- "foo/bar.so" format. If no modules are found or if package or version
+-- are invalid, an empty table is returned.
+function package_modules(package, version)
+ assert(type(package) == "string")
+ assert(type(version) == "string")
+
+ local result = {}
+ local rock_manifest = manif.load_rock_manifest(package, version)
+ store_package_data(result, package, rock_manifest.lib)
+ store_package_data(result, package, rock_manifest.lua)
+ return result
+end
+
+--- Obtain a list of command-line scripts within an installed package.
+-- @param package string: The package name; for example "luasocket"
+-- @param version string: The exact version number including revision;
+-- for example "2.0.1-1".
+-- @return table: A table of items where keys are command names
+-- as strings and values are pathnames in architecture-dependent
+-- ".../bin/foo" format. If no modules are found or if package or version
+-- are invalid, an empty table is returned.
+function package_commands(package, version)
+ assert(type(package) == "string")
+ assert(type(version) == "string")
+
+ local result = {}
+ local rock_manifest = manif.load_rock_manifest(package, version)
+ store_package_data(result, package, rock_manifest.bin)
+ return result
+end
+
+
+--- Check if a rock contains binary executables.
+-- @param name string: name of an installed rock
+-- @param version string: version of an installed rock
+-- @return boolean: returns true if rock contains platform-specific
+-- binary executables, or false if it is a pure-Lua rock.
+function has_binaries(name, version)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ local rock_manifest = manif.load_rock_manifest(name, version)
+ if rock_manifest.bin then
+ for name, md5 in pairs(rock_manifest.bin) do
+ -- TODO verify that it is the same file. If it isn't, find the actual command.
+ if fs.is_actual_binary(dir.path(cfg.deploy_bin_dir, name)) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function run_hook(rockspec, hook_name)
+ assert(type(rockspec) == "table")
+ assert(type(hook_name) == "string")
+
+ local hooks = rockspec.hooks
+ if not hooks then
+ return true
+ end
+ if not hooks.substituted_variables then
+ util.variable_substitutions(hooks, rockspec.variables)
+ hooks.substituted_variables = true
+ end
+ local hook = hooks[hook_name]
+ if hook then
+ util.printout(hook)
+ if not fs.execute(hook) then
+ return nil, "Failed running "..hook_name.." hook."
+ end
+ end
+ return true
+end
+
+local function install_binary(source, target)
+ assert(type(source) == "string")
+ assert(type(target) == "string")
+
+ local match = source:match("%.lua$")
+ local file, ok, err
+ if not match then
+ file = io.open(source)
+ end
+ if match or (file and file:read():match("^#!.*lua.*")) then
+ ok, err = fs.wrap_script(source, target)
+ else
+ ok, err = fs.copy_binary(source, target)
+ end
+ if file then file:close() end
+ return ok, err
+end
+
+local function resolve_conflict(target, deploy_dir, name, version)
+ local cname, cversion = manif.find_current_provider(target)
+ if not cname then
+ return nil, cversion
+ end
+ if name ~= cname or deps.compare_versions(version, cversion) then
+ local versioned = path.versioned_name(target, deploy_dir, cname, cversion)
+ fs.make_dir(dir.dir_name(versioned))
+ fs.move(target, versioned)
+ return target
+ else
+ return path.versioned_name(target, deploy_dir, name, version)
+ end
+end
+
+function should_wrap_bin_scripts(rockspec)
+ assert(type(rockspec) == "table")
+
+ if cfg.wrap_bin_scripts ~= nil then
+ return cfg.wrap_bin_scripts
+ end
+ if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
+ return false
+ end
+ return true
+end
+
+function deploy_files(name, version, wrap_bin_scripts)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ assert(type(wrap_bin_scripts) == "boolean")
+
+ local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn)
+ if not move_fn then
+ move_fn = fs.move
+ end
+ return recurse_rock_manifest_tree(file_tree,
+ function(parent_path, parent_module, file)
+ local source = dir.path(source_dir, parent_path, file)
+ local target = dir.path(deploy_dir, parent_path, file)
+ local ok, err
+ if fs.exists(target) then
+ local new_target, err = resolve_conflict(target, deploy_dir, name, version)
+ if err == "untracked" then
+ fs.delete(target)
+ elseif err then
+ return nil, err.." Cannot install new version."
+ else
+ target = new_target
+ end
+ end
+ fs.make_dir(dir.dir_name(target))
+ ok, err = move_fn(source, target)
+ fs.remove_dir_tree_if_empty(dir.dir_name(source))
+ if not ok then return nil, err end
+ return true
+ end
+ )
+ end
+
+ local rock_manifest = manif.load_rock_manifest(name, version)
+
+ local ok, err = true
+ if rock_manifest.bin then
+ local move_bin_fn = wrap_bin_scripts and install_binary or fs.copy_binary
+ ok, err = deploy_file_tree(rock_manifest.bin, path.bin_dir(name, version), cfg.deploy_bin_dir, move_bin_fn)
+ end
+ if ok and rock_manifest.lua then
+ ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir)
+ end
+ if ok and rock_manifest.lib then
+ ok, err = deploy_file_tree(rock_manifest.lib, path.lib_dir(name, version), cfg.deploy_lib_dir)
+ end
+ return ok, err
+end
+
+--- Delete a package from the local repository.
+-- Version numbers are compared as exact string comparison.
+-- @param name string: name of package
+-- @param version string: package version in string format
+-- @param quick boolean: do not try to fix the versioned name
+-- of another version that provides the same module that
+-- was deleted. This is used during 'purge', as every module
+-- will be eventually deleted.
+function delete_version(name, version, quick)
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+
+ local function delete_deployed_file_tree(file_tree, deploy_dir)
+ return recurse_rock_manifest_tree(file_tree,
+ function(parent_path, parent_module, file)
+ local target = dir.path(deploy_dir, parent_path, file)
+ local versioned = path.versioned_name(target, deploy_dir, name, version)
+ if fs.exists(versioned) then
+ local ok = fs.delete(versioned)
+ fs.remove_dir_tree_if_empty(dir.dir_name(versioned))
+ if not ok then return nil, "Failed deleting "..versioned end
+ else
+ local ok = fs.delete(target)
+ if not quick then
+ local next_name, next_version = manif.find_next_provider(target)
+ if next_name then
+ local versioned = path.versioned_name(target, deploy_dir, next_name, next_version)
+ fs.move(versioned, target)
+ fs.remove_dir_tree_if_empty(dir.dir_name(versioned))
+ end
+ end
+ fs.remove_dir_tree_if_empty(dir.dir_name(target))
+ if not ok then return nil, "Failed deleting "..target end
+ end
+ return true
+ end
+ )
+ end
+
+ local rock_manifest = manif.load_rock_manifest(name, version)
+ if not rock_manifest then
+ return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
+ end
+
+ local ok, err = true
+ if rock_manifest.bin then
+ ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir)
+ end
+ if ok and rock_manifest.lua then
+ ok, err = delete_deployed_file_tree(rock_manifest.lua, cfg.deploy_lua_dir)
+ end
+ if ok and rock_manifest.lib then
+ ok, err = delete_deployed_file_tree(rock_manifest.lib, cfg.deploy_lib_dir)
+ end
+ if err then return nil, err end
+
+ fs.delete(path.install_dir(name, version))
+ if not get_installed_versions(name) then
+ fs.delete(dir.path(cfg.rocks_dir, name))
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/require.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/require.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,6 @@
+--- Retained for compatibility reasons only. Use luarocks.loader instead.
+local require, pairs = require, pairs
+module("luarocks.require")
+for k,v in pairs(require("luarocks.loader")) do
+ _M[k] = v
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/search.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/search.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,386 @@
+
+--- Module implementing the LuaRocks "search" command.
+-- Queries LuaRocks servers.
+module("luarocks.search", package.seeall)
+
+local dir = require("luarocks.dir")
+local path = require("luarocks.path")
+local manif = require("luarocks.manif")
+local deps = require("luarocks.deps")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+
+help_summary = "Query the LuaRocks servers."
+help_arguments = "[--source] [--binary] { [] | --all }"
+help = [[
+--source Return only rockspecs and source rocks,
+ to be used with the "build" command.
+--binary Return only pure Lua and binary rocks (rocks that can be used
+ with the "install" command without requiring a C toolchain).
+--all List all contents of the server that are suitable to
+ this platform, do not filter by name.
+]]
+
+--- Convert the arch field of a query table to table format.
+-- @param query table: A query table.
+local function query_arch_as_table(query)
+ local format = type(query.arch)
+ if format == "table" then
+ return
+ elseif format == "nil" then
+ local accept = {}
+ accept["src"] = true
+ accept["all"] = true
+ accept["rockspec"] = true
+ accept["installed"] = true
+ accept[cfg.arch] = true
+ query.arch = accept
+ elseif format == "string" then
+ local accept = {}
+ for a in query.arch:gmatch("[%w_-]+") do
+ accept[a] = true
+ end
+ query.arch = accept
+ end
+end
+
+--- Store a search result (a rock or rockspec) in the results table.
+-- @param results table: The results table, where keys are package names and
+-- versions are tables matching version strings to an array of servers.
+-- @param name string: Package name.
+-- @param version string: Package version.
+-- @param arch string: Architecture of rock ("all", "src" or platform
+-- identifier), "rockspec" or "installed"
+-- @param repo string: Pathname of a local repository of URL of
+-- rocks server.
+local function store_result(results, name, version, arch, repo)
+ assert(type(results) == "table")
+ assert(type(name) == "string")
+ assert(type(version) == "string")
+ assert(type(arch) == "string")
+ assert(type(repo) == "string")
+
+ if not results[name] then results[name] = {} end
+ if not results[name][version] then results[name][version] = {} end
+ table.insert(results[name][version], {
+ arch = arch,
+ repo = repo
+ })
+end
+
+--- Test the name field of a query.
+-- If query has a boolean field exact_name set to false,
+-- then substring match is performed; otherwise, exact string
+-- comparison is done.
+-- @param query table: A query in dependency table format.
+-- @param name string: A package name.
+-- @return boolean: True if names match, false otherwise.
+local function match_name(query, name)
+ assert(type(query) == "table")
+ assert(type(name) == "string")
+ if query.exact_name == false then
+ return name:find(query.name, 0, true) and true or false
+ else
+ return name == query.name
+ end
+end
+
+--- Store a match in a results table if version matches query.
+-- Name, version, arch and repository path are stored in a given
+-- table, optionally checking if version and arch (if given) match
+-- a query.
+-- @param results table: The results table, where keys are package names and
+-- versions are tables matching version strings to an array of servers.
+-- @param repo string: URL or pathname of the repository.
+-- @param name string: The name of the package being tested.
+-- @param version string: The version of the package being tested.
+-- @param arch string: The arch of the package being tested.
+-- @param query table: A table describing the query in dependency
+-- format (for example, {name = "filesystem", exact_name = false,
+-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
+-- If the arch field is omitted, the local architecture (cfg.arch)
+-- is used. The special value "any" is also recognized, returning all
+-- matches regardless of architecture.
+local function store_if_match(results, repo, name, version, arch, query)
+ if match_name(query, name) then
+ if query.arch[arch] or query.arch["any"] then
+ if deps.match_constraints(deps.parse_version(version), query.constraints) then
+ store_result(results, name, version, arch, repo)
+ end
+ end
+ end
+end
+
+--- Perform search on a local repository.
+-- @param repo string: The pathname of the local repository.
+-- @param query table: A table describing the query in dependency
+-- format (for example, {name = "filesystem", exact_name = false,
+-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
+-- If the arch field is omitted, the local architecture (cfg.arch)
+-- is used. The special value "any" is also recognized, returning all
+-- matches regardless of architecture.
+-- @param results table or nil: If given, this table will store the
+-- results; if not given, a new table will be created.
+-- @param table: The results table, where keys are package names and
+-- versions are tables matching version strings to an array of servers.
+-- If a table was given in the "results" parameter, that is the result value.
+function disk_search(repo, query, results)
+ assert(type(repo) == "string")
+ assert(type(query) == "table")
+ assert(type(results) == "table" or not results)
+
+ local fs = require("luarocks.fs")
+
+ if not results then
+ results = {}
+ end
+ query_arch_as_table(query)
+
+ for _, name in pairs(fs.list_dir(repo)) do
+ local pathname = dir.path(repo, name)
+ local rname, rversion, rarch = path.parse_name(name)
+ if fs.is_dir(pathname) then
+ for _, version in pairs(fs.list_dir(pathname)) do
+ if version:match("-%d+$") then
+ store_if_match(results, repo, name, version, "installed", query)
+ end
+ end
+ elseif rname then
+ store_if_match(results, repo, rname, rversion, rarch, query)
+ end
+ end
+ return results
+end
+
+--- Perform search on a rocks server.
+-- @param results table: The results table, where keys are package names and
+-- versions are tables matching version strings to an array of servers.
+-- @param repo string: The URL of the rocks server.
+-- @param query table: A table describing the query in dependency
+-- format (for example, {name = "filesystem", exact_name = false,
+-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
+-- If the arch field is omitted, the local architecture (cfg.arch)
+-- is used. The special value "any" is also recognized, returning all
+-- matches regardless of architecture.
+-- @return true or, in case of errors, nil and an error message.
+function manifest_search(results, repo, query)
+ assert(type(results) == "table")
+ assert(type(repo) == "string")
+ assert(type(query) == "table")
+
+ query_arch_as_table(query)
+ local manifest, err = manif.load_manifest(repo)
+ if not manifest then
+ return nil, "Failed loading manifest: "..err
+ end
+ for name, versions in pairs(manifest.repository) do
+ for version, items in pairs(versions) do
+ for _, item in ipairs(items) do
+ store_if_match(results, repo, name, version, item.arch, query)
+ end
+ end
+ end
+ return true
+end
+
+--- Search on all configured rocks servers.
+-- @param query table: A dependency query.
+-- @return table: A table where keys are package names
+-- and values are tables matching version strings to an array of
+-- rocks servers; if no results are found, an empty table is returned.
+function search_repos(query)
+ assert(type(query) == "table")
+
+ local results = {}
+ for _, repo in ipairs(cfg.rocks_servers) do
+ if type(repo) == "string" then
+ repo = { repo }
+ end
+ for _, mirror in ipairs(repo) do
+ local protocol, pathname = dir.split_url(mirror)
+ if protocol == "file" then
+ mirror = pathname
+ end
+ local ok, err = manifest_search(results, mirror, query)
+ if ok then
+ break
+ else
+ util.warning("Failed searching manifest: "..err)
+ end
+ end
+ end
+ return results
+end
+
+--- Prepare a query in dependency table format.
+-- @param name string: The query name.
+-- @param version string or nil:
+-- @return table: A query in table format
+function make_query(name, version)
+ assert(type(name) == "string")
+ assert(type(version) == "string" or not version)
+
+ local query = {
+ name = name,
+ constraints = {}
+ }
+ if version then
+ table.insert(query.constraints, { op = "==", version = deps.parse_version(version)})
+ end
+ return query
+end
+
+--- Get the URL for the latest in a set of versions.
+-- @param name string: The package name to be used in the URL.
+-- @param versions table: An array of version informations, as stored
+-- in search results tables.
+-- @return string or nil: the URL for the latest version if one could
+-- be picked, or nil.
+local function pick_latest_version(name, versions)
+ assert(type(name) == "string")
+ assert(type(versions) == "table")
+
+ local vtables = {}
+ for v, _ in pairs(versions) do
+ table.insert(vtables, deps.parse_version(v))
+ end
+ table.sort(vtables)
+ local version = vtables[#vtables].string
+ local items = versions[version]
+ if items then
+ local pick = 1
+ for i, item in ipairs(items) do
+ if (item.arch == 'src' and items[pick].arch == 'rockspec')
+ or (item.arch ~= 'src' and item.arch ~= 'rockspec') then
+ pick = i
+ end
+ end
+ return path.make_url(items[pick].repo, name, version, items[pick].arch)
+ end
+ return nil
+end
+
+--- Attempt to get a single URL for a given search.
+-- @param query table: A dependency query.
+-- @return string or table or (nil, string): URL for matching rock if
+-- a single one was found, a table of candidates if it could not narrow to
+-- a single result, or nil followed by an error message.
+function find_suitable_rock(query)
+ assert(type(query) == "table")
+
+ local results = search_repos(query)
+ local first = next(results)
+ if not first then
+ return nil, "No results matching query were found."
+ elseif not next(results, first) then
+ return pick_latest_version(query.name, results[first])
+ else
+ return results
+ end
+end
+
+--- Print a list of rocks/rockspecs on standard output.
+-- @param results table: A table where keys are package names and versions
+-- are tables matching version strings to an array of rocks servers.
+-- @param porcelain boolean or nil: A flag to force machine-friendly output.
+function print_results(results, porcelain)
+ assert(type(results) == "table")
+ assert(type(porcelain) == "boolean" or not porcelain)
+
+ for package, versions in util.sortedpairs(results) do
+ if not porcelain then
+ util.printout(package)
+ end
+ for version, repos in util.sortedpairs(versions, deps.compare_versions) do
+ for _, repo in ipairs(repos) do
+ if porcelain then
+ util.printout(package, version, repo.arch, repo.repo)
+ else
+ util.printout(" "..version.." ("..repo.arch..") - "..repo.repo)
+ end
+ end
+ end
+ if not porcelain then
+ util.printout()
+ end
+ end
+end
+
+--- Splits a list of search results into two lists, one for "source" results
+-- to be used with the "build" command, and one for "binary" results to be
+-- used with the "install" command.
+-- @param results table: A search results table.
+-- @return (table, table): Two tables, one for source and one for binary
+-- results.
+local function split_source_and_binary_results(results)
+ local sources, binaries = {}, {}
+ for name, versions in pairs(results) do
+ for version, repositories in pairs(versions) do
+ for _, repo in ipairs(repositories) do
+ local where = sources
+ if repo.arch == "all" or repo.arch == cfg.arch then
+ where = binaries
+ end
+ store_result(where, name, version, repo.arch, repo.repo)
+ end
+ end
+ end
+ return sources, binaries
+end
+
+--- Given a name and optionally a version, try to find in the rocks
+-- servers a single .src.rock or .rockspec file that satisfies
+-- the request, and run the given function on it; or display to the
+-- user possibilities if it couldn't narrow down a single match.
+-- @param action function: A function that takes a .src.rock or
+-- .rockspec URL as a parameter.
+-- @param name string: A rock name
+-- @param version string or nil: A version number may also be given.
+-- @return The result of the action function, or nil and an error message.
+function act_on_src_or_rockspec(action, name, version, ...)
+ assert(type(action) == "function")
+ assert(type(name) == "string")
+ assert(type(version) == "string" or not version)
+
+ local query = make_query(name, version)
+ query.arch = "src|rockspec"
+ local results, err = find_suitable_rock(query)
+ if type(results) == "string" then
+ return action(results, ...)
+ else
+ return nil, "Could not find a result named "..name..(version and " "..version or "").."."
+ end
+end
+
+--- Driver function for "search" command.
+-- @param name string: A substring of a rock name to search.
+-- @param version string or nil: a version may also be passed.
+-- @return boolean or (nil, string): True if build was successful; nil and an
+-- error message otherwise.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+
+ if flags["all"] then
+ name, version = "", nil
+ end
+
+ if type(name) ~= "string" and not flags["all"] then
+ return nil, "Enter name and version or use --all; see help."
+ end
+
+ local query = make_query(name:lower(), version)
+ query.exact_name = false
+ local results, err = search_repos(query)
+ local porcelain = flags["porcelain"]
+ util.title("Search results:", porcelain, "=")
+ local sources, binaries = split_source_and_binary_results(results)
+ if next(sources) and not flags["binary"] then
+ util.title("Rockspecs and source rocks:", porcelain)
+ print_results(sources, porcelain)
+ end
+ if next(binaries) and not flags["source"] then
+ util.title("Binary and pure-Lua rocks:", porcelain)
+ print_results(binaries, porcelain)
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/show.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/show.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,156 @@
+
+--- Module implementing the LuaRocks "show" command.
+-- Shows information about an installed rock.
+module("luarocks.show", package.seeall)
+
+local search = require("luarocks.search")
+local cfg = require("luarocks.cfg")
+local util = require("luarocks.util")
+local path = require("luarocks.path")
+local dir = require("luarocks.dir")
+local deps = require("luarocks.deps")
+local fetch = require("luarocks.fetch")
+local manif = require("luarocks.manif")
+help_summary = "Shows information about an installed rock."
+
+help = [[
+ is an existing package name.
+Without any flags, show all module information.
+With these flags, return only the desired information:
+
+--home home page of project
+--modules all modules provided by this package as used by require()
+--deps packages this package depends on
+--rockspec the full path of the rockspec file
+--mversion the package version
+--rock-tree local tree where rock is installed
+--rock-dir data directory of the installed rock
+]]
+
+local function keys_as_string(t, sep)
+ return table.concat(util.keys(t), sep or " ")
+end
+
+local function word_wrap(line)
+ local width = tonumber(os.getenv("COLUMNS")) or 80
+ if width > 80 then width = 80 end
+ if #line > width then
+ local brk = width
+ while brk > 0 and line:sub(brk, brk) ~= " " do
+ brk = brk - 1
+ end
+ if brk > 0 then
+ return line:sub(1, brk-1) .. "\n" .. word_wrap(line:sub(brk+1))
+ end
+ end
+ return line
+end
+
+local function format_text(text)
+ text = text:gsub("^%s*",""):gsub("%s$", ""):gsub("\n[ \t]+","\n"):gsub("([^\n])\n([^\n])","%1 %2")
+ local paragraphs = util.split_string(text, "\n\n")
+ for n, line in ipairs(paragraphs) do
+ paragraphs[n] = word_wrap(line)
+ end
+ return (table.concat(paragraphs, "\n\n"):gsub("%s$", ""))
+end
+
+local function module_name(mod, filename, name, version, repo, manifest)
+ local base_dir
+ if filename:match("%.lua$") then
+ base_dir = path.deploy_lua_dir(repo)
+ else
+ base_dir = path.deploy_lib_dir(repo)
+ end
+
+ return dir.path(base_dir, filename)
+end
+
+--- Driver function for "show" command.
+-- @param name or nil: an existing package name.
+-- @param version string or nil: a version may also be passed.
+-- @return boolean: True if succeeded, nil on errors.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+ if not name then
+ return nil, "Argument missing, see help."
+ end
+ local results = {}
+ local query = search.make_query(name, version)
+ query.exact_name = true
+ local tree_map = {}
+ local trees = cfg.rocks_trees
+ if flags["tree"] then
+ trees = { flags["tree"] }
+ end
+ for _, tree in ipairs(trees) do
+ local rocks_dir = path.rocks_dir(tree)
+ tree_map[rocks_dir] = tree
+ search.manifest_search(results, rocks_dir, query)
+ end
+
+ if not next(results) then --
+ return nil,"cannot find package "..name.." "..(version or "").."\nUse 'list' to find installed rocks."
+ end
+
+ version = nil
+ local repo_url
+ local package, versions = util.sortedpairs(results)()
+ --question: what do we do about multiple versions? This should
+ --give us the latest version on the last repo (which is usually the global one)
+ for vs, repositories in util.sortedpairs(versions, deps.compare_versions) do
+ if not version then version = vs end
+ for _, rp in ipairs(repositories) do repo_url = rp.repo end
+ end
+
+
+ local repo = tree_map[repo_url]
+ local directory = path.install_dir(name,version,repo)
+ local rockspec_file = path.rockspec_file(name, version, repo)
+ local rockspec, err = fetch.load_local_rockspec(rockspec_file)
+ if not rockspec then return nil,err end
+
+ local descript = rockspec.description or {}
+ local manifest, err = manif.load_manifest(repo_url)
+ if not manifest then return nil,err end
+ local minfo = manifest.repository[name][version][1]
+
+ if flags["rock-tree"] then util.printout(repo)
+ elseif flags["rock-dir"] then util.printout(directory)
+ elseif flags["home"] then util.printout(descript.homepage)
+ elseif flags["modules"] then util.printout(keys_as_string(minfo.modules))
+ elseif flags["deps"] then util.printout(keys_as_string(minfo.dependencies))
+ elseif flags["rockspec"] then util.printout(rockspec_file)
+ elseif flags["mversion"] then util.printout(version)
+ else
+ util.printout()
+ util.printout(rockspec.package.." "..rockspec.version.." - "..(descript.summary or ""))
+ util.printout()
+ if descript.detailed then
+ util.printout(format_text(descript.detailed))
+ util.printout()
+ end
+ if descript.license then
+ util.printout("License: ", descript.license)
+ end
+ if descript.homepage then
+ util.printout("Homepage: ", descript.homepage)
+ end
+ util.printout("Installed in: ", repo)
+ if next(minfo.modules) then
+ util.printout()
+ util.printout("Modules:")
+ for mod, filename in util.sortedpairs(minfo.modules) do
+ util.printout("\t"..mod.." ("..path.which(mod, filename, name, version, repo, manifest)..")")
+ end
+ end
+ if next(minfo.dependencies) then
+ util.printout()
+ util.printout("Depends on:")
+ util.printout("\t"..keys_as_string(minfo.dependencies, "\n\t"))
+ end
+ util.printout()
+ end
+ return true
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/tools/patch.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/tools/patch.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,712 @@
+--- Patch utility to apply unified diffs.
+--
+-- http://lua-users.org/wiki/LuaPatch
+--
+-- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license).
+-- Code is heavilly based on the Python-based patch.py version 8.06-1
+-- Copyright (c) 2008 rainforce.org, MIT License
+-- Project home: http://code.google.com/p/python-patch/ .
+
+module("luarocks.tools.patch", package.seeall)
+
+local fs = require("luarocks.fs")
+
+local version = '0.1'
+
+local io = io
+local os = os
+local string = string
+local table = table
+local format = string.format
+
+-- logging
+local debugmode = false
+local function debug(s) end
+local function info(s) end
+local function warning(s) io.stderr:write(s .. '\n') end
+
+-- Returns boolean whether string s2 starts with string s.
+local function startswith(s, s2)
+ return s:sub(1, #s2) == s2
+end
+
+-- Returns boolean whether string s2 ends with string s.
+local function endswith(s, s2)
+ return #s >= #s2 and s:sub(#s-#s2+1) == s2
+end
+
+-- Returns string s after filtering out any new-line characters from end.
+local function endlstrip(s)
+ return s:gsub('[\r\n]+$', '')
+end
+
+-- Returns shallow copy of table t.
+local function table_copy(t)
+ local t2 = {}
+ for k,v in pairs(t) do t2[k] = v end
+ return t2
+end
+
+-- Returns boolean whether array t contains value v.
+local function array_contains(t, v)
+ for _,v2 in ipairs(t) do if v == v2 then return true end end
+ return false
+end
+
+local function exists(filename)
+ local fh = io.open(filename)
+ local result = fh ~= nil
+ if fh then fh:close() end
+ return result
+end
+local function isfile() return true end --FIX?
+
+local function read_file(filename)
+ local fh, err, oserr = io.open(filename, 'rb')
+ if not fh then return fh, err, oserr end
+ local data, err, oserr = fh:read'*a'
+ fh:close()
+ if not data then return nil, err, oserr end
+ return data
+end
+
+local function write_file(filename, data)
+ local fh, err, oserr = io.open(filename 'wb')
+ if not fh then return fh, err, oserr end
+ local status, err, oserr = fh:write(data)
+ fh:close()
+ if not status then return nil, err, oserr end
+ return true
+end
+
+local function file_copy(src, dest)
+ local data, err, oserr = read_file(src)
+ if not data then return data, err, oserr end
+ local status, err, oserr = write_file(dest)
+ if not status then return status, err, oserr end
+ return true
+end
+
+local function string_as_file(s)
+ return {
+ at = 0,
+ str = s,
+ len = #s,
+ eof = false,
+ read = function(self, n)
+ if self.eof then return nil end
+ local chunk = self.str:sub(self.at, self.at+n)
+ self.at = self.at + n
+ if self.at > self.len then
+ self.eof = true
+ end
+ return chunk
+ end,
+ close = function(self)
+ self.eof = true
+ end,
+ }
+end
+
+--
+-- file_lines(f) is similar to f:lines() for file f.
+-- The main difference is that read_lines includes
+-- new-line character sequences ("\n", "\r\n", "\r"),
+-- if any, at the end of each line. Embedded "\0" are also handled.
+-- Caution: The newline behavior can depend on whether f is opened
+-- in binary or ASCII mode.
+-- (file_lines - version 20080913)
+--
+local function file_lines(f)
+ local CHUNK_SIZE = 1024
+ local buffer = ""
+ local pos_beg = 1
+ return function()
+ local pos, chars
+ while 1 do
+ pos, chars = buffer:match('()([\r\n].)', pos_beg)
+ if pos or not f then
+ break
+ elseif f then
+ local chunk = f:read(CHUNK_SIZE)
+ if chunk then
+ buffer = buffer:sub(pos_beg) .. chunk
+ pos_beg = 1
+ else
+ f = nil
+ end
+ end
+ end
+ if not pos then
+ pos = #buffer
+ elseif chars == '\r\n' then
+ pos = pos + 1
+ end
+ local line = buffer:sub(pos_beg, pos)
+ pos_beg = pos + 1
+ if #line > 0 then
+ return line
+ end
+ end
+end
+
+local function match_linerange(line)
+ local m1, m2, m3, m4 = line:match("^@@ %-(%d+),(%d+) %+(%d+),(%d+)")
+ if not m1 then m1, m3, m4 = line:match("^@@ %-(%d+) %+(%d+),(%d+)") end
+ if not m1 then m1, m2, m3 = line:match("^@@ %-(%d+),(%d+) %+(%d+)") end
+ if not m1 then m1, m3 = line:match("^@@ %-(%d+) %+(%d+)") end
+ return m1, m2, m3, m4
+end
+
+function read_patch(filename, data)
+ -- define possible file regions that will direct the parser flow
+ local state = 'header'
+ -- 'header' - comments before the patch body
+ -- 'filenames' - lines starting with --- and +++
+ -- 'hunkhead' - @@ -R +R @@ sequence
+ -- 'hunkbody'
+ -- 'hunkskip' - skipping invalid hunk mode
+
+ local all_ok = true
+ local lineends = {lf=0, crlf=0, cr=0}
+ local files = {source={}, target={}, hunks={}, fileends={}, hunkends={}}
+ local nextfileno = 0
+ local nexthunkno = 0 --: even if index starts with 0 user messages
+ -- number hunks from 1
+
+ -- hunkinfo holds parsed values, hunkactual - calculated
+ local hunkinfo = {
+ startsrc=nil, linessrc=nil, starttgt=nil, linestgt=nil,
+ invalid=false, text={}
+ }
+ local hunkactual = {linessrc=nil, linestgt=nil}
+
+ info(format("reading patch %s", filename))
+
+ local fp
+ if data then
+ fp = string_as_file(data)
+ else
+ fp = filename == '-' and io.stdin or assert(io.open(filename, "rb"))
+ end
+ local lineno = 0
+
+ for line in file_lines(fp) do
+ lineno = lineno + 1
+ if state == 'header' then
+ if startswith(line, "--- ") then
+ state = 'filenames'
+ end
+ -- state is 'header' or 'filenames'
+ end
+ if state == 'hunkbody' then
+ -- skip hunkskip and hunkbody code until definition of hunkhead read
+
+ -- process line first
+ if line:match"^[- +\\]" or line:match"^[\r\n]*$" then
+ -- gather stats about line endings
+ local he = files.hunkends[nextfileno]
+ if endswith(line, "\r\n") then
+ he.crlf = he.crlf + 1
+ elseif endswith(line, "\n") then
+ he.lf = he.lf + 1
+ elseif endswith(line, "\r") then
+ he.cr = he.cr + 1
+ end
+ if startswith(line, "-") then
+ hunkactual.linessrc = hunkactual.linessrc + 1
+ elseif startswith(line, "+") then
+ hunkactual.linestgt = hunkactual.linestgt + 1
+ elseif startswith(line, "\\") then
+ -- nothing
+ else
+ hunkactual.linessrc = hunkactual.linessrc + 1
+ hunkactual.linestgt = hunkactual.linestgt + 1
+ end
+ table.insert(hunkinfo.text, line)
+ -- todo: handle \ No newline cases
+ else
+ warning(format("invalid hunk no.%d at %d for target file %s",
+ nexthunkno, lineno, files.target[nextfileno]))
+ -- add hunk status node
+ table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
+ files.hunks[nextfileno][nexthunkno].invalid = true
+ all_ok = false
+ state = 'hunkskip'
+ end
+
+ -- check exit conditions
+ if hunkactual.linessrc > hunkinfo.linessrc or
+ hunkactual.linestgt > hunkinfo.linestgt
+ then
+ warning(format("extra hunk no.%d lines at %d for target %s",
+ nexthunkno, lineno, files.target[nextfileno]))
+ -- add hunk status node
+ table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
+ files.hunks[nextfileno][nexthunkno].invalid = true
+ state = 'hunkskip'
+ elseif hunkinfo.linessrc == hunkactual.linessrc and
+ hunkinfo.linestgt == hunkactual.linestgt
+ then
+ table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
+ state = 'hunkskip'
+
+ -- detect mixed window/unix line ends
+ local ends = files.hunkends[nextfileno]
+ if (ends.cr~=0 and 1 or 0) + (ends.crlf~=0 and 1 or 0) +
+ (ends.lf~=0 and 1 or 0) > 1
+ then
+ warning(format("inconsistent line ends in patch hunks for %s",
+ files.source[nextfileno]))
+ end
+ if debugmode then
+ local debuglines = {crlf=ends.crlf, lf=ends.lf, cr=ends.cr,
+ file=files.target[nextfileno], hunk=nexthunkno}
+ debug(format("crlf: %(crlf)d lf: %(lf)d cr: %(cr)d\t " ..
+ "- file: %(file)s hunk: %(hunk)d", debuglines))
+ end
+ end
+ -- state is 'hunkbody' or 'hunkskip'
+ end
+
+ if state == 'hunkskip' then
+ if match_linerange(line) then
+ state = 'hunkhead'
+ elseif startswith(line, "--- ") then
+ state = 'filenames'
+ if debugmode and #files.source > 0 then
+ debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
+ files.source[nextfileno]))
+ end
+ end
+ -- state is 'hunkskip', 'hunkhead', or 'filenames'
+ end
+ local advance
+ if state == 'filenames' then
+ if startswith(line, "--- ") then
+ if array_contains(files.source, nextfileno) then
+ all_ok = false
+ warning(format("skipping invalid patch for %s",
+ files.source[nextfileno+1]))
+ table.remove(files.source, nextfileno+1)
+ -- double source filename line is encountered
+ -- attempt to restart from this second line
+ end
+ -- Accept a space as a terminator, like GNU patch does.
+ -- Breaks patches containing filenames with spaces...
+ -- FIXME Figure out what does GNU patch do in those cases.
+ local match = line:match("^--- ([^\t ]+)")
+ if not match then
+ all_ok = false
+ warning(format("skipping invalid filename at line %d", lineno+1))
+ state = 'header'
+ else
+ table.insert(files.source, match)
+ end
+ elseif not startswith(line, "+++ ") then
+ if array_contains(files.source, nextfileno) then
+ all_ok = false
+ warning(format("skipping invalid patch with no target for %s",
+ files.source[nextfileno+1]))
+ table.remove(files.source, nextfileno+1)
+ else
+ -- this should be unreachable
+ warning("skipping invalid target patch")
+ end
+ state = 'header'
+ else
+ if array_contains(files.target, nextfileno) then
+ all_ok = false
+ warning(format("skipping invalid patch - double target at line %d",
+ lineno+1))
+ table.remove(files.source, nextfileno+1)
+ table.remove(files.target, nextfileno+1)
+ nextfileno = nextfileno - 1
+ -- double target filename line is encountered
+ -- switch back to header state
+ state = 'header'
+ else
+ -- Accept a space as a terminator, like GNU patch does.
+ -- Breaks patches containing filenames with spaces...
+ -- FIXME Figure out what does GNU patch do in those cases.
+ local re_filename = "^%+%+%+ ([^ \t]+)"
+ local match = line:match(re_filename)
+ if not match then
+ all_ok = false
+ warning(format(
+ "skipping invalid patch - no target filename at line %d",
+ lineno+1))
+ state = 'header'
+ else
+ table.insert(files.target, match)
+ nextfileno = nextfileno + 1
+ nexthunkno = 0
+ table.insert(files.hunks, {})
+ table.insert(files.hunkends, table_copy(lineends))
+ table.insert(files.fileends, table_copy(lineends))
+ state = 'hunkhead'
+ advance = true
+ end
+ end
+ end
+ -- state is 'filenames', 'header', or ('hunkhead' with advance)
+ end
+ if not advance and state == 'hunkhead' then
+ local m1, m2, m3, m4 = match_linerange(line)
+ if not m1 then
+ if not array_contains(files.hunks, nextfileno-1) then
+ all_ok = false
+ warning(format("skipping invalid patch with no hunks for file %s",
+ files.target[nextfileno]))
+ end
+ state = 'header'
+ else
+ hunkinfo.startsrc = tonumber(m1)
+ hunkinfo.linessrc = tonumber(m2 or 1)
+ hunkinfo.starttgt = tonumber(m3)
+ hunkinfo.linestgt = tonumber(m4 or 1)
+ hunkinfo.invalid = false
+ hunkinfo.text = {}
+
+ hunkactual.linessrc = 0
+ hunkactual.linestgt = 0
+
+ state = 'hunkbody'
+ nexthunkno = nexthunkno + 1
+ end
+ -- state is 'header' or 'hunkbody'
+ end
+ end
+ if state ~= 'hunkskip' then
+ warning(format("patch file incomplete - %s", filename))
+ all_ok = false
+ -- os.exit(?)
+ else
+ -- duplicated message when an eof is reached
+ if debugmode and #files.source > 0 then
+ debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
+ files.source[nextfileno]))
+ end
+ end
+
+ local sum = 0; for _,hset in ipairs(files.hunks) do sum = sum + #hset end
+ info(format("total files: %d total hunks: %d", #files.source, sum))
+ fp:close()
+ return files, all_ok
+end
+
+local function find_hunk(file, h, hno)
+ for fuzz=0,2 do
+ local lineno = h.startsrc
+ for i=0,#file do
+ local found = true
+ local location = lineno
+ local total = #h.text - fuzz
+ for l, hline in ipairs(h.text) do
+ if l > fuzz then
+ -- todo: \ No newline at the end of file
+ if startswith(hline, " ") or startswith(hline, "-") then
+ local line = file[lineno]
+ lineno = lineno + 1
+ if not line or #line == 0 then
+ found = false
+ break
+ end
+ if endlstrip(line) ~= endlstrip(hline:sub(2)) then
+ found = false
+ break
+ end
+ end
+ end
+ end
+ if found then
+ local offset = location - h.startsrc - fuzz
+ if offset ~= 0 then
+ warning(format("Hunk %d found at offset %d%s...", hno, offset, fuzz == 0 and "" or format(" (fuzz %d)", fuzz)))
+ end
+ h.startsrc = location
+ h.starttgt = h.starttgt + offset
+ for i=1,fuzz do
+ table.remove(h.text, 1)
+ table.remove(h.text, #h.text)
+ end
+ return true
+ end
+ lineno = i
+ end
+ end
+ return false
+end
+
+local function load_file(filename)
+ local fp = assert(io.open(filename))
+ local file = {}
+ local readline = file_lines(fp)
+ while true do
+ local line = readline()
+ if not line then break end
+ table.insert(file, line)
+ end
+ fp:close()
+ return file
+end
+
+local function find_hunks(file, hunks)
+ local matched = true
+ local lineno = 1
+ local hno = nil
+ for hno, h in ipairs(hunks) do
+ find_hunk(file, h, hno)
+ end
+end
+
+local function check_patched(file, hunks)
+ local matched = true
+ local lineno = 1
+ local hno = nil
+ local ok, err = pcall(function()
+ if #file == 0 then
+ error 'nomatch'
+ end
+ for hno, h in ipairs(hunks) do
+ -- skip to line just before hunk starts
+ if #file < h.starttgt then
+ error 'nomatch'
+ end
+ lineno = h.starttgt
+ for _, hline in ipairs(h.text) do
+ -- todo: \ No newline at the end of file
+ if not startswith(hline, "-") and not startswith(hline, "\\") then
+ local line = file[lineno]
+ lineno = lineno + 1
+ if #line == 0 then
+ error 'nomatch'
+ end
+ if endlstrip(line) ~= endlstrip(hline:sub(2)) then
+ warning(format("file is not patched - failed hunk: %d", hno))
+ error 'nomatch'
+ end
+ end
+ end
+ end
+ end)
+ if err == 'nomatch' then
+ matched = false
+ end
+ -- todo: display failed hunk, i.e. expected/found
+
+ return matched
+end
+
+local function patch_hunks(srcname, tgtname, hunks)
+ local src = assert(io.open(srcname, "rb"))
+ local tgt = assert(io.open(tgtname, "wb"))
+
+ local src_readline = file_lines(src)
+
+ -- todo: detect linefeeds early - in apply_files routine
+ -- to handle cases when patch starts right from the first
+ -- line and no lines are processed. At the moment substituted
+ -- lineends may not be the same at the start and at the end
+ -- of patching. Also issue a warning about mixed lineends
+
+ local srclineno = 1
+ local lineends = {['\n']=0, ['\r\n']=0, ['\r']=0}
+ for hno, h in ipairs(hunks) do
+ debug(format("processing hunk %d for file %s", hno, tgtname))
+ -- skip to line just before hunk starts
+ while srclineno < h.startsrc do
+ local line = src_readline()
+ -- Python 'U' mode works only with text files
+ if endswith(line, "\r\n") then
+ lineends["\r\n"] = lineends["\r\n"] + 1
+ elseif endswith(line, "\n") then
+ lineends["\n"] = lineends["\n"] + 1
+ elseif endswith(line, "\r") then
+ lineends["\r"] = lineends["\r"] + 1
+ end
+ tgt:write(line)
+ srclineno = srclineno + 1
+ end
+
+ for _,hline in ipairs(h.text) do
+ -- todo: check \ No newline at the end of file
+ if startswith(hline, "-") or startswith(hline, "\\") then
+ src_readline()
+ srclineno = srclineno + 1
+ else
+ if not startswith(hline, "+") then
+ src_readline()
+ srclineno = srclineno + 1
+ end
+ local line2write = hline:sub(2)
+ -- detect if line ends are consistent in source file
+ local sum = 0
+ for k,v in pairs(lineends) do if v > 0 then sum=sum+1 end end
+ if sum == 1 then
+ local newline
+ for k,v in pairs(lineends) do if v ~= 0 then newline = k end end
+ tgt:write(endlstrip(line2write) .. newline)
+ else -- newlines are mixed or unknown
+ tgt:write(line2write)
+ end
+ end
+ end
+ end
+ for line in src_readline do
+ tgt:write(line)
+ end
+ tgt:close()
+ src:close()
+ return true
+end
+
+local function strip_dirs(filename, strip)
+ if strip == nil then return filename end
+ for i=1,strip do
+ filename=filename:gsub("^[^/]*/", "")
+ end
+ return filename
+end
+
+function apply_patch(patch, strip)
+ local all_ok = true
+ local total = #patch.source
+ for fileno, filename in ipairs(patch.source) do
+ filename = strip_dirs(filename, strip)
+ local continue
+ local f2patch = filename
+ if not exists(f2patch) then
+ f2patch = strip_dirs(patch.target[fileno], strip)
+ f2patch = fs.absolute_name(f2patch)
+ if not exists(f2patch) then --FIX:if f2patch nil
+ warning(format("source/target file does not exist\n--- %s\n+++ %s",
+ filename, f2patch))
+ all_ok = false
+ continue = true
+ end
+ end
+ if not continue and not isfile(f2patch) then
+ warning(format("not a file - %s", f2patch))
+ all_ok = false
+ continue = true
+ end
+ if not continue then
+
+ filename = f2patch
+
+ info(format("processing %d/%d:\t %s", fileno, total, filename))
+
+ -- validate before patching
+ local hunks = patch.hunks[fileno]
+ local file = load_file(filename)
+ local hunkno = 1
+ local hunk = hunks[hunkno]
+ local hunkfind = {}
+ local hunkreplace = {}
+ local validhunks = 0
+ local canpatch = false
+ local hunklineno
+ local isbreak
+ local lineno = 0
+
+ find_hunks(file, hunks)
+
+ for _, line in ipairs(file) do
+ lineno = lineno + 1
+ local continue
+ if not hunk or lineno < hunk.startsrc then
+ continue = true
+ elseif lineno == hunk.startsrc then
+ hunkfind = {}
+ for _,x in ipairs(hunk.text) do
+ if x:sub(1,1) == ' ' or x:sub(1,1) == '-' then
+ hunkfind[#hunkfind+1] = endlstrip(x:sub(2))
+ end end
+ hunkreplace = {}
+ for _,x in ipairs(hunk.text) do
+ if x:sub(1,1) == ' ' or x:sub(1,1) == '+' then
+ hunkreplace[#hunkreplace+1] = endlstrip(x:sub(2))
+ end end
+ --pprint(hunkreplace)
+ hunklineno = 1
+
+ -- todo \ No newline at end of file
+ end
+ -- check hunks in source file
+ if not continue and lineno < hunk.startsrc + #hunkfind - 1 then
+ if endlstrip(line) == hunkfind[hunklineno] then
+ hunklineno = hunklineno + 1
+ else
+ debug(format("hunk no.%d doesn't match source file %s",
+ hunkno, filename))
+ -- file may be already patched, but check other hunks anyway
+ hunkno = hunkno + 1
+ if hunkno <= #hunks then
+ hunk = hunks[hunkno]
+ continue = true
+ else
+ isbreak = true; break
+ end
+ end
+ end
+ -- check if processed line is the last line
+ if not continue and lineno == hunk.startsrc + #hunkfind - 1 then
+ debug(format("file %s hunk no.%d -- is ready to be patched",
+ filename, hunkno))
+ hunkno = hunkno + 1
+ validhunks = validhunks + 1
+ if hunkno <= #hunks then
+ hunk = hunks[hunkno]
+ else
+ if validhunks == #hunks then
+ -- patch file
+ canpatch = true
+ isbreak = true; break
+ end
+ end
+ end
+ end
+ if not isbreak then
+ if hunkno <= #hunks then
+ warning(format("premature end of source file %s at hunk %d",
+ filename, hunkno))
+ all_ok = false
+ end
+ end
+ if validhunks < #hunks then
+ if check_patched(file, hunks) then
+ warning(format("already patched %s", filename))
+ else
+ warning(format("source file is different - %s", filename))
+ all_ok = false
+ end
+ end
+ if canpatch then
+ local backupname = filename .. ".orig"
+ if exists(backupname) then
+ warning(format("can't backup original file to %s - aborting",
+ backupname))
+ all_ok = false
+ else
+ assert(os.rename(filename, backupname))
+ if patch_hunks(backupname, filename, hunks) then
+ warning(format("successfully patched %s", filename))
+ assert(os.remove(backupname))
+ else
+ warning(format("error patching file %s", filename))
+ assert(file_copy(filename, filename .. ".invalid"))
+ warning(format("invalid version is saved to %s",
+ filename .. ".invalid"))
+ -- todo: proper rejects
+ assert(os.rename(backupname, filename))
+ all_ok = false
+ end
+ end
+ end
+
+ end -- if not continue
+ end -- for
+ -- todo: check for premature eof
+ return all_ok
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/tools/tar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/tools/tar.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,144 @@
+
+--- A pure-Lua implementation of untar (unpacking .tar archives)
+module("luarocks.tools.tar", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+local blocksize = 512
+
+local function get_typeflag(flag)
+ if flag == "0" or flag == "\0" then return "file"
+ elseif flag == "1" then return "link"
+ elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU
+ elseif flag == "3" then return "character"
+ elseif flag == "4" then return "block"
+ elseif flag == "5" then return "directory"
+ elseif flag == "6" then return "fifo"
+ elseif flag == "7" then return "contiguous" -- "reserved" in POSIX, "contiguous" in GNU
+ elseif flag == "x" then return "next file"
+ elseif flag == "g" then return "global extended header"
+ elseif flag == "L" then return "long name"
+ elseif flag == "K" then return "long link name"
+ end
+ return "unknown"
+end
+
+local function octal_to_number(octal)
+ local exp = 0
+ local number = 0
+ for i = #octal,1,-1 do
+ local digit = tonumber(octal:sub(i,i))
+ if not digit then break end
+ number = number + (digit * 8^exp)
+ exp = exp + 1
+ end
+ return number
+end
+
+local function checksum_header(block)
+ local sum = 256
+ for i = 1,148 do
+ sum = sum + block:byte(i)
+ end
+ for i = 157,500 do
+ sum = sum + block:byte(i)
+ end
+ return sum
+end
+
+local function nullterm(s)
+ return s:match("^[^%z]*")
+end
+
+local function read_header_block(block)
+ local header = {}
+ header.name = nullterm(block:sub(1,100))
+ header.mode = nullterm(block:sub(101,108))
+ header.uid = octal_to_number(nullterm(block:sub(109,116)))
+ header.gid = octal_to_number(nullterm(block:sub(117,124)))
+ header.size = octal_to_number(nullterm(block:sub(125,136)))
+ header.mtime = octal_to_number(nullterm(block:sub(137,148)))
+ header.chksum = octal_to_number(nullterm(block:sub(149,156)))
+ header.typeflag = get_typeflag(block:sub(157,157))
+ header.linkname = nullterm(block:sub(158,257))
+ header.magic = block:sub(258,263)
+ header.version = block:sub(264,265)
+ header.uname = nullterm(block:sub(266,297))
+ header.gname = nullterm(block:sub(298,329))
+ header.devmajor = octal_to_number(nullterm(block:sub(330,337)))
+ header.devminor = octal_to_number(nullterm(block:sub(338,345)))
+ header.prefix = block:sub(346,500)
+ if header.magic ~= "ustar " and header.magic ~= "ustar\0" then
+ return false, "Invalid header magic "..header.magic
+ end
+ if header.version ~= "00" and header.version ~= " \0" then
+ return false, "Unknown version "..header.version
+ end
+ if not checksum_header(block) == header.chksum then
+ return false, "Failed header checksum"
+ end
+ return header
+end
+
+function untar(filename, destdir)
+ assert(type(filename) == "string")
+ assert(type(destdir) == "string")
+
+ local tar_handle = io.open(filename, "r")
+ if not tar_handle then return nil, "Error opening file "..filename end
+
+ local long_name, long_link_name
+ while true do
+ local block
+ repeat
+ block = tar_handle:read(blocksize)
+ until (not block) or checksum_header(block) > 256
+ if not block then break end
+ local header, err = read_header_block(block)
+ if not header then
+ util.printerr(err)
+ end
+
+ local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size)
+
+ if header.typeflag == "long name" then
+ long_name = nullterm(file_data)
+ elseif header.typeflag == "long link name" then
+ long_link_name = nullterm(file_data)
+ else
+ if long_name then
+ header.name = long_name
+ long_name = nil
+ end
+ if long_link_name then
+ header.name = long_link_name
+ long_link_name = nil
+ end
+ end
+ local pathname = dir.path(destdir, header.name)
+ if header.typeflag == "directory" then
+ fs.make_dir(pathname)
+ elseif header.typeflag == "file" then
+ local dirname = dir.dir_name(pathname)
+ if dirname ~= "" then
+ fs.make_dir(dirname)
+ end
+ local file_handle = io.open(pathname, "wb")
+ file_handle:write(file_data)
+ file_handle:close()
+ fs.set_time(pathname, header.mtime)
+ if fs.chmod then
+ fs.chmod(pathname, header.mode)
+ end
+ end
+ --[[
+ for k,v in pairs(header) do
+ util.printout("[\""..tostring(k).."\"] = "..(type(v)=="number" and v or "\""..v:gsub("%z", "\\0").."\""))
+ end
+ util.printout()
+ --]]
+ end
+ return true
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/tools/zip.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/tools/zip.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,245 @@
+
+--- A Lua implementation of .zip file archiving (used for creating .rock files),
+-- using only lua-zlib.
+module("luarocks.tools.zip", package.seeall)
+
+local zlib = require("zlib")
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+
+local function number_to_bytestring(number, nbytes)
+ local out = {}
+ for i = 1, nbytes do
+ local byte = number % 256
+ table.insert(out, string.char(byte))
+ number = (number - byte) / 256
+ end
+ return table.concat(out)
+end
+
+--- Begin a new file to be stored inside the zipfile.
+-- @param self handle of the zipfile being written.
+-- @param filename filenome of the file to be added to the zipfile.
+-- @return true if succeeded, nil in case of failure.
+local function zipwriter_open_new_file_in_zip(self, filename)
+ if self.in_open_file then
+ self:close_file_in_zip()
+ return nil
+ end
+ local lfh = {}
+ self.local_file_header = lfh
+ lfh.last_mod_file_time = 0 -- TODO
+ lfh.last_mod_file_date = 0 -- TODO
+ lfh.crc32 = 0 -- initial value
+ lfh.compressed_size = 0 -- unknown yet
+ lfh.uncompressed_size = 0 -- unknown yet
+ lfh.file_name_length = #filename
+ lfh.extra_field_length = 0
+ lfh.file_name = filename:gsub("\\", "/")
+ lfh.external_attr = 0 -- TODO properly store permissions
+ self.in_open_file = true
+ self.data = {}
+ return true
+end
+
+--- Write data to the file currently being stored in the zipfile.
+-- @param self handle of the zipfile being written.
+-- @param buf string containing data to be written.
+-- @return true if succeeded, nil in case of failure.
+local function zipwriter_write_file_in_zip(self, buf)
+ if not self.in_open_file then
+ return nil
+ end
+ local lfh = self.local_file_header
+ local cbuf = zlib.compress(buf):sub(3, -5)
+ lfh.crc32 = zlib.crc32(lfh.crc32, buf)
+ lfh.compressed_size = lfh.compressed_size + #cbuf
+ lfh.uncompressed_size = lfh.uncompressed_size + #buf
+ table.insert(self.data, cbuf)
+ return true
+end
+
+--- Complete the writing of a file stored in the zipfile.
+-- @param self handle of the zipfile being written.
+-- @return true if succeeded, nil in case of failure.
+local function zipwriter_close_file_in_zip(self)
+ local zh = self.ziphandle
+
+ if not self.in_open_file then
+ return nil
+ end
+
+ -- Local file header
+ local lfh = self.local_file_header
+ lfh.offset = zh:seek()
+ zh:write(number_to_bytestring(0x04034b50, 4)) -- signature
+ zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
+ zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
+ zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
+ zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
+ zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
+ zh:write(number_to_bytestring(lfh.crc32, 4))
+ zh:write(number_to_bytestring(lfh.compressed_size, 4))
+ zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
+ zh:write(number_to_bytestring(lfh.file_name_length, 2))
+ zh:write(number_to_bytestring(lfh.extra_field_length, 2))
+ zh:write(lfh.file_name)
+
+ -- File data
+ for _, cbuf in ipairs(self.data) do
+ zh:write(cbuf)
+ end
+
+ -- Data descriptor
+ zh:write(number_to_bytestring(lfh.crc32, 4))
+ zh:write(number_to_bytestring(lfh.compressed_size, 4))
+ zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
+
+ table.insert(self.files, lfh)
+ self.in_open_file = false
+
+ return true
+end
+
+-- @return boolean or (boolean, string): true on success,
+-- false and an error message on failure.
+local function zipwriter_add(self, file)
+ local fin
+ local ok, err = self:open_new_file_in_zip(file)
+ if not ok then
+ err = "error in opening "..file.." in zipfile"
+ else
+ fin = io.open(fs.absolute_name(file), "rb")
+ if not fin then
+ ok = false
+ err = "error opening "..file.." for reading"
+ end
+ end
+ if ok then
+ local buf = fin:read("*a")
+ if not buf then
+ err = "error reading "..file
+ ok = false
+ else
+ ok = self:write_file_in_zip(buf)
+ if not ok then
+ err = "error in writing "..file.." in the zipfile"
+ end
+ end
+ end
+ if fin then
+ fin:close()
+ end
+ if ok then
+ ok = self:close_file_in_zip()
+ if not ok then
+ err = "error in writing "..file.." in the zipfile"
+ end
+ end
+ return ok == true, err
+end
+
+--- Complete the writing of the zipfile.
+-- @param self handle of the zipfile being written.
+-- @return true if succeeded, nil in case of failure.
+local function zipwriter_close(self)
+ local zh = self.ziphandle
+
+ local central_directory_offset = zh:seek()
+
+ local size_of_central_directory = 0
+ -- Central directory structure
+ for _, lfh in ipairs(self.files) do
+ zh:write(number_to_bytestring(0x02014b50, 4)) -- signature
+ zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX
+ zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
+ zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
+ zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
+ zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
+ zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
+ zh:write(number_to_bytestring(lfh.crc32, 4))
+ zh:write(number_to_bytestring(lfh.compressed_size, 4))
+ zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
+ zh:write(number_to_bytestring(lfh.file_name_length, 2))
+ zh:write(number_to_bytestring(lfh.extra_field_length, 2))
+ zh:write(number_to_bytestring(0, 2)) -- file comment length
+ zh:write(number_to_bytestring(0, 2)) -- disk number start
+ zh:write(number_to_bytestring(0, 2)) -- internal file attributes
+ zh:write(number_to_bytestring(lfh.external_attr, 4)) -- external file attributes
+ zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header
+ zh:write(lfh.file_name)
+ size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length
+ end
+
+ -- End of central directory record
+ zh:write(number_to_bytestring(0x06054b50, 4)) -- signature
+ zh:write(number_to_bytestring(0, 2)) -- number of this disk
+ zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory
+ zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir on this disk
+ zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir
+ zh:write(number_to_bytestring(size_of_central_directory, 4))
+ zh:write(number_to_bytestring(central_directory_offset, 4))
+ zh:write(number_to_bytestring(0, 2)) -- zip file comment length
+ zh:close()
+
+ return true
+end
+
+--- Return a zip handle open for writing.
+-- @param name filename of the zipfile to be created.
+-- @return a zip handle, or nil in case of error.
+function new_zipwriter(name)
+
+ local zw = {}
+
+ zw.ziphandle = io.open(fs.absolute_name(name), "wb")
+ if not zw.ziphandle then
+ return nil
+ end
+ zw.files = {}
+ zw.in_open_file = false
+
+ zw.add = zipwriter_add
+ zw.close = zipwriter_close
+ zw.open_new_file_in_zip = zipwriter_open_new_file_in_zip
+ zw.write_file_in_zip = zipwriter_write_file_in_zip
+ zw.close_file_in_zip = zipwriter_close_file_in_zip
+
+ return zw
+end
+
+--- Compress files in a .zip archive.
+-- @param zipfile string: pathname of .zip archive to be created.
+-- @param ... Filenames to be stored in the archive are given as
+-- additional arguments.
+-- @return boolean or (boolean, string): true on success,
+-- false and an error message on failure.
+function zip(zipfile, ...)
+ local zw = new_zipwriter(zipfile)
+ if not zw then
+ return nil, "error opening "..zipfile
+ end
+
+ local ok, err
+ for _, file in pairs({...}) do
+ if fs.is_dir(file) then
+ for _, entry in pairs(fs.find(file)) do
+ local fullname = dir.path(file, entry)
+ if fs.is_file(fullname) then
+ ok, err = zw:add(fullname)
+ if not ok then break end
+ end
+ end
+ else
+ ok, err = zw:add(file)
+ if not ok then break end
+ end
+ end
+
+ local ok = zw:close()
+ if not ok then
+ return false, "error closing "..zipfile
+ end
+ return ok, err
+end
+
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/type_check.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/type_check.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,267 @@
+
+--- Type-checking functions.
+-- Functions and definitions for doing a basic lint check on files
+-- loaded by LuaRocks.
+module("luarocks.type_check", package.seeall)
+
+local cfg = require("luarocks.cfg")
+
+rockspec_format = "1.0"
+
+rockspec_types = {
+ rockspec_format = "string",
+ MUST_package = "string",
+ MUST_version = "[%w.]+-[%d]+",
+ description = {
+ summary = "string",
+ detailed = "string",
+ homepage = "string",
+ license = "string",
+ maintainer = "string"
+ },
+ dependencies = {
+ platforms = {},
+ ANY = "string"
+ },
+ supported_platforms = {
+ ANY = "string"
+ },
+ external_dependencies = {
+ platforms = {},
+ ANY = {
+ program = "string",
+ header = "string",
+ library = "string"
+ }
+ },
+ MUST_source = {
+ platforms = {},
+ MUST_url = "string",
+ md5 = "string",
+ file = "string",
+ dir = "string",
+ tag = "string",
+ branch = "string",
+ module = "string",
+ cvs_tag = "string",
+ cvs_module = "string"
+ },
+ build = {
+ platforms = {},
+ type = "string",
+ install = {
+ lua = {
+ MORE = true
+ },
+ lib = {
+ MORE = true
+ },
+ conf = {
+ MORE = true
+ },
+ bin = {
+ MORE = true
+ }
+ },
+ copy_directories = {
+ ANY = "string"
+ },
+ MORE = true
+ },
+ hooks = {
+ platforms = {},
+ post_install = "string"
+ }
+}
+
+function load_extensions()
+ rockspec_format = "1.1"
+ rockspec_types.deploy = {
+ wrap_bin_scripts = true,
+ }
+end
+
+if cfg.use_extensions then
+ load_extensions()
+end
+
+rockspec_types.build.platforms.ANY = rockspec_types.build
+rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies
+rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies
+rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source
+rockspec_types.hooks.platforms.ANY = rockspec_types.hooks
+
+manifest_types = {
+ MUST_repository = {
+ -- packages
+ ANY = {
+ -- versions
+ ANY = {
+ -- items
+ ANY = {
+ MUST_arch = "string",
+ modules = { ANY = "string" },
+ commands = { ANY = "string" },
+ dependencies = { ANY = "string" },
+ -- TODO: to be extended with more metadata.
+ }
+ }
+ }
+ },
+ MUST_modules = {
+ -- modules
+ ANY = {
+ -- providers
+ ANY = "string"
+ }
+ },
+ MUST_commands = {
+ -- modules
+ ANY = {
+ -- commands
+ ANY = "string"
+ }
+ },
+ dependencies = {
+ -- each module
+ ANY = {
+ -- each version
+ ANY = {
+ -- each dependency
+ ANY = {
+ name = "string",
+ constraints = {
+ ANY = {
+ no_upgrade = "boolean",
+ op = "string",
+ version = {
+ string = "string",
+ ANY = 0,
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+local type_check_table
+
+--- Type check an object.
+-- The object is compared against an archetypical value
+-- matching the expected type -- the actual values don't matter,
+-- only their types. Tables are type checked recursively.
+-- @param name any: The object name (for error messages).
+-- @param item any: The object being checked.
+-- @param expected any: The reference object. In case of a table,
+-- its is structured as a type reference table.
+-- @param context string: A string indicating the "context" where the
+-- error occurred (such as the name of the table the item is a part of),
+-- to be used by error messages.
+-- @return boolean or (nil, string): true if type checking
+-- succeeded, or nil and an error message if it failed.
+-- @see type_check_table
+local function type_check_item(name, item, expected, context)
+ name = tostring(name)
+
+ local item_type = type(item)
+ local expected_type = type(expected)
+ if expected_type == "number" then
+ if not tonumber(item) then
+ return nil, "Type mismatch on field "..context..name..": expected a number"
+ end
+ elseif expected_type == "string" then
+ if type(item) ~= "string" then
+ return nil, "Type mismatch on field "..context..name..": expected a string"
+ end
+ if expected ~= "string" then
+ if not item:match("^"..expected.."$") then
+ return nil, "Type mismatch on field "..context..name..": invalid value "..item
+ end
+ end
+ elseif expected_type == "table" then
+ if item_type ~= expected_type then
+ return nil, "Type mismatch on field "..context..name..": expected a table"
+ else
+ return type_check_table(item, expected, context..name..".")
+ end
+ elseif item_type ~= expected_type then
+ return nil, "Type mismatch on field "..context..name..": expected a "..expected_type
+ end
+ return true
+end
+
+--- Type check the contents of a table.
+-- The table's contents are compared against a reference table,
+-- which contains the recognized fields, with archetypical values
+-- matching the expected types -- the actual values of items in the
+-- reference table don't matter, only their types (ie, for field x
+-- in tbl that is correctly typed, type(tbl.x) == type(types.x)).
+-- If the reference table contains a field called MORE, then
+-- unknown fields in the checked table are accepted.
+-- If it contains a field called ANY, then its type will be
+-- used to check any unknown fields. If a field is prefixed
+-- with MUST_, it is mandatory; its absence from the table is
+-- a type error.
+-- Tables are type checked recursively.
+-- @param tbl table: The table to be type checked.
+-- @param types table: The reference table, containing
+-- values for recognized fields in the checked table.
+-- @param context string: A string indicating the "context" where the
+-- error occurred (such as the name of the table the item is a part of),
+-- to be used by error messages.
+-- @return boolean or (nil, string): true if type checking
+-- succeeded, or nil and an error message if it failed.
+type_check_table = function(tbl, types, context)
+ assert(type(tbl) == "table")
+ assert(type(types) == "table")
+ for k, v in pairs(tbl) do
+ local t = types[k] or (type(k) == "string" and types["MUST_"..k]) or types.ANY
+ if t then
+ local ok, err = type_check_item(k, v, t, context)
+ if not ok then return nil, err end
+ elseif types.MORE then
+ -- Accept unknown field
+ else
+ if not cfg.accept_unknown_fields then
+ return nil, "Unknown field "..k
+ end
+ end
+ end
+ for k, v in pairs(types) do
+ local mandatory_key = k:match("^MUST_(.+)")
+ if mandatory_key then
+ if not tbl[mandatory_key] then
+ return nil, "Mandatory field "..context..mandatory_key.." is missing."
+ end
+ end
+ end
+ return true
+end
+
+--- Type check a rockspec table.
+-- Verify the correctness of elements from a
+-- rockspec table, reporting on unknown fields and type
+-- mismatches.
+-- @return boolean or (nil, string): true if type checking
+-- succeeded, or nil and an error message if it failed.
+function type_check_rockspec(rockspec)
+ assert(type(rockspec) == "table")
+ if rockspec.rockspec_format then
+ -- relies on global state
+ load_extensions()
+ end
+ return type_check_table(rockspec, rockspec_types, "")
+end
+
+--- Type check a manifest table.
+-- Verify the correctness of elements from a
+-- manifest table, reporting on unknown fields and type
+-- mismatches.
+-- @return boolean or (nil, string): true if type checking
+-- succeeded, or nil and an error message if it failed.
+function type_check_manifest(manifest)
+ assert(type(manifest) == "table")
+ return type_check_table(manifest, manifest_types, "")
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/unpack.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/unpack.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,151 @@
+
+--- Module implementing the LuaRocks "unpack" command.
+-- Unpack the contents of a rock.
+module("luarocks.unpack", package.seeall)
+
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+local build = require("luarocks.build")
+local dir = require("luarocks.dir")
+
+help_summary = "Unpack the contents of a rock."
+help_arguments = "{| []}"
+help = [[
+Unpacks the contents of a rock in a newly created directory.
+Argument may be a rock file, or the name of a rock in a rocks server.
+In the latter case, the app version may be given as a second argument.
+]]
+
+--- Load a rockspec file to the given directory, fetches the source
+-- files specified in the rockspec, and unpack them inside the directory.
+-- @param rockspec_file string: The URL for a rockspec file.
+-- @param dir_name string: The directory where to store and unpack files.
+-- @return table or (nil, string): the loaded rockspec table or
+-- nil and an error message.
+local function unpack_rockspec(rockspec_file, dir_name)
+ assert(type(rockspec_file) == "string")
+ assert(type(dir_name) == "string")
+
+ local rockspec, err = fetch.load_rockspec(rockspec_file)
+ if not rockspec then
+ return nil, "Failed loading rockspec "..rockspec_file..": "..err
+ end
+ fs.change_dir(dir_name)
+ local ok, sources_dir = fetch.fetch_sources(rockspec, true, ".")
+ if not ok then
+ return nil, sources_dir
+ end
+ fs.change_dir(dir_name)
+ build.apply_patches(rockspec)
+ fs.pop_dir()
+ return rockspec
+end
+
+--- Load a .rock file to the given directory and unpack it inside it.
+-- @param rock_file string: The URL for a .rock file.
+-- @param dir_name string: The directory where to unpack.
+-- @param kind string: the kind of rock file, as in the second-level
+-- extension in the rock filename (eg. "src", "all", "linux-x86")
+-- @return table or (nil, string): the loaded rockspec table or
+-- nil and an error message.
+local function unpack_rock(rock_file, dir_name, kind)
+ assert(type(rock_file) == "string")
+ assert(type(dir_name) == "string")
+
+ local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, dir_name)
+ if not ok then
+ return nil, "Failed unzipping rock "..rock_file, errcode
+ end
+ fs.change_dir(dir_name)
+ local rockspec_file = dir_name..".rockspec"
+ local rockspec, err = fetch.load_rockspec(rockspec_file)
+ if not rockspec then
+ return nil, "Failed loading rockspec "..rockspec_file..": "..err
+ end
+ if kind == "src" then
+ if rockspec.source.file then
+ local ok, err = fs.unpack_archive(rockspec.source.file)
+ if not ok then
+ return nil, err
+ end
+ fs.change_dir(rockspec.source.dir)
+ build.apply_patches(rockspec)
+ fs.pop_dir()
+ end
+ end
+ return rockspec
+end
+
+--- Create a directory and perform the necessary actions so that
+-- the sources for the rock and its rockspec are unpacked inside it,
+-- laid out properly so that the 'make' command is able to build the module.
+-- @param file string: A rockspec or .rock URL.
+-- @return boolean or (nil, string): true if successful or nil followed
+-- by an error message.
+local function run_unpacker(file)
+ assert(type(file) == "string")
+
+ local base_name = dir.base_name(file)
+ local dir_name, kind, extension = base_name:match("(.*)%.([^.]+)%.(rock)$")
+ if not extension then
+ dir_name, extension = base_name:match("(.*)%.(rockspec)$")
+ kind = "rockspec"
+ end
+ if not extension then
+ return nil, file.." does not seem to be a valid filename."
+ end
+
+ if (fs.exists(dir_name)) then
+ return nil, "Directory "..dir_name.." already exists."
+ end
+ fs.make_dir(dir_name)
+ local rollback = util.schedule_function(fs.delete, fs.absolute_name(dir_name))
+
+ local rockspec, err
+ if extension == "rock" then
+ rockspec, err = unpack_rock(file, dir_name, kind)
+ elseif extension == "rockspec" then
+ rockspec, err = unpack_rockspec(file, dir_name)
+ end
+ if not rockspec then
+ return nil, err
+ end
+ if kind == "src" or kind == "rockspec" then
+ if rockspec.source.dir ~= "." then
+ local ok = fs.copy(rockspec.local_filename, rockspec.source.dir)
+ if not ok then
+ return nil, "Failed copying unpacked rockspec into unpacked source directory."
+ end
+ end
+ util.printout()
+ util.printout("Done. You may now enter directory ")
+ util.printout(dir.path(dir_name, rockspec.source.dir))
+ util.printout("and type 'luarocks make' to build.")
+ end
+ util.remove_scheduled_function(rollback)
+ return true
+end
+
+--- Driver function for the "unpack" command.
+-- @param name string: may be a rock filename, for unpacking a
+-- rock file or the name of a rock to be fetched and unpacked.
+-- @param version string or nil: if the name of a package is given, a
+-- version may also be passed.
+-- @return boolean or (nil, string): true if successful or nil followed
+-- by an error message.
+function run(...)
+ local flags, name, version = util.parse_flags(...)
+
+ assert(type(version) == "string" or not version)
+ if type(name) ~= "string" then
+ return nil, "Argument missing, see help."
+ end
+
+ if name:match(".*%.rock") or name:match(".*%.rockspec") then
+ return run_unpacker(name)
+ else
+ local search = require("luarocks.search")
+ return search.act_on_src_or_rockspec(run_unpacker, name, version)
+ end
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/util.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/util.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,436 @@
+
+--- Assorted utilities for managing tables, plus a scheduler for rollback functions.
+-- Does not requires modules directly (only as locals
+-- inside specific functions) to avoid interdependencies,
+-- as this is used in the bootstrapping stage of luarocks.cfg.
+
+local global_env = _G
+
+module("luarocks.util", package.seeall)
+
+local scheduled_functions = {}
+
+--- Schedule a function to be executed upon program termination.
+-- This is useful for actions such as deleting temporary directories
+-- or failure rollbacks.
+-- @param f function: Function to be executed.
+-- @param ... arguments to be passed to function.
+-- @return table: A token representing the scheduled execution,
+-- which can be used to remove the item later from the list.
+function schedule_function(f, ...)
+ assert(type(f) == "function")
+
+ local item = { fn = f, args = {...} }
+ table.insert(scheduled_functions, item)
+ return item
+end
+
+--- Unschedule a function.
+-- This is useful for cancelling a rollback of a completed operation.
+-- @param item table: The token representing the scheduled function that was
+-- returned from the schedule_function call.
+function remove_scheduled_function(item)
+ for k, v in pairs(scheduled_functions) do
+ if v == item then
+ table.remove(scheduled_functions, k)
+ return
+ end
+ end
+end
+
+--- Execute scheduled functions.
+-- Some calls create temporary files and/or directories and register
+-- corresponding cleanup functions. Calling this function will run
+-- these function, erasing temporaries.
+-- Functions are executed in the inverse order they were scheduled.
+function run_scheduled_functions()
+ local fs = require("luarocks.fs")
+ fs.change_dir_to_root()
+ for i = #scheduled_functions, 1, -1 do
+ local item = scheduled_functions[i]
+ item.fn(unpack(item.args))
+ end
+end
+
+--- Extract flags from an arguments list.
+-- Given string arguments, extract flag arguments into a flags set.
+-- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz",
+-- it would return the following:
+-- {["bla"] = true, ["tux"] = "beep", ["baz"] = true}, "foo", "bar".
+function parse_flags(...)
+ local args = {...}
+ local flags = {}
+ for i = #args, 1, -1 do
+ local flag = args[i]:match("^%-%-(.*)")
+ if flag then
+ local var,val = flag:match("([a-z_%-]*)=(.*)")
+ if val then
+ flags[var] = val
+ else
+ flags[flag] = true
+ end
+ table.remove(args, i)
+ end
+ end
+ return flags, unpack(args)
+end
+
+--- Merges contents of src on top of dst's contents.
+-- @param dst Destination table, which will receive src's contents.
+-- @param src Table which provides new contents to dst.
+-- @see platform_overrides
+function deep_merge(dst, src)
+ for k, v in pairs(src) do
+ if type(v) == "table" then
+ if not dst[k] then
+ dst[k] = {}
+ end
+ if type(dst[k]) == "table" then
+ deep_merge(dst[k], v)
+ else
+ dst[k] = v
+ end
+ else
+ dst[k] = v
+ end
+ end
+end
+
+--- Perform platform-specific overrides on a table.
+-- Overrides values of table with the contents of the appropriate
+-- subset of its "platforms" field. The "platforms" field should
+-- be a table containing subtables keyed with strings representing
+-- platform names. Names that match the contents of the global
+-- cfg.platforms setting are used. For example, if
+-- cfg.platforms= {"foo"}, then the fields of
+-- tbl.platforms.foo will overwrite those of tbl with the same
+-- names. For table values, the operation is performed recursively
+-- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of
+-- tbl.x are preserved).
+-- @param tbl table or nil: Table which may contain a "platforms" field;
+-- if it doesn't (or if nil is passed), this function does nothing.
+function platform_overrides(tbl)
+ assert(type(tbl) == "table" or not tbl)
+
+ local cfg = require("luarocks.cfg")
+
+ if not tbl then return end
+
+ if tbl.platforms then
+ for _, platform in ipairs(cfg.platforms) do
+ local platform_tbl = tbl.platforms[platform]
+ if platform_tbl then
+ deep_merge(tbl, platform_tbl)
+ end
+ end
+ end
+ tbl.platforms = nil
+end
+
+local var_format_pattern = "%$%((%a[%a%d_]+)%)"
+
+--- Create a new shallow copy of a table: a new table with
+-- the same keys and values. Keys point to the same objects as
+-- the original table (ie, does not copy recursively).
+-- @param tbl table: the input table
+-- @return table: a new table with the same contents.
+local function make_shallow_copy(tbl)
+ local copy = {}
+ for k,v in pairs(tbl) do
+ copy[k] = v
+ end
+ return copy
+end
+
+-- Check if a set of needed variables are referenced
+-- somewhere in a list of definitions, warning the user
+-- about any unused ones. Each key in needed_set should
+-- appear as a $(XYZ) variable at least once as a
+-- substring of some value of var_defs.
+-- @param var_defs: a table with string keys and string
+-- values, containing variable definitions.
+-- @param needed_set: a set where keys are the names of
+-- needed variables.
+-- @param msg string: the warning message to display.
+function warn_if_not_used(var_defs, needed_set, msg)
+ needed_set = make_shallow_copy(needed_set)
+ for var,val in pairs(var_defs) do
+ for used in val:gmatch(var_format_pattern) do
+ needed_set[used] = nil
+ end
+ end
+ for var,_ in pairs(needed_set) do
+ warning(msg:format(var))
+ end
+end
+
+-- Output any entries that might remain in $(XYZ) format,
+-- warning the user that substitutions have failed.
+-- @param line string: the input string
+local function warn_failed_matches(line)
+ local any_failed = false
+ if line:match(var_format_pattern) then
+ for unmatched in line:gmatch(var_format_pattern) do
+ warning("unmatched variable " .. unmatched)
+ any_failed = true
+ end
+ end
+ return any_failed
+end
+
+--- Perform make-style variable substitutions on string values of a table.
+-- For every string value tbl.x which contains a substring of the format
+-- "$(XYZ)" will have this substring replaced by vars["XYZ"], if that field
+-- exists in vars. Only string values are processed; this function
+-- does not scan subtables recursively.
+-- @param tbl table: Table to have its string values modified.
+-- @param vars table: Table containing string-string key-value pairs
+-- representing variables to replace in the strings values of tbl.
+function variable_substitutions(tbl, vars)
+ assert(type(tbl) == "table")
+ assert(type(vars) == "table")
+
+ local updated = {}
+ for k, v in pairs(tbl) do
+ if type(v) == "string" then
+ updated[k] = v:gsub(var_format_pattern, vars)
+ if warn_failed_matches(updated[k]) then
+ updated[k] = updated[k]:gsub(var_format_pattern, "")
+ end
+ end
+ end
+ for k, v in pairs(updated) do
+ tbl[k] = v
+ end
+end
+
+--- Return an array of keys of a table.
+-- @param tbl table: The input table.
+-- @return table: The array of keys.
+function keys(tbl)
+ local ks = {}
+ for k,_ in pairs(tbl) do
+ table.insert(ks, k)
+ end
+ return ks
+end
+
+local function default_sort(a, b)
+ local ta = type(a)
+ local tb = type(b)
+ if ta == "number" and tb == "number" then
+ return a < b
+ elseif ta == "number" then
+ return true
+ elseif tb == "number" then
+ return false
+ else
+ return tostring(a) < tostring(b)
+ end
+end
+
+-- The iterator function used internally by util.sortedpairs.
+-- @param tbl table: The table to be iterated.
+-- @param sort_function function or nil: An optional comparison function
+-- to be used by table.sort when sorting keys.
+-- @see sortedpairs
+local function sortedpairs_iterator(tbl, sort_function)
+ local ks = keys(tbl)
+ if not sort_function or type(sort_function) == "function" then
+ table.sort(ks, sort_function or default_sort)
+ for _, k in ipairs(ks) do
+ coroutine.yield(k, tbl[k])
+ end
+ else
+ local order = sort_function
+ local done = {}
+ for _, k in ipairs(order) do
+ local sub_order
+ if type(k) == "table" then
+ sub_order = k[2]
+ k = k[1]
+ end
+ if tbl[k] then
+ done[k] = true
+ coroutine.yield(k, tbl[k], sub_order)
+ end
+ end
+ table.sort(ks, default_sort)
+ for _, k in ipairs(ks) do
+ if not done[k] then
+ coroutine.yield(k, tbl[k])
+ end
+ end
+ end
+end
+
+--- A table iterator generator that returns elements sorted by key,
+-- to be used in "for" loops.
+-- @param tbl table: The table to be iterated.
+-- @param sort_function function or table or nil: An optional comparison function
+-- to be used by table.sort when sorting keys, or an array listing an explicit order
+-- for keys. If a value itself is an array, it is taken so that the first element
+-- is a string representing the field name, and the second element is a priority table
+-- for that key.
+-- @return function: the iterator function.
+function sortedpairs(tbl, sort_function)
+ return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end)
+end
+
+function starts_with(s, prefix)
+ return s:sub(1,#prefix) == prefix
+end
+
+--- Print a line to standard output
+function printout(...)
+ io.stdout:write(table.concat({...},"\t"))
+ io.stdout:write("\n")
+end
+
+--- Print a line to standard error
+function printerr(...)
+ io.stderr:write(table.concat({...},"\t"))
+ io.stderr:write("\n")
+end
+
+--- Display a warning message.
+-- @param msg string: the warning message
+function warning(msg)
+ printerr("Warning: "..msg)
+end
+
+function title(msg, porcelain, underline)
+ if porcelain then return end
+ printout()
+ printout(msg)
+ printout((underline or "-"):rep(#msg))
+ printout()
+end
+
+-- from http://lua-users.org/wiki/SplitJoin
+-- by PhilippeLhoste
+function split_string(str, delim, maxNb)
+ -- Eliminate bad cases...
+ if string.find(str, delim) == nil then
+ return { str }
+ end
+ if maxNb == nil or maxNb < 1 then
+ maxNb = 0 -- No limit
+ end
+ local result = {}
+ local pat = "(.-)" .. delim .. "()"
+ local nb = 0
+ local lastPos
+ for part, pos in string.gmatch(str, pat) do
+ nb = nb + 1
+ result[nb] = part
+ lastPos = pos
+ if nb == maxNb then break end
+ end
+ -- Handle the last field
+ if nb ~= maxNb then
+ result[nb + 1] = string.sub(str, lastPos)
+ end
+ return result
+end
+
+--- Remove repeated entries from a path-style string.
+-- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d".
+-- @param list string: A path string (from $PATH or package.path)
+-- @param sep string: The separator
+function remove_path_dupes(list, sep)
+ assert(type(list) == "string")
+ assert(type(sep) == "string")
+ local parts = split_string(list, sep)
+ local final, entries = {}, {}
+ for _, part in ipairs(parts) do
+ if not entries[part] then
+ table.insert(final, part)
+ entries[part] = true
+ end
+ end
+ return table.concat(final, sep)
+end
+
+---
+-- Formats tables with cycles recursively to any depth.
+-- References to other tables are shown as values.
+-- Self references are indicated.
+-- The string returned is "Lua code", which can be procesed
+-- (in the case in which indent is composed by spaces or "--").
+-- Userdata and function keys and values are shown as strings,
+-- which logically are exactly not equivalent to the original code.
+-- This routine can serve for pretty formating tables with
+-- proper indentations, apart from printing them:
+-- io.write(table.show(t, "t")) -- a typical use
+-- Written by Julio Manuel Fernandez-Diaz,
+-- Heavily based on "Saving tables with cycles", PIL2, p. 113.
+-- @param t table: is the table.
+-- @param name string: is the name of the table (optional)
+-- @param indent string: is a first indentation (optional).
+-- @return string: the pretty-printed table
+function show_table(t, name, indent)
+ local cart -- a container
+ local autoref -- for self references
+
+ local function isemptytable(t) return next(t) == nil end
+
+ local function basicSerialize (o)
+ local so = tostring(o)
+ if type(o) == "function" then
+ local info = debug.getinfo(o, "S")
+ -- info.name is nil because o is not a calling level
+ if info.what == "C" then
+ return ("%q"):format(so .. ", C function")
+ else
+ -- the information is defined through lines
+ return ("%q"):format(so .. ", defined in (" .. info.linedefined .. "-" .. info.lastlinedefined .. ")" .. info.source)
+ end
+ elseif type(o) == "number" then
+ return so
+ else
+ return ("%q"):format(so)
+ end
+ end
+
+ local function addtocart (value, name, indent, saved, field)
+ indent = indent or ""
+ saved = saved or {}
+ field = field or name
+
+ cart = cart .. indent .. field
+
+ if type(value) ~= "table" then
+ cart = cart .. " = " .. basicSerialize(value) .. ";\n"
+ else
+ if saved[value] then
+ cart = cart .. " = {}; -- " .. saved[value] .. " (self reference)\n"
+ autoref = autoref .. name .. " = " .. saved[value] .. ";\n"
+ else
+ saved[value] = name
+ --if tablecount(value) == 0 then
+ if isemptytable(value) then
+ cart = cart .. " = {};\n"
+ else
+ cart = cart .. " = {\n"
+ for k, v in pairs(value) do
+ k = basicSerialize(k)
+ local fname = ("%s[%s]"):format(name, k)
+ field = ("[%s]"):format(k)
+ -- three spaces between levels
+ addtocart(v, fname, indent .. " ", saved, field)
+ end
+ cart = cart .. indent .. "};\n"
+ end
+ end
+ end
+ end
+
+ name = name or "__unnamed__"
+ if type(t) ~= "table" then
+ return name .. " = " .. basicSerialize(t)
+ end
+ cart, autoref = "", ""
+ addtocart(t, name, indent)
+ return cart .. autoref
+end
diff -r ff65dfb63263 -r d137f631bad5 share/lua/5.2/luarocks/validate.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/lua/5.2/luarocks/validate.lua Fri Dec 14 22:24:27 2012 +0000
@@ -0,0 +1,160 @@
+
+--- Sandboxed test of build/install of all packages in a repository (unfinished and disabled).
+module("luarocks.validate", package.seeall)
+
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
+local path = require("luarocks.path")
+local cfg = require("luarocks.cfg")
+local build = require("luarocks.build")
+local install = require("luarocks.install")
+local util = require("luarocks.util")
+
+help_summary = "Sandboxed test of build/install of all packages in a repository."
+
+help = [[
+, if given, is a local repository pathname.
+]]
+
+local function save_settings(repo)
+ local protocol, path = dir.split_url(repo)
+ table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
+ return {
+ root_dir = cfg.root_dir,
+ rocks_dir = cfg.rocks_dir,
+ deploy_bin_dir = cfg.deploy_bin_dir,
+ deploy_lua_dir = cfg.deploy_lua_dir,
+ deploy_lib_dir = cfg.deploy_lib_dir,
+ }
+end
+
+local function restore_settings(settings)
+ cfg.root_dir = settings.root_dir
+ cfg.rocks_dir = settings.rocks_dir
+ cfg.deploy_bin_dir = settings.deploy_bin_dir
+ cfg.deploy_lua_dir = settings.deploy_lua_dir
+ cfg.deploy_lib_dir = settings.deploy_lib_dir
+ cfg.variables.ROCKS_TREE = settings.rocks_dir
+ cfg.variables.SCRIPTS_DIR = settings.deploy_bin_dir
+ table.remove(cfg.rocks_servers, 1)
+end
+
+local function prepare_sandbox(file)
+ local root_dir = fs.make_temp_dir(file):gsub("/+$", "")
+ cfg.root_dir = root_dir
+ cfg.rocks_dir = path.rocks_dir(root_dir)
+ cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir)
+ cfg.variables.ROCKS_TREE = cfg.rocks_dir
+ cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
+ return root_dir
+end
+
+local function validate_rockspec(file)
+ local ok, err, errcode = build.build_rockspec(file, true, "one")
+ if not ok then
+ util.printerr(err)
+ end
+ return ok, err, errcode
+end
+
+local function validate_src_rock(file)
+ local ok, err, errcode = build.build_rock(file, false, "one")
+ if not ok then
+ util.printerr(err)
+ end
+ return ok, err, errcode
+end
+
+local function validate_rock(file)
+ local ok, err, errcode = install.install_binary_rock(file, "one")
+ if not ok then
+ util.printerr(err)
+ end
+ return ok, err, errcode
+end
+
+local function validate(repo, flags)
+ local results = {
+ ok = {}
+ }
+ local settings = save_settings(repo)
+ local sandbox
+ if flags["quick"] then
+ sandbox = prepare_sandbox("luarocks_validate")
+ end
+ if not fs.exists(repo) then
+ return nil, repo.." is not a local repository."
+ end
+ for _, file in pairs(fs.list_dir(repo)) do for _=1,1 do
+ if file == "manifest" or file == "index.html" then
+ break -- continue for
+ end
+ local pathname = fs.absolute_name(dir.path(repo, file))
+ if not flags["quick"] then
+ sandbox = prepare_sandbox(file)
+ end
+ local ok, err, errcode
+ util.printout()
+ util.printout("Verifying "..pathname)
+ if file:match("%.rockspec$") then
+ ok, err, errcode = validate_rockspec(pathname, "one")
+ elseif file:match("%.src%.rock$") then
+ ok, err, errcode = validate_src_rock(pathname)
+ elseif file:match("%.rock$") then
+ ok, err, errcode = validate_rock(pathname)
+ end
+ if ok then
+ table.insert(results.ok, {file=file} )
+ else
+ if not errcode then
+ errcode = "misc"
+ end
+ if not results[errcode] then
+ results[errcode] = {}
+ end
+ table.insert(results[errcode], {file=file, err=err} )
+ end
+ util.run_scheduled_functions()
+ if not flags["quick"] then
+ fs.delete(sandbox)
+ end
+ repeat until not fs.pop_dir()
+ end end
+ if flags["quick"] then
+ fs.delete(sandbox)
+ end
+ restore_settings(settings)
+ util.title("Results:")
+ util.printout("OK: "..tostring(#results.ok))
+ for _, entry in ipairs(results.ok) do
+ util.printout(entry.file)
+ end
+ for errcode, errors in pairs(results) do
+ if errcode ~= "ok" then
+ util.printout()
+ util.printout(errcode.." errors: "..tostring(#errors))
+ for _, entry in ipairs(errors) do
+ util.printout(entry.file, entry.err)
+ end
+ end
+ end
+
+ util.title("Summary:")
+ local total = 0
+ for errcode, errors in pairs(results) do
+ util.printout(errcode..": "..tostring(#errors))
+ total = total + #errors
+ end
+ util.printout("Total: "..total)
+ return true
+end
+
+function run(...)
+ local flags, repo = util.parse_flags(...)
+ repo = repo or cfg.rocks_dir
+
+ util.printout("Verifying contents of "..repo)
+
+ return validate(repo, flags)
+end
+