diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2019-03-21 18:47:44 -0400 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2019-04-01 16:26:30 -0300 |
| commit | e388deecaa13b7b89da202d09d328a79bbcf40dd (patch) | |
| tree | 1adcd8df720b0bb247f141342efed1f851341b52 /src | |
| parent | 5cdaa0ad83f79e7c8ecfa87e5d58f4a42d907a44 (diff) | |
| download | luarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.tar.gz luarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.tar.bz2 luarocks-e388deecaa13b7b89da202d09d328a79bbcf40dd.zip | |
cmd: refactor detection code and improve detection of project dir
Diffstat (limited to 'src')
| -rw-r--r-- | src/luarocks/cmd.lua | 198 | ||||
| -rw-r--r-- | src/luarocks/core/cfg.lua | 50 | ||||
| -rw-r--r-- | src/luarocks/util.lua | 109 |
3 files changed, 186 insertions, 171 deletions
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 |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | local 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 | ||
| 48 | end | ||
| 49 | |||
| 50 | do | ||
| 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 | ||
| 139 | end | ||
| 140 | |||
| 141 | local function check_popen() | 41 | local 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 |
| 152 | end | 52 | end |
| 153 | 53 | ||
| 154 | local function find_project_dir() | 54 | local 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 | ||
| 164 | end | 65 | end |
| 165 | 66 | ||
| 166 | local process_tree_flags | 67 | local process_tree_flags |
| @@ -261,19 +162,6 @@ local function process_server_flags(flags) | |||
| 261 | return true | 162 | return true |
| 262 | end | 163 | end |
| 263 | 164 | ||
| 264 | local 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 | } | ||
| 275 | end | ||
| 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. |
| 551 | function cfg.init(lua_data, project_dir, warning) | 551 | function 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 |
| 549 | end | 549 | end |
| 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. | ||
| 554 | function 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 | ||
| 566 | end | ||
| 567 | |||
| 568 | do | ||
| 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 | ||
| 657 | end | ||
| 658 | |||
| 551 | return util | 659 | return util |
| 660 | |||
