aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-06-29 22:58:32 +0300
committerV1K1NGbg <victor@ilchev.com>2024-08-05 20:49:17 +0300
commit90c01d94d37b475eb6f2fa898ed0650b826f3620 (patch)
tree44e3d8b0391433299708509e9fe77a4eb7fa36be
parente0033c09890cae40769e5a6990bcda5c29587c0c (diff)
downloadluarocks-90c01d94d37b475eb6f2fa898ed0650b826f3620.tar.gz
luarocks-90c01d94d37b475eb6f2fa898ed0650b826f3620.tar.bz2
luarocks-90c01d94d37b475eb6f2fa898ed0650b826f3620.zip
fixed more bugs
-rw-r--r--src/luarocks/core/cfg.lua940
-rw-r--r--src/luarocks/core/dir.tl41
-rw-r--r--src/luarocks/core/path.tl8
-rw-r--r--src/luarocks/core/util.tl23
-rw-r--r--src/luarocks/core/vers.tl55
-rw-r--r--tlconfig.lua5
6 files changed, 1013 insertions, 59 deletions
diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua
new file mode 100644
index 00000000..6d8fe55b
--- /dev/null
+++ b/src/luarocks/core/cfg.lua
@@ -0,0 +1,940 @@
1
2--- Configuration for LuaRocks.
3-- Tries to load the user's configuration file and
4-- defines defaults for unset values. See the
5-- <a href="http://luarocks.org/en/Config_file_format">config
6-- file format documentation</a> for details.
7--
8-- End-users shouldn't edit this file. They can override any defaults
9-- set in this file using their system-wide or user-specific configuration
10-- files. Run `luarocks` with no arguments to see the locations of
11-- these files in your platform.
12
13local table, pairs, require, os, pcall, ipairs, package, type, assert =
14 table, pairs, require, os, pcall, ipairs, package, type, assert
15
16local dir = require("luarocks.core.dir")
17local util = require("luarocks.core.util")
18local persist = require("luarocks.core.persist")
19local sysdetect = require("luarocks.core.sysdetect")
20local vers = require("luarocks.core.vers")
21
22--------------------------------------------------------------------------------
23
24local program_version = "dev"
25
26local is_windows = package.config:sub(1,1) == "\\"
27
28-- Set order for platform overrides.
29-- More general platform identifiers should be listed first,
30-- more specific ones later.
31local platform_order = {
32 -- Unixes
33 "unix",
34 "bsd",
35 "solaris",
36 "netbsd",
37 "openbsd",
38 "freebsd",
39 "dragonfly",
40 "linux",
41 "macosx",
42 "cygwin",
43 "msys",
44 "haiku",
45 -- Windows
46 "windows",
47 "win32",
48 "mingw",
49 "mingw32",
50 "msys2_mingw_w64",
51}
52
53local function detect_sysconfdir()
54 if not debug then
55 return
56 end
57 local src = debug.getinfo(1, "S").source
58 if not src then
59 return
60 end
61 src = dir.normalize(src)
62 if src:sub(1, 1) == "@" then
63 src = src:sub(2)
64 end
65 local basedir = src:match("^(.*)[\\/]luarocks[\\/]core[\\/]cfg.lua$")
66 if not basedir then
67 return
68 end
69 -- If installed in a Unix-like tree, use a Unix-like sysconfdir
70 local installdir = basedir:match("^(.*)[\\/]share[\\/]lua[\\/][^/]*$")
71 if installdir then
72 if installdir == "/usr" then
73 return "/etc/luarocks"
74 end
75 return dir.path(installdir, "etc", "luarocks")
76 end
77 -- Otherwise, use base directory of sources
78 return basedir
79end
80
81local load_config_file
82do
83 -- Create global environment for the config files;
84 local function env_for_config_file(cfg, platforms)
85 local platforms_copy = {}
86 for k,v in pairs(platforms) do
87 platforms_copy[k] = v
88 end
89
90 local e
91 e = {
92 home = cfg.home,
93 lua_version = cfg.lua_version,
94 platforms = platforms_copy,
95 processor = cfg.target_cpu, -- remains for compat reasons
96 target_cpu = cfg.target_cpu, -- replaces `processor`
97 os_getenv = os.getenv,
98 variables = cfg.variables or {},
99 dump_env = function()
100 -- debug function, calling it from a config file will show all
101 -- available globals to that config file
102 print(util.show_table(e, "global environment"))
103 end,
104 }
105 return e
106 end
107
108 -- Merge values from config files read into the `cfg` table
109 local function merge_overrides(cfg, overrides)
110 -- remove some stuff we do not want to integrate
111 overrides.os_getenv = nil
112 overrides.dump_env = nil
113 -- remove tables to be copied verbatim instead of deeply merged
114 if overrides.rocks_trees then cfg.rocks_trees = nil end
115 if overrides.rocks_servers then cfg.rocks_servers = nil end
116 -- perform actual merge
117 util.deep_merge(cfg, overrides)
118 end
119
120 local function update_platforms(platforms, overrides)
121 if overrides[1] then
122 for k, _ in pairs(platforms) do
123 platforms[k] = nil
124 end
125 for _, v in ipairs(overrides) do
126 platforms[v] = true
127 end
128 -- set some fallback default in case the user provides an incomplete configuration.
129 -- LuaRocks expects a set of defaults to be available.
130 if not (platforms.unix or platforms.windows) then
131 platforms[is_windows and "windows" or "unix"] = true
132 end
133 end
134 end
135
136 -- Load config file and merge its contents into the `cfg` module table.
137 -- @return filepath of successfully loaded file or nil if it failed
138 load_config_file = function(cfg, platforms, filepath)
139 local result, err, errcode = persist.load_into_table(filepath, env_for_config_file(cfg, platforms))
140 if (not result) and errcode ~= "open" then
141 -- errcode is either "load" or "run"; bad config file, so error out
142 return nil, err, "config"
143 end
144 if result then
145 -- success in loading and running, merge contents and exit
146 update_platforms(platforms, result.platforms)
147 result.platforms = nil
148 merge_overrides(cfg, result)
149 return filepath
150 end
151 return nil -- nothing was loaded
152 end
153end
154
155local platform_sets = {
156 freebsd = { unix = true, bsd = true, freebsd = true },
157 openbsd = { unix = true, bsd = true, openbsd = true },
158 dragonfly = { unix = true, bsd = true, dragonfly = true },
159 solaris = { unix = true, solaris = true },
160 windows = { windows = true, win32 = true },
161 cygwin = { unix = true, cygwin = true },
162 macosx = { unix = true, bsd = true, macosx = true, macos = true },
163 netbsd = { unix = true, bsd = true, netbsd = true },
164 haiku = { unix = true, haiku = true },
165 linux = { unix = true, linux = true },
166 mingw = { windows = true, win32 = true, mingw32 = true, mingw = true },
167 msys = { unix = true, cygwin = true, msys = true },
168 msys2_mingw_w64 = { windows = true, win32 = true, mingw32 = true, mingw = true, msys = true, msys2_mingw_w64 = true },
169}
170
171local function make_platforms(system)
172 -- fallback to Unix in unknown systems
173 return platform_sets[system] or { unix = true }
174end
175
176--------------------------------------------------------------------------------
177
178local function make_defaults(lua_version, target_cpu, platforms, home)
179
180 -- Configure defaults:
181 local defaults = {
182
183 local_by_default = false,
184 accept_unknown_fields = false,
185 fs_use_modules = true,
186 hooks_enabled = true,
187 deps_mode = "one",
188 no_manifest = false,
189 check_certificates = false,
190
191 cache_timeout = 60,
192 cache_fail_timeout = 86400,
193
194 lua_modules_path = dir.path("share", "lua", lua_version),
195 lib_modules_path = dir.path("lib", "lua", lua_version),
196 rocks_subdir = dir.path("lib", "luarocks", "rocks-"..lua_version),
197
198 arch = "unknown",
199 lib_extension = "unknown",
200 obj_extension = "unknown",
201 link_lua_explicitly = false,
202
203 rocks_servers = {
204 {
205 "https://luarocks.org",
206 "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",
207 "https://loadk.com/luarocks/",
208 }
209 },
210 disabled_servers = {},
211
212 upload = {
213 server = "https://luarocks.org",
214 tool_version = "1.0.0",
215 api_version = "1",
216 },
217
218 lua_extension = "lua",
219 connection_timeout = 30, -- 0 = no timeout
220
221 variables = {
222 MAKE = os.getenv("MAKE") or "make",
223 CC = os.getenv("CC") or "cc",
224 LD = os.getenv("CC") or "ld",
225 AR = os.getenv("AR") or "ar",
226 RANLIB = os.getenv("RANLIB") or "ranlib",
227
228 CVS = "cvs",
229 GIT = "git",
230 SSCM = "sscm",
231 SVN = "svn",
232 HG = "hg",
233
234 GPG = "gpg",
235
236 RSYNC = "rsync",
237 WGET = "wget",
238 SCP = "scp",
239 CURL = "curl",
240
241 PWD = "pwd",
242 MKDIR = "mkdir",
243 RMDIR = "rmdir",
244 CP = "cp",
245 LN = "ln",
246 LS = "ls",
247 RM = "rm",
248 FIND = "find",
249 CHMOD = "chmod",
250 ICACLS = "icacls",
251 MKTEMP = "mktemp",
252
253 ZIP = "zip",
254 UNZIP = "unzip -n",
255 GUNZIP = "gunzip",
256 BUNZIP2 = "bunzip2",
257 TAR = "tar",
258
259 MD5SUM = "md5sum",
260 OPENSSL = "openssl",
261 MD5 = "md5",
262 TOUCH = "touch",
263
264 CMAKE = "cmake",
265 SEVENZ = "7z",
266
267 RSYNCFLAGS = "--exclude=.git -Oavz",
268 CURLNOCERTFLAG = "",
269 WGETNOCERTFLAG = "",
270 },
271
272 external_deps_subdirs = {
273 bin = "bin",
274 lib = "lib",
275 include = "include"
276 },
277 runtime_external_deps_subdirs = {
278 bin = "bin",
279 lib = "lib",
280 include = "include"
281 },
282 }
283
284 if platforms.windows then
285
286 defaults.arch = "win32-"..target_cpu
287 defaults.lib_extension = "dll"
288 defaults.external_lib_extension = "dll"
289 defaults.static_lib_extension = "lib"
290 defaults.obj_extension = "obj"
291 defaults.external_deps_dirs = {
292 dir.path("c:", "external"),
293 dir.path("c:", "windows", "system32"),
294 }
295
296 defaults.makefile = "Makefile.win"
297 defaults.variables.PWD = "echo %cd%"
298 defaults.variables.MKDIR = "md"
299 defaults.variables.MAKE = os.getenv("MAKE") or "nmake"
300 defaults.variables.CC = os.getenv("CC") or "cl"
301 defaults.variables.RC = os.getenv("WINDRES") or "rc"
302 defaults.variables.LD = os.getenv("LINK") or "link"
303 defaults.variables.MT = os.getenv("MT") or "mt"
304 defaults.variables.AR = os.getenv("AR") or "lib"
305 defaults.variables.CFLAGS = os.getenv("CFLAGS") or "/nologo /MD /O2"
306 defaults.variables.LDFLAGS = os.getenv("LDFLAGS")
307 defaults.variables.LIBFLAG = "/nologo /dll"
308
309 defaults.external_deps_patterns = {
310 bin = { "?.exe", "?.bat" },
311 lib = { "?.lib", "lib?.lib", "?.dll", "lib?.dll" },
312 include = { "?.h" }
313 }
314 defaults.runtime_external_deps_patterns = {
315 bin = { "?.exe", "?.bat" },
316 lib = { "?.dll", "lib?.dll" },
317 include = { "?.h" }
318 }
319 defaults.export_path_separator = ";"
320 defaults.wrapper_suffix = ".bat"
321
322 local localappdata = os.getenv("LOCALAPPDATA")
323 if not localappdata then
324 -- for Windows versions below Vista
325 localappdata = dir.path((os.getenv("USERPROFILE") or dir.path("c:", "Users", "All Users")), "Local Settings", "Application Data")
326 end
327 defaults.local_cache = dir.path(localappdata, "LuaRocks", "Cache")
328 defaults.web_browser = "start"
329
330 defaults.external_deps_subdirs.lib = { "lib", "", "bin" }
331 defaults.runtime_external_deps_subdirs.lib = { "lib", "", "bin" }
332 defaults.link_lua_explicitly = true
333 defaults.fs_use_modules = false
334 end
335
336 if platforms.mingw32 then
337 defaults.obj_extension = "o"
338 defaults.static_lib_extension = "a"
339 defaults.external_deps_dirs = {
340 dir.path("c:", "external"),
341 dir.path("c:", "mingw"),
342 dir.path("c:", "windows", "system32"),
343 }
344 defaults.cmake_generator = "MinGW Makefiles"
345 defaults.variables.MAKE = os.getenv("MAKE") or "mingw32-make"
346 if target_cpu == "x86_64" then
347 defaults.variables.CC = os.getenv("CC") or "x86_64-w64-mingw32-gcc"
348 defaults.variables.LD = os.getenv("CC") or "x86_64-w64-mingw32-gcc"
349 else
350 defaults.variables.CC = os.getenv("CC") or "mingw32-gcc"
351 defaults.variables.LD = os.getenv("CC") or "mingw32-gcc"
352 end
353 defaults.variables.AR = os.getenv("AR") or "ar"
354 defaults.variables.RC = os.getenv("WINDRES") or "windres"
355 defaults.variables.RANLIB = os.getenv("RANLIB") or "ranlib"
356 defaults.variables.CFLAGS = os.getenv("CFLAGS") or "-O2"
357 defaults.variables.LDFLAGS = os.getenv("LDFLAGS")
358 defaults.variables.LIBFLAG = "-shared"
359 defaults.makefile = "Makefile"
360 defaults.external_deps_patterns = {
361 bin = { "?.exe", "?.bat" },
362 -- mingw lookup list from http://stackoverflow.com/a/15853231/1793220
363 -- ...should we keep ?.lib at the end? It's not in the above list.
364 lib = { "lib?.dll.a", "?.dll.a", "lib?.a", "cyg?.dll", "lib?.dll", "?.dll", "?.lib" },
365 include = { "?.h" }
366 }
367 defaults.runtime_external_deps_patterns = {
368 bin = { "?.exe", "?.bat" },
369 lib = { "cyg?.dll", "?.dll", "lib?.dll" },
370 include = { "?.h" }
371 }
372 defaults.link_lua_explicitly = true
373 end
374
375 if platforms.unix then
376 defaults.lib_extension = "so"
377 defaults.static_lib_extension = "a"
378 defaults.external_lib_extension = "so"
379 defaults.obj_extension = "o"
380 defaults.external_deps_dirs = { "/usr/local", "/usr", "/" }
381
382 defaults.variables.CFLAGS = os.getenv("CFLAGS") or "-O2"
383 -- we pass -fPIC via CFLAGS because of old Makefile-based Lua projects
384 -- which didn't have -fPIC in their Makefiles but which honor CFLAGS
385 if not defaults.variables.CFLAGS:match("-fPIC") then
386 defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
387 end
388
389 defaults.variables.LDFLAGS = os.getenv("LDFLAGS")
390
391 defaults.cmake_generator = "Unix Makefiles"
392 defaults.variables.CC = os.getenv("CC") or "gcc"
393 defaults.variables.LD = os.getenv("CC") or "gcc"
394 defaults.gcc_rpath = true
395 defaults.variables.LIBFLAG = "-shared"
396 defaults.variables.TEST = "test"
397
398 defaults.external_deps_patterns = {
399 bin = { "?" },
400 lib = { "lib?.a", "lib?.so", "lib?.so.*" },
401 include = { "?.h" }
402 }
403 defaults.runtime_external_deps_patterns = {
404 bin = { "?" },
405 lib = { "lib?.so", "lib?.so.*" },
406 include = { "?.h" }
407 }
408 defaults.export_path_separator = ":"
409 defaults.wrapper_suffix = ""
410 local xdg_cache_home = os.getenv("XDG_CACHE_HOME") or home.."/.cache"
411 defaults.local_cache = xdg_cache_home.."/luarocks"
412 defaults.web_browser = "xdg-open"
413 end
414
415 if platforms.cygwin then
416 defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
417 defaults.arch = "cygwin-"..target_cpu
418 defaults.cmake_generator = "Unix Makefiles"
419 defaults.variables.CC = "echo -llua | xargs " .. (os.getenv("CC") or "gcc")
420 defaults.variables.LD = "echo -llua | xargs " .. (os.getenv("CC") or "gcc")
421 defaults.variables.LIBFLAG = "-shared"
422 defaults.link_lua_explicitly = true
423 end
424
425 if platforms.msys then
426 -- msys is basically cygwin made out of mingw, meaning the subsytem is unixish
427 -- enough, yet we can freely mix with native win32
428 defaults.external_deps_patterns = {
429 bin = { "?.exe", "?.bat", "?" },
430 lib = { "lib?.so", "lib?.so.*", "lib?.dll.a", "?.dll.a",
431 "lib?.a", "lib?.dll", "?.dll", "?.lib" },
432 include = { "?.h" }
433 }
434 defaults.runtime_external_deps_patterns = {
435 bin = { "?.exe", "?.bat" },
436 lib = { "lib?.so", "?.dll", "lib?.dll" },
437 include = { "?.h" }
438 }
439 if platforms.mingw then
440 -- MSYS2 can build Windows programs that depend on
441 -- msys-2.0.dll (based on Cygwin) but MSYS2 is also designed
442 -- for building native Windows programs by MinGW. These
443 -- programs don't depend on msys-2.0.dll.
444 local pipe = io.popen("cygpath --windows %MINGW_PREFIX%")
445 local mingw_prefix = pipe:read("*l")
446 pipe:close()
447 defaults.external_deps_dirs = {
448 mingw_prefix,
449 dir.path("c:", "windows", "system32"),
450 }
451 defaults.makefile = "Makefile"
452 defaults.cmake_generator = "MSYS Makefiles"
453 defaults.local_cache = dir.path(home, ".cache", "luarocks")
454 defaults.variables.MAKE = os.getenv("MAKE") or "make"
455 defaults.variables.CC = os.getenv("CC") or "gcc"
456 defaults.variables.RC = os.getenv("WINDRES") or "windres"
457 defaults.variables.LD = os.getenv("CC") or "gcc"
458 defaults.variables.MT = os.getenv("MT") or nil
459 defaults.variables.AR = os.getenv("AR") or "ar"
460 defaults.variables.RANLIB = os.getenv("RANLIB") or "ranlib"
461
462 defaults.variables.CFLAGS = os.getenv("CFLAGS") or "-O2 -fPIC"
463 if not defaults.variables.CFLAGS:match("-fPIC") then
464 defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
465 end
466
467 defaults.variables.LIBFLAG = "-shared"
468 end
469 end
470
471 if platforms.bsd then
472 defaults.variables.MAKE = "gmake"
473 defaults.gcc_rpath = false
474 defaults.variables.CC = os.getenv("CC") or "cc"
475 defaults.variables.LD = os.getenv("CC") or defaults.variables.CC
476 end
477
478 if platforms.macosx then
479 defaults.variables.MAKE = os.getenv("MAKE") or "make"
480 defaults.external_lib_extension = "dylib"
481 defaults.arch = "macosx-"..target_cpu
482 defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
483 local version = util.popen_read("sw_vers -productVersion")
484 if not (version:match("^%d+%.%d+%.%d+$") or version:match("^%d+%.%d+$")) then
485 version = "10.3"
486 end
487 version = vers.parse_version(version)
488 if version >= vers.parse_version("11.0") then
489 version = vers.parse_version("11.0")
490 elseif version >= vers.parse_version("10.10") then
491 version = vers.parse_version("10.8")
492 elseif version >= vers.parse_version("10.5") then
493 version = vers.parse_version("10.5")
494 else
495 defaults.gcc_rpath = false
496 end
497 defaults.variables.CC = "env MACOSX_DEPLOYMENT_TARGET="..tostring(version).." gcc"
498 defaults.variables.LD = "env MACOSX_DEPLOYMENT_TARGET="..tostring(version).." gcc"
499 defaults.web_browser = "open"
500
501 -- XCode SDK
502 local sdk_path = util.popen_read("xcrun --show-sdk-path 2>/dev/null")
503 if sdk_path then
504 table.insert(defaults.external_deps_dirs, sdk_path .. "/usr")
505 table.insert(defaults.external_deps_patterns.lib, 1, "lib?.tbd")
506 table.insert(defaults.runtime_external_deps_patterns.lib, 1, "lib?.tbd")
507 end
508
509 -- Homebrew
510 table.insert(defaults.external_deps_dirs, "/usr/local/opt")
511 defaults.external_deps_subdirs.lib = { "lib", "" }
512 defaults.runtime_external_deps_subdirs.lib = { "lib", "" }
513 table.insert(defaults.external_deps_patterns.lib, 1, "/?/lib/lib?.dylib")
514 table.insert(defaults.runtime_external_deps_patterns.lib, 1, "/?/lib/lib?.dylib")
515 end
516
517 if platforms.linux then
518 defaults.arch = "linux-"..target_cpu
519
520 local gcc_arch = util.popen_read("gcc -print-multiarch 2>/dev/null")
521 if gcc_arch and gcc_arch ~= "" then
522 defaults.external_deps_subdirs.lib = { "lib/" .. gcc_arch, "lib64", "lib" }
523 defaults.runtime_external_deps_subdirs.lib = { "lib/" .. gcc_arch, "lib64", "lib" }
524 else
525 defaults.external_deps_subdirs.lib = { "lib64", "lib" }
526 defaults.runtime_external_deps_subdirs.lib = { "lib64", "lib" }
527 end
528 end
529
530 if platforms.freebsd then
531 defaults.arch = "freebsd-"..target_cpu
532 elseif platforms.dragonfly then
533 defaults.arch = "dragonfly-"..target_cpu
534 elseif platforms.openbsd then
535 defaults.arch = "openbsd-"..target_cpu
536 elseif platforms.netbsd then
537 defaults.arch = "netbsd-"..target_cpu
538 elseif platforms.solaris then
539 defaults.arch = "solaris-"..target_cpu
540 defaults.variables.MAKE = "gmake"
541 end
542
543 -- Expose some more values detected by LuaRocks for use by rockspec authors.
544 defaults.variables.LIB_EXTENSION = defaults.lib_extension
545 defaults.variables.OBJ_EXTENSION = defaults.obj_extension
546
547 return defaults
548end
549
550local function use_defaults(cfg, defaults)
551
552 -- Populate variables with values from their 'defaults' counterparts
553 -- if they were not already set by user.
554 if not cfg.variables then
555 cfg.variables = {}
556 end
557 for k,v in pairs(defaults.variables) do
558 if not cfg.variables[k] then
559 cfg.variables[k] = v
560 end
561 end
562
563 util.deep_merge_under(cfg, defaults)
564
565 -- FIXME get rid of this
566 if not cfg.check_certificates then
567 cfg.variables.CURLNOCERTFLAG = "-k"
568 cfg.variables.WGETNOCERTFLAG = "--no-check-certificate"
569 end
570end
571
572--------------------------------------------------------------------------------
573
574local cfg = {}
575
576--- Initializes the LuaRocks configuration for variables, paths
577-- and OS detection.
578-- @param detected table containing information detected about the
579-- environment. All fields below are optional:
580-- * lua_version (in x.y format, e.g. "5.3")
581-- * lua_bindir (e.g. "/usr/local/bin")
582-- * lua_dir (e.g. "/usr/local")
583-- * lua (e.g. "/usr/local/bin/lua-5.3")
584-- * project_dir (a string with the path of the project directory
585-- when using per-project environments, as created with `luarocks init`)
586-- @param warning a logging function for warnings that takes a string
587-- @return true on success; nil and an error message on failure.
588function cfg.init(detected, warning)
589 detected = detected or {}
590
591 local exit_ok = true
592 local exit_err = nil
593 local exit_what = nil
594
595 local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded")
596 if not hc_ok then
597 hardcoded = {}
598 end
599
600 local init = cfg.init
601
602 ----------------------------------------
603 -- Reset the cfg table.
604 ----------------------------------------
605
606 for k, _ in pairs(cfg) do
607 cfg[k] = nil
608 end
609
610 cfg.program_version = program_version
611
612 if hardcoded.IS_BINARY then
613 cfg.is_binary = true
614 end
615
616 -- Use detected values as defaults, overridable via config files or CLI args
617
618 local hardcoded_lua = hardcoded.LUA
619 local hardcoded_lua_dir = hardcoded.LUA_DIR
620 local hardcoded_lua_bindir = hardcoded.LUA_BINDIR
621 local hardcoded_lua_incdir = hardcoded.LUA_INCDIR
622 local hardcoded_lua_libdir = hardcoded.LUA_LIBDIR
623 local hardcoded_lua_version = hardcoded.LUA_VERSION or _VERSION:sub(5)
624
625 -- if --lua-version or --lua-dir are passed from the CLI,
626 -- don't use the hardcoded paths at all
627 if detected.given_lua_version or detected.given_lua_dir then
628 hardcoded_lua = nil
629 hardcoded_lua_dir = nil
630 hardcoded_lua_bindir = nil
631 hardcoded_lua_incdir = nil
632 hardcoded_lua_libdir = nil
633 hardcoded_lua_version = nil
634 end
635
636 cfg.lua_version = detected.lua_version or hardcoded_lua_version
637 cfg.project_dir = (not hardcoded.FORCE_CONFIG) and detected.project_dir
638
639 do
640 local lua = detected.lua or hardcoded_lua
641 local lua_dir = detected.lua_dir or hardcoded_lua_dir
642 local lua_bindir = detected.lua_bindir or hardcoded_lua_bindir
643 cfg.variables = {
644 LUA = lua,
645 LUA_DIR = lua_dir,
646 LUA_BINDIR = lua_bindir,
647 LUA_LIBDIR = hardcoded_lua_libdir,
648 LUA_INCDIR = hardcoded_lua_incdir,
649 }
650 end
651
652 cfg.init = init
653
654 ----------------------------------------
655 -- System detection.
656 ----------------------------------------
657
658 -- A proper build of LuaRocks will hardcode the system
659 -- and proc values with hardcoded.SYSTEM and hardcoded.PROCESSOR.
660 -- If that is not available, we try to identify the system.
661 local system, processor = sysdetect.detect()
662 if hardcoded.SYSTEM then
663 system = hardcoded.SYSTEM
664 end
665 if hardcoded.PROCESSOR then
666 processor = hardcoded.PROCESSOR
667 end
668
669 if system == "windows" then
670 if os.getenv("VCINSTALLDIR") then
671 -- running from the Development Command prompt for VS 2017
672 system = "windows"
673 else
674 local msystem = os.getenv("MSYSTEM")
675 if msystem == nil then
676 system = "mingw"
677 elseif msystem == "MSYS" then
678 system = "msys"
679 else
680 -- MINGW32 or MINGW64
681 system = "msys2_mingw_w64"
682 end
683 end
684 end
685
686 cfg.target_cpu = processor
687
688 local platforms = make_platforms(system)
689
690 ----------------------------------------
691 -- Platform is determined.
692 -- Let's load the config files.
693 ----------------------------------------
694
695 local sys_config_file
696 local home_config_file
697 local project_config_file
698
699 local config_file_name = "config-"..cfg.lua_version..".lua"
700
701 do
702 local sysconfdir = os.getenv("LUAROCKS_SYSCONFDIR") or hardcoded.SYSCONFDIR
703 if platforms.windows and not platforms.msys2_mingw_w64 then
704 cfg.home = os.getenv("APPDATA") or "c:"
705 cfg.home_tree = dir.path(cfg.home, "luarocks")
706 cfg.sysconfdir = sysconfdir or dir.path((os.getenv("PROGRAMFILES") or "c:"), "luarocks")
707 else
708 cfg.home = os.getenv("HOME") or ""
709 cfg.home_tree = dir.path(cfg.home, ".luarocks")
710 cfg.sysconfdir = sysconfdir or detect_sysconfdir() or "/etc/luarocks"
711 end
712 end
713
714 -- Load system configuration file
715 sys_config_file = dir.path(cfg.sysconfdir, config_file_name)
716 local sys_config_ok, err = load_config_file(cfg, platforms, sys_config_file)
717 if err then
718 exit_ok, exit_err, exit_what = nil, err, "config"
719 end
720
721 -- Load user configuration file (if allowed)
722 local home_config_ok
723 local project_config_ok
724 if not hardcoded.FORCE_CONFIG then
725 local env_var = "LUAROCKS_CONFIG_" .. cfg.lua_version:gsub("%.", "_")
726 local env_value = os.getenv(env_var)
727 if not env_value then
728 env_var = "LUAROCKS_CONFIG"
729 env_value = os.getenv(env_var)
730 end
731 -- first try environment provided file, so we can explicitly warn when it is missing
732 if env_value then
733 local env_ok, err = load_config_file(cfg, platforms, env_value)
734 if err then
735 exit_ok, exit_err, exit_what = nil, err, "config"
736 elseif warning and not env_ok then
737 warning("Warning: could not load configuration file `"..env_value.."` given in environment variable "..env_var.."\n")
738 end
739 if env_ok then
740 home_config_ok = true
741 home_config_file = env_value
742 end
743 end
744
745 -- try XDG config home
746 if platforms.unix and not home_config_ok then
747 local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or dir.path(cfg.home, ".config")
748 cfg.homeconfdir = dir.path(xdg_config_home, "luarocks")
749 home_config_file = dir.path(cfg.homeconfdir, config_file_name)
750 home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
751 if err then
752 exit_ok, exit_err, exit_what = nil, err, "config"
753 end
754 end
755
756 -- try the alternative defaults if there was no environment specified file or it didn't work
757 if not home_config_ok then
758 cfg.homeconfdir = cfg.home_tree
759 home_config_file = dir.path(cfg.homeconfdir, config_file_name)
760 home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
761 if err then
762 exit_ok, exit_err, exit_what = nil, err, "config"
763 end
764 end
765
766 -- finally, use the project-specific config file if any
767 if cfg.project_dir then
768 project_config_file = dir.path(cfg.project_dir, ".luarocks", config_file_name)
769 project_config_ok, err = load_config_file(cfg, platforms, project_config_file)
770 if err then
771 exit_ok, exit_err, exit_what = nil, err, "config"
772 end
773 end
774 end
775
776 -- backwards compatibility:
777 if cfg.lua_interpreter and cfg.variables.LUA_BINDIR and not cfg.variables.LUA then
778 cfg.variables.LUA = dir.path(cfg.variables.LUA_BINDIR, cfg.lua_interpreter)
779 end
780
781 ----------------------------------------
782 -- Config files are loaded.
783 -- Let's finish up the cfg table.
784 ----------------------------------------
785
786 -- Settings given via the CLI (i.e. --lua-dir) take precedence over config files.
787 cfg.project_dir = detected.given_project_dir or cfg.project_dir
788 cfg.lua_version = detected.given_lua_version or cfg.lua_version
789 if detected.given_lua_dir then
790 cfg.variables.LUA = detected.lua
791 cfg.variables.LUA_DIR = detected.given_lua_dir
792 cfg.variables.LUA_BINDIR = detected.lua_bindir
793 cfg.variables.LUA_LIBDIR = nil
794 cfg.variables.LUA_INCDIR = nil
795 end
796
797 -- Build a default list of rocks trees if not given
798 if cfg.rocks_trees == nil then
799 cfg.rocks_trees = {}
800 if cfg.home_tree then
801 table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } )
802 end
803 if hardcoded.PREFIX and hardcoded.PREFIX ~= cfg.home_tree then
804 table.insert(cfg.rocks_trees, { name = "system", root = hardcoded.PREFIX } )
805 end
806 end
807
808 local defaults = make_defaults(cfg.lua_version, processor, platforms, cfg.home)
809
810 if platforms.windows and hardcoded.WIN_TOOLS then
811 local tools = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", "WGET", }
812 for _, tool in ipairs(tools) do
813 defaults.variables[tool] = '"' .. dir.path(hardcoded.WIN_TOOLS, defaults.variables[tool] .. '.exe') .. '"'
814 end
815 else
816 defaults.fs_use_modules = true
817 end
818
819 -- if only cfg.variables.LUA is given in config files,
820 -- derive LUA_BINDIR and LUA_DIR from them.
821 if cfg.variables.LUA and not cfg.variables.LUA_BINDIR then
822 cfg.variables.LUA_BINDIR = cfg.variables.LUA:match("^(.*)[\\/][^\\/]*$")
823 if not cfg.variables.LUA_DIR then
824 cfg.variables.LUA_DIR = cfg.variables.LUA_BINDIR:gsub("[\\/]bin$", "") or cfg.variables.LUA_BINDIR
825 end
826 end
827
828 use_defaults(cfg, defaults)
829
830 cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
831
832 cfg.config_files = {
833 project = cfg.project_dir and {
834 file = project_config_file,
835 found = not not project_config_ok,
836 },
837 system = {
838 file = sys_config_file,
839 found = not not sys_config_ok,
840 },
841 user = {
842 file = home_config_file,
843 found = not not home_config_ok,
844 },
845 nearest = project_config_ok
846 and project_config_file
847 or (home_config_ok
848 and home_config_file
849 or sys_config_file),
850 }
851
852 cfg.cache = {}
853
854 ----------------------------------------
855 -- Attributes of cfg are set.
856 -- Let's add some methods.
857 ----------------------------------------
858
859 do
860 local function make_paths_from_tree(tree)
861 local lua_path, lib_path, bin_path
862 if type(tree) == "string" then
863 lua_path = dir.path(tree, cfg.lua_modules_path)
864 lib_path = dir.path(tree, cfg.lib_modules_path)
865 bin_path = dir.path(tree, "bin")
866 else
867 lua_path = tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path)
868 lib_path = tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path)
869 bin_path = tree.bin_dir or dir.path(tree.root, "bin")
870 end
871 return lua_path, lib_path, bin_path
872 end
873
874 function cfg.package_paths(current)
875 local new_path, new_cpath, new_bin = {}, {}, {}
876 local function add_tree_to_paths(tree)
877 local lua_path, lib_path, bin_path = make_paths_from_tree(tree)
878 table.insert(new_path, dir.path(lua_path, "?.lua"))
879 table.insert(new_path, dir.path(lua_path, "?", "init.lua"))
880 table.insert(new_cpath, dir.path(lib_path, "?."..cfg.lib_extension))
881 table.insert(new_bin, bin_path)
882 end
883 if current then
884 add_tree_to_paths(current)
885 end
886 for _,tree in ipairs(cfg.rocks_trees) do
887 add_tree_to_paths(tree)
888 end
889 return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
890 end
891 end
892
893 function cfg.init_package_paths()
894 local lr_path, lr_cpath, lr_bin = cfg.package_paths()
895 package.path = util.cleanup_path(package.path .. ";" .. lr_path, ";", cfg.lua_version, true)
896 package.cpath = util.cleanup_path(package.cpath .. ";" .. lr_cpath, ";", cfg.lua_version, true)
897 end
898
899 --- Check if platform was detected
900 -- @param name string: The platform name to check.
901 -- @return boolean: true if LuaRocks is currently running on queried platform.
902 function cfg.is_platform(name)
903 assert(type(name) == "string")
904 return platforms[name]
905 end
906
907 -- @param direction (optional) "least-specific-first" (default) or "most-specific-first"
908 function cfg.each_platform(direction)
909 direction = direction or "least-specific-first"
910 local i, delta
911 if direction == "least-specific-first" then
912 i = 0
913 delta = 1
914 else
915 i = #platform_order + 1
916 delta = -1
917 end
918 return function()
919 local p
920 repeat
921 i = i + delta
922 p = platform_order[i]
923 until (not p) or platforms[p]
924 return p
925 end
926 end
927
928 function cfg.print_platforms()
929 local platform_keys = {}
930 for k,_ in pairs(platforms) do
931 table.insert(platform_keys, k)
932 end
933 table.sort(platform_keys)
934 return table.concat(platform_keys, ", ")
935 end
936
937 return exit_ok, exit_err, exit_what
938end
939
940return cfg
diff --git a/src/luarocks/core/dir.tl b/src/luarocks/core/dir.tl
index 7cd8d0c1..87efec12 100644
--- a/src/luarocks/core/dir.tl
+++ b/src/luarocks/core/dir.tl
@@ -13,26 +13,6 @@ local function unquote(c: string): string
13 return c 13 return c
14end 14end
15 15
16--- Describe a path in a cross-platform way.
17-- Use this function to avoid platform-specific directory
18-- separators in other modules. Removes trailing slashes from
19-- each component given, to avoid repeated separators.
20-- Separators inside strings are kept, to handle URLs containing
21-- protocols.
22-- @param ... strings representing directories
23-- @return string: a string with a platform-specific representation
24-- of the path.
25function dir.path(...: string): string
26 local t = {...}
27 while t[1] == "" do
28 table.remove(t, 1)
29 end
30 for i, c in ipairs(t) do
31 t[i] = unquote(c)
32 end
33 return dir.normalize(table.concat(t, "/")) --! normalize(tconcat(t, "/")
34end
35
36--- Split protocol and path from an URL or local pathname. 16--- Split protocol and path from an URL or local pathname.
37-- URLs should be in the "protocol://path" format. 17-- URLs should be in the "protocol://path" format.
38-- For local pathnames, "file" is returned as the protocol. 18-- For local pathnames, "file" is returned as the protocol.
@@ -92,5 +72,26 @@ function dir.normalize(name: string): string
92 return pathname 72 return pathname
93end 73end
94 74
75
76--- Describe a path in a cross-platform way.
77-- Use this function to avoid platform-specific directory
78-- separators in other modules. Removes trailing slashes from
79-- each component given, to avoid repeated separators.
80-- Separators inside strings are kept, to handle URLs containing
81-- protocols.
82-- @param ... strings representing directories
83-- @return string: a string with a platform-specific representation
84-- of the path.
85function dir.path(...: string): string
86 local t = {...}
87 while t[1] == "" do
88 table.remove(t, 1)
89 end
90 for i, c in ipairs(t) do
91 t[i] = unquote(c)
92 end
93 return dir.normalize(table.concat(t, "/"))
94end
95
95return dir 96return dir
96 97
diff --git a/src/luarocks/core/path.tl b/src/luarocks/core/path.tl
index 998ab199..a866f4d7 100644
--- a/src/luarocks/core/path.tl
+++ b/src/luarocks/core/path.tl
@@ -3,7 +3,7 @@
3local record path 3local record path
4end 4end
5 5
6local cfg = require("luarocks.core.cfg") --! 6local cfg = require("luarocks.core.cfg") --? cannot index key ... in boolean 'cfg' of type boolean
7local dir = require("luarocks.core.dir") 7local dir = require("luarocks.core.dir")
8 8
9local dir_sep = package.config:sub(1, 1) 9local dir_sep = package.config:sub(1, 1)
@@ -16,7 +16,7 @@ function path.rocks_dir(tree: string | {any: any}): string
16 if tree is string then 16 if tree is string then
17 return dir.path(tree, cfg.rocks_subdir) 17 return dir.path(tree, cfg.rocks_subdir)
18 end 18 end
19 return tostring(tree.rocks_dir) or dir.path(tree.root, cfg.rocks_subdir) 19 return tostring(tree.rocks_dir) or dir.path(tree.root, cfg.rocks_subdir) --? tostring(tree.root)
20end 20end
21 21
22--- Produce a versioned version of a filename. 22--- Produce a versioned version of a filename.
@@ -74,7 +74,7 @@ function path.deploy_lua_dir(tree: string | {any: any}): string
74 return dir.path(tree, cfg.lua_modules_path) 74 return dir.path(tree, cfg.lua_modules_path)
75 else 75 else
76 assert(type(tree) == "table") 76 assert(type(tree) == "table")
77 return tostring(tree.lua_dir) or dir.path(tree.root, cfg.lua_modules_path) --? 77 return tostring(tree.lua_dir) or dir.path(tree.root, cfg.lua_modules_path) --? tostring(tree.root)
78 end 78 end
79end 79end
80 80
@@ -83,7 +83,7 @@ function path.deploy_lib_dir(tree: string | {any: any}): string
83 return dir.path(tree, cfg.lib_modules_path) 83 return dir.path(tree, cfg.lib_modules_path)
84 else 84 else
85 assert(type(tree) == "table") 85 assert(type(tree) == "table")
86 return tostring(tree.lib_dir) or dir.path(tree.root, cfg.lib_modules_path) 86 return tostring(tree.lib_dir) or dir.path(tree.root, cfg.lib_modules_path) --? tostring(tree.root)
87 end 87 end
88end 88end
89 89
diff --git a/src/luarocks/core/util.tl b/src/luarocks/core/util.tl
index 176c3402..e1e473da 100644
--- a/src/luarocks/core/util.tl
+++ b/src/luarocks/core/util.tl
@@ -6,7 +6,7 @@ end
6 6
7local dir_sep = package.config:sub(1, 1) 7local dir_sep = package.config:sub(1, 1)
8 8
9local type CompFn = function(a: any, b: any): boolean 9local type CompFn = function(any, any): boolean
10 10
11--- Run a process and read a its output. 11--- Run a process and read a its output.
12-- Equivalent to io.popen(cmd):read("*l"), except that it 12-- Equivalent to io.popen(cmd):read("*l"), except that it
@@ -120,15 +120,16 @@ end
120-- (i.e. if an key from src already exists in dst, replace it). 120-- (i.e. if an key from src already exists in dst, replace it).
121-- @param dst Destination table, which will receive src's contents. 121-- @param dst Destination table, which will receive src's contents.
122-- @param src Table which provides new contents to dst. 122-- @param src Table which provides new contents to dst.
123function util.deep_merge(dst: {any: any}, src: {any: any}) --! {any: any} | {any: {any: any}} 123function util.deep_merge(dst: {any: any}, src: {any: any})
124 for k, v in pairs(src) do 124 for k, v in pairs(src) do
125 if v is {any: any} then 125 if v is {any: any} then
126 local dstk: any | {any: any} = dst[k] --? 126 local dstk: any | {any: any} = dst[k]
127 if dstk == nil then 127 if dstk == nil then
128 dst[k] = {} 128 dst[k] = {}
129 dstk = dst[k]
129 end 130 end
130 if dstk is {any: any} then --! "is" unavailable for table 131 if dstk is {any: any} then
131 util.deep_merge(dst[k], v) 132 util.deep_merge(dstk, v)
132 else 133 else
133 dst[k] = v 134 dst[k] = v
134 end 135 end
@@ -142,14 +143,16 @@ end
142-- (i.e. if an key from src already exists in dst, do not replace it). 143-- (i.e. if an key from src already exists in dst, do not replace it).
143-- @param dst Destination table, which will receive src's contents. 144-- @param dst Destination table, which will receive src's contents.
144-- @param src Table which provides new contents to dst. 145-- @param src Table which provides new contents to dst.
145function util.deep_merge_under(dst: {any: any}, src: {any: any}) --! same as above 146function util.deep_merge_under(dst: {any: any}, src: {any: any})
146 for k, v in pairs(src) do 147 for k, v in pairs(src) do
147 if type(v) == "table" then 148 if v is {any: any} then
148 if dst[k] == nil then 149 local dstk: any | {any: any} = dst[k]
150 if dstk == nil then
149 dst[k] = {} 151 dst[k] = {}
152 dstk = dst[k]
150 end 153 end
151 if dst[k] is {any: any} then --! "is" unavailable for table 154 if dstk is {any: any} then
152 util.deep_merge_under(dst[k], v) 155 util.deep_merge_under(dstk, v)
153 end 156 end
154 elseif dst[k] == nil then 157 elseif dst[k] == nil then
155 dst[k] = v 158 dst[k] = v
diff --git a/src/luarocks/core/vers.tl b/src/luarocks/core/vers.tl
index d00ae25d..7d0f0a83 100644
--- a/src/luarocks/core/vers.tl
+++ b/src/luarocks/core/vers.tl
@@ -1,11 +1,10 @@
1
2local record vers 1local record vers
3end 2end
4 3
5local util = require("luarocks.core.util") --! 4local util = require("luarocks.core.util")
6-------------------------------------------------------------------------------- 5--------------------------------------------------------------------------------
7 6
8local deltas = { 7local deltas: {string: integer} = { --?1
9 dev = 120000000, 8 dev = 120000000,
10 scm = 110000000, 9 scm = 110000000,
11 cvs = 100000000, 10 cvs = 100000000,
@@ -17,12 +16,14 @@ local deltas = {
17 16
18local record Version 17local record Version
19 {number} -- next version of Teal: "is {number}" 18 {number} -- next version of Teal: "is {number}"
20
21 string: string 19 string: string
22 revision: number 20 revision: number
21 metamethod __eq: function(Version, Version): boolean
22 metamethod __lt: function(Version, Version): boolean
23 metamethod __le: function(Version, Version): boolean
23end 24end
24 25
25local version_mt = { --? anything to do here 26local version_mt: metatable<Version> = { --? anything to do here
26 --- Equality comparison for versions. 27 --- Equality comparison for versions.
27 -- All version numbers must be equal. 28 -- All version numbers must be equal.
28 -- If both versions have revision numbers, they must be equal; 29 -- If both versions have revision numbers, they must be equal;
@@ -67,7 +68,7 @@ local version_mt = { --? anything to do here
67 -- @param v2 table: version table to compare. 68 -- @param v2 table: version table to compare.
68 -- @return boolean: true if v1 is considered lower than or equal to v2. 69 -- @return boolean: true if v1 is considered lower than or equal to v2.
69 __le = function(v1: Version, v2: Version): boolean 70 __le = function(v1: Version, v2: Version): boolean
70 return not (v2 < v1) -- luacheck: ignore --! 71 return not (v2 < v1)
71 end, 72 end,
72 --- Return version as a string. 73 --- Return version as a string.
73 -- @param v The version table. 74 -- @param v The version table.
@@ -93,8 +94,8 @@ setmetatable(version_cache, {
93-- @param vstring string: A version number in string format. 94-- @param vstring string: A version number in string format.
94-- @return table or nil: A version table or nil 95-- @return table or nil: A version table or nil
95-- if the input string contains invalid characters. 96-- if the input string contains invalid characters.
96function vers.parse_version(vstring: string): Version | nil 97function vers.parse_version(vstring: string): Version
97 if not vstring then return nil end --? needed? 98 if not vstring then return nil end
98 99
99 local cached = version_cache[vstring] 100 local cached = version_cache[vstring]
100 if cached then 101 if cached then
@@ -131,7 +132,7 @@ function vers.parse_version(vstring: string): Version | nil
131 version[i] = 0 132 version[i] = 0
132 break 133 break
133 end 134 end
134 version[i] = deltas[token] or (token:byte() / 1000) 135 version[i] = deltas[token] or (token:byte() / 1000) --?1
135 end 136 end
136 v = rest 137 v = rest
137 end 138 end
@@ -148,7 +149,7 @@ function vers.compare_versions(a: string, b: string): boolean
148 if a == b then 149 if a == b then
149 return false 150 return false
150 end 151 end
151 return vers.parse_version(a) > vers.parse_version(b) --! 152 return vers.parse_version(b) < vers.parse_version(a)
152end 153end
153 154
154--- A more lenient check for equivalence between versions. 155--- A more lenient check for equivalence between versions.
@@ -163,13 +164,13 @@ end
163-- in string format or already parsed into a table. 164-- in string format or already parsed into a table.
164-- @return boolean: True if the tested version matches the requested 165-- @return boolean: True if the tested version matches the requested
165-- version, false otherwise. 166-- version, false otherwise.
166local function partial_match(version_for_parse: string | table, requested_for_parce: string | table): boolean 167local function partial_match(version_for_parse: string | Version, requested_for_parce: string | Version): boolean
167 168
168 local version, requested: Version, Version 169 local version, requested: Version, Version
169 170
170 if not version_for_parse is {any: any} then version = vers.parse_version(version_for_parse) end 171 if not version_for_parse is Version then version = vers.parse_version(version_for_parse) end
171 if not requested_for_parce is {any: any} then requested = vers.parse_version(requested_for_parce) end 172 if not requested_for_parce is Version then requested = vers.parse_version(requested_for_parce) end
172 if not version is Version or not requested is Version then return false end --? needed? 173 if not version is Version or not requested is Version then return false end
173 174
174 for i, ri in ipairs(requested) do 175 for i, ri in ipairs(requested) do
175 local vi = version[i] or 0 176 local vi = version[i] or 0
@@ -190,18 +191,22 @@ function vers.match_constraints(version: Version, constraints: {any: {any: Versi
190 local ok = true 191 local ok = true
191 setmetatable(version, version_mt) 192 setmetatable(version, version_mt)
192 for _, constr in pairs(constraints) do 193 for _, constr in pairs(constraints) do
193 if constr.version is string then --!
194 constr.version = vers.parse_version(constr.version)
195 end
196 local constr_version, constr_op = constr.version, constr.op 194 local constr_version, constr_op = constr.version, constr.op
197 setmetatable(constr_version, version_mt) 195 local cv: Version
198 if constr_op == "==" then ok = version == constr_version 196 if constr_version is string then
199 elseif constr_op == "~=" then ok = version ~= constr_version 197 cv = vers.parse_version(constr_version)
200 elseif constr_op == ">" then ok = version > constr_version --! 198 constr.version = cv
201 elseif constr_op == "<" then ok = version < constr_version 199 else
202 elseif constr_op == ">=" then ok = version >= constr_version 200 cv = constr_version
203 elseif constr_op == "<=" then ok = version <= constr_version 201 end
204 elseif constr_op == "~>" then ok = partial_match(version, constr_version) --! 202 setmetatable(cv, version_mt)
203 if constr_op == "==" then ok = version == cv
204 elseif constr_op == "~=" then ok = version ~= cv
205 elseif constr_op == ">" then ok = cv < version
206 elseif constr_op == "<" then ok = version < cv
207 elseif constr_op == ">=" then ok = cv <= version
208 elseif constr_op == "<=" then ok = version <= cv
209 elseif constr_op == "~>" then ok = partial_match(version, cv)
205 end 210 end
206 if not ok then break end 211 if not ok then break end
207 end 212 end
diff --git a/tlconfig.lua b/tlconfig.lua
new file mode 100644
index 00000000..a6667cb1
--- /dev/null
+++ b/tlconfig.lua
@@ -0,0 +1,5 @@
1return {
2 build_dir = "build",
3 source_dir = "src",
4 include_dir = { "src" },
5 } \ No newline at end of file