aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-07-28 00:12:23 +0300
committerV1K1NGbg <victor@ilchev.com>2024-08-05 20:49:17 +0300
commit00cb13ccd83adad7d8816ada99f6aae4a47d849d (patch)
treeece0a640002e25628b4a7698683f328755ab22f4
parent7101268df03250c371bec9cc25de791ae790d22f (diff)
downloadluarocks-00cb13ccd83adad7d8816ada99f6aae4a47d849d.tar.gz
luarocks-00cb13ccd83adad7d8816ada99f6aae4a47d849d.tar.bz2
luarocks-00cb13ccd83adad7d8816ada99f6aae4a47d849d.zip
util test
-rw-r--r--src/luarocks/cmd/install.lua2
-rw-r--r--src/luarocks/type_check.tl213
-rw-r--r--src/luarocks/util.lua643
-rw-r--r--src/luarocks/util.tl1
4 files changed, 858 insertions, 1 deletions
diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua
index 4f27e471..b50271f0 100644
--- a/src/luarocks/cmd/install.lua
+++ b/src/luarocks/cmd/install.lua
@@ -54,7 +54,7 @@ function install.add_to_parser(parser)
54 parser:flag("--sign"):hidden(true) 54 parser:flag("--sign"):hidden(true)
55end 55end
56 56
57install.opts = util.opts_table("install.opts", { --WORK 57install.opts = util.opts_table("install.opts", { --WORK util.opts_table doesn't exist. Make a record
58 namespace = "string?", 58 namespace = "string?",
59 keep = "boolean", 59 keep = "boolean",
60 force = "boolean", 60 force = "boolean",
diff --git a/src/luarocks/type_check.tl b/src/luarocks/type_check.tl
new file mode 100644
index 00000000..0e8ce60f
--- /dev/null
+++ b/src/luarocks/type_check.tl
@@ -0,0 +1,213 @@
1
2local type_check = {}
3
4local cfg = require("luarocks.core.cfg")
5local fun = require("luarocks.fun")
6local util = require("luarocks.util")
7local vers = require("luarocks.core.vers")
8--------------------------------------------------------------------------------
9
10-- A magic constant that is not used anywhere in a schema definition
11-- and retains equality when the table is deep-copied.
12type_check.MAGIC_PLATFORMS = 0xEBABEFAC
13
14do
15 local function fill_in_version(tbl, version)
16 for _, v in pairs(tbl) do
17 if v is table then
18 if v._version == nil then
19 v._version = version
20 end
21 fill_in_version(v)
22 end
23 end
24 end
25
26 local function expand_magic_platforms(tbl)
27 for k,v in pairs(tbl) do
28 if v == type_check.MAGIC_PLATFORMS then
29 tbl[k] = {
30 _any = util.deep_copy(tbl)
31 }
32 tbl[k]._any[k] = nil
33 elseif type(v) == "table" then
34 expand_magic_platforms(v)
35 end
36 end
37 end
38
39 -- Build a table of schemas.
40 -- @param versions a table where each key is a version number as a string,
41 -- and the value is a schema specification. Schema versions are considered
42 -- incremental: version "2.0" only needs to specify what's new/changed from
43 -- version "1.0".
44 function type_check.declare_schemas(inputs)
45 local schemas = {}
46 local parent_version
47
48 local versions = fun.reverse_in(fun.sort_in(util.keys(inputs), vers.compare_versions))
49
50 for _, version in ipairs(versions) do
51 local schema = inputs[version]
52 if parent_version ~= nil then
53 local copy = util.deep_copy(schemas[parent_version])
54 util.deep_merge(copy, schema)
55 schema = copy
56 end
57 fill_in_version(schema, version)
58 expand_magic_platforms(schema)
59 parent_version = version
60 schemas[version] = schema
61 end
62
63 return schemas, versions
64 end
65end
66
67--------------------------------------------------------------------------------
68
69local function check_version(version, typetbl, context)
70 local typetbl_version = typetbl._version or "1.0"
71 if vers.compare_versions(typetbl_version, version) then
72 if context == "" then
73 return nil, "Invalid rockspec_format version number in rockspec? Please fix rockspec accordingly."
74 else
75 return nil, context.." is not supported in rockspec format "..version.." (requires version "..typetbl_version.."), please fix the rockspec_format field accordingly."
76 end
77 end
78 return true
79end
80
81--- Type check an object.
82-- The object is compared against an archetypical value
83-- matching the expected type -- the actual values don't matter,
84-- only their types. Tables are type checked recursively.
85-- @param version string: The version of the item.
86-- @param item any: The object being checked.
87-- @param typetbl any: The type-checking table for the object.
88-- @param context string: A string indicating the "context" where the
89-- error occurred (the full table path), for error messages.
90-- @return boolean or (nil, string): true if type checking
91-- succeeded, or nil and an error message if it failed.
92-- @see type_check_table
93local function type_check_item(version, item, typetbl, context)
94 assert(type(version) == "string")
95
96 if typetbl._version and typetbl._version ~= "1.0" then
97 local ok, err = check_version(version, typetbl, context)
98 if not ok then
99 return nil, err
100 end
101 end
102
103 local item_type = type(item) or "nil"
104 local expected_type = typetbl._type or "table"
105
106 if expected_type == "number" then
107 if not tonumber(item) then
108 return nil, "Type mismatch on field "..context..": expected a number"
109 end
110 elseif expected_type == "string" then
111 if item_type ~= "string" then
112 return nil, "Type mismatch on field "..context..": expected a string, got "..item_type
113 end
114 local pattern = typetbl._pattern
115 if pattern then
116 if not item:match("^"..pattern.."$") then
117 local what = typetbl._name or ("'"..pattern.."'")
118 return nil, "Type mismatch on field "..context..": invalid value '"..item.."' does not match " .. what
119 end
120 end
121 elseif expected_type == "table" then
122 if item_type ~= expected_type then
123 return nil, "Type mismatch on field "..context..": expected a table"
124 else
125 return type_check.type_check_table(version, item, typetbl, context)
126 end
127 elseif item_type ~= expected_type then
128 return nil, "Type mismatch on field "..context..": expected "..expected_type
129 end
130 return true
131end
132
133local function mkfield(context, field)
134 if context == "" then
135 return tostring(field)
136 elseif type(field) == "string" then
137 return context.."."..field
138 else
139 return context.."["..tostring(field).."]"
140 end
141end
142
143--- Type check the contents of a table.
144-- The table's contents are compared against a reference table,
145-- which contains the recognized fields, with archetypical values
146-- matching the expected types -- the actual values of items in the
147-- reference table don't matter, only their types (ie, for field x
148-- in tbl that is correctly typed, type(tbl.x) == type(types.x)).
149-- If the reference table contains a field called MORE, then
150-- unknown fields in the checked table are accepted.
151-- If it contains a field called ANY, then its type will be
152-- used to check any unknown fields. If a field is prefixed
153-- with MUST_, it is mandatory; its absence from the table is
154-- a type error.
155-- Tables are type checked recursively.
156-- @param version string: The version of tbl.
157-- @param tbl table: The table to be type checked.
158-- @param typetbl table: The type-checking table, containing
159-- values for recognized fields in the checked table.
160-- @param context string: A string indicating the "context" where the
161-- error occurred (such as the name of the table the item is a part of),
162-- to be used by error messages.
163-- @return boolean or (nil, string): true if type checking
164-- succeeded, or nil and an error message if it failed.
165function type_check.type_check_table(version, tbl, typetbl, context)
166 assert(type(version) == "string")
167 assert(type(tbl) == "table")
168 assert(type(typetbl) == "table")
169
170 local ok, err = check_version(version, typetbl, context)
171 if not ok then
172 return nil, err
173 end
174
175 for k, v in pairs(tbl) do
176 local t = typetbl[k] or typetbl._any
177 if t then
178 local ok, err = type_check_item(version, v, t, mkfield(context, k))
179 if not ok then return nil, err end
180 elseif typetbl._more then
181 -- Accept unknown field
182 else
183 if not cfg.accept_unknown_fields then
184 return nil, "Unknown field "..k
185 end
186 end
187 end
188 for k, v in pairs(typetbl) do
189 if k:sub(1,1) ~= "_" and v._mandatory then
190 if not tbl[k] then
191 return nil, "Mandatory field "..mkfield(context, k).." is missing."
192 end
193 end
194 end
195 return true
196end
197
198function type_check.check_undeclared_globals(globals, typetbl)
199 local undeclared = {}
200 for glob, _ in pairs(globals) do
201 if not (typetbl[glob] or typetbl["MUST_"..glob]) then
202 table.insert(undeclared, glob)
203 end
204 end
205 if #undeclared == 1 then
206 return nil, "Unknown variable: "..undeclared[1]
207 elseif #undeclared > 1 then
208 return nil, "Unknown variables: "..table.concat(undeclared, ", ")
209 end
210 return true
211end
212
213return type_check
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
new file mode 100644
index 00000000..59aff9a7
--- /dev/null
+++ b/src/luarocks/util.lua
@@ -0,0 +1,643 @@
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 debug = _tl_compat and _tl_compat.debug or debug; local io = _tl_compat and _tl_compat.io or io; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local os = _tl_compat and _tl_compat.os or os; local package = _tl_compat and _tl_compat.package or package; local pairs = _tl_compat and _tl_compat.pairs or pairs; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table; local _tl_table_unpack = unpack or table.unpack
2
3
4
5
6
7local core = require("luarocks.core.util")
8local cfg = require("luarocks.core.cfg")
9
10local util = {Fn = {}, Parser = {}, }
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
39util.cleanup_path = core.cleanup_path
40util.split_string = core.split_string
41util.sortedpairs = core.sortedpairs
42util.deep_merge = core.deep_merge
43util.deep_merge_under = core.deep_merge_under
44util.popen_read = core.popen_read
45util.show_table = core.show_table
46util.printerr = core.printerr
47util.warning = core.warning
48util.keys = core.keys
49util.matchquote = core.matchquote
50
51
52
53
54
55
56local scheduled_functions = {}
57
58
59
60
61
62
63
64
65function util.schedule_function(f, ...)
66 local item = { fn = f, args = table.pack(...) }
67 table.insert(scheduled_functions, item)
68 return item
69end
70
71
72
73
74
75function util.remove_scheduled_function(item)
76 for k, v in ipairs(scheduled_functions) do
77 if v == item then
78 table.remove(scheduled_functions, k)
79 return
80 end
81 end
82end
83
84
85
86
87
88
89function util.run_scheduled_functions()
90 local fs = require("luarocks.fs")
91 if fs.change_dir_to_root then
92 fs.change_dir_to_root()
93 end
94 for i = #scheduled_functions, 1, -1 do
95 local item = scheduled_functions[i]
96 item.fn(_tl_table_unpack(item.args, 1, item.args.n))
97 end
98end
99
100local var_format_pattern = "%$%((%a[%a%d_]+)%)"
101
102
103
104
105
106
107
108
109
110
111
112function util.warn_if_not_used(var_defs, needed_set, msg)
113 local seen = {}
114 for _, val in pairs(var_defs) do
115 for used in val:gmatch(var_format_pattern) do
116 seen[used] = true
117 end
118 end
119 for var, _ in pairs(needed_set) do
120 if not seen[var] then
121 util.warning(msg:format(var))
122 end
123 end
124end
125
126
127
128
129local function warn_failed_matches(line)
130 local any_failed = false
131 if line:match(var_format_pattern) then
132 for unmatched in line:gmatch(var_format_pattern) do
133 util.warning("unmatched variable " .. unmatched)
134 any_failed = true
135 end
136 end
137 return any_failed
138end
139
140
141
142
143
144
145
146
147
148function util.variable_substitutions(tbl, vars)
149
150 local updated = {}
151 for k, v in pairs(tbl) do
152 if type(v) == "string" then
153 updated[k] = string.gsub(v, var_format_pattern, vars)
154 if warn_failed_matches(updated[k]) then
155 updated[k] = updated[k]:gsub(var_format_pattern, "")
156 end
157 end
158 end
159 for k, v in pairs(updated) do
160 tbl[k] = v
161 end
162end
163
164function util.lua_versions(sort)
165 local versions = { "5.1", "5.2", "5.3", "5.4" }
166 local i = 0
167 if sort == "descending" then
168 i = #versions + 1
169 return function()
170 i = i - 1
171 return versions[i]
172 end
173 else
174 return function()
175 i = i + 1
176 return versions[i]
177 end
178 end
179end
180
181function util.lua_path_variables()
182 local lpath_var = "LUA_PATH"
183 local lcpath_var = "LUA_CPATH"
184
185 local lv = cfg.lua_version:gsub("%.", "_")
186 if lv ~= "5_1" then
187 if os.getenv("LUA_PATH_" .. lv) then
188 lpath_var = "LUA_PATH_" .. lv
189 end
190 if os.getenv("LUA_CPATH_" .. lv) then
191 lcpath_var = "LUA_CPATH_" .. lv
192 end
193 end
194 return lpath_var, lcpath_var
195end
196
197function util.starts_with(s, prefix)
198 return s:sub(1, #prefix) == prefix
199end
200
201
202function util.printout(...)
203 io.stdout:write(table.concat({ ... }, "\t"))
204 io.stdout:write("\n")
205end
206
207function util.title(msg, porcelain, underline)
208 if porcelain then return end
209 util.printout()
210 util.printout(msg)
211 util.printout((underline or "-"):rep(#msg))
212 util.printout()
213end
214
215function util.this_program(default)
216 local i = 1
217 local last, cur = default, default
218 while i do
219 local dbg = debug and debug.getinfo(i, "S")
220 if not dbg then break end
221 last = cur
222 cur = dbg.source
223 i = i + 1
224 end
225 local prog = last:sub(1, 1) == "@" and last:sub(2) or last
226
227
228 local lrdir, binpath = prog:match("^(.*)/lib/luarocks/rocks%-[0-9.]*/[^/]+/[^/]+(/bin/[^/]+)$")
229 if lrdir then
230
231 return lrdir .. binpath
232 end
233
234 return prog
235end
236
237function util.format_rock_name(name, namespace, version)
238 return (namespace and namespace .. "/" or "") .. name .. (version and " " .. version or "")
239end
240
241function util.deps_mode_option(parser, program)
242
243 parser:option("--deps-mode", "How to handle dependencies. Four modes are supported:\n" ..
244 "* all - use all trees from the rocks_trees list for finding dependencies\n" ..
245 "* one - use only the current tree (possibly set with --tree)\n" ..
246 "* order - use trees based on order (use the current tree and all " ..
247 "trees below it on the rocks_trees list)\n" ..
248 "* none - ignore dependencies altogether.\n" ..
249 "The default mode may be set with the deps_mode entry in the configuration file.\n" ..
250 'The current default is "' .. cfg.deps_mode .. '".\n' ..
251 "Type '" .. util.this_program(program or "luarocks") .. "' with no " ..
252 "arguments to see your list of rocks trees."):
253 argname("<mode>"):
254 choices({ "all", "one", "order", "none" })
255 parser:flag("--nodeps"):hidden(true)
256end
257
258function util.see_help(command, program)
259 return "See '" .. util.this_program(program or "luarocks") .. ' help' .. (command and " " .. command or "") .. "'."
260end
261
262function util.see_also(text)
263 local see_also = "See also:\n"
264 if text then
265 see_also = see_also .. text .. "\n"
266 end
267 return see_also .. " '" .. util.this_program("luarocks") .. " help' for general options and configuration."
268end
269
270function util.announce_install(rockspec)
271 local path = require("luarocks.path")
272
273 local suffix = ""
274 if rockspec.description and rockspec.description.license then
275 suffix = " (license: " .. rockspec.description.license .. ")"
276 end
277
278 util.printout(rockspec.name .. " " .. rockspec.version .. " is now installed in " .. path.root_dir(cfg.root_dir) .. suffix)
279 util.printout()
280end
281
282
283
284
285
286
287
288local function collect_rockspecs(versions, paths, unnamed_paths, subdir)
289 local fs = require("luarocks.fs")
290 local dir = require("luarocks.dir")
291 local path = require("luarocks.path")
292 local vers = require("luarocks.core.vers")
293 if fs.is_dir(subdir) then
294 for file in fs.dir(subdir) do
295 file = dir.path(subdir, file)
296
297 if file:match("rockspec$") and fs.is_file(file) then
298 local rock, version = path.parse_name(file)
299
300 if rock then
301 if not versions[rock] or vers.compare_versions(version, versions[rock]) then
302 versions[rock] = version
303 paths[rock] = file
304 end
305 else
306 table.insert(unnamed_paths, file)
307 end
308 end
309 end
310 end
311end
312
313
314
315function util.get_default_rockspec()
316
317 local versions = {}
318 local paths = {}
319 local unnamed_paths = {}
320
321 collect_rockspecs(versions, paths, unnamed_paths, ".")
322 collect_rockspecs(versions, paths, unnamed_paths, "rockspec")
323 collect_rockspecs(versions, paths, unnamed_paths, "rockspecs")
324
325 if #unnamed_paths > 0 then
326
327
328 if #unnamed_paths > 1 then
329 return nil, "Please specify which rockspec file to use."
330 else
331 return unnamed_paths[1]
332 end
333 else
334 local fs = require("luarocks.fs")
335 local dir = require("luarocks.dir")
336 local basename = dir.base_name(fs.current_dir())
337
338 if paths[basename] then
339 return paths[basename]
340 end
341
342 local rock = next(versions)
343
344 if rock then
345
346 if next(versions, rock) ~= nil then
347 return nil, "Please specify which rockspec file to use."
348 else
349 return paths[rock]
350 end
351 else
352 return nil, "Argument missing: please specify a rockspec to use on current directory."
353 end
354 end
355end
356
357
358
359
360function util.LQ(s)
361 return ("%q"):format(s)
362end
363
364
365
366
367function util.split_namespace(ns_name)
368 local p1, p2 = ns_name:match("^([^/]+)/([^/]+)$")
369 if p1 then
370 return p2, p1
371 end
372 return ns_name
373end
374
375
376function util.namespaced_name_action(args, target, ns_name)
377
378 if not ns_name then
379 return
380 end
381
382 if ns_name:match("%.rockspec$") or ns_name:match("%.rock$") then
383 args[target] = ns_name
384 else
385 local name, namespace = util.split_namespace(ns_name)
386 args[target] = name:lower()
387 if namespace then
388 args.namespace = namespace:lower()
389 end
390 end
391end
392
393function util.deep_copy(tbl)
394 local copy = {}
395 for k, v in pairs(tbl) do
396 if type(v) == "table" then
397 copy[k] = util.deep_copy(v)
398 else
399 copy[k] = v
400 end
401 end
402 return copy
403end
404
405
406
407
408function util.exists(file)
409 local fd, _, code = io.open(file, "r")
410 if code == 13 then
411
412
413 return true
414 end
415 if fd then
416 fd:close()
417 return true
418 end
419 return false
420end
421
422function util.lua_is_wrapper(interp)
423 local fd, err = io.open(interp, "r")
424 if not fd then
425 return nil, err
426 end
427 local data
428 data, err = fd:read(1000)
429 fd:close()
430 if not data then
431 return nil, err
432 end
433 return not not data:match("LUAROCKS_SYSCONFDIR")
434end
435
436do
437 local function Q(pathname)
438 if pathname:match("^.:") then
439 return pathname:sub(1, 2) .. '"' .. pathname:sub(3) .. '"'
440 end
441 return '"' .. pathname .. '"'
442 end
443
444 function util.check_lua_version(lua, luaver)
445 if not util.exists(lua) then
446 return nil
447 end
448 local lv = util.popen_read(Q(lua) .. ' -e "io.write(_VERSION:sub(5))"')
449 if lv == "" then
450 return nil
451 end
452 if luaver and luaver ~= lv then
453 return nil
454 end
455 return lv
456 end
457
458 function util.get_luajit_version()
459 if cfg.cache.luajit_version_checked then
460 return cfg.cache.luajit_version
461 end
462 cfg.cache.luajit_version_checked = true
463
464 if not cfg.variables.LUA then
465 return nil
466 end
467
468 local ljv
469 if cfg.lua_version == "5.1" then
470
471 ljv = util.popen_read(Q(cfg.variables.LUA) .. ' -e "io.write(tostring(jit and jit.version:gsub([[^%S+ (%S+).*]], [[%1]])))"')
472 if ljv == "nil" then
473 ljv = nil
474 end
475 end
476 cfg.cache.luajit_version = ljv
477 return ljv
478 end
479
480 local find_lua_bindir
481 do
482 local exe_suffix = (package.config:sub(1, 1) == "\\" and ".exe" or "")
483
484 local function insert_lua_variants(names, luaver)
485 local variants = {
486 "lua" .. luaver .. exe_suffix,
487 "lua" .. luaver:gsub("%.", "") .. exe_suffix,
488 "lua-" .. luaver .. exe_suffix,
489 "lua-" .. luaver:gsub("%.", "") .. exe_suffix,
490 }
491 for _, name in ipairs(variants) do
492 table.insert(names, name)
493 end
494 end
495
496 find_lua_bindir = function(prefix, luaver, verbose)
497 local names = {}
498 if luaver then
499 insert_lua_variants(names, luaver)
500 else
501 for v in util.lua_versions("descending") do
502 insert_lua_variants(names, v)
503 end
504 end
505 if luaver == "5.1" or not luaver then
506 table.insert(names, "luajit" .. exe_suffix)
507 end
508 table.insert(names, "lua" .. exe_suffix)
509
510 local tried = {}
511 local dir_sep = package.config:sub(1, 1)
512 for _, d in ipairs({ prefix .. dir_sep .. "bin", prefix }) do
513 for _, name in ipairs(names) do
514 local lua = d .. dir_sep .. name
515 local is_wrapper, err = util.lua_is_wrapper(lua)
516 if is_wrapper == false then
517 local lv = util.check_lua_version(lua, luaver)
518 if lv then
519 return lua, d, lv
520 end
521 elseif is_wrapper == true or err == nil then
522 table.insert(tried, lua)
523 else
524 table.insert(tried, string.format("%-13s (%s)", lua, err))
525 end
526 end
527 end
528 local interp = luaver and
529 ("Lua " .. luaver .. " interpreter") or
530 "Lua interpreter"
531 return nil, interp .. " not found at " .. prefix .. "\n" ..
532 (verbose and "Tried:\t" .. table.concat(tried, "\n\t") or "")
533 end
534 end
535
536 function util.find_lua(prefix, luaver, verbose)
537 local lua, bindir
538 lua, bindir, luaver = find_lua_bindir(prefix, luaver, verbose)
539 if not lua then
540 return nil, bindir
541 end
542
543 return {
544 lua_version = luaver,
545 lua = lua,
546 lua_dir = prefix,
547 lua_bindir = bindir,
548 }
549 end
550end
551
552
553
554function util.opts_table(type_name, valid_opts) --! TEMP
555 local opts_mt = {}
556
557 opts_mt.__index = opts_mt
558
559 function opts_mt.type()
560 return type_name
561 end
562
563 return function(opts)
564 for k, v in pairs(opts) do
565 local tv = type(v)
566 if not valid_opts[k] then
567 error("invalid option: "..k)
568 end
569 local vo, optional = valid_opts[k]:match("^(.-)(%??)$")
570 if not (tv == vo or (optional == "?" and tv == nil)) then
571 error("invalid type option: "..k.." - got "..tv..", expected "..vo)
572 end
573 end
574 for k, v in pairs(valid_opts) do
575 if (not v:find("?", 1, true)) and opts[k] == nil then
576 error("missing option: "..k)
577 end
578 end
579 return setmetatable(opts, opts_mt)
580 end
581end
582
583
584
585
586function util.get_rocks_provided(rockspec)
587
588 if not rockspec and cfg.cache.rocks_provided then
589 return cfg.cache.rocks_provided
590 end
591
592 local rocks_provided = {}
593
594 local lv = cfg.lua_version
595
596 rocks_provided["lua"] = lv .. "-1"
597
598 if lv == "5.2" then
599 rocks_provided["bit32"] = lv .. "-1"
600 end
601
602 if lv == "5.3" or lv == "5.4" then
603 rocks_provided["utf8"] = lv .. "-1"
604 end
605
606 if lv == "5.1" then
607 local ljv = util.get_luajit_version()
608 if ljv then
609 rocks_provided["luabitop"] = ljv .. "-1"
610 if (not rockspec) or rockspec:format_is_at_least("3.0") then
611 rocks_provided["luajit"] = ljv .. "-1"
612 end
613 end
614 end
615
616 if cfg.rocks_provided then
617 util.deep_merge_under(rocks_provided, cfg.rocks_provided)
618 end
619
620 if not rockspec then
621 cfg.cache.rocks_provided = rocks_provided
622 end
623
624 return rocks_provided
625end
626
627function util.remove_doc_dir(name, version)
628 local path = require("luarocks.path")
629 local fs = require("luarocks.fs")
630 local dir = require("luarocks.dir")
631
632 local install_dir = path.install_dir(name, version)
633 for _, f in ipairs(fs.list_dir(install_dir)) do
634 local doc_dirs = { "doc", "docs" }
635 for _, d in ipairs(doc_dirs) do
636 if f == d then
637 fs.delete(dir.path(install_dir, f))
638 end
639 end
640 end
641end
642
643return util
diff --git a/src/luarocks/util.tl b/src/luarocks/util.tl
index aa04a3f3..72b8d995 100644
--- a/src/luarocks/util.tl
+++ b/src/luarocks/util.tl
@@ -548,6 +548,7 @@ do
548 } 548 }
549 end 549 end
550end 550end
551
551--- Return a table of modules that are already provided by the VM, which 552--- Return a table of modules that are already provided by the VM, which
552-- can be specified as dependencies without having to install an actual rock. 553-- can be specified as dependencies without having to install an actual rock.
553-- @param rockspec (optional) a rockspec table, so that rockspec format 554-- @param rockspec (optional) a rockspec table, so that rockspec format