1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
--- Functions for command-line scripts.
--module("luarocks.command_line", package.seeall)
local command_line = {}
local unpack = unpack or table.unpack
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")
local fs = require("luarocks.fs")
local program = util.this_program("luarocks")
--- Display an error message and exit.
-- @param message string: The error message.
-- @param exitcode number: the exitcode to use
local function die(message, exitcode)
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 https://github.com/keplerproject/luarocks/issues):\n"..err)
end
util.printerr("\nError: "..message)
os.exit(exitcode or cfg.errorcodes.UNSPECIFIED)
end
local function replace_tree(flags, args, tree)
tree = dir.normalize(tree)
flags["tree"] = tree
local added = false
for i = 1, #args do
if args[i]:match("%-%-tree=") then
args[i] = "--tree="..tree
added = true
break
end
end
if not added then
args[#args + 1] = "--tree="..tree
end
path.use_tree(tree)
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 command_line.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.ERROR then
die(flags.ERROR.." See --help.")
end
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["verbose"] then -- setting it in the config file will kick-in earlier in the process
cfg.verbose = true
fs.verbose()
end
if flags["timeout"] then -- setting it in the config file will kick-in earlier in the process
local timeout = tonumber(flags["timeout"])
if timeout then
cfg.connection_timeout = timeout
else
die "Argument error: --timeout expects a numeric argument."
end
end
if flags["version"] then
util.printout(program.." "..cfg.program_version)
util.printout(program_description)
util.printout()
os.exit(cfg.errorcodes.OK)
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 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["branch"] then
cfg.branch = flags["branch"]
end
if flags["tree"] then
local named = false
for _, tree in ipairs(cfg.rocks_trees) do
if type(tree) == "table" and flags["tree"] == tree.name then
if not tree.root then
die("Configuration error: tree '"..tree.name.."' has no 'root' field.")
end
replace_tree(flags, args, tree.root)
named = true
break
end
end
if not named then
local fs = require("luarocks.fs")
local root_dir = fs.absolute_name(flags["tree"])
replace_tree(flags, args, root_dir)
end
elseif flags["local"] then
if not cfg.home_tree then
die("The --local flag is meant for operating in a user's home directory.\n"..
"You are running as a superuser, which is intended for system-wide operation.\n"..
"To force using the superuser's home, use --tree explicitly.")
end
replace_tree(flags, args, 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
local protocol, path = dir.split_url(flags["server"])
table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
end
if flags["only-server"] then
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 not fs.current_dir() or fs.current_dir() == "" then
die("Current directory does not exist. Please run LuaRocks from an existing directory.")
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 cmd = require(commands[command])
local xp, ok, err, exitcode = xpcall(function() return cmd.run(unpack(args)) end, function(err)
die(debug.traceback("LuaRocks "..cfg.program_version
.." bug (please report at https://github.com/keplerproject/luarocks/issues).\n"
..err, 2), cfg.errorcodes.CRASH)
end)
if xp and (not ok) then
die(err, exitcode)
end
else
die("Unknown command: "..command)
end
util.run_scheduled_functions()
end
return command_line
|