aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2019-06-03 15:59:29 -0300
committerHisham Muhammad <hisham@gobolinux.org>2019-06-03 18:48:42 -0300
commitdaf7e7e5f5ede8c3a5a00e2edaf8246209712781 (patch)
treeb6435881ad91881de672f0281e59e0913d51c576 /src
parentf7eb8df5363430a2b5ac288da5710ff382c632fe (diff)
downloadluarocks-daf7e7e5f5ede8c3a5a00e2edaf8246209712781.tar.gz
luarocks-daf7e7e5f5ede8c3a5a00e2edaf8246209712781.tar.bz2
luarocks-daf7e7e5f5ede8c3a5a00e2edaf8246209712781.zip
Fix and reorganize Lua version detection
Make it more robust when detecting the Lua version when working inside a project, and hopefully make the detection logic easier to track in the code. Reorganized code so that the `detected` table becomes internal to the `init_config` operation and only the regular `cfg` global table is used after that. Includes regression tests.
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/cmd.lua312
-rw-r--r--src/luarocks/core/cfg.lua10
2 files changed, 163 insertions, 159 deletions
diff --git a/src/luarocks/cmd.lua b/src/luarocks/cmd.lua
index bbbdcba1..08505129 100644
--- a/src/luarocks/cmd.lua
+++ b/src/luarocks/cmd.lua
@@ -36,19 +36,6 @@ local function check_popen()
36 end 36 end
37end 37end
38 38
39local function check_if_config_is_present(detected, try)
40 local versions = detected.lua_version
41 and { detected.lua_version }
42 or util.lua_versions("descending")
43 return fun.find(versions, function(v)
44 if util.exists(dir.path(try, ".luarocks", "config-"..v..".lua")) then
45 detected.project_dir = try
46 detected.lua_version = v
47 return detected
48 end
49 end)
50end
51
52local process_tree_flags 39local process_tree_flags
53do 40do
54 local function replace_tree(flags, root, tree) 41 local function replace_tree(flags, root, tree)
@@ -152,32 +139,153 @@ local function process_server_flags(flags)
152 return true 139 return true
153end 140end
154 141
155local function get_lua_version(flags) 142local function error_handler(err)
156 if flags["lua-version"] then 143 local mode = "Arch.: " .. (cfg and cfg.arch or "unknown")
157 return flags["lua-version"] 144 if package.config:sub(1, 1) == "\\" then
145 if cfg and cfg.fs_use_modules then
146 mode = mode .. " (fs_use_modules = true)"
147 end
158 end 148 end
159 local dirs = {} 149 return debug.traceback("LuaRocks "..cfg.program_version..
160 if flags["project-tree"] then 150 " bug (please report at https://github.com/luarocks/luarocks/issues).\n"..
161 table.insert(dirs, dir.path(flags["project-tree"], "..", ".luarocks")) 151 mode.."\n"..err, 2)
152end
153
154--- Display an error message and exit.
155-- @param message string: The error message.
156-- @param exitcode number: the exitcode to use
157local function die(message, exitcode)
158 assert(type(message) == "string", "bad error, expected string, got: " .. type(message))
159 util.printerr("\nError: "..message)
160
161 local ok, err = xpcall(util.run_scheduled_functions, error_handler)
162 if not ok then
163 util.printerr("\nError: "..err)
164 exitcode = cmd.errorcodes.CRASH
162 end 165 end
163 if cfg.home_tree then 166
164 table.insert(dirs, dir.path(cfg.home_tree, ".luarocks")) 167 os.exit(exitcode or cmd.errorcodes.UNSPECIFIED)
168end
169
170local init_config
171do
172 local detect_config_via_flags
173 do
174 local function find_project_dir(project_tree)
175 if project_tree then
176 return project_tree:gsub("[/\\][^/\\]+$", "")
177 else
178 local try = "."
179 for _ = 1, 10 do -- FIXME detect when root dir was hit instead
180 if util.exists(try .. "/.luarocks") and util.exists(try .. "/lua_modules") then
181 return try
182 elseif util.exists(try .. "/.luarocks-no-project") then
183 break
184 end
185 try = try .. "/.."
186 end
187 end
188 return nil
189 end
190
191 local function find_default_lua_version(flags, project_dir)
192 local dirs = {}
193 if project_dir then
194 table.insert(dirs, dir.path(project_dir, ".luarocks"))
195 end
196 if cfg.home_tree then
197 table.insert(dirs, dir.path(cfg.home_tree, ".luarocks"))
198 end
199 table.insert(dirs, cfg.sysconfdir)
200 for _, d in ipairs(dirs) do
201 local f = dir.path(d, "default-lua-version.lua")
202 local mod, err = loadfile(f, "t")
203 if mod then
204 local pok, ver = pcall(mod)
205 if pok and type(ver) == "string" and ver:match("%d+.%d+") then
206 if flags["verbose"] then
207 util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...")
208 end
209 return ver
210 end
211 end
212 end
213 return nil
214 end
215
216 local function find_version_from_config(dirname)
217 return fun.find(util.lua_versions("descending"), function(v)
218 if util.exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then
219 return v
220 end
221 end)
222 end
223
224 local function detect_lua_via_flags(flags, project_dir)
225 local lua_version = flags["lua-version"]
226 or find_default_lua_version(flags, project_dir)
227 or (project_dir and find_version_from_config(project_dir))
228
229 if flags["lua-dir"] then
230 local detected, err = util.find_lua(flags["lua-dir"], lua_version)
231 if not detected then
232 die(err)
233 end
234 return detected
235 end
236
237 if lua_version then
238 local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":")
239 for bindir in os.getenv("PATH"):gmatch("[^"..path_sep.."]+") do
240 local parentdir = bindir:gsub("[\\/][^\\/]+[\\/]?$", "")
241 local detected = util.find_lua(dir.path(parentdir), lua_version)
242 if detected then
243 return detected
244 end
245 detected = util.find_lua(bindir, lua_version)
246 if detected then
247 return detected
248 end
249 end
250 return {
251 lua_version = lua_version,
252 }
253 end
254
255 return {}
256 end
257
258 detect_config_via_flags = function(flags)
259 local project_dir = find_project_dir(flags["project-tree"])
260 local detected = detect_lua_via_flags(flags, project_dir)
261 detected.project_dir = project_dir
262 return detected
263 end
165 end 264 end
166 table.insert(dirs, cfg.sysconfdir) 265
167 for _, d in ipairs(dirs) do 266 init_config = function(flags)
168 local f = dir.path(d, "default-lua-version.lua") 267 local detected = detect_config_via_flags(flags)
169 local mod, err = loadfile(f, "t") 268
170 if mod then 269 -- FIXME A quick hack for the experimental Windows build
171 local pok, ver = pcall(mod) 270 if os.getenv("LUAROCKS_CROSS_COMPILING") then
172 if pok and type(ver) == "string" and ver:match("%d+.%d+") then 271 cfg.each_platform = function()
173 if flags["verbose"] then 272 local i = 0
174 util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...") 273 local plats = { "unix", "linux" }
274 return function()
275 i = i + 1
276 return plats[i]
175 end 277 end
176 return ver
177 end 278 end
279 fs.init()
280 end
281
282 local ok, err = cfg.init(detected, util.warning)
283 if not ok then
284 return nil, err
178 end 285 end
286
287 return (detected.lua_dir ~= nil)
179 end 288 end
180 return nil
181end 289end
182 290
183--- Main command-line processor. 291--- Main command-line processor.
@@ -192,34 +300,6 @@ function cmd.run_command(description, commands, external_namespace, ...)
192 300
193 check_popen() 301 check_popen()
194 302
195 local function error_handler(err)
196 local mode = "Arch.: " .. (cfg and cfg.arch or "unknown")
197 if package.config:sub(1, 1) == "\\" then
198 if cfg and cfg.fs_use_modules then
199 mode = mode .. " (fs_use_modules = true)"
200 end
201 end
202 return debug.traceback("LuaRocks "..cfg.program_version..
203 " bug (please report at https://github.com/luarocks/luarocks/issues).\n"..
204 mode.."\n"..err, 2)
205 end
206
207 --- Display an error message and exit.
208 -- @param message string: The error message.
209 -- @param exitcode number: the exitcode to use
210 local function die(message, exitcode)
211 assert(type(message) == "string", "bad error, expected string, got: " .. type(message))
212 util.printerr("\nError: "..message)
213
214 local ok, err = xpcall(util.run_scheduled_functions, error_handler)
215 if not ok then
216 util.printerr("\nError: "..err)
217 exitcode = cmd.errorcodes.CRASH
218 end
219
220 os.exit(exitcode or cmd.errorcodes.UNSPECIFIED)
221 end
222
223 local function process_arguments(...) 303 local function process_arguments(...)
224 local args = {...} 304 local args = {...}
225 local cmdline_vars = {} 305 local cmdline_vars = {}
@@ -285,122 +365,44 @@ function cmd.run_command(description, commands, external_namespace, ...)
285 end 365 end
286 end 366 end
287 367
288 local lua_version = get_lua_version(flags)
289
290 if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then 368 if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then
291 die("Invalid entry for --deps-mode.") 369 die("Invalid entry for --deps-mode.")
292 end 370 end
293 371
294 local lua_found = false
295
296 local detected
297 if flags["lua-dir"] then
298 local err
299 detected, err = util.find_lua(flags["lua-dir"], lua_version)
300 if not detected then
301 die(err)
302 end
303 lua_found = true
304 assert(detected.lua_version)
305 assert(detected.lua_dir)
306 elseif lua_version then
307 local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":")
308 for bindir in os.getenv("PATH"):gmatch("[^"..path_sep.."]+") do
309 local parentdir = bindir:gsub("[\\/][^\\/]+[\\/]?$", "")
310 detected = util.find_lua(dir.path(parentdir), lua_version)
311 if detected then
312 break
313 end
314 detected = util.find_lua(bindir, lua_version)
315 if detected then
316 break
317 end
318 end
319 if detected then
320 lua_found = true
321 else
322 detected = {
323 lua_version = lua_version,
324 }
325 end
326 end
327
328 if flags["project-tree"] then
329 local project_tree = flags["project-tree"]:gsub("[/\\][^/\\]+$", "")
330 detected = detected or {}
331 detected.project_dir = project_tree
332 local d = check_if_config_is_present(detected, project_tree)
333 if d then
334 detected = d
335 end
336 else
337 detected = detected or {}
338 local try = "."
339 for _ = 1, 10 do -- FIXME detect when root dir was hit instead
340 if util.exists(try .. "/.luarocks") and util.exists(try .. "/lua_modules") then
341 local d = check_if_config_is_present(detected, try)
342 if d then
343 detected = d
344 break
345 end
346 elseif util.exists(try .. "/.luarocks-no-project") then
347 break
348 end
349 try = try .. "/.."
350 end
351 end
352
353 -- FIXME A quick hack for the experimental Windows build
354 if os.getenv("LUAROCKS_CROSS_COMPILING") then
355 cfg.each_platform = function()
356 local i = 0
357 local plats = { "unix", "linux" }
358 return function()
359 i = i + 1
360 return plats[i]
361 end
362 end
363 fs.init()
364 end
365
366 ----------------------------------------------------------------------------- 372 -----------------------------------------------------------------------------
367 local ok, err = cfg.init(detected, util.warning) 373 local lua_found, err = init_config(flags)
368 if not ok then 374 if err then
369 die(err) 375 die(err)
370 end 376 end
371 ----------------------------------------------------------------------------- 377 -----------------------------------------------------------------------------
372 378
373 fs.init() 379 if flags["version"] then
380 util.printout(program.." "..cfg.program_version)
381 util.printout(description)
382 util.printout()
383 os.exit(cmd.errorcodes.OK)
384 end
374 385
375 lua_version = cfg.lua_version 386 fs.init()
376 387
388 -- if the Lua interpreter wasn't explicitly found before cfg.init,
389 -- try again now.
377 if not lua_found then 390 if not lua_found then
378 if cfg.variables.LUA_DIR then 391 if cfg.variables.LUA_DIR then
379 local found = util.find_lua(cfg.variables.LUA_DIR, cfg.lua_version) 392 lua_found = util.find_lua(cfg.variables.LUA_DIR, cfg.lua_version)
380 if found then
381 lua_found = true
382 end
383 end 393 end
384 end 394 end
385 395
386 if not lua_found then 396 if not lua_found then
387 util.warning("Could not find a Lua interpreter for version " .. 397 util.warning("Could not find a Lua " .. cfg.lua_version .. " interpreter in your PATH. " ..
388 lua_version .. " in your PATH. " ..
389 "Modules may not install with the correct configurations. " .. 398 "Modules may not install with the correct configurations. " ..
390 "You may want to specify to the path prefix to your build " .. 399 "You may want to specify to the path prefix to your build " ..
391 "of Lua " .. lua_version .. " using --lua-dir") 400 "of Lua " .. cfg.lua_version .. " using --lua-dir")
392 end 401 end
393 cfg.lua_found = lua_found 402 cfg.lua_found = lua_found
394 403
395 if detected.project_dir then 404 if cfg.project_dir then
396 detected.project_dir = fs.absolute_name(detected.project_dir) 405 cfg.project_dir = fs.absolute_name(cfg.project_dir)
397 end
398
399 if flags["version"] then
400 util.printout(program.." "..cfg.program_version)
401 util.printout(description)
402 util.printout()
403 os.exit(cmd.errorcodes.OK)
404 end 406 end
405 407
406 for _, module_name in ipairs(fs.modules(external_namespace)) do 408 for _, module_name in ipairs(fs.modules(external_namespace)) do
@@ -418,7 +420,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
418 die("Current directory does not exist. Please run LuaRocks from an existing directory.") 420 die("Current directory does not exist. Please run LuaRocks from an existing directory.")
419 end 421 end
420 422
421 ok, err = process_tree_flags(flags, detected.project_dir) 423 ok, err = process_tree_flags(flags, cfg.project_dir)
422 if not ok then 424 if not ok then
423 die(err) 425 die(err)
424 end 426 end
diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua
index 02fb564b..d8442962 100644
--- a/src/luarocks/core/cfg.lua
+++ b/src/luarocks/core/cfg.lua
@@ -561,6 +561,7 @@ function cfg.init(detected, warning)
561 local lua_incdir = detected.lua_incdir or hardcoded.LUA_INCDIR 561 local lua_incdir = detected.lua_incdir or hardcoded.LUA_INCDIR
562 local lua_libdir = detected.lua_libdir or hardcoded.LUA_LIBDIR 562 local lua_libdir = detected.lua_libdir or hardcoded.LUA_LIBDIR
563 local lua_dir = detected.lua_dir or hardcoded.LUA_DIR or (lua_bindir and lua_bindir:gsub("[\\/]bin$", "")) 563 local lua_dir = detected.lua_dir or hardcoded.LUA_DIR or (lua_bindir and lua_bindir:gsub("[\\/]bin$", ""))
564 local project_dir = detected.project_dir
564 565
565 local init = cfg.init 566 local init = cfg.init
566 567
@@ -636,8 +637,8 @@ function cfg.init(detected, warning)
636 local name = "config-"..cfg.lua_version..".lua" 637 local name = "config-"..cfg.lua_version..".lua"
637 sys_config_file = (cfg.sysconfdir .. "/" .. name):gsub("\\", "/") 638 sys_config_file = (cfg.sysconfdir .. "/" .. name):gsub("\\", "/")
638 home_config_file = (cfg.homeconfdir .. "/" .. name):gsub("\\", "/") 639 home_config_file = (cfg.homeconfdir .. "/" .. name):gsub("\\", "/")
639 if detected.project_dir then 640 if project_dir then
640 project_config_file = detected.project_dir .. "/.luarocks/" .. name 641 project_config_file = project_dir .. "/.luarocks/" .. name
641 end 642 end
642 end 643 end
643 644
@@ -680,7 +681,7 @@ function cfg.init(detected, warning)
680 end 681 end
681 682
682 -- finally, use the project-specific config file if any 683 -- finally, use the project-specific config file if any
683 if detected.project_dir then 684 if project_dir then
684 project_config_ok, err = load_config_file(cfg, platforms, project_config_file) 685 project_config_ok, err = load_config_file(cfg, platforms, project_config_file)
685 if err then 686 if err then
686 return nil, err, "config" 687 return nil, err, "config"
@@ -694,6 +695,7 @@ function cfg.init(detected, warning)
694 ---------------------------------------- 695 ----------------------------------------
695 696
696 -- Settings detected or given via the CLI (i.e. --lua-dir) take precedence over config files: 697 -- Settings detected or given via the CLI (i.e. --lua-dir) take precedence over config files:
698 cfg.project_dir = detected.project_dir
697 cfg.lua_version = detected.lua_version or cfg.lua_version 699 cfg.lua_version = detected.lua_version or cfg.lua_version
698 cfg.luajit_version = detected.luajit_version or cfg.luajit_version 700 cfg.luajit_version = detected.luajit_version or cfg.luajit_version
699 cfg.lua_interpreter = detected.lua_interpreter or cfg.lua_interpreter 701 cfg.lua_interpreter = detected.lua_interpreter or cfg.lua_interpreter
@@ -731,7 +733,7 @@ function cfg.init(detected, warning)
731 cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch 733 cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
732 734
733 cfg.config_files = { 735 cfg.config_files = {
734 project = detected.project_dir and { 736 project = project_dir and {
735 file = project_config_file, 737 file = project_config_file,
736 found = not not project_config_ok, 738 found = not not project_config_ok,
737 }, 739 },