summaryrefslogtreecommitdiff
path: root/src/luarocks/core/path.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/luarocks/core/path.lua')
-rw-r--r--src/luarocks/core/path.lua157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/luarocks/core/path.lua b/src/luarocks/core/path.lua
new file mode 100644
index 0000000..2f037b4
--- /dev/null
+++ b/src/luarocks/core/path.lua
@@ -0,0 +1,157 @@
+
+--- Core LuaRocks-specific path handling functions.
+local path = {}
+
+local cfg = require("luarocks.core.cfg")
+local dir = require("luarocks.core.dir")
+local require = nil
+
+local dir_sep = package.config:sub(1, 1)
+--------------------------------------------------------------------------------
+
+function path.rocks_dir(tree)
+ if tree == nil then
+ tree = cfg.root_dir
+ end
+ if type(tree) == "string" then
+ return dir.path(tree, cfg.rocks_subdir)
+ end
+ assert(type(tree) == "table")
+ return tree.rocks_dir or dir.path(tree.root, cfg.rocks_subdir)
+end
+
+--- Produce a versioned version of a filename.
+-- @param file string: filename (must start with prefix)
+-- @param prefix string: Path prefix for file
+-- @param name string: Rock name
+-- @param version string: Rock version
+-- @return string: a pathname with the same directory parts and a versioned basename.
+function path.versioned_name(file, prefix, name, version)
+ assert(type(file) == "string")
+ assert(type(name) == "string" and not name:match(dir_sep))
+ assert(type(version) == "string")
+
+ local rest = file:sub(#prefix+1):gsub("^" .. dir_sep .. "*", "")
+ local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_")
+ return dir.path(prefix, name_version.."-"..rest)
+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.init"; "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.path_to_module(file)
+ assert(type(file) == "string")
+
+ local exts = {}
+ local paths = package.path .. ";" .. package.cpath
+ for entry in paths:gmatch("[^;]+") do
+ local ext = entry:match("%.([a-z]+)$")
+ if ext then
+ exts[ext] = true
+ end
+ end
+
+ local name
+ for ext, _ in pairs(exts) do
+ name = file:match("(.*)%." .. ext .. "$")
+ if name then
+ name = name:gsub("[\\/]", ".")
+ break
+ end
+ end
+
+ if not name then name = file end
+
+ -- remove any beginning and trailing slashes-converted-to-dots
+ name = name:gsub("^%.+", ""):gsub("%.+$", "")
+
+ return name
+end
+
+function path.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 path.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
+
+local is_src_extension = { [".lua"] = true, [".tl"] = true, [".tld"] = true, [".moon"] = true }
+
+--- Return the pathname of the file that would be loaded for a module, indexed.
+-- @param file_name string: module file name as in manifest (eg. "socket/core.so")
+-- @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 path.which_i(file_name, name, version, tree, i)
+ local deploy_dir
+ local extension = file_name:match("%.[a-z]+$")
+ if is_src_extension[extension] then
+ deploy_dir = path.deploy_lua_dir(tree)
+ file_name = dir.path(deploy_dir, file_name)
+ else
+ deploy_dir = path.deploy_lib_dir(tree)
+ file_name = dir.path(deploy_dir, file_name)
+ end
+ if i > 1 then
+ file_name = path.versioned_name(file_name, deploy_dir, name, version)
+ end
+ return file_name
+end
+
+function path.rocks_tree_to_string(tree)
+ if type(tree) == "string" then
+ return tree
+ else
+ assert(type(tree) == "table")
+ return tree.root
+ end
+end
+
+--- Apply a given function to the active rocks trees based on chosen dependency mode.
+-- @param deps_mode string: Dependency mode: "one" for the current default tree,
+-- "all" for all trees, "order" for all trees with priority >= the current default,
+-- "none" for no trees (this function becomes a nop).
+-- @param fn function: function to be applied, with the tree dir (string) as the first
+-- argument and the remaining varargs of map_trees as the following arguments.
+-- @return a table with all results of invocations of fn collected.
+function path.map_trees(deps_mode, fn, ...)
+ local result = {}
+ local current = cfg.root_dir or cfg.rocks_trees[1]
+ if deps_mode == "one" then
+ table.insert(result, (fn(current, ...)) or 0)
+ else
+ local use = false
+ if deps_mode == "all" then
+ use = true
+ end
+ for _, tree in ipairs(cfg.rocks_trees or {}) do
+ if dir.normalize(path.rocks_tree_to_string(tree)) == dir.normalize(path.rocks_tree_to_string(current)) then
+ use = true
+ end
+ if use then
+ table.insert(result, (fn(tree, ...)) or 0)
+ end
+ end
+ end
+ return result
+end
+
+return path