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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
--- Module implementing the LuaRocks "install" command.
-- Installs binary rocks.
local record install
needs_lock: function(Args): boolean
end
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local repos = require("luarocks.repos")
local fetch = require("luarocks.fetch")
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local repo_writer = require("luarocks.repo_writer")
local remove = require("luarocks.remove")
local search = require("luarocks.search")
local queries = require("luarocks.queries")
local cfg = require("luarocks.core.cfg")
local type Parser = require("luarocks.vendor.argparse").Parser
local type Args = require("luarocks.core.types.args").Args
local type IOpts = require("luarocks.core.types.installs").IOpts
local type Rockspec = require("luarocks.core.types.rockspec").Rockspec
function install.add_to_parser(parser: Parser)
local cmd = parser:command("install", "Install a rock.", util.see_also()) -- luacheck: ignore 431
cmd:argument("rock", "The name of a rock to be fetched from a repository "..
"or a filename of a locally available rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "Version of the rock.")
:args("?")
cmd:flag("--keep", "Do not remove previously installed versions of the "..
"rock after building a new one. This behavior can be made permanent by "..
"setting keep_other_versions=true in the configuration file.")
cmd:flag("--force", "If --keep is not specified, force removal of "..
"previously installed versions if it would break dependencies. "..
"If rock is already installed, reinstall it anyway.")
cmd:flag("--force-fast", "Like --force, but performs a forced removal "..
"without reporting dependency issues.")
cmd:flag("--only-deps --deps-only", "Install only the dependencies of the rock.")
cmd:flag("--no-doc", "Install the rock without its documentation.")
cmd:flag("--verify", "Verify signature of the rockspec or src.rock being "..
"built. If the rockspec or src.rock is being downloaded, LuaRocks will "..
"attempt to download the signature as well. Otherwise, the signature "..
"file should be already available locally in the same directory.\n"..
"You need the signer’s public key in your local keyring for this "..
"option to work properly.")
cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
"and report if it is available for another Lua version.")
util.deps_mode_option(cmd as Parser)
cmd:flag("--no-manifest", "Skip creating/updating the manifest")
cmd:flag("--pin", "If the installed rock is a Lua module, create a "..
"luarocks.lock file listing the exact versions of each dependency found for "..
"this rock (recursively), and store it in the rock's directory. "..
"Ignores any existing luarocks.lock file in the rock's sources.")
-- luarocks build options
parser:flag("--pack-binary-rock"):hidden(true)
parser:option("--branch"):hidden(true)
parser:flag("--sign"):hidden(true)
end
--- Install a binary rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param opts table: installation options
-- @return (string, string) or (nil, string, [string]): Name and version of
-- installed rock if succeeded or nil and an error message followed by an error code.
function install.install_binary_rock(rock_file: string, opts: IOpts): string, string, string
local namespace = opts.namespace
local deps_mode = opts.deps_mode
local name, version, arch = path.parse_name(rock_file)
if not name then
return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
end
if arch ~= "all" and arch ~= cfg.arch then
return nil, "Incompatible architecture "..arch, "arch"
end
if repos.is_installed(name, version) then
if not (opts.force or opts.force_fast) then
util.printout(name .. " " .. version .. " is already installed in " .. path.root_dir(cfg.root_dir))
util.printout("Use --force to reinstall.")
return name, version
end
repo_writer.delete_version(name, version, opts.deps_mode)
end
local install_dir = path.install_dir(name, version)
local rollback = util.schedule_function(function()
fs.delete(install_dir)
fs.remove_dir_if_empty(path.versions_dir(name))
end)
local ok, err, errcode: boolean, string, string
local filename: string
filename, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
if not filename then return nil, err, errcode end
local rockspec: Rockspec
rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
if err then
return nil, "Failed loading rockspec for installed package: " .. err, errcode
end
if opts.deps_mode ~= "none" then
ok, err, errcode = deps.check_external_deps(rockspec, "install")
if err then return nil, err, errcode end
end
if deps_mode ~= "none" then
local deplock_dir = fs.exists(dir.path(".", "luarocks.lock"))
and "."
or install_dir
ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify, deplock_dir)
if err then return nil, err, errcode end
end
ok, err = repo_writer.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode, namespace)
if err then return nil, err end
util.remove_scheduled_function(rollback)
rollback = util.schedule_function(function()
repo_writer.delete_version(name, version, deps_mode)
end)
ok, err = repos.run_hook(rockspec, "post_install")
if err then return nil, err end
util.announce_install(rockspec)
util.remove_scheduled_function(rollback)
return name, version
end
--- Installs the dependencies of a binary rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param opts table: installation options
-- @return (string, string) or (nil, string, [string]): Name and version of
-- the rock whose dependencies were installed if succeeded or nil and an error message
-- followed by an error code.
function install.install_binary_rock_deps(rock_file: string, opts: IOpts): string, string, string
local name, version, arch = path.parse_name(rock_file)
if not name then
return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
end
if arch ~= "all" and arch ~= cfg.arch then
return nil, "Incompatible architecture "..arch, "arch"
end
local install_dir = path.install_dir(name, version)
local ok: boolean
local oks, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
if not oks then return nil, err, errcode end
local rockspec: Rockspec
rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version))
if err then
return nil, "Failed loading rockspec for installed package: "..err, errcode
end
local deplock_dir = fs.exists(dir.path(".", "luarocks.lock"))
and "."
or install_dir
ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify, deplock_dir)
if err then return nil, err, errcode end
util.printout()
util.printout("Successfully installed dependencies for " ..name.." "..version)
return name, version
end
local function install_rock_file_deps(filename: string, opts: IOpts): boolean, string
local name, version = install.install_binary_rock_deps(filename, opts)
if not name then return nil, version end
deps.check_dependencies(nil, opts.deps_mode)
return true
end
local function install_rock_file(filename: string, opts: IOpts): boolean, string
local name, version = install.install_binary_rock(filename, opts)
if not name then return nil, version end
if opts.no_doc then
util.remove_doc_dir(name, version)
end
if (not opts.keep) and not cfg.keep_other_versions then
local ok, err, warn = remove.remove_other_versions(name, version, opts.force, opts.force_fast)
if not ok then
return nil, err
elseif warn then
util.printerr(err)
end
end
deps.check_dependencies(nil, opts.deps_mode)
return true
end
--- Driver function for the "install" command.
-- If an URL or pathname to a binary rock is given, fetches and installs it.
-- If a rockspec or a source rock is given, forwards the request to the "build"
-- command.
-- If a package name is given, forwards the request to "search" and,
-- if returned a result, installs the matching rock.
-- @return boolean or (nil, string, exitcode): True if installation was
-- successful, nil and an error message otherwise. exitcode is optionally returned.
function install.command(args: Args): boolean, string, string
if args.rock:match("%.rockspec$") or args.rock:match("%.src%.rock$") then
local build = require("luarocks.cmd.build")
return build.command(args)
elseif args.rock:match("%.rock$") then
local deps_mode = deps.get_deps_mode(args)
local opts = {
namespace = args.namespace,
keep = not not args.keep,
force = not not args.force,
force_fast = not not args.force_fast,
no_doc = not not args.no_doc,
deps_mode = deps_mode,
verify = not not args.verify,
}
if args.only_deps then
return install_rock_file_deps(args.rock, opts)
else
return install_rock_file(args.rock, opts)
end
else
local url, err = search.find_rock_checking_lua_versions(
queries.new(args.rock, args.namespace, args.version),
args.check_lua_versions)
if not url then
return nil, err
end
util.printout("Installing "..url)
args.rock = url
return install.command(args)
end
end
install.needs_lock = function(args: Args): boolean
if args.pack_binary_rock then
return false
end
return true
end
deps.installer = install.command
return install
|