aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/cmd.tl (renamed from src/luarocks/cmd.lua)144
1 files changed, 85 insertions, 59 deletions
diff --git a/src/luarocks/cmd.lua b/src/luarocks/cmd.tl
index 7710dc68..a3d2970f 100644
--- a/src/luarocks/cmd.lua
+++ b/src/luarocks/cmd.tl
@@ -1,6 +1,16 @@
1 1
2--- Functions for command-line scripts. 2--- Functions for command-line scripts.
3local cmd = {} 3local record cmd
4 errorcodes: {string: integer}
5
6 record Module
7 add_to_parser: function(Parser)
8 command: function(Args, ...: string): boolean, string, integer
9 needs_lock: function(Args): boolean
10 help: string
11 help_summary: string
12 end
13end
4 14
5local manif = require("luarocks.manif") 15local manif = require("luarocks.manif")
6local config = require("luarocks.config") 16local config = require("luarocks.config")
@@ -12,10 +22,19 @@ local fun = require("luarocks.fun")
12local fs = require("luarocks.fs") 22local fs = require("luarocks.fs")
13local argparse = require("luarocks.vendor.argparse") 23local argparse = require("luarocks.vendor.argparse")
14 24
15local unpack = table.unpack or unpack 25local type Tree = require("luarocks.core.types.tree").Tree
16local pack = table.pack or function(...) return { n = select("#", ...), ... } end 26
27local type Parser = argparse.Parser
28
29local type Args = require("luarocks.core.types.args").Args
30
31local type Module = cmd.Module
17 32
18local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded") 33local type PersistableTable = require("luarocks.core.types.persist").PersistableTable
34
35local type Config = cfg
36
37local hc_ok, hardcoded: boolean, {string: string} = pcall(require, "luarocks.core.hardcoded")
19if not hc_ok then 38if not hc_ok then
20 hardcoded = {} 39 hardcoded = {}
21end 40end
@@ -44,19 +63,20 @@ local function check_popen()
44 end 63 end
45end 64end
46 65
47local process_tree_args 66local process_tree_args: function(Args, string): boolean, string
48do 67do
49 local function replace_tree(args, root, tree) 68 local function replace_tree(args: Args, root: string, tree?: Tree)
50 root = dir.normalize(root) 69 root = dir.normalize(root)
51 args.tree = root 70 args.tree = root
52 path.use_tree(tree or root) 71 path.use_tree(tree or root)
53 end 72 end
54 73
55 local function strip_trailing_slashes() 74 local function strip_trailing_slashes()
56 if type(cfg.root_dir) == "string" then 75 local cfg_root_dir = cfg.root_dir
57 cfg.root_dir = cfg.root_dir:gsub("/+$", "") 76 if cfg_root_dir is string then
77 cfg.root_dir = (cfg.root_dir as string):gsub("/+$", "")
58 else 78 else
59 cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "") 79 (cfg.root_dir as Tree).root = (cfg.root_dir as Tree).root:gsub("/+$", "")
60 end 80 end
61 cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "") 81 cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
62 cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "") 82 cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
@@ -64,9 +84,9 @@ do
64 cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "") 84 cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
65 end 85 end
66 86
67 local function set_named_tree(args, name) 87 local function set_named_tree(args: Args, name: string): boolean, string
68 for _, tree in ipairs(cfg.rocks_trees) do 88 for _, tree in ipairs(cfg.rocks_trees) do
69 if type(tree) == "table" and name == tree.name then 89 if tree is Tree and name == tree.name then
70 if not tree.root then 90 if not tree.root then
71 return nil, "Configuration error: tree '"..tree.name.."' has no 'root' field." 91 return nil, "Configuration error: tree '"..tree.name.."' has no 'root' field."
72 end 92 end
@@ -77,7 +97,7 @@ do
77 return false 97 return false
78 end 98 end
79 99
80 process_tree_args = function(args, project_dir) 100 process_tree_args = function(args: Args, project_dir: string): boolean, string
81 101
82 if args.global then 102 if args.global then
83 local ok, err = set_named_tree(args, "system") 103 local ok, err = set_named_tree(args, "system")
@@ -133,16 +153,22 @@ do
133 end 153 end
134end 154end
135 155
136local function process_server_args(args) 156local function process_server_args(args: Args): boolean, string
137 if args.server then 157 if args.server then
138 local protocol, pathname = dir.split_url(args.server) 158 local protocol, pathname = dir.split_url(args.server)
139 table.insert(cfg.rocks_servers, 1, protocol.."://"..pathname) 159 table.insert(cfg.rocks_servers, 1, protocol.."://"..pathname)
140 end 160 end
141 161
142 if args.dev then 162 if args.dev then
143 local append_dev = function(s) return dir.path(s, "dev") end 163 for i, server in ipairs(cfg.rocks_servers) do
144 local dev_servers = fun.traverse(cfg.rocks_servers, append_dev) 164 if server is string then
145 cfg.rocks_servers = fun.concat(dev_servers, cfg.rocks_servers) 165 cfg.rocks_servers[i] = dir.path(server, "dev")
166 else
167 for j, mirror in ipairs(server) do
168 server[j] = dir.path(mirror, "dev")
169 end
170 end
171 end
146 end 172 end
147 173
148 if args.only_server then 174 if args.only_server then
@@ -158,7 +184,7 @@ local function process_server_args(args)
158 return true 184 return true
159end 185end
160 186
161local function error_handler(err) 187local function error_handler(err: string): string
162 if not debug then 188 if not debug then
163 return err 189 return err
164 end 190 end
@@ -179,8 +205,8 @@ end
179--- Display an error message and exit. 205--- Display an error message and exit.
180-- @param message string: The error message. 206-- @param message string: The error message.
181-- @param exitcode number: the exitcode to use 207-- @param exitcode number: the exitcode to use
182local function die(message, exitcode) 208local function die(message: string, exitcode?: integer)
183 assert(type(message) == "string", "bad error, expected string, got: " .. type(message)) 209 assert(type(message) == "string", "bad error, expected string, got: " .. type(message)) --!
184 assert(exitcode == nil or type(exitcode) == "number", "bad error, expected number, got: " .. type(exitcode) .. " - " .. tostring(exitcode)) 210 assert(exitcode == nil or type(exitcode) == "number", "bad error, expected number, got: " .. type(exitcode) .. " - " .. tostring(exitcode))
185 util.printerr("\nError: "..message) 211 util.printerr("\nError: "..message)
186 212
@@ -193,7 +219,7 @@ local function die(message, exitcode)
193 os.exit(exitcode or cmd.errorcodes.UNSPECIFIED) 219 os.exit(exitcode or cmd.errorcodes.UNSPECIFIED)
194end 220end
195 221
196local function search_lua(lua_version, verbose, search_at) 222local function search_lua(lua_version: string, verbose?: string, search_at?: string): {string : string}, string
197 if search_at then 223 if search_at then
198 return util.find_lua(search_at, lua_version, verbose) 224 return util.find_lua(search_at, lua_version, verbose)
199 end 225 end
@@ -215,11 +241,11 @@ local function search_lua(lua_version, verbose, search_at)
215 (verbose and " Tried:\n" .. table.concat(all_tried, "\n") or "") 241 (verbose and " Tried:\n" .. table.concat(all_tried, "\n") or "")
216end 242end
217 243
218local init_config 244local init_config: function(Args): boolean, string
219do 245do
220 local detect_config_via_args 246 local detect_config_via_args: function(Args): {string : string}
221 do 247 do
222 local function find_project_dir(project_tree) 248 local function find_project_dir(project_tree: string): string, boolean
223 if project_tree then 249 if project_tree then
224 return project_tree:gsub("[/\\][^/\\]+$", ""), true 250 return project_tree:gsub("[/\\][^/\\]+$", ""), true
225 else 251 else
@@ -236,12 +262,12 @@ do
236 return nil 262 return nil
237 end 263 end
238 264
239 local function find_default_lua_version(args, project_dir) 265 local function find_default_lua_version(args: Args, project_dir: string): string
240 if hardcoded.FORCE_CONFIG then 266 if hardcoded.FORCE_CONFIG then
241 return nil 267 return nil
242 end 268 end
243 269
244 local dirs = {} 270 local dirs: {string} = {}
245 if project_dir then 271 if project_dir then
246 table.insert(dirs, dir.path(project_dir, ".luarocks")) 272 table.insert(dirs, dir.path(project_dir, ".luarocks"))
247 end 273 end
@@ -251,10 +277,10 @@ do
251 table.insert(dirs, cfg.sysconfdir) 277 table.insert(dirs, cfg.sysconfdir)
252 for _, d in ipairs(dirs) do 278 for _, d in ipairs(dirs) do
253 local f = dir.path(d, "default-lua-version.lua") 279 local f = dir.path(d, "default-lua-version.lua")
254 local mod, err = loadfile(f, "t") 280 local mod, _ = loadfile(f, "t")
255 if mod then 281 if mod then
256 local pok, ver = pcall(mod) 282 local pok, ver = pcall(mod)
257 if pok and type(ver) == "string" and ver:match("%d+.%d+") then 283 if pok and ver is string and ver:match("%d+.%d+") then
258 if args.verbose then 284 if args.verbose then
259 util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...") 285 util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...")
260 end 286 end
@@ -265,15 +291,15 @@ do
265 return nil 291 return nil
266 end 292 end
267 293
268 local function find_version_from_config(dirname) 294 local function find_version_from_config(dirname: string): string
269 return fun.find(util.lua_versions("descending"), function(v) 295 return fun.find(util.lua_versions("descending"), function(v: string): string
270 if util.exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then 296 if util.exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then
271 return v 297 return v
272 end 298 end
273 end) 299 end)
274 end 300 end
275 301
276 local function detect_lua_via_args(args, project_dir) 302 local function detect_lua_via_args(args: Args, project_dir: string): {string : string}
277 local lua_version = args.lua_version 303 local lua_version = args.lua_version
278 or find_default_lua_version(args, project_dir) 304 or find_default_lua_version(args, project_dir)
279 or (project_dir and find_version_from_config(project_dir)) 305 or (project_dir and find_version_from_config(project_dir))
@@ -302,8 +328,8 @@ do
302 return {} 328 return {}
303 end 329 end
304 330
305 detect_config_via_args = function(args) 331 detect_config_via_args = function(args: Args): {string : string}
306 local project_dir, given 332 local project_dir, given: string, boolean
307 if not args.no_project then 333 if not args.no_project then
308 project_dir, given = find_project_dir(args.project_tree) 334 project_dir, given = find_project_dir(args.project_tree)
309 end 335 end
@@ -323,7 +349,7 @@ do
323 end 349 end
324 end 350 end
325 351
326 init_config = function(args) 352 init_config = function(args: Args): boolean, string
327 local detected = detect_config_via_args(args) 353 local detected = detect_config_via_args(args)
328 354
329 local ok, err = cfg.init(detected, util.warning) 355 local ok, err = cfg.init(detected, util.warning)
@@ -346,11 +372,11 @@ local lua_example = package.config:sub(1, 1) == "\\"
346 and "<d:\\path\\lua.exe>" 372 and "<d:\\path\\lua.exe>"
347 or "</path/lua>" 373 or "</path/lua>"
348 374
349local function show_status(file, status, err) 375local function show_status(file: string, status: boolean, err?: string): string
350 return (file and file .. " " or "") .. (status and "(ok)" or ("(" .. (err or "not found") ..")")) 376 return (file and file .. " " or "") .. (status and "(ok)" or ("(" .. (err or "not found") ..")"))
351end 377end
352 378
353local function use_to_fix_location(key, what) 379local function use_to_fix_location(key: string, what?: string): string
354 local buf = " ****************************************\n" 380 local buf = " ****************************************\n"
355 buf = buf .. " Use the command\n\n" 381 buf = buf .. " Use the command\n\n"
356 buf = buf .. " luarocks config " .. key .. " " .. (what or "<dir>") .. "\n\n" 382 buf = buf .. " luarocks config " .. key .. " " .. (what or "<dir>") .. "\n\n"
@@ -359,7 +385,7 @@ local function use_to_fix_location(key, what)
359 return buf 385 return buf
360end 386end
361 387
362local function get_config_text(cfg) -- luacheck: ignore 431 388local function get_config_text(cfg: Config): string -- luacheck: ignore 431
363 local deps = require("luarocks.deps") 389 local deps = require("luarocks.deps")
364 390
365 local libdir_ok = deps.check_lua_libdir(cfg.variables) 391 local libdir_ok = deps.check_lua_libdir(cfg.variables)
@@ -398,7 +424,7 @@ local function get_config_text(cfg) -- luacheck: ignore 431
398 end 424 end
399 buf = buf.."\n Rocks trees in use: \n" 425 buf = buf.."\n Rocks trees in use: \n"
400 for _, tree in ipairs(cfg.rocks_trees) do 426 for _, tree in ipairs(cfg.rocks_trees) do
401 if type(tree) == "string" then 427 if tree is string then
402 buf = buf.." "..fs.absolute_name(tree) 428 buf = buf.." "..fs.absolute_name(tree)
403 else 429 else
404 local name = tree.name and " (\""..tree.name.."\")" or "" 430 local name = tree.name and " (\""..tree.name.."\")" or ""
@@ -410,7 +436,7 @@ local function get_config_text(cfg) -- luacheck: ignore 431
410 return buf 436 return buf
411end 437end
412 438
413local function get_parser(description, cmd_modules) 439local function get_parser(description: string, cmd_modules: {string: Module}): Parser
414 local basename = dir.base_name(program) 440 local basename = dir.base_name(program)
415 local parser = argparse( 441 local parser = argparse(
416 basename, "LuaRocks "..cfg.program_version..", the Lua package manager\n\n".. 442 basename, "LuaRocks "..cfg.program_version..", the Lua package manager\n\n"..
@@ -477,7 +503,7 @@ Enabling completion for Fish:
477 :argname("<prefix>") 503 :argname("<prefix>")
478 parser:option("--lua-version", "Which Lua version to use.") 504 parser:option("--lua-version", "Which Lua version to use.")
479 :argname("<ver>") 505 :argname("<ver>")
480 :convert(function(s) return (s:match("^%d+%.%d+$")) end) 506 :convert(function(s: string): string return (s:match("^%d+%.%d+$")) end)
481 parser:option("--tree", "Which tree to operate on.") 507 parser:option("--tree", "Which tree to operate on.")
482 :hidden_name("--to") 508 :hidden_name("--to")
483 parser:flag("--local", "Use the tree in the user's home directory.\n".. 509 parser:flag("--local", "Use the tree in the user's home directory.\n"..
@@ -503,7 +529,7 @@ Enabling completion for Fish:
503 return parser 529 return parser
504end 530end
505 531
506local function get_first_arg() 532local function get_first_arg(): string
507 if not arg then 533 if not arg then
508 return 534 return
509 end 535 end
@@ -524,7 +550,7 @@ end
524-- @param commands table: contains the loaded modules representing commands. 550-- @param commands table: contains the loaded modules representing commands.
525-- @param external_namespace string: where to look for external commands. 551-- @param external_namespace string: where to look for external commands.
526-- @param ... string: Arguments given on the command-line. 552-- @param ... string: Arguments given on the command-line.
527function cmd.run_command(description, commands, external_namespace, ...) 553function cmd.run_command(description: string, commands: {string: string}, external_namespace: string, ...: string)
528 554
529 check_popen() 555 check_popen()
530 556
@@ -539,14 +565,14 @@ function cmd.run_command(description, commands, external_namespace, ...)
539 end 565 end
540 end 566 end
541 567
542 local cmd_modules = {} 568 local cmd_modules: {string: Module} = {}
543 for name, module in pairs(commands) do 569 for name, module in pairs(commands) do
544 local pok, mod = pcall(require, module) 570 local pok, mod = pcall(require, module) as (boolean, Module)
545 if pok and type(mod) == "table" then 571 if pok and mod is Module then
546 local original_command = mod.command 572 local original_command = mod.command
547 if original_command then 573 if original_command then
548 if not mod.add_to_parser then 574 if not mod.add_to_parser then
549 mod.add_to_parser = function(parser) 575 mod.add_to_parser = function(parser: Parser)
550 parser:command(name, mod.help, util.see_also()) 576 parser:command(name, mod.help, util.see_also())
551 :summary(mod.help_summary) 577 :summary(mod.help_summary)
552 :handle_options(false) 578 :handle_options(false)
@@ -554,8 +580,8 @@ function cmd.run_command(description, commands, external_namespace, ...)
554 :args("*") 580 :args("*")
555 end 581 end
556 582
557 mod.command = function(args) 583 mod.command = function(args: Args): boolean, string, integer
558 return original_command(args, unpack(args.input)) 584 return original_command(args, table.unpack(args.input))
559 end 585 end
560 end 586 end
561 cmd_modules[name] = mod 587 cmd_modules[name] = mod
@@ -563,13 +589,13 @@ function cmd.run_command(description, commands, external_namespace, ...)
563 util.warning("command module " .. module .. " does not implement command(), skipping") 589 util.warning("command module " .. module .. " does not implement command(), skipping")
564 end 590 end
565 else 591 else
566 util.warning("failed to load command module " .. module .. ": " .. mod) 592 util.warning("failed to load command module " .. module .. ": " .. tostring(mod))
567 end 593 end
568 end 594 end
569 595
570 local function process_cmdline_vars(...) 596 local function process_cmdline_vars(...: string): table.PackTable<string>, {string : string}
571 local args = pack(...) 597 local args = table.pack(...)
572 local cmdline_vars = {} 598 local cmdline_vars: {string: string} = {}
573 local last = args.n 599 local last = args.n
574 for i = 1, args.n do 600 for i = 1, args.n do
575 if args[i] == "--" then 601 if args[i] == "--" then
@@ -593,9 +619,9 @@ function cmd.run_command(description, commands, external_namespace, ...)
593 return args, cmdline_vars 619 return args, cmdline_vars
594 end 620 end
595 621
596 local args, cmdline_vars = process_cmdline_vars(...) 622 local cmdline_args, cmdline_vars = process_cmdline_vars(...)
597 local parser = get_parser(description, cmd_modules) 623 local parser = get_parser(description, cmd_modules)
598 args = parser:parse(args) 624 local args: Args = parser:parse(cmdline_args) as Args
599 625
600 -- Compatibility for old flag 626 -- Compatibility for old flag
601 if args.nodeps then 627 if args.nodeps then
@@ -627,9 +653,9 @@ function cmd.run_command(description, commands, external_namespace, ...)
627 653
628 -- if the Lua interpreter wasn't explicitly found before cfg.init, 654 -- if the Lua interpreter wasn't explicitly found before cfg.init,
629 -- try again now. 655 -- try again now.
630 local tried 656 local tried: string
631 if not lua_found then 657 if not lua_found then
632 local detected 658 local detected: {string : string}
633 detected, tried = search_lua(cfg.lua_version, args.verbose, cfg.variables.LUA_DIR) 659 detected, tried = search_lua(cfg.lua_version, args.verbose, cfg.variables.LUA_DIR)
634 if detected then 660 if detected then
635 lua_found = true 661 lua_found = true
@@ -683,7 +709,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
683 print(("-"):rep(79)) 709 print(("-"):rep(79))
684 print("Current configuration:") 710 print("Current configuration:")
685 print(("-"):rep(79)) 711 print(("-"):rep(79))
686 print(config.to_string(cfg)) 712 print(config.to_string(cfg as PersistableTable))
687 print(("-"):rep(79)) 713 print(("-"):rep(79))
688 fs.verbose() 714 fs.verbose()
689 end 715 end
@@ -741,7 +767,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
741 767
742 local cmd_mod = cmd_modules[args.command] 768 local cmd_mod = cmd_modules[args.command]
743 769
744 local lock 770 local lock: fs.Lock
745 if cmd_mod.needs_lock and cmd_mod.needs_lock(args) then 771 if cmd_mod.needs_lock and cmd_mod.needs_lock(args) then
746 local ok, err = fs.check_command_permissions(args) 772 local ok, err = fs.check_command_permissions(args)
747 if not ok then 773 if not ok then
@@ -762,7 +788,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
762 end 788 end
763 end 789 end
764 790
765 local call_ok, ok, err, exitcode = xpcall(function() 791 local call_ok, ok, err, exitcode = xpcall(function(): boolean, string, integer
766 return cmd_mod.command(args) 792 return cmd_mod.command(args)
767 end, error_handler) 793 end, error_handler)
768 794
@@ -771,7 +797,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
771 end 797 end
772 798
773 if not call_ok then 799 if not call_ok then
774 die(ok, cmd.errorcodes.CRASH) 800 die(tostring(ok), cmd.errorcodes.CRASH)
775 elseif not ok then 801 elseif not ok then
776 die(err, exitcode) 802 die(err, exitcode)
777 end 803 end