aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2019-03-21 18:47:44 -0400
committerHisham Muhammad <hisham@gobolinux.org>2019-04-01 16:26:30 -0300
commite388deecaa13b7b89da202d09d328a79bbcf40dd (patch)
tree1adcd8df720b0bb247f141342efed1f851341b52
parent5cdaa0ad83f79e7c8ecfa87e5d58f4a42d907a44 (diff)
downloadluarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.tar.gz
luarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.tar.bz2
luarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.zip
cmd: refactor detection code and improve detection of project dir
-rw-r--r--spec/init_spec.lua4
-rw-r--r--src/luarocks/cmd.lua198
-rw-r--r--src/luarocks/core/cfg.lua50
-rw-r--r--src/luarocks/util.lua109
4 files changed, 189 insertions, 172 deletions
diff --git a/spec/init_spec.lua b/spec/init_spec.lua
index 2c8dd64c..22570df2 100644
--- a/spec/init_spec.lua
+++ b/spec/init_spec.lua
@@ -111,7 +111,9 @@ describe("Luarocks init test #integration", function()
111 ]], finally) 111 ]], finally)
112 write_file(tmpdir .. "/my_dependency.lua", "return {}", finally) 112 write_file(tmpdir .. "/my_dependency.lua", "return {}", finally)
113 113
114 assert.is_true(run.luarocks_bool("build --verbose my_dependency-1.0-1.rockspec")) 114 print(run.luarocks("install inspect"))
115
116 print(run.luarocks("build --verbose my_dependency-1.0-1.rockspec"))
115 assert.truthy(lfs.attributes(myproject .. "/lua_modules/share/lua/" .. test_env.lua_version .."/my_dependency.lua")) 117 assert.truthy(lfs.attributes(myproject .. "/lua_modules/share/lua/" .. test_env.lua_version .."/my_dependency.lua"))
116 118
117 os.remove(rockspec_filename) 119 os.remove(rockspec_filename)
diff --git a/src/luarocks/cmd.lua b/src/luarocks/cmd.lua
index 4397d43b..a46b0722 100644
--- a/src/luarocks/cmd.lua
+++ b/src/luarocks/cmd.lua
@@ -38,106 +38,6 @@ local function is_ownership_ok(directory)
38 return false 38 return false
39end 39end
40 40
41local function exists(file)
42 local fd = io.open(file, "r")
43 if fd then
44 fd:close()
45 return true
46 end
47 return false
48end
49
50do
51 local function Q(pathname)
52 if pathname:match("^.:") then
53 return pathname:sub(1, 2) .. '"' .. pathname:sub(3) .. '"'
54 end
55 return '"' .. pathname .. '"'
56 end
57
58 local function check_lua_version(lua_exe, luaver)
59 if not exists(lua_exe) then
60 return nil
61 end
62 local lv, err = util.popen_read(Q(lua_exe) .. ' -e "io.write(_VERSION:sub(5))"')
63 if luaver and luaver ~= lv then
64 return nil
65 end
66 local ljv
67 if lv == "5.1" then
68 ljv = util.popen_read(Q(lua_exe) .. ' -e "io.write(tostring(jit and jit.version:sub(8)))"')
69 if ljv == "nil" then
70 ljv = nil
71 end
72 end
73 return lv, ljv
74 end
75
76 local find_lua_bindir
77 do
78 local exe_suffix = (package.config:sub(1, 1) == "\\" and ".exe" or "")
79
80 local function insert_lua_versions(names, luaver)
81 local variants = {
82 "lua" .. luaver .. exe_suffix,
83 "lua" .. luaver:gsub("%.", "") .. exe_suffix,
84 "lua-" .. luaver .. exe_suffix,
85 "lua-" .. luaver:gsub("%.", "") .. exe_suffix,
86 }
87 for _, name in ipairs(variants) do
88 names[name] = luaver
89 table.insert(names, name)
90 end
91 end
92
93 find_lua_bindir = function(prefix, luaver)
94 local names = {}
95 if luaver then
96 insert_lua_versions(names, luaver)
97 else
98 for v in util.lua_versions("descending") do
99 insert_lua_versions(names, v)
100 end
101 end
102 if luaver == "5.1" or not luaver then
103 table.insert(names, "luajit" .. exe_suffix)
104 end
105 table.insert(names, "lua" .. exe_suffix)
106
107 local bindirs = { prefix .. "/bin", prefix }
108 local tried = {}
109 for _, d in ipairs(bindirs) do
110 for _, name in ipairs(names) do
111 local lua_exe = dir.path(d, name)
112 table.insert(tried, lua_exe)
113 local lv, ljv = check_lua_version(lua_exe, luaver)
114 if lv then
115 return name, d, lv, ljv
116 end
117 end
118 end
119 return nil, "Lua interpreter not found at " .. prefix .. "\n" ..
120 "Tried:\t" .. table.concat(tried, "\n\t")
121 end
122 end
123
124 function cmd.find_lua(prefix, luaver)
125 local lua_interpreter, bindir, luajitver
126 lua_interpreter, bindir, luaver, luajitver = find_lua_bindir(prefix, luaver)
127 if not lua_interpreter then
128 return nil, bindir
129 end
130
131 return {
132 lua_version = luaver,
133 luajit_version = luajitver,
134 lua_interpreter = lua_interpreter,
135 lua_dir = prefix,
136 lua_bindir = bindir,
137 }
138 end
139end
140
141local function check_popen() 41local function check_popen()
142 local popen_ok, popen_result = pcall(io.popen, "") 42 local popen_ok, popen_result = pcall(io.popen, "")
143 if popen_ok then 43 if popen_ok then
@@ -151,16 +51,17 @@ local function check_popen()
151 end 51 end
152end 52end
153 53
154local function find_project_dir() 54local function check_if_config_is_present(detected, try)
155 local try = "." 55 local versions = detected.lua_version
156 for _ = 1, 10 do -- FIXME detect when root dir was hit instead 56 and { detected.lua_version }
157 if exists(try .. "/.luarocks") and exists(try .. "/lua_modules") then 57 or util.lua_versions("descending")
158 return try 58 return fun.find(versions, function(v)
159 elseif exists(try .. "/.luarocks-no-project") then 59 if util.exists(dir.path(try, ".luarocks", "config-"..v..".lua")) then
160 return nil 60 detected.project_dir = try
61 detected.lua_version = v
62 return detected
161 end 63 end
162 try = try .. "/.." 64 end)
163 end
164end 65end
165 66
166local process_tree_flags 67local process_tree_flags
@@ -261,19 +162,6 @@ local function process_server_flags(flags)
261 return true 162 return true
262end 163end
263 164
264local function find_lua_version_at(dirname)
265 local lua_version
266 for v in util.lua_versions("descending") do
267 if exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then
268 lua_version = v
269 break
270 end
271 end
272 return {
273 lua_version = lua_version
274 }
275end
276
277--- Main command-line processor. 165--- Main command-line processor.
278-- Parses input arguments and calls the appropriate driver function 166-- Parses input arguments and calls the appropriate driver function
279-- to execute the action requested on the command-line, forwarding 167-- to execute the action requested on the command-line, forwarding
@@ -375,47 +263,65 @@ function cmd.run_command(description, commands, external_namespace, ...)
375 die("Invalid entry for --deps-mode.") 263 die("Invalid entry for --deps-mode.")
376 end 264 end
377 265
378 local project_dir 266 local detected
379 if flags["project-tree"] then
380 project_dir = flags["project-tree"]:gsub("[/\\][^/\\]+$", "")
381 end
382
383 local lua_data
384 if flags["lua-dir"] then 267 if flags["lua-dir"] then
385 local err 268 local err
386 lua_data, err = cmd.find_lua(flags["lua-dir"], flags["lua-version"]) 269 detected, err = util.find_lua(flags["lua-dir"], flags["lua-version"])
387 if not lua_data then 270 if not detected then
388 die(err) 271 die(err)
389 end 272 end
273 assert(detected.lua_version)
274 assert(detected.lua_dir)
390 elseif flags["lua-version"] then 275 elseif flags["lua-version"] then
391 local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":") 276 local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":")
392 for bindir in os.getenv("PATH"):gmatch("[^"..path_sep.."]+") do 277 for bindir in os.getenv("PATH"):gmatch("[^"..path_sep.."]+") do
393 local parentdir = bindir:gsub("[\\/][^\\/]+[\\/]?$", "") 278 local parentdir = bindir:gsub("[\\/][^\\/]+[\\/]?$", "")
394 lua_data = cmd.find_lua(dir.path(parentdir), flags["lua-version"]) 279 detected = util.find_lua(dir.path(parentdir), flags["lua-version"])
395 if lua_data then 280 if detected then
396 break 281 break
397 end 282 end
398 lua_data = cmd.find_lua(bindir, flags["lua-version"]) 283 detected = util.find_lua(bindir, flags["lua-version"])
399 if lua_data then 284 if detected then
400 break 285 break
401 end 286 end
402 end 287 end
403 if not lua_data then 288 if not detected then
404 util.warning("Could not find a Lua interpreter for version " .. 289 util.warning("Could not find a Lua interpreter for version " ..
405 flags["lua-version"] .. " in your PATH. " .. 290 flags["lua-version"] .. " in your PATH. " ..
406 "Modules may not install with the correct configurations. " .. 291 "Modules may not install with the correct configurations. " ..
407 "You may want to specify to the path prefix to your build " .. 292 "You may want to specify to the path prefix to your build " ..
408 "of Lua " .. flags["lua-version"] .. " using --lua-dir") 293 "of Lua " .. flags["lua-version"] .. " using --lua-dir")
409 lua_data = { 294 detected = {
410 lua_version = flags["lua-version"], 295 lua_version = flags["lua-version"],
411 } 296 }
412 end 297 end
413 else 298 end
414 if not project_dir then 299
415 project_dir = find_project_dir() 300 if flags["project-tree"] then
301 local project_tree = flags["project-tree"]:gsub("[/\\][^/\\]+$", "")
302 detected = detected or {
303 project_dir = project_tree
304 }
305 local d = check_if_config_is_present(detected, project_tree)
306 if d then
307 detected = d
308 else
309 detected.project_dir = nil
416 end 310 end
417 if project_dir then 311 else
418 lua_data = find_lua_version_at(project_dir) 312 detected = detected or {}
313 local try = "."
314 for _ = 1, 10 do -- FIXME detect when root dir was hit instead
315 if util.exists(try .. "/.luarocks") and util.exists(try .. "/lua_modules") then
316 local d = check_if_config_is_present(detected, try)
317 if d then
318 detected = d
319 break
320 end
321 elseif util.exists(try .. "/.luarocks-no-project") then
322 break
323 end
324 try = try .. "/.."
419 end 325 end
420 end 326 end
421 327
@@ -433,16 +339,16 @@ function cmd.run_command(description, commands, external_namespace, ...)
433 end 339 end
434 340
435 ----------------------------------------------------------------------------- 341 -----------------------------------------------------------------------------
436 local ok, err = cfg.init(lua_data, project_dir, util.warning) 342 local ok, err = cfg.init(detected, util.warning)
437 if not ok then 343 if not ok then
438 die(err) 344 die(err)
439 end 345 end
440 ----------------------------------------------------------------------------- 346 -----------------------------------------------------------------------------
441 347
442 fs.init() 348 fs.init()
443 349
444 if project_dir then 350 if detected.project_dir then
445 project_dir = fs.absolute_name(project_dir) 351 detected.project_dir = fs.absolute_name(detected.project_dir)
446 end 352 end
447 353
448 if flags["version"] then 354 if flags["version"] then
@@ -467,7 +373,7 @@ function cmd.run_command(description, commands, external_namespace, ...)
467 die("Current directory does not exist. Please run LuaRocks from an existing directory.") 373 die("Current directory does not exist. Please run LuaRocks from an existing directory.")
468 end 374 end
469 375
470 ok, err = process_tree_flags(flags, project_dir) 376 ok, err = process_tree_flags(flags, detected.project_dir)
471 if not ok then 377 if not ok then
472 die(err) 378 die(err)
473 end 379 end
diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua
index 5cfa10c3..670f04b2 100644
--- a/src/luarocks/core/cfg.lua
+++ b/src/luarocks/core/cfg.lua
@@ -535,8 +535,8 @@ local cfg = {}
535 535
536--- Initializes the LuaRocks configuration for variables, paths 536--- Initializes the LuaRocks configuration for variables, paths
537-- and OS detection. 537-- and OS detection.
538-- @param lua_data table containing information pertaining the location 538-- @param detected table containing information detected about the
539-- of Lua in the environment. All fields below are optional: 539-- environment. All fields below are optional:
540-- * lua_version (in x.y format, e.g. "5.3") 540-- * lua_version (in x.y format, e.g. "5.3")
541-- * luajit_version (complete, e.g. "2.1.0-beta3") 541-- * luajit_version (complete, e.g. "2.1.0-beta3")
542-- * lua_bindir (e.g. "/usr/local/bin") 542-- * lua_bindir (e.g. "/usr/local/bin")
@@ -544,25 +544,25 @@ local cfg = {}
544-- * lua_libdir(e.g. "/usr/local/lib") 544-- * lua_libdir(e.g. "/usr/local/lib")
545-- * lua_dir (e.g. "/usr/local") 545-- * lua_dir (e.g. "/usr/local")
546-- * lua_interpreter (e.g. "lua-5.3") 546-- * lua_interpreter (e.g. "lua-5.3")
547-- @param project_dir a string with the path of the project directory 547-- * project_dir (a string with the path of the project directory
548-- when using per-project environments, as created with `luarocks init` 548-- when using per-project environments, as created with `luarocks init`)
549-- @param warning a logging function for warnings that takes a string 549-- @param warning a logging function for warnings that takes a string
550-- @return true on success; nil and an error message on failure. 550-- @return true on success; nil and an error message on failure.
551function cfg.init(lua_data, project_dir, warning) 551function cfg.init(detected, warning)
552 lua_data = lua_data or {} 552 detected = detected or {}
553 553
554 local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded") 554 local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded")
555 if not hc_ok then 555 if not hc_ok then
556 hardcoded = {} 556 hardcoded = {}
557 end 557 end
558 558
559 local lua_version = lua_data.lua_version or hardcoded.LUA_VERSION or _VERSION:sub(5) 559 local lua_version = detected.lua_version or hardcoded.LUA_VERSION or _VERSION:sub(5)
560 local luajit_version = lua_data.luajit_version or hardcoded.LUAJIT_VERSION or (jit and jit.version:sub(8)) 560 local luajit_version = detected.luajit_version or hardcoded.LUAJIT_VERSION or (jit and jit.version:sub(8))
561 local lua_interpreter = lua_data.lua_interpreter or hardcoded.LUA_INTERPRETER or (arg and arg[-1] and arg[-1]:gsub(".*[\\/]", "")) or (is_windows and "lua.exe" or "lua") 561 local lua_interpreter = detected.lua_interpreter or hardcoded.LUA_INTERPRETER or (arg and arg[-1] and arg[-1]:gsub(".*[\\/]", "")) or (is_windows and "lua.exe" or "lua")
562 local lua_bindir = lua_data.lua_bindir or hardcoded.LUA_BINDIR or (arg and arg[-1] and arg[-1]:gsub("[\\/][^\\/]+$", "")) 562 local lua_bindir = detected.lua_bindir or hardcoded.LUA_BINDIR or (arg and arg[-1] and arg[-1]:gsub("[\\/][^\\/]+$", ""))
563 local lua_incdir = lua_data.lua_incdir or hardcoded.LUA_INCDIR 563 local lua_incdir = detected.lua_incdir or hardcoded.LUA_INCDIR
564 local lua_libdir = lua_data.lua_libdir or hardcoded.LUA_LIBDIR 564 local lua_libdir = detected.lua_libdir or hardcoded.LUA_LIBDIR
565 local lua_dir = lua_data.lua_dir or hardcoded.LUA_DIR 565 local lua_dir = detected.lua_dir or hardcoded.LUA_DIR
566 566
567 local init = cfg.init 567 local init = cfg.init
568 568
@@ -638,8 +638,8 @@ function cfg.init(lua_data, project_dir, warning)
638 local name = "config-"..cfg.lua_version..".lua" 638 local name = "config-"..cfg.lua_version..".lua"
639 sys_config_file = (cfg.sysconfdir .. "/" .. name):gsub("\\", "/") 639 sys_config_file = (cfg.sysconfdir .. "/" .. name):gsub("\\", "/")
640 home_config_file = (cfg.homeconfdir .. "/" .. name):gsub("\\", "/") 640 home_config_file = (cfg.homeconfdir .. "/" .. name):gsub("\\", "/")
641 if project_dir then 641 if detected.project_dir then
642 project_config_file = project_dir .. "/.luarocks/" .. name 642 project_config_file = detected.project_dir .. "/.luarocks/" .. name
643 end 643 end
644 end 644 end
645 645
@@ -682,7 +682,7 @@ function cfg.init(lua_data, project_dir, warning)
682 end 682 end
683 683
684 -- finally, use the project-specific config file if any 684 -- finally, use the project-specific config file if any
685 if project_dir then 685 if detected.project_dir then
686 project_config_ok, err = load_config_file(cfg, platforms, project_config_file) 686 project_config_ok, err = load_config_file(cfg, platforms, project_config_file)
687 if err then 687 if err then
688 return nil, err, "config" 688 return nil, err, "config"
@@ -695,14 +695,14 @@ function cfg.init(lua_data, project_dir, warning)
695 -- Let's finish up the cfg table. 695 -- Let's finish up the cfg table.
696 ---------------------------------------- 696 ----------------------------------------
697 697
698 -- Settings given via lua_data (i.e. --lua-dir) take precedence over config files: 698 -- Settings detected or given via the CLI (i.e. --lua-dir) take precedence over config files:
699 cfg.lua_version = lua_data.lua_version or cfg.lua_version 699 cfg.lua_version = detected.lua_version or cfg.lua_version
700 cfg.luajit_version = lua_data.luajit_version or cfg.luajit_version 700 cfg.luajit_version = detected.luajit_version or cfg.luajit_version
701 cfg.lua_interpreter = lua_data.lua_interpreter or cfg.lua_interpreter 701 cfg.lua_interpreter = detected.lua_interpreter or cfg.lua_interpreter
702 cfg.variables.LUA_BINDIR = lua_data.lua_bindir or cfg.variables.LUA_BINDIR or lua_bindir 702 cfg.variables.LUA_BINDIR = detected.lua_bindir or cfg.variables.LUA_BINDIR or lua_bindir
703 cfg.variables.LUA_INCDIR = lua_data.lua_incdir or cfg.variables.LUA_INCDIR or lua_incdir 703 cfg.variables.LUA_INCDIR = detected.lua_incdir or cfg.variables.LUA_INCDIR or lua_incdir
704 cfg.variables.LUA_LIBDIR = lua_data.lua_libdir or cfg.variables.LUA_LIBDIR or lua_libdir 704 cfg.variables.LUA_LIBDIR = detected.lua_libdir or cfg.variables.LUA_LIBDIR or lua_libdir
705 cfg.variables.LUA_DIR = lua_data.lua_dir or cfg.variables.LUA_DIR or lua_dir 705 cfg.variables.LUA_DIR = detected.lua_dir or cfg.variables.LUA_DIR or lua_dir
706 706
707 -- Build a default list of rocks trees if not given 707 -- Build a default list of rocks trees if not given
708 if cfg.rocks_trees == nil then 708 if cfg.rocks_trees == nil then
@@ -739,7 +739,7 @@ function cfg.init(lua_data, project_dir, warning)
739 739
740 function cfg.which_config() 740 function cfg.which_config()
741 return { 741 return {
742 project = project_dir and { 742 project = detected.project_dir and {
743 file = project_config_file, 743 file = project_config_file,
744 ok = project_config_ok, 744 ok = project_config_ok,
745 }, 745 },
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index 7d7ce921..25c521ea 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -548,4 +548,113 @@ function util.require_json()
548 return nil, errmsg 548 return nil, errmsg
549end 549end
550 550
551-- A portable version of fs.exists that can be used at early startup,
552-- before the platform has been determined and luarocks.fs has been
553-- initialized.
554function util.exists(file)
555 local fd, _, code = io.open(file, "r")
556 if code == 13 then
557 -- code 13 means "Permission denied" on both Unix and Windows
558 -- io.open on folders always fails with code 13 on Windows
559 return true
560 end
561 if fd then
562 fd:close()
563 return true
564 end
565 return false
566end
567
568do
569 local function Q(pathname)
570 if pathname:match("^.:") then
571 return pathname:sub(1, 2) .. '"' .. pathname:sub(3) .. '"'
572 end
573 return '"' .. pathname .. '"'
574 end
575
576 function util.check_lua_version(lua_exe, luaver)
577 if not util.exists(lua_exe) then
578 return nil
579 end
580 local lv, err = util.popen_read(Q(lua_exe) .. ' -e "io.write(_VERSION:sub(5))"')
581 if luaver and luaver ~= lv then
582 return nil
583 end
584 local ljv
585 if lv == "5.1" then
586 ljv = util.popen_read(Q(lua_exe) .. ' -e "io.write(tostring(jit and jit.version:sub(8)))"')
587 if ljv == "nil" then
588 ljv = nil
589 end
590 end
591 return lv, ljv
592 end
593
594 local find_lua_bindir
595 do
596 local exe_suffix = (package.config:sub(1, 1) == "\\" and ".exe" or "")
597
598 local function insert_lua_variants(names, luaver)
599 local variants = {
600 "lua" .. luaver .. exe_suffix,
601 "lua" .. luaver:gsub("%.", "") .. exe_suffix,
602 "lua-" .. luaver .. exe_suffix,
603 "lua-" .. luaver:gsub("%.", "") .. exe_suffix,
604 }
605 for _, name in ipairs(variants) do
606 names[name] = luaver
607 table.insert(names, name)
608 end
609 end
610
611 find_lua_bindir = function(prefix, luaver)
612 local names = {}
613 if luaver then
614 insert_lua_variants(names, luaver)
615 else
616 for v in util.lua_variants("descending") do
617 insert_lua_variants(names, v)
618 end
619 end
620 if luaver == "5.1" or not luaver then
621 table.insert(names, "luajit" .. exe_suffix)
622 end
623 table.insert(names, "lua" .. exe_suffix)
624
625 local bindirs = { prefix .. "/bin", prefix }
626 local tried = {}
627 for _, d in ipairs(bindirs) do
628 for _, name in ipairs(names) do
629 local lua_exe = d .. "/" .. name
630 table.insert(tried, lua_exe)
631 local lv, ljv = util.check_lua_version(lua_exe, luaver)
632 if lv then
633 return name, d, lv, ljv
634 end
635 end
636 end
637 return nil, "Lua interpreter not found at " .. prefix .. "\n" ..
638 "Tried:\t" .. table.concat(tried, "\n\t")
639 end
640 end
641
642 function util.find_lua(prefix, luaver)
643 local lua_interpreter, bindir, luajitver
644 lua_interpreter, bindir, luaver, luajitver = find_lua_bindir(prefix, luaver)
645 if not lua_interpreter then
646 return nil, bindir
647 end
648
649 return {
650 lua_version = luaver,
651 luajit_version = luajitver,
652 lua_interpreter = lua_interpreter,
653 lua_dir = prefix,
654 lua_bindir = bindir,
655 }
656 end
657end
658
551return util 659return util
660