aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-08-16 16:06:51 +0300
committerV1K1NGbg <victor@ilchev.com>2024-08-16 16:06:51 +0300
commit8ee47fb70d06da6878454aa800b44264a76c36b9 (patch)
tree70df3023775f8e5d139752f43ccfc2551c2fe157
parent2369d7c2830cd3d0a75aaf195e41a56ed3100e0c (diff)
downloadluarocks-8ee47fb70d06da6878454aa800b44264a76c36b9.tar.gz
luarocks-8ee47fb70d06da6878454aa800b44264a76c36b9.tar.bz2
luarocks-8ee47fb70d06da6878454aa800b44264a76c36b9.zip
require, remove
-rw-r--r--src/luarocks/build/builtin.tl2
-rw-r--r--src/luarocks/cmd.tl782
-rw-r--r--src/luarocks/fs.d.tl2
-rw-r--r--src/luarocks/pack.tl17
-rw-r--r--src/luarocks/remove-original.lua136
-rw-r--r--src/luarocks/remove.lua49
-rw-r--r--src/luarocks/remove.tl141
-rw-r--r--src/luarocks/require-original.lua2
-rw-r--r--src/luarocks/require.lua2
-rw-r--r--src/luarocks/require.tl2
10 files changed, 1103 insertions, 32 deletions
diff --git a/src/luarocks/build/builtin.tl b/src/luarocks/build/builtin.tl
index 6b244024..d4bd7fd7 100644
--- a/src/luarocks/build/builtin.tl
+++ b/src/luarocks/build/builtin.tl
@@ -104,7 +104,7 @@ do
104 if bindir then 104 if bindir then
105 install = { bin = {} } 105 install = { bin = {} }
106 for _, file in ipairs(fs.list_dir(bindir)) do 106 for _, file in ipairs(fs.list_dir(bindir)) do
107 table.insert(install.bin, dir.path(bindir, file)) 107 table.insert((install.bin as {string}), dir.path(bindir, file))
108 end 108 end
109 end 109 end
110 110
diff --git a/src/luarocks/cmd.tl b/src/luarocks/cmd.tl
new file mode 100644
index 00000000..e7ea3b19
--- /dev/null
+++ b/src/luarocks/cmd.tl
@@ -0,0 +1,782 @@
1
2--- Functions for command-line scripts.
3local record cmd
4end
5
6local manif = require("luarocks.manif")
7local config = require("luarocks.config")
8local util = require("luarocks.util")
9local path = require("luarocks.path")
10local cfg = require("luarocks.core.cfg")
11local dir = require("luarocks.dir")
12local fun = require("luarocks.fun")
13local fs = require("luarocks.fs")
14local argparse = require("luarocks.vendor.argparse")
15
16local unpack = table.unpack or unpack
17local pack = table.pack or function(...) return { n = select("#", ...), ... } end
18
19local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded")
20if not hc_ok then
21 hardcoded = {}
22end
23
24local program = util.this_program("luarocks")
25
26cmd.errorcodes = {
27 OK = 0,
28 UNSPECIFIED = 1,
29 PERMISSIONDENIED = 2,
30 CONFIGFILE = 3,
31 LOCK = 4,
32 CRASH = 99
33}
34
35local function check_popen()
36 local popen_ok, popen_result = pcall(io.popen, "")
37 if popen_ok then
38 if popen_result then
39 popen_result:close()
40 end
41 else
42 io.stderr:write("Your version of Lua does not support io.popen,\n")
43 io.stderr:write("which is required by LuaRocks. Please check your Lua installation.\n")
44 os.exit(cmd.errorcodes.UNSPECIFIED)
45 end
46end
47
48local process_tree_args
49do
50 local function replace_tree(args, root, tree)
51 root = dir.normalize(root)
52 args.tree = root
53 path.use_tree(tree or root)
54 end
55
56 local function strip_trailing_slashes()
57 if type(cfg.root_dir) == "string" then
58 cfg.root_dir = cfg.root_dir:gsub("/+$", "")
59 else
60 cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "")
61 end
62 cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
63 cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
64 cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "")
65 cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
66 end
67
68 local function set_named_tree(args, name)
69 for _, tree in ipairs(cfg.rocks_trees) do
70 if type(tree) == "table" and name == tree.name then
71 if not tree.root then
72 return nil, "Configuration error: tree '"..tree.name.."' has no 'root' field."
73 end
74 replace_tree(args, tree.root, tree)
75 return true
76 end
77 end
78 return false
79 end
80
81 process_tree_args = function(args, project_dir)
82
83 if args.global then
84 local ok, err = set_named_tree(args, "system")
85 if not ok then
86 return nil, err
87 end
88 elseif args.tree then
89 local named = set_named_tree(args, args.tree)
90 if not named then
91 local root_dir = fs.absolute_name(args.tree)
92 replace_tree(args, root_dir)
93 if (args.deps_mode or cfg.deps_mode) ~= "order" then
94 table.insert(cfg.rocks_trees, 1, { name = "arg", root = root_dir } )
95 end
96 end
97 elseif args["local"] then
98 if fs.is_superuser() then
99 return nil, "The --local flag is meant for operating in a user's home directory.\n"..
100 "You are running as a superuser, which is intended for system-wide operation.\n"..
101 "To force using the superuser's home, use --tree explicitly."
102 else
103 local ok, err = set_named_tree(args, "user")
104 if not ok then
105 return nil, err
106 end
107 end
108 elseif args.project_tree then
109 local tree = args.project_tree
110 table.insert(cfg.rocks_trees, 1, { name = "project", root = tree } )
111 manif.load_rocks_tree_manifests()
112 path.use_tree(tree)
113 elseif project_dir then
114 local project_tree = project_dir .. "/lua_modules"
115 table.insert(cfg.rocks_trees, 1, { name = "project", root = project_tree } )
116 manif.load_rocks_tree_manifests()
117 path.use_tree(project_tree)
118 elseif cfg.local_by_default then
119 local ok, err = set_named_tree(args, "user")
120 if not ok then
121 return nil, err
122 end
123 else
124 local trees = cfg.rocks_trees
125 path.use_tree(trees[#trees])
126 end
127
128 strip_trailing_slashes()
129
130 cfg.variables.ROCKS_TREE = cfg.rocks_dir
131 cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
132
133 return true
134 end
135end
136
137local function process_server_args(args)
138 if args.server then
139 local protocol, pathname = dir.split_url(args.server)
140 table.insert(cfg.rocks_servers, 1, protocol.."://"..pathname)
141 end
142
143 if args.dev then
144 local append_dev = function(s) return dir.path(s, "dev") end
145 local dev_servers = fun.traverse(cfg.rocks_servers, append_dev)
146 cfg.rocks_servers = fun.concat(dev_servers, cfg.rocks_servers)
147 end
148
149 if args.only_server then
150 if args.dev then
151 return nil, "--only-server cannot be used with --dev"
152 end
153 if args.server then
154 return nil, "--only-server cannot be used with --server"
155 end
156 cfg.rocks_servers = { args.only_server }
157 end
158
159 return true
160end
161
162local function error_handler(err)
163 if not debug then
164 return err
165 end
166 local mode = "Arch.: " .. (cfg and cfg.arch or "unknown")
167 if package.config:sub(1, 1) == "\\" then
168 if cfg and cfg.fs_use_modules then
169 mode = mode .. " (fs_use_modules = true)"
170 end
171 end
172 if cfg and cfg.is_binary then
173 mode = mode .. " (binary)"
174 end
175 return debug.traceback("LuaRocks "..cfg.program_version..
176 " bug (please report at https://github.com/luarocks/luarocks/issues).\n"..
177 mode.."\n"..err, 2)
178end
179
180--- Display an error message and exit.
181-- @param message string: The error message.
182-- @param exitcode number: the exitcode to use
183local function die(message, exitcode)
184 assert(type(message) == "string", "bad error, expected string, got: " .. type(message))
185 assert(exitcode == nil or type(exitcode) == "number", "bad error, expected number, got: " .. type(exitcode) .. " - " .. tostring(exitcode))
186 util.printerr("\nError: "..message)
187
188 local ok, err = xpcall(util.run_scheduled_functions, error_handler)
189 if not ok then
190 util.printerr("\nError: "..err)
191 exitcode = cmd.errorcodes.CRASH
192 end
193
194 os.exit(exitcode or cmd.errorcodes.UNSPECIFIED)
195end
196
197local function search_lua(lua_version, verbose, search_at)
198 if search_at then
199 return util.find_lua(search_at, lua_version, verbose)
200 end
201
202 local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":")
203 local all_tried = {}
204 for bindir in (os.getenv("PATH") or ""):gmatch("[^"..path_sep.."]+") do
205 local searchdir = (bindir:gsub("[\\/]+bin[\\/]?$", ""))
206 local detected, tried = util.find_lua(searchdir, lua_version)
207 if detected then
208 return detected
209 else
210 table.insert(all_tried, tried)
211 end
212 end
213 return nil, "Could not find " ..
214 (lua_version and "Lua " .. lua_version or "Lua") ..
215 " in PATH." ..
216 (verbose and " Tried:\n" .. table.concat(all_tried, "\n") or "")
217end
218
219local init_config
220do
221 local detect_config_via_args
222 do
223 local function find_project_dir(project_tree)
224 if project_tree then
225 return project_tree:gsub("[/\\][^/\\]+$", ""), true
226 else
227 local try = "."
228 for _ = 1, 10 do -- FIXME detect when root dir was hit instead
229 if util.exists(try .. "/.luarocks") and util.exists(try .. "/lua_modules") then
230 return dir.normalize(try), false
231 elseif util.exists(try .. "/.luarocks-no-project") then
232 break
233 end
234 try = try .. "/.."
235 end
236 end
237 return nil
238 end
239
240 local function find_default_lua_version(args, project_dir)
241 if hardcoded.FORCE_CONFIG then
242 return nil
243 end
244
245 local dirs = {}
246 if project_dir then
247 table.insert(dirs, dir.path(project_dir, ".luarocks"))
248 end
249 if cfg.homeconfdir then
250 table.insert(dirs, cfg.homeconfdir)
251 end
252 table.insert(dirs, cfg.sysconfdir)
253 for _, d in ipairs(dirs) do
254 local f = dir.path(d, "default-lua-version.lua")
255 local mod, err = loadfile(f, "t")
256 if mod then
257 local pok, ver = pcall(mod)
258 if pok and type(ver) == "string" and ver:match("%d+.%d+") then
259 if args.verbose then
260 util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...")
261 end
262 return ver
263 end
264 end
265 end
266 return nil
267 end
268
269 local function find_version_from_config(dirname)
270 return fun.find(util.lua_versions("descending"), function(v)
271 if util.exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then
272 return v
273 end
274 end)
275 end
276
277 local function detect_lua_via_args(args, project_dir)
278 local lua_version = args.lua_version
279 or find_default_lua_version(args, project_dir)
280 or (project_dir and find_version_from_config(project_dir))
281
282 if args.lua_dir then
283 local detected, err = util.find_lua(args.lua_dir, lua_version)
284 if not detected then
285 local suggestion = (not args.lua_version)
286 and "\nYou may want to specify a different Lua version with --lua-version\n"
287 or ""
288 die(err .. suggestion)
289 end
290 return detected
291 end
292
293 if lua_version then
294 local detected = search_lua(lua_version)
295 if detected then
296 return detected
297 end
298 return {
299 lua_version = lua_version,
300 }
301 end
302
303 return {}
304 end
305
306 detect_config_via_args = function(args)
307 local project_dir, given
308 if not args.no_project then
309 project_dir, given = find_project_dir(args.project_tree)
310 end
311
312 local detected = detect_lua_via_args(args, project_dir)
313 if args.lua_version then
314 detected.given_lua_version = args.lua_version
315 end
316 if args.lua_dir then
317 detected.given_lua_dir = args.lua_dir
318 end
319 if given then
320 detected.given_project_dir = project_dir
321 end
322 detected.project_dir = project_dir
323 return detected
324 end
325 end
326
327 init_config = function(args)
328 local detected = detect_config_via_args(args)
329
330 local ok, err = cfg.init(detected, util.warning)
331 if not ok then
332 return nil, err
333 end
334
335 return (detected.lua_dir ~= nil)
336 end
337end
338
339local variables_help = [[
340Variables:
341 Variables from the "variables" table of the configuration file can be
342 overridden with VAR=VALUE assignments.
343
344]]
345
346local lua_example = package.config:sub(1, 1) == "\\"
347 and "<d:\\path\\lua.exe>"
348 or "</path/lua>"
349
350local function show_status(file, status, err)
351 return (file and file .. " " or "") .. (status and "(ok)" or ("(" .. (err or "not found") ..")"))
352end
353
354local function use_to_fix_location(key, what)
355 local buf = " ****************************************\n"
356 buf = buf .. " Use the command\n\n"
357 buf = buf .. " luarocks config " .. key .. " " .. (what or "<dir>") .. "\n\n"
358 buf = buf .. " to fix the location\n"
359 buf = buf .. " ****************************************\n"
360 return buf
361end
362
363local function get_config_text(cfg) -- luacheck: ignore 431
364 local deps = require("luarocks.deps")
365
366 local libdir_ok = deps.check_lua_libdir(cfg.variables)
367 local incdir_ok = deps.check_lua_incdir(cfg.variables)
368 local lua_ok = cfg.variables.LUA and fs.exists(cfg.variables.LUA)
369
370 local buf = "Configuration:\n"
371 buf = buf.." Lua:\n"
372 buf = buf.." Version : "..cfg.lua_version.."\n"
373 if cfg.luajit_version then
374 buf = buf.." LuaJIT : "..cfg.luajit_version.."\n"
375 end
376 buf = buf.." LUA : "..show_status(cfg.variables.LUA, lua_ok, "interpreter not found").."\n"
377 if not lua_ok then
378 buf = buf .. use_to_fix_location("variables.LUA", lua_example)
379 end
380 buf = buf.." LUA_INCDIR : "..show_status(cfg.variables.LUA_INCDIR, incdir_ok, "lua.h not found").."\n"
381 if lua_ok and not incdir_ok then
382 buf = buf .. use_to_fix_location("variables.LUA_INCDIR")
383 end
384 buf = buf.." LUA_LIBDIR : "..show_status(cfg.variables.LUA_LIBDIR, libdir_ok, "Lua library itself not found").."\n"
385 if lua_ok and not libdir_ok then
386 buf = buf .. use_to_fix_location("variables.LUA_LIBDIR")
387 end
388
389 buf = buf.."\n Configuration files:\n"
390 local conf = cfg.config_files
391 buf = buf.." System : "..show_status(fs.absolute_name(conf.system.file), conf.system.found).."\n"
392 if conf.user.file then
393 buf = buf.." User : "..show_status(fs.absolute_name(conf.user.file), conf.user.found).."\n"
394 else
395 buf = buf.." User : disabled in this LuaRocks installation.\n"
396 end
397 if conf.project then
398 buf = buf.." Project : "..show_status(fs.absolute_name(conf.project.file), conf.project.found).."\n"
399 end
400 buf = buf.."\n Rocks trees in use: \n"
401 for _, tree in ipairs(cfg.rocks_trees) do
402 if type(tree) == "string" then
403 buf = buf.." "..fs.absolute_name(tree)
404 else
405 local name = tree.name and " (\""..tree.name.."\")" or ""
406 buf = buf.." "..fs.absolute_name(tree.root)..name
407 end
408 buf = buf .. "\n"
409 end
410
411 return buf
412end
413
414local function get_parser(description, cmd_modules)
415 local basename = dir.base_name(program)
416 local parser = argparse(
417 basename, "LuaRocks "..cfg.program_version..", the Lua package manager\n\n"..
418 program.." - "..description, variables_help.."Run '"..basename..
419 "' without any arguments to see the configuration.")
420 :help_max_width(80)
421 :add_help_command()
422 :add_complete_command({
423 help_max_width = 100,
424 summary = "Output a shell completion script.",
425 description = [[
426Output a shell completion script.
427
428Enabling completions for Bash:
429
430 Add the following line to your ~/.bashrc:
431 source <(]]..basename..[[ completion bash)
432 or save the completion script to the local completion directory:
433 ]]..basename..[[ completion bash > ~/.local/share/bash-completion/completions/]]..basename..[[
434
435
436Enabling completions for Zsh:
437
438 Save the completion script to a file in your $fpath.
439 You can add a new directory to your $fpath by adding e.g.
440 fpath=(~/.zfunc $fpath)
441 to your ~/.zshrc.
442 Then run:
443 ]]..basename..[[ completion zsh > ~/.zfunc/_]]..basename..[[
444
445
446Enabling completion for Fish:
447
448 Add the following line to your ~/.config/fish/config.fish:
449 ]]..basename..[[ completion fish | source
450 or save the completion script to the local completion directory:
451 ]]..basename..[[ completion fish > ~/.config/fish/completions/]]..basename..[[.fish
452]]})
453 :command_target("command")
454 :require_command(false)
455
456 parser:flag("--version", "Show version info and exit.")
457 :action(function()
458 util.printout(program.." "..cfg.program_version)
459 util.printout(description)
460 util.printout()
461 os.exit(cmd.errorcodes.OK)
462 end)
463 parser:flag("--dev", "Enable the sub-repositories in rocks servers for "..
464 "rockspecs of in-development versions.")
465 parser:option("--server", "Fetch rocks/rockspecs from this server "..
466 "(takes priority over config file).")
467 :hidden_name("--from")
468 parser:option("--only-server", "Fetch rocks/rockspecs from this server only "..
469 "(overrides any entries in the config file).")
470 :argname("<server>")
471 :hidden_name("--only-from")
472 parser:option("--only-sources", "Restrict downloads to paths matching the given URL.")
473 :argname("<url>")
474 :hidden_name("--only-sources-from")
475 parser:option("--namespace", "Specify the rocks server namespace to use.")
476 :convert(string.lower)
477 parser:option("--lua-dir", "Which Lua installation to use.")
478 :argname("<prefix>")
479 parser:option("--lua-version", "Which Lua version to use.")
480 :argname("<ver>")
481 :convert(function(s) return (s:match("^%d+%.%d+$")) end)
482 parser:option("--tree", "Which tree to operate on.")
483 :hidden_name("--to")
484 parser:flag("--local", "Use the tree in the user's home directory.\n"..
485 "To enable it, see '"..program.." help path'.")
486 parser:flag("--global", "Use the system tree when `local_by_default` is `true`.")
487 parser:flag("--no-project", "Do not use project tree even if running from a project folder.")
488 parser:flag("--force-lock", "Attempt to overwrite the lock for commands " ..
489 "that require exclusive access, such as 'install'")
490 parser:flag("--verbose", "Display verbose output of commands executed.")
491 parser:option("--timeout", "Timeout on network operations, in seconds.\n"..
492 "0 means no timeout (wait forever). Default is "..
493 tostring(cfg.connection_timeout)..".")
494 :argname("<seconds>")
495 :convert(tonumber)
496
497 -- Used internally to force the use of a particular project tree
498 parser:option("--project-tree"):hidden(true)
499
500 for _, module in util.sortedpairs(cmd_modules) do
501 module.add_to_parser(parser)
502 end
503
504 return parser
505end
506
507local function get_first_arg()
508 if not arg then
509 return
510 end
511 local first_arg = arg[0]
512 local i = -1
513 while arg[i] do
514 first_arg = arg[i]
515 i = i -1
516 end
517 return first_arg
518end
519
520--- Main command-line processor.
521-- Parses input arguments and calls the appropriate driver function
522-- to execute the action requested on the command-line, forwarding
523-- to it any additional arguments passed by the user.
524-- @param description string: Short summary description of the program.
525-- @param commands table: contains the loaded modules representing commands.
526-- @param external_namespace string: where to look for external commands.
527-- @param ... string: Arguments given on the command-line.
528function cmd.run_command(description, commands, external_namespace, ...)
529
530 check_popen()
531
532 -- Preliminary initialization
533 cfg.init()
534
535 fs.init()
536
537 for _, module_name in ipairs(fs.modules(external_namespace)) do
538 if not commands[module_name] then
539 commands[module_name] = external_namespace.."."..module_name
540 end
541 end
542
543 local cmd_modules = {}
544 for name, module in pairs(commands) do
545 local pok, mod = pcall(require, module)
546 if pok and type(mod) == "table" then
547 local original_command = mod.command
548 if original_command then
549 if not mod.add_to_parser then
550 mod.add_to_parser = function(parser)
551 parser:command(name, mod.help, util.see_also())
552 :summary(mod.help_summary)
553 :handle_options(false)
554 :argument("input")
555 :args("*")
556 end
557
558 mod.command = function(args)
559 return original_command(args, unpack(args.input))
560 end
561 end
562 cmd_modules[name] = mod
563 else
564 util.warning("command module " .. module .. " does not implement command(), skipping")
565 end
566 else
567 util.warning("failed to load command module " .. module .. ": " .. mod)
568 end
569 end
570
571 local function process_cmdline_vars(...)
572 local args = pack(...)
573 local cmdline_vars = {}
574 local last = args.n
575 for i = 1, args.n do
576 if args[i] == "--" then
577 last = i - 1
578 break
579 end
580 end
581 for i = last, 1, -1 do
582 local arg = args[i]
583 if arg:match("^[^-][^=]*=") then
584 local var, val = arg:match("^([A-Z_][A-Z0-9_]*)=(.*)")
585 if val then
586 cmdline_vars[var] = val
587 table.remove(args, i)
588 else
589 die("Invalid assignment: "..arg)
590 end
591 end
592 end
593
594 return args, cmdline_vars
595 end
596
597 local args, cmdline_vars = process_cmdline_vars(...)
598 local parser = get_parser(description, cmd_modules)
599 args = parser:parse(args)
600
601 -- Compatibility for old flag
602 if args.nodeps then
603 args.deps_mode = "none"
604 end
605
606 if args.timeout then -- setting it in the config file will kick-in earlier in the process
607 cfg.connection_timeout = args.timeout
608 end
609
610 if args.command == "config" then
611 if args.key == "lua_version" and args.value then
612 args.lua_version = args.value
613 elseif args.key == "lua_dir" and args.value then
614 args.lua_dir = args.value
615 end
616 end
617
618 -----------------------------------------------------------------------------
619 local lua_found, err = init_config(args)
620 if err then
621 die(err)
622 end
623 -----------------------------------------------------------------------------
624
625 -- Now that the config is fully loaded, reinitialize fs using the full
626 -- feature set.
627 fs.init()
628
629 -- if the Lua interpreter wasn't explicitly found before cfg.init,
630 -- try again now.
631 local tried
632 if not lua_found then
633 local detected
634 detected, tried = search_lua(cfg.lua_version, args.verbose, cfg.variables.LUA_DIR)
635 if detected then
636 lua_found = true
637 cfg.variables.LUA = detected.lua
638 cfg.variables.LUA_DIR = detected.lua_dir
639 cfg.variables.LUA_BINDIR = detected.lua_bindir
640 if args.lua_dir then
641 cfg.variables.LUA_INCDIR = nil
642 cfg.variables.LUA_LIBDIR = nil
643 end
644 else
645 cfg.variables.LUA = nil
646 cfg.variables.LUA_DIR = nil
647 cfg.variables.LUA_BINDIR = nil
648 cfg.variables.LUA_INCDIR = nil
649 cfg.variables.LUA_LIBDIR = nil
650 end
651 end
652
653 if lua_found then
654 assert(cfg.variables.LUA)
655 else
656 -- Fallback producing _some_ Lua configuration based on the running interpreter.
657 -- Most likely won't produce correct results when running from the standalone binary,
658 -- so eventually we need to drop this and outright fail if Lua is not found
659 -- or explictly configured
660 if not cfg.variables.LUA then
661 local first_arg = get_first_arg()
662 local bin_dir = dir.dir_name(fs.absolute_name(first_arg))
663 local exe = dir.base_name(first_arg)
664 exe = exe:match("rocks") and ("lua" .. (cfg.arch:match("win") and ".exe" or "")) or exe
665 local full_path = dir.path(bin_dir, exe)
666 if util.check_lua_version(full_path, cfg.lua_version) then
667 cfg.variables.LUA = dir.path(bin_dir, exe)
668 cfg.variables.LUA_DIR = bin_dir:gsub("[/\\]bin[/\\]?$", "")
669 cfg.variables.LUA_BINDIR = bin_dir
670 cfg.variables.LUA_INCDIR = nil
671 cfg.variables.LUA_LIBDIR = nil
672 end
673 end
674 end
675
676 cfg.lua_found = lua_found
677
678 if cfg.project_dir then
679 cfg.project_dir = fs.absolute_name(cfg.project_dir)
680 end
681
682 if args.verbose then
683 cfg.verbose = true
684 print(("-"):rep(79))
685 print("Current configuration:")
686 print(("-"):rep(79))
687 print(config.to_string(cfg))
688 print(("-"):rep(79))
689 fs.verbose()
690 end
691
692 if (not fs.current_dir()) or fs.current_dir() == "" then
693 die("Current directory does not exist. Please run LuaRocks from an existing directory.")
694 end
695
696 local ok, err = process_tree_args(args, cfg.project_dir)
697 if not ok then
698 die(err)
699 end
700
701 ok, err = process_server_args(args)
702 if not ok then
703 die(err)
704 end
705
706 if args.only_sources then
707 cfg.only_sources_from = args.only_sources
708 end
709
710 for k, v in pairs(cmdline_vars) do
711 cfg.variables[k] = v
712 end
713
714 -- if running as superuser, use system cache dir
715 if fs.is_superuser() then
716 cfg.local_cache = dir.path(fs.system_cache_dir(), "luarocks")
717 end
718
719 if args.no_manifest then
720 cfg.no_manifest = true
721 end
722
723 if not args.command then
724 parser:epilog(variables_help..get_config_text(cfg))
725 util.printout()
726 util.printout(parser:get_help())
727 util.printout()
728 os.exit(cmd.errorcodes.OK)
729 end
730
731 if not cfg.variables["LUA"] and args.command ~= "config" and args.command ~= "help" then
732 local flag = (not cfg.project_tree)
733 and "--local "
734 or ""
735 if args.lua_version then
736 flag = "--lua-version=" .. args.lua_version .. " " .. flag
737 end
738 die((tried or "Lua interpreter not found.") ..
739 "\nPlease set your Lua interpreter with:\n\n" ..
740 " luarocks " .. flag.. "config variables.LUA " .. lua_example .. "\n")
741 end
742
743 local cmd_mod = cmd_modules[args.command]
744
745 local lock
746 if cmd_mod.needs_lock and cmd_mod.needs_lock(args) then
747 local ok, err = fs.check_command_permissions(args)
748 if not ok then
749 die(err, cmd.errorcodes.PERMISSIONDENIED)
750 end
751
752 lock, err = fs.lock_access(path.root_dir(cfg.root_dir), args.force_lock)
753 if not lock then
754 err = args.force_lock
755 and ("failed to force the lock" .. (err and ": " .. err or ""))
756 or (err and err ~= "File exists")
757 and err
758 or "try --force-lock to overwrite the lock"
759
760 die("command '" .. args.command .. "' " ..
761 "requires exclusive write access to " .. path.root_dir(cfg.root_dir) .. " - " ..
762 err, cmd.errorcodes.LOCK)
763 end
764 end
765
766 local call_ok, ok, err, exitcode = xpcall(function()
767 return cmd_mod.command(args)
768 end, error_handler)
769
770 if lock then
771 fs.unlock_access(lock)
772 end
773
774 if not call_ok then
775 die(ok, cmd.errorcodes.CRASH)
776 elseif not ok then
777 die(err, exitcode)
778 end
779 util.run_scheduled_functions()
780end
781
782return cmd
diff --git a/src/luarocks/fs.d.tl b/src/luarocks/fs.d.tl
index 1e593c40..b72bd35a 100644
--- a/src/luarocks/fs.d.tl
+++ b/src/luarocks/fs.d.tl
@@ -66,7 +66,7 @@ local record fs
66 -- command 66 -- command
67 execute_env: function({any: any}, string, ...:string): boolean 67 execute_env: function({any: any}, string, ...:string): boolean
68 -- pack 68 -- pack
69 zip: function(string, string, string): boolean, string 69 zip: function(string, ...:string): boolean, string
70end 70end
71 71
72return fs 72return fs
diff --git a/src/luarocks/pack.tl b/src/luarocks/pack.tl
index c9ebae2e..a1ed796f 100644
--- a/src/luarocks/pack.tl
+++ b/src/luarocks/pack.tl
@@ -21,6 +21,9 @@ local type Tree = t.Tree
21local type q = require("luarocks.core.types.query") 21local type q = require("luarocks.core.types.query")
22local type Query = q.Query 22local type Query = q.Query
23 23
24local type rm = require("luarocks.core.types.rockmanifest")
25local type RockManifest = rm.RockManifest
26local type Entry = rm.RockManifest.Entry
24 27
25--- Create a source rock. 28--- Create a source rock.
26-- Packages a rockspec and its required source files in a rock 29-- Packages a rockspec and its required source files in a rock
@@ -90,7 +93,7 @@ end
90-- @param tree string or nil: An optional tree to pick the package from. 93-- @param tree string or nil: An optional tree to pick the package from.
91-- @return string or (nil, string): The filename of the resulting 94-- @return string or (nil, string): The filename of the resulting
92-- .src.rock file; or nil and an error message. 95-- .src.rock file; or nil and an error message.
93function pack.pack_installed_rock(query: Query, tree: string | Tree) 96function pack.pack_installed_rock(query: Query, tree: string | Tree): string, string
94 97
95 local name, version, repo, repo_url = search.pick_installed_rock(query, tree) 98 local name, version, repo, repo_url = search.pick_installed_rock(query, tree)
96 if not name then 99 if not name then
@@ -114,12 +117,12 @@ function pack.pack_installed_rock(query: Query, tree: string | Tree)
114 117
115 local is_binary = false 118 local is_binary = false
116 if rock_manifest.lib then 119 if rock_manifest.lib then
117 local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(repo), dir.path(temp_dir, "lib"), "exec") 120 local ok, err = copy_back_files(name, version, (rock_manifest.lib as {string: Entry}), path.deploy_lib_dir(repo), dir.path(temp_dir, "lib"), "exec")
118 if not ok then return nil, "Failed copying back files: " .. err end 121 if not ok then return nil, "Failed copying back files: " .. err end
119 is_binary = true 122 is_binary = true
120 end 123 end
121 if rock_manifest.lua then 124 if rock_manifest.lua then
122 local ok, err = copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(repo), dir.path(temp_dir, "lua"), "read") 125 local ok, err = copy_back_files(name, version, (rock_manifest.lua as {string: Entry}), path.deploy_lua_dir(repo), dir.path(temp_dir, "lua"), "read")
123 if not ok then return nil, "Failed copying back files: " .. err end 126 if not ok then return nil, "Failed copying back files: " .. err end
124 end 127 end
125 128
@@ -129,7 +132,7 @@ function pack.pack_installed_rock(query: Query, tree: string | Tree)
129 rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.") 132 rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
130 end 133 end
131 fs.delete(rock_file) 134 fs.delete(rock_file)
132 ok, err = fs.zip(rock_file, unpack(fs.list_dir())) 135 ok, err = fs.zip(rock_file, table.unpack(fs.list_dir()))
133 if not ok then 136 if not ok then
134 return nil, "Failed packing " .. rock_file .. " - " .. err 137 return nil, "Failed packing " .. rock_file .. " - " .. err
135 end 138 end
@@ -138,11 +141,11 @@ function pack.pack_installed_rock(query: Query, tree: string | Tree)
138 return rock_file 141 return rock_file
139end 142end
140 143
141function pack.report_and_sign_local_file(file, err, sign) 144function pack.report_and_sign_local_file(file: string, err: string, sign: boolean): boolean, string
142 if err then 145 if err then
143 return nil, err 146 return nil, err
144 end 147 end
145 local sigfile 148 local sigfile: string
146 if sign then 149 if sign then
147 sigfile, err = signing.sign_file(file) 150 sigfile, err = signing.sign_file(file)
148 util.printout() 151 util.printout()
@@ -157,7 +160,7 @@ function pack.report_and_sign_local_file(file, err, sign)
157 return true 160 return true
158end 161end
159 162
160function pack.pack_binary_rock(name, namespace, version, sign, cmd) 163function pack.pack_binary_rock(name: string, namespace: string, version: string, sign: boolean, cmd: function(): (boolean, string)): boolean, string
161 164
162 -- The --pack-binary-rock option for "luarocks build" basically performs 165 -- The --pack-binary-rock option for "luarocks build" basically performs
163 -- "luarocks build" on a temporary tree and then "luarocks pack". The 166 -- "luarocks build" on a temporary tree and then "luarocks pack". The
diff --git a/src/luarocks/remove-original.lua b/src/luarocks/remove-original.lua
new file mode 100644
index 00000000..e00097fa
--- /dev/null
+++ b/src/luarocks/remove-original.lua
@@ -0,0 +1,136 @@
1local remove = {}
2
3local search = require("luarocks.search")
4local deps = require("luarocks.deps")
5local fetch = require("luarocks.fetch")
6local repos = require("luarocks.repos")
7local repo_writer = require("luarocks.repo_writer")
8local path = require("luarocks.path")
9local util = require("luarocks.util")
10local cfg = require("luarocks.core.cfg")
11local manif = require("luarocks.manif")
12local queries = require("luarocks.queries")
13
14--- Obtain a list of packages that depend on the given set of packages
15-- (where all packages of the set are versions of one program).
16-- @param name string: the name of a program
17-- @param versions array of string: the versions to be deleted.
18-- @return array of string: an empty table if no packages depend on any
19-- of the given list, or an array of strings in "name/version" format.
20local function check_dependents(name, versions, deps_mode)
21 local dependents = {}
22
23 local skip_set = {}
24 skip_set[name] = {}
25 for version, _ in pairs(versions) do
26 skip_set[name][version] = true
27 end
28
29 local local_rocks = {}
30 local query_all = queries.all()
31 search.local_manifest_search(local_rocks, cfg.rocks_dir, query_all)
32 local_rocks[name] = nil
33 for rock_name, rock_versions in pairs(local_rocks) do
34 for rock_version, _ in pairs(rock_versions) do
35 local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version))
36 if rockspec then
37 local _, missing = deps.match_deps(rockspec.dependencies.queries, rockspec.rocks_provided, deps_mode, skip_set)
38 if missing[name] then
39 table.insert(dependents, { name = rock_name, version = rock_version })
40 end
41 end
42 end
43 end
44
45 return dependents
46end
47
48--- Delete given versions of a program.
49-- @param name string: the name of a program
50-- @param versions array of string: the versions to be deleted.
51-- @param deps_mode: string: Which trees to check dependencies for:
52-- "one" for the current default tree, "all" for all trees,
53-- "order" for all trees with priority >= the current default, "none" for no trees.
54-- @return boolean or (nil, string): true on success or nil and an error message.
55local function delete_versions(name, versions, deps_mode)
56
57 for version, _ in pairs(versions) do
58 util.printout("Removing "..name.." "..version.."...")
59 local ok, err = repo_writer.delete_version(name, version, deps_mode)
60 if not ok then return nil, err end
61 end
62
63 return true
64end
65
66function remove.remove_search_results(results, name, deps_mode, force, fast)
67 local versions = results[name]
68
69 local version = next(versions)
70 local second = next(versions, version)
71
72 local dependents = {}
73 if not fast then
74 util.printout("Checking stability of dependencies in the absence of")
75 util.printout(name.." "..table.concat(util.keys(versions), ", ").."...")
76 util.printout()
77 dependents = check_dependents(name, versions, deps_mode)
78 end
79
80 if #dependents > 0 then
81 if force or fast then
82 util.printerr("The following packages may be broken by this forced removal:")
83 for _, dependent in ipairs(dependents) do
84 util.printerr(dependent.name.." "..dependent.version)
85 end
86 util.printerr()
87 else
88 if not second then
89 util.printerr("Will not remove "..name.." "..version..".")
90 util.printerr("Removing it would break dependencies for: ")
91 else
92 util.printerr("Will not remove installed versions of "..name..".")
93 util.printerr("Removing them would break dependencies for: ")
94 end
95 for _, dependent in ipairs(dependents) do
96 util.printerr(dependent.name.." "..dependent.version)
97 end
98 util.printerr()
99 util.printerr("Use --force to force removal (warning: this may break modules).")
100 return nil, "Failed removing."
101 end
102 end
103
104 local ok, err = delete_versions(name, versions, deps_mode)
105 if not ok then return nil, err end
106
107 util.printout("Removal successful.")
108 return true
109end
110
111function remove.remove_other_versions(name, version, force, fast)
112 local results = {}
113 local query = queries.new(name, nil, version, false, nil, "~=")
114 search.local_manifest_search(results, cfg.rocks_dir, query)
115 local warn
116 if results[name] then
117 local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
118 if not ok then -- downgrade failure to a warning
119 warn = err
120 end
121 end
122
123 if not fast then
124 -- since we're not using --keep, this means that all files of the rock being installed
125 -- should be available as non-versioned variants. Double-check that:
126 local rock_manifest, load_err = manif.load_rock_manifest(name, version)
127 local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false)
128 if not ok then
129 return nil, err
130 end
131 end
132
133 return true, nil, warn
134end
135
136return remove
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua
index e00097fa..386bccb0 100644
--- a/src/luarocks/remove.lua
+++ b/src/luarocks/remove.lua
@@ -1,5 +1,7 @@
1local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local pairs = _tl_compat and _tl_compat.pairs or pairs; local table = _tl_compat and _tl_compat.table or table
1local remove = {} 2local remove = {}
2 3
4
3local search = require("luarocks.search") 5local search = require("luarocks.search")
4local deps = require("luarocks.deps") 6local deps = require("luarocks.deps")
5local fetch = require("luarocks.fetch") 7local fetch = require("luarocks.fetch")
@@ -11,12 +13,15 @@ local cfg = require("luarocks.core.cfg")
11local manif = require("luarocks.manif") 13local manif = require("luarocks.manif")
12local queries = require("luarocks.queries") 14local queries = require("luarocks.queries")
13 15
14--- Obtain a list of packages that depend on the given set of packages 16
15-- (where all packages of the set are versions of one program). 17
16-- @param name string: the name of a program 18
17-- @param versions array of string: the versions to be deleted. 19
18-- @return array of string: an empty table if no packages depend on any 20
19-- of the given list, or an array of strings in "name/version" format. 21
22
23
24
20local function check_dependents(name, versions, deps_mode) 25local function check_dependents(name, versions, deps_mode)
21 local dependents = {} 26 local dependents = {}
22 27
@@ -45,17 +50,17 @@ local function check_dependents(name, versions, deps_mode)
45 return dependents 50 return dependents
46end 51end
47 52
48--- Delete given versions of a program. 53
49-- @param name string: the name of a program 54
50-- @param versions array of string: the versions to be deleted. 55
51-- @param deps_mode: string: Which trees to check dependencies for: 56
52-- "one" for the current default tree, "all" for all trees, 57
53-- "order" for all trees with priority >= the current default, "none" for no trees. 58
54-- @return boolean or (nil, string): true on success or nil and an error message. 59
55local function delete_versions(name, versions, deps_mode) 60local function delete_versions(name, versions, deps_mode)
56 61
57 for version, _ in pairs(versions) do 62 for version, _ in pairs(versions) do
58 util.printout("Removing "..name.." "..version.."...") 63 util.printout("Removing " .. name .. " " .. version .. "...")
59 local ok, err = repo_writer.delete_version(name, version, deps_mode) 64 local ok, err = repo_writer.delete_version(name, version, deps_mode)
60 if not ok then return nil, err end 65 if not ok then return nil, err end
61 end 66 end
@@ -72,7 +77,7 @@ function remove.remove_search_results(results, name, deps_mode, force, fast)
72 local dependents = {} 77 local dependents = {}
73 if not fast then 78 if not fast then
74 util.printout("Checking stability of dependencies in the absence of") 79 util.printout("Checking stability of dependencies in the absence of")
75 util.printout(name.." "..table.concat(util.keys(versions), ", ").."...") 80 util.printout(name .. " " .. table.concat((util.keys(versions)), ", ") .. "...")
76 util.printout() 81 util.printout()
77 dependents = check_dependents(name, versions, deps_mode) 82 dependents = check_dependents(name, versions, deps_mode)
78 end 83 end
@@ -81,19 +86,19 @@ function remove.remove_search_results(results, name, deps_mode, force, fast)
81 if force or fast then 86 if force or fast then
82 util.printerr("The following packages may be broken by this forced removal:") 87 util.printerr("The following packages may be broken by this forced removal:")
83 for _, dependent in ipairs(dependents) do 88 for _, dependent in ipairs(dependents) do
84 util.printerr(dependent.name.." "..dependent.version) 89 util.printerr(dependent.name .. " " .. dependent.version)
85 end 90 end
86 util.printerr() 91 util.printerr()
87 else 92 else
88 if not second then 93 if not second then
89 util.printerr("Will not remove "..name.." "..version..".") 94 util.printerr("Will not remove " .. name .. " " .. version .. ".")
90 util.printerr("Removing it would break dependencies for: ") 95 util.printerr("Removing it would break dependencies for: ")
91 else 96 else
92 util.printerr("Will not remove installed versions of "..name..".") 97 util.printerr("Will not remove installed versions of " .. name .. ".")
93 util.printerr("Removing them would break dependencies for: ") 98 util.printerr("Removing them would break dependencies for: ")
94 end 99 end
95 for _, dependent in ipairs(dependents) do 100 for _, dependent in ipairs(dependents) do
96 util.printerr(dependent.name.." "..dependent.version) 101 util.printerr(dependent.name .. " " .. dependent.version)
97 end 102 end
98 util.printerr() 103 util.printerr()
99 util.printerr("Use --force to force removal (warning: this may break modules).") 104 util.printerr("Use --force to force removal (warning: this may break modules).")
@@ -115,14 +120,14 @@ function remove.remove_other_versions(name, version, force, fast)
115 local warn 120 local warn
116 if results[name] then 121 if results[name] then
117 local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast) 122 local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
118 if not ok then -- downgrade failure to a warning 123 if not ok then
119 warn = err 124 warn = err
120 end 125 end
121 end 126 end
122 127
123 if not fast then 128 if not fast then
124 -- since we're not using --keep, this means that all files of the rock being installed 129
125 -- should be available as non-versioned variants. Double-check that: 130
126 local rock_manifest, load_err = manif.load_rock_manifest(name, version) 131 local rock_manifest, load_err = manif.load_rock_manifest(name, version)
127 local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false) 132 local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false)
128 if not ok then 133 if not ok then
diff --git a/src/luarocks/remove.tl b/src/luarocks/remove.tl
new file mode 100644
index 00000000..81935652
--- /dev/null
+++ b/src/luarocks/remove.tl
@@ -0,0 +1,141 @@
1
2local record remove
3end
4
5local search = require("luarocks.search")
6local deps = require("luarocks.deps")
7local fetch = require("luarocks.fetch")
8local repos = require("luarocks.repos")
9local repo_writer = require("luarocks.repo_writer")
10local path = require("luarocks.path")
11local util = require("luarocks.util")
12local cfg = require("luarocks.core.cfg")
13local manif = require("luarocks.manif")
14local queries = require("luarocks.queries")
15
16local type r = require("luarocks.core.types.result")
17local type Result = r.Result
18
19--- Obtain a list of packages that depend on the given set of packages
20-- (where all packages of the set are versions of one program).
21-- @param name string: the name of a program
22-- @param versions array of string: the versions to be deleted.
23-- @return array of string: an empty table if no packages depend on any
24-- of the given list, or an array of strings in "name/version" format.
25local function check_dependents(name: string, versions: {string: any}, deps_mode: string): {Result}
26 local dependents: {Result} = {}
27
28 local skip_set = {}
29 skip_set[name] = {}
30 for version, _ in pairs(versions) do
31 skip_set[name][version] = true
32 end
33
34 local local_rocks = {}
35 local query_all = queries.all()
36 search.local_manifest_search(local_rocks, cfg.rocks_dir, query_all)
37 local_rocks[name] = nil
38 for rock_name, rock_versions in pairs(local_rocks) do
39 for rock_version, _ in pairs(rock_versions) do
40 local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version))
41 if rockspec then
42 local _, missing = deps.match_deps(rockspec.dependencies.queries, rockspec.rocks_provided, deps_mode, skip_set)
43 if missing[name] then
44 table.insert(dependents, { name = rock_name, version = rock_version })
45 end
46 end
47 end
48 end
49
50 return dependents
51end
52
53--- Delete given versions of a program.
54-- @param name string: the name of a program
55-- @param versions array of string: the versions to be deleted.
56-- @param deps_mode: string: Which trees to check dependencies for:
57-- "one" for the current default tree, "all" for all trees,
58-- "order" for all trees with priority >= the current default, "none" for no trees.
59-- @return boolean or (nil, string): true on success or nil and an error message.
60local function delete_versions(name: string, versions: {string: any}, deps_mode: string): boolean, string
61
62 for version, _ in pairs(versions) do
63 util.printout("Removing "..name.." "..version.."...")
64 local ok, err = repo_writer.delete_version(name, version, deps_mode)
65 if not ok then return nil, err end
66 end
67
68 return true
69end
70
71function remove.remove_search_results(results: {string : {string : {Result}}}, name: string, deps_mode: string, force: boolean, fast: boolean): boolean, string
72 local versions = results[name]
73
74 local version = next(versions)
75 local second = next(versions, version)
76
77 local dependents = {}
78 if not fast then
79 util.printout("Checking stability of dependencies in the absence of")
80 util.printout(name.." "..table.concat((util.keys(versions) as {string | number}), ", ").."...")
81 util.printout()
82 dependents = check_dependents(name, versions, deps_mode)
83 end
84
85 if #dependents > 0 then
86 if force or fast then
87 util.printerr("The following packages may be broken by this forced removal:")
88 for _, dependent in ipairs(dependents) do
89 util.printerr(dependent.name.." "..dependent.version)
90 end
91 util.printerr()
92 else
93 if not second then
94 util.printerr("Will not remove "..name.." "..version..".")
95 util.printerr("Removing it would break dependencies for: ")
96 else
97 util.printerr("Will not remove installed versions of "..name..".")
98 util.printerr("Removing them would break dependencies for: ")
99 end
100 for _, dependent in ipairs(dependents) do
101 util.printerr(dependent.name.." "..dependent.version)
102 end
103 util.printerr()
104 util.printerr("Use --force to force removal (warning: this may break modules).")
105 return nil, "Failed removing."
106 end
107 end
108
109 local ok, err = delete_versions(name, versions, deps_mode)
110 if not ok then return nil, err end
111
112 util.printout("Removal successful.")
113 return true
114end
115
116function remove.remove_other_versions(name: string, version: string, force: boolean, fast: boolean): boolean, string, string
117 local results = {}
118 local query = queries.new(name, nil, version, false, nil, "~=")
119 search.local_manifest_search(results, cfg.rocks_dir, query)
120 local warn: string
121 if results[name] then
122 local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
123 if not ok then -- downgrade failure to a warning
124 warn = err
125 end
126 end
127
128 if not fast then
129 -- since we're not using --keep, this means that all files of the rock being installed
130 -- should be available as non-versioned variants. Double-check that:
131 local rock_manifest, load_err = manif.load_rock_manifest(name, version)
132 local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false)
133 if not ok then
134 return nil, err
135 end
136 end
137
138 return true, nil, warn
139end
140
141return remove
diff --git a/src/luarocks/require-original.lua b/src/luarocks/require-original.lua
new file mode 100644
index 00000000..902bd1a3
--- /dev/null
+++ b/src/luarocks/require-original.lua
@@ -0,0 +1,2 @@
1--- Retained for compatibility reasons only. Use luarocks.loader instead.
2return require("luarocks.loader")
diff --git a/src/luarocks/require.lua b/src/luarocks/require.lua
index 902bd1a3..5b7ca3c3 100644
--- a/src/luarocks/require.lua
+++ b/src/luarocks/require.lua
@@ -1,2 +1,2 @@
1--- Retained for compatibility reasons only. Use luarocks.loader instead. 1
2return require("luarocks.loader") 2return require("luarocks.loader")
diff --git a/src/luarocks/require.tl b/src/luarocks/require.tl
new file mode 100644
index 00000000..902bd1a3
--- /dev/null
+++ b/src/luarocks/require.tl
@@ -0,0 +1,2 @@
1--- Retained for compatibility reasons only. Use luarocks.loader instead.
2return require("luarocks.loader")