summaryrefslogtreecommitdiff
path: root/src/luarocks/cmd/config.lua
diff options
context:
space:
mode:
authorMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
committerMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
commit5155816b7b925dec5d5feb1568b1d7ceb00938b9 (patch)
treedeca28ea15e79f6f804c3d90d2ba757881638af5 /src/luarocks/cmd/config.lua
fetch tarballHEADmaster
Diffstat (limited to 'src/luarocks/cmd/config.lua')
-rw-r--r--src/luarocks/cmd/config.lua392
1 files changed, 392 insertions, 0 deletions
diff --git a/src/luarocks/cmd/config.lua b/src/luarocks/cmd/config.lua
new file mode 100644
index 0000000..d67711a
--- /dev/null
+++ b/src/luarocks/cmd/config.lua
@@ -0,0 +1,392 @@
+--- Module implementing the LuaRocks "config" command.
+-- Queries information about the LuaRocks configuration.
+local config_cmd = {}
+
+local persist = require("luarocks.persist")
+local config = require("luarocks.config")
+local cfg = require("luarocks.core.cfg")
+local util = require("luarocks.util")
+local deps = require("luarocks.deps")
+local dir = require("luarocks.dir")
+local fs = require("luarocks.fs")
+local json = require("luarocks.vendor.dkjson")
+
+function config_cmd.add_to_parser(parser)
+ local cmd = parser:command("config", [[
+Query information about the LuaRocks configuration.
+
+* When given a configuration key, it prints the value of that key according to
+ the currently active configuration (taking into account all config files and
+ any command-line flags passed)
+
+ Examples:
+ luarocks config variables.LUA_INCDIR
+ luarocks config lua_version
+
+* When given a configuration key and a value, it overwrites the config file (see
+ the --scope option below to determine which) and replaces the value of the
+ given key with the given value.
+
+ * `lua_dir` is a special key as it checks for a valid Lua installation
+ (equivalent to --lua-dir) and sets several keys at once.
+ * `lua_version` is a special key as it changes the default Lua version
+ used by LuaRocks commands (equivalent to passing --lua-version).
+
+ Examples:
+ luarocks config variables.OPENSSL_DIR /usr/local/openssl
+ luarocks config lua_dir /usr/local
+ luarocks config lua_version 5.3
+
+* When given a configuration key and --unset, it overwrites the config file (see
+ the --scope option below to determine which) and deletes that key from the
+ file.
+
+ Example: luarocks config variables.OPENSSL_DIR --unset
+
+* When given no arguments, it prints the entire currently active configuration,
+ resulting from reading the config files from all scopes.
+
+ Example: luarocks config]], util.see_also([[
+ https://github.com/luarocks/luarocks/wiki/Config-file-format
+ for detailed information on the LuaRocks config file format.
+]]))
+ :summary("Query information about the LuaRocks configuration.")
+
+ cmd:argument("key", "The configuration key.")
+ :args("?")
+ cmd:argument("value", "The configuration value.")
+ :args("?")
+
+ cmd:option("--scope", "The scope indicates which config file should be rewritten.\n"..
+ '* Using a wrapper created with `luarocks init`, the default is "project".\n'..
+ '* Using --local (or when `local_by_default` is `true`), the default is "user".\n'..
+ '* Otherwise, the default is "system".')
+ :choices({"system", "user", "project"})
+ cmd:flag("--unset", "Delete the key from the configuration file.")
+ cmd:flag("--json", "Output as JSON.")
+
+ -- Deprecated flags
+ cmd:flag("--lua-incdir"):hidden(true)
+ cmd:flag("--lua-libdir"):hidden(true)
+ cmd:flag("--lua-ver"):hidden(true)
+ cmd:flag("--system-config"):hidden(true)
+ cmd:flag("--user-config"):hidden(true)
+ cmd:flag("--rock-trees"):hidden(true)
+end
+
+local function config_file(conf)
+ print(dir.normalize(conf.file))
+ if conf.found then
+ return true
+ else
+ return nil, "file not found"
+ end
+end
+
+local function traverse_varstring(var, tbl, fn, missing_parent)
+ local k, r = var:match("^%[([0-9]+)%]%.(.*)$")
+ if k then
+ k = tonumber(k)
+ else
+ k, r = var:match("^([^.[]+)%.(.*)$")
+ if not k then
+ k, r = var:match("^([^[]+)(%[.*)$")
+ end
+ end
+
+ if k then
+ if not tbl[k] and missing_parent then
+ missing_parent(tbl, k)
+ end
+
+ if tbl[k] then
+ return traverse_varstring(r, tbl[k], fn, missing_parent)
+ else
+ return nil, "Unknown entry " .. k
+ end
+ end
+
+ local i = var:match("^%[([0-9]+)%]$")
+ if i then
+ var = tonumber(i)
+ end
+
+ return fn(tbl, var)
+end
+
+local function print_json(value)
+ print(json.encode(value))
+ return true
+end
+
+local function print_entry(var, tbl, is_json)
+ return traverse_varstring(var, tbl, function(t, k)
+ if not t[k] then
+ return nil, "Unknown entry " .. k
+ end
+ local val = t[k]
+
+ if not config.should_skip(var, val) then
+ if is_json then
+ return print_json(val)
+ elseif type(val) == "string" then
+ print(val)
+ else
+ persist.write_value(io.stdout, val)
+ end
+ end
+ return true
+ end)
+end
+
+local function infer_type(var)
+ local typ
+ traverse_varstring(var, cfg, function(t, k)
+ if t[k] ~= nil then
+ typ = type(t[k])
+ end
+ end)
+ return typ
+end
+
+local function write_entries(keys, scope, do_unset)
+ if scope == "project" and not cfg.config_files.project then
+ return nil, "Current directory is not part of a project. You may want to run `luarocks init`."
+ end
+
+ local file_name = cfg.config_files[scope].file
+
+ local tbl, err = persist.load_config_file_if_basic(file_name, cfg)
+ if not tbl then
+ return nil, err
+ end
+
+ for var, val in util.sortedpairs(keys) do
+ traverse_varstring(var, tbl, function(t, k)
+ if do_unset then
+ t[k] = nil
+ else
+ local typ = infer_type(var)
+ local v
+ if typ == "number" and tonumber(val) then
+ v = tonumber(val)
+ elseif typ == "boolean" and val == "true" then
+ v = true
+ elseif typ == "boolean" and val == "false" then
+ v = false
+ else
+ v = val
+ end
+ t[k] = v
+ keys[var] = v
+ end
+ return true
+ end, function(p, k)
+ p[k] = {}
+ end)
+ end
+
+ local ok, err = fs.make_dir(dir.dir_name(file_name))
+ if not ok then
+ return nil, err
+ end
+
+ ok, err = persist.save_from_table(file_name, tbl)
+ if ok then
+ print(do_unset and "Removed" or "Wrote")
+ for var, val in util.sortedpairs(keys) do
+ if do_unset then
+ print(("\t%s"):format(var))
+ else
+ if type(val) == "string" then
+ print(("\t%s = %q"):format(var, val))
+ else
+ print(("\t%s = %s"):format(var, tostring(val)))
+ end
+ end
+ end
+ print(do_unset and "from" or "to")
+ print("\t" .. file_name)
+ return true
+ else
+ return nil, err
+ end
+end
+
+local function get_scope(args)
+ return args.scope
+ or (args["local"] and "user")
+ or (args.project_tree and "project")
+ or (cfg.local_by_default and "user")
+ or (fs.is_writable(cfg.config_files["system"].file) and "system")
+ or "user"
+end
+
+local function report_on_lua_incdir_config(value, lua_version)
+ local variables = {
+ ["LUA_DIR"] = cfg.variables.LUA_DIR,
+ ["LUA_BINDIR"] = cfg.variables.LUA_BINDIR,
+ ["LUA_INCDIR"] = value,
+ ["LUA_LIBDIR"] = cfg.variables.LUA_LIBDIR,
+ ["LUA"] = cfg.variables.LUA,
+ }
+
+ local ok, err = deps.check_lua_incdir(variables, lua_version)
+ if not ok then
+ util.printerr()
+ util.warning((err:gsub(" You can use.*", "")))
+ end
+ return ok
+end
+
+local function report_on_lua_libdir_config(value, lua_version)
+ local variables = {
+ ["LUA_DIR"] = cfg.variables.LUA_DIR,
+ ["LUA_BINDIR"] = cfg.variables.LUA_BINDIR,
+ ["LUA_INCDIR"] = cfg.variables.LUA_INCDIR,
+ ["LUA_LIBDIR"] = value,
+ ["LUA"] = cfg.variables.LUA,
+ }
+
+ local ok, err, _, err_files = deps.check_lua_libdir(variables, lua_version)
+ if not ok then
+ util.printerr()
+ util.warning((err:gsub(" You can use.*", "")))
+ util.printerr("Tried:")
+ for _, l in pairs(err_files or {}) do
+ for _, d in ipairs(l) do
+ util.printerr("\t" .. d)
+ end
+ end
+ end
+ return ok
+end
+
+local function warn_bad_c_config()
+ util.printerr()
+ util.printerr("LuaRocks may not work correctly when building C modules using this configuration.")
+ util.printerr()
+end
+
+--- Driver function for "config" command.
+-- @return boolean: True if succeeded, nil on errors.
+function config_cmd.command(args)
+ local lua_version = args.lua_version or cfg.lua_version
+
+ deps.check_lua_incdir(cfg.variables, lua_version)
+ deps.check_lua_libdir(cfg.variables, lua_version)
+
+ -- deprecated flags
+ if args.lua_incdir then
+ print(cfg.variables.LUA_INCDIR)
+ return true
+ end
+ if args.lua_libdir then
+ print(cfg.variables.LUA_LIBDIR)
+ return true
+ end
+ if args.lua_ver then
+ print(cfg.lua_version)
+ return true
+ end
+ if args.system_config then
+ return config_file(cfg.config_files.system)
+ end
+ if args.user_config then
+ return config_file(cfg.config_files.user)
+ end
+ if args.rock_trees then
+ for _, tree in ipairs(cfg.rocks_trees) do
+ if type(tree) == "string" then
+ util.printout(dir.normalize(tree))
+ else
+ local name = tree.name and "\t"..tree.name or ""
+ util.printout(dir.normalize(tree.root)..name)
+ end
+ end
+ return true
+ end
+
+ if args.key == "lua_version" and args.value then
+ local scope = get_scope(args)
+ if scope == "project" and not cfg.config_files.project then
+ return nil, "Current directory is not part of a project. You may want to run `luarocks init`."
+ end
+
+ local location = cfg.config_files[scope]
+ if (not location) or (not location.file) then
+ return nil, "could not get config file location for " .. tostring(scope) .. " scope"
+ end
+
+ local prefix = dir.dir_name(location.file)
+ local ok, err = persist.save_default_lua_version(prefix, args.value)
+ if not ok then
+ return nil, "could not set default Lua version: " .. err
+ end
+ print("Lua version will default to " .. args.value .. " in " .. prefix)
+ end
+
+ if args.key == "lua_dir" and args.value then
+ local scope = get_scope(args)
+ local keys = {
+ ["variables.LUA_DIR"] = cfg.variables.LUA_DIR,
+ ["variables.LUA_BINDIR"] = cfg.variables.LUA_BINDIR,
+ ["variables.LUA_INCDIR"] = cfg.variables.LUA_INCDIR,
+ ["variables.LUA_LIBDIR"] = cfg.variables.LUA_LIBDIR,
+ ["variables.LUA"] = cfg.variables.LUA,
+ }
+ if args.lua_version then
+ local prefix = dir.dir_name(cfg.config_files[scope].file)
+ persist.save_default_lua_version(prefix, args.lua_version)
+ end
+ local ok, err = write_entries(keys, scope, args.unset)
+ if ok then
+ local inc_ok = report_on_lua_incdir_config(cfg.variables.LUA_INCDIR, lua_version)
+ local lib_ok = ok and report_on_lua_libdir_config(cfg.variables.LUA_LIBDIR, lua_version)
+ if not (inc_ok and lib_ok) then
+ warn_bad_c_config()
+ end
+ end
+
+ return ok, err
+ end
+
+ if args.key then
+ if args.key:match("^[A-Z]") then
+ args.key = "variables." .. args.key
+ end
+
+ if args.value or args.unset then
+ local scope = get_scope(args)
+
+ local ok, err = write_entries({ [args.key] = args.value or args.unset }, scope, args.unset)
+
+ if ok then
+ if args.key == "variables.LUA_INCDIR" then
+ local ok = report_on_lua_incdir_config(args.value, lua_version)
+ if not ok then
+ warn_bad_c_config()
+ end
+ elseif args.key == "variables.LUA_LIBDIR" then
+ local ok = report_on_lua_libdir_config(args.value, lua_version)
+ if not ok then
+ warn_bad_c_config()
+ end
+ end
+ end
+
+ return ok, err
+ else
+ return print_entry(args.key, cfg, args.json)
+ end
+ end
+
+ if args.json then
+ return print_json(config.get_config_for_display(cfg))
+ else
+ print(config.to_string(cfg))
+ return true
+ end
+end
+
+return config_cmd