aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2015-12-05 16:45:25 -0200
committerHisham Muhammad <hisham@gobolinux.org>2015-12-05 16:45:25 -0200
commit619b8165186741e99d3274826fd95a6f546681be (patch)
tree142466631f0698b606336181e31c53720b43a03c
parente95bfca9f1f1e417a2f554cb756cd44a7eb105cb (diff)
parentbf12327a64400884b2be50c88cc8b223db57260c (diff)
downloadluarocks-619b8165186741e99d3274826fd95a6f546681be.tar.gz
luarocks-619b8165186741e99d3274826fd95a6f546681be.tar.bz2
luarocks-619b8165186741e99d3274826fd95a6f546681be.zip
Merge branch 'master' into luarocks-3
-rw-r--r--install.bat151
-rw-r--r--src/luarocks/cfg.lua6
-rw-r--r--src/luarocks/command_line.lua5
-rw-r--r--src/luarocks/deps.lua53
-rw-r--r--src/luarocks/fs/lua.lua23
-rw-r--r--src/luarocks/fs/unix.lua8
-rw-r--r--src/luarocks/fs/win32.lua18
7 files changed, 225 insertions, 39 deletions
diff --git a/install.bat b/install.bat
index 42b01c43..8e3df4d9 100644
--- a/install.bat
+++ b/install.bat
@@ -8,6 +8,7 @@ local vars = {}
8vars.PREFIX = nil 8vars.PREFIX = nil
9vars.VERSION = "2.2" 9vars.VERSION = "2.2"
10vars.SYSCONFDIR = nil 10vars.SYSCONFDIR = nil
11vars.SYSCONFFORCE = nil
11vars.CONFBACKUPDIR = nil 12vars.CONFBACKUPDIR = nil
12vars.SYSCONFFILENAME = nil 13vars.SYSCONFFILENAME = nil
13vars.CONFIG_FILE = nil 14vars.CONFIG_FILE = nil
@@ -29,11 +30,13 @@ vars.LUA_SHORTV = nil -- "51"
29vars.LUA_LIB_NAMES = "lua5.1.lib lua51.lib lua5.1.dll lua51.dll liblua.dll.a" 30vars.LUA_LIB_NAMES = "lua5.1.lib lua51.lib lua5.1.dll lua51.dll liblua.dll.a"
30vars.LUA_RUNTIME = nil 31vars.LUA_RUNTIME = nil
31vars.UNAME_M = nil 32vars.UNAME_M = nil
33vars.COMPILER_ENV_CMD = nil
32 34
33local FORCE = false 35local FORCE = false
34local FORCE_CONFIG = false 36local FORCE_CONFIG = false
35local INSTALL_LUA = false 37local INSTALL_LUA = false
36local USE_MINGW = false 38local USE_MINGW = false
39local USE_MSVC_MANUAL = false
37local REGISTRY = true 40local REGISTRY = true
38local NOADMIN = false 41local NOADMIN = false
39local PROMPT = true 42local PROMPT = true
@@ -166,7 +169,14 @@ Configuring the Lua interpreter:
166 (/LUA, /INC, /LIB, /BIN cannot be used with /L) 169 (/LUA, /INC, /LIB, /BIN cannot be used with /L)
167 170
168Compiler configuration: 171Compiler configuration:
169/MW Use mingw as build system instead of MSVC 172 By default the installer will try to determine the
173 Microsoft toolchain to use. And will automatically use
174 a setup command to initialize that toolchain when
175 LuaRocks is run. If it cannot find it, it will default
176 to the /MSVC switch.
177/MSVC Use MS toolchain, without a setup command (tools must
178 be in your path)
179/MW Use mingw as build system (tools must be in your path)
170 180
171Other options: 181Other options:
172/FORCECONFIG Use a single config location. Do not use the 182/FORCECONFIG Use a single config location. Do not use the
@@ -199,6 +209,7 @@ local function parse_options(args)
199 vars.PREFIX = option.value 209 vars.PREFIX = option.value
200 elseif name == "/CONFIG" then 210 elseif name == "/CONFIG" then
201 vars.SYSCONFDIR = option.value 211 vars.SYSCONFDIR = option.value
212 vars.SYSCONFFORCE = true
202 elseif name == "/TREE" then 213 elseif name == "/TREE" then
203 vars.TREE_ROOT = option.value 214 vars.TREE_ROOT = option.value
204 elseif name == "/SCRIPTS" then 215 elseif name == "/SCRIPTS" then
@@ -213,6 +224,8 @@ local function parse_options(args)
213 INSTALL_LUA = true 224 INSTALL_LUA = true
214 elseif name == "/MW" then 225 elseif name == "/MW" then
215 USE_MINGW = true 226 USE_MINGW = true
227 elseif name == "/MSVC" then
228 USE_MSVC_MANUAL = true
216 elseif name == "/LUA" then 229 elseif name == "/LUA" then
217 vars.LUA_PREFIX = option.value 230 vars.LUA_PREFIX = option.value
218 elseif name == "/LIB" then 231 elseif name == "/LIB" then
@@ -266,6 +279,9 @@ local function check_flags()
266 die("Bad argument: /LV must either be 5.1, 5.2, or 5.3") 279 die("Bad argument: /LV must either be 5.1, 5.2, or 5.3")
267 end 280 end
268 end 281 end
282 if USE_MSVC_MANUAL and USE_MINGW then
283 die("Cannot combine option /MSVC and /MW")
284 end
269end 285end
270 286
271-- *********************************************************** 287-- ***********************************************************
@@ -408,6 +424,117 @@ local function get_architecture()
408 return proc 424 return proc
409end 425end
410 426
427-- get a string value from windows registry.
428local function get_registry(key, value)
429 local keys = {key}
430 local key64, replaced = key:gsub("(%u+\\Software\\)", "\1Wow6432Node\\", 1)
431
432 if replaced == 1 then
433 keys = {key64, key}
434 end
435
436 for _, k in ipairs(keys) do
437 local h = io.popen('reg query "'..k..'" /v '..value..' 2>NUL')
438 local output = h:read("*a")
439 h:close()
440
441 local v = output:match("REG_SZ%s+([^\n]+)")
442 if v then
443 return v
444 end
445 end
446 return nil
447end
448
449local function get_visual_studio_directory()
450 assert(type(vars.LUA_RUNTIME)=="string", "requires vars.LUA_RUNTIME to be set before calling this function.")
451 local major, minor = vars.LUA_RUNTIME:match('VCR%u*(%d+)(%d)$') -- MSVCR<x><y> or VCRUNTIME<x><y>
452 if not major then
453 print(S[[ Cannot auto-detect Visual Studio version from $LUA_RUNTIME]])
454 return nil
455 end
456 local keys = {
457 "HKLM\\Software\\Microsoft\\VisualStudio\\%d.%d\\Setup\\VC",
458 "HKLM\\Software\\Microsoft\\VCExpress\\%d.%d\\Setup\\VS"
459 }
460 for _, key in ipairs(keys) do
461 local versionedkey = key:format(major, minor)
462 local vcdir = get_registry(versionedkey, "ProductDir")
463 print(" checking: "..versionedkey)
464 if vcdir then
465 print(" Found: "..vcdir)
466 return vcdir
467 end
468 end
469 return nil
470end
471
472local function get_windows_sdk_directory()
473 assert(type(vars.LUA_RUNTIME) == "string", "requires vars.LUA_RUNTIME to be set before calling this function.")
474 -- Only v7.1 and v6.1 shipped with compilers
475 -- Other versions requires a separate installation of Visual Studio.
476 -- see https://github.com/keplerproject/luarocks/pull/443#issuecomment-152792516
477 local wsdks = {
478 ["MSVCR100"] = "v7.1", -- shipped with Visual Studio 2010 compilers.
479 ["MSVCR100D"] = "v7.1", -- shipped with Visual Studio 2010 compilers.
480 ["MSVCR90"] = "v6.1", -- shipped with Visual Studio 2008 compilers.
481 ["MSVCR90D"] = "v6.1", -- shipped with Visual Studio 2008 compilers.
482 }
483 local wsdkver = wsdks[vars.LUA_RUNTIME]
484 if not wsdkver then
485 print(S[[ Cannot auto-detect Windows SDK version from $LUA_RUNTIME]])
486 return nil
487 end
488
489 local key = "HKLM\\Software\\Microsoft\\Microsoft SDKs\\Windows\\"..wsdkver
490 print(" checking: "..key)
491 local dir = get_registry(key, "InstallationFolder")
492 if dir then
493 print(" Found: "..dir)
494 return dir
495 end
496 print(" No SDK found")
497 return nil
498end
499
500-- returns the batch command to setup msvc compiler path.
501-- or an empty string (eg. "") if not found
502local function get_msvc_env_setup_cmd()
503 print(S[[Looking for Microsoft toolchain matching runtime $LUA_RUNTIME and architecture $UNAME_M]])
504
505 assert(type(vars.UNAME_M) == "string", "requires vars.UNAME_M to be set before calling this function.")
506 local x64 = vars.UNAME_M=="x86_64"
507
508 -- 1. try visual studio command line tools
509 local vcdir = get_visual_studio_directory()
510 if vcdir then
511 -- 1.1. try vcvarsall.bat
512 local vcvarsall = vcdir .. 'vcvarsall.bat'
513 if exists(vcvarsall) then
514 return ('call "%s"%s'):format(vcvarsall, x64 and ' amd64' or '')
515 end
516
517 -- 1.2. try vcvars32.bat / vcvars64.bat
518 local relative_path = x64 and "bin\\amd64\\vcvars64.bat" or "bin\\vcvars32.bat"
519 local full_path = vcdir .. relative_path
520 if exists(full_path) then
521 return ('call "%s"'):format(full_path)
522 end
523 end
524
525 -- 2. try for Windows SDKs command line tools.
526 local wsdkdir = get_windows_sdk_directory()
527 if wsdkdir then
528 local setenv = wsdkdir.."Bin\\SetEnv.cmd"
529 if exists(setenv) then
530 return ('call "%s" /%s'):format(setenv, x64 and "x64" or "x86")
531 end
532 end
533
534 -- finally, we can't detect more, just don't setup the msvc compiler in luarocks.bat.
535 return ""
536end
537
411local function look_for_lua_install () 538local function look_for_lua_install ()
412 print("Looking for Lua interpreter") 539 print("Looking for Lua interpreter")
413 local directories 540 local directories
@@ -650,9 +777,11 @@ vars.SYSCONFFILENAME = S"config-$LUA_VERSION.lua"
650vars.CONFIG_FILE = vars.SYSCONFDIR.."\\"..vars.SYSCONFFILENAME 777vars.CONFIG_FILE = vars.SYSCONFDIR.."\\"..vars.SYSCONFFILENAME
651if SELFCONTAINED then 778if SELFCONTAINED then
652 vars.SYSCONFDIR = vars.PREFIX 779 vars.SYSCONFDIR = vars.PREFIX
780 vars.SYSCONFFORCE = true
653 vars.TREE_ROOT = vars.PREFIX..[[\systree]] 781 vars.TREE_ROOT = vars.PREFIX..[[\systree]]
654 REGISTRY = false 782 REGISTRY = false
655end 783end
784vars.COMPILER_ENV_CMD = (USE_MINGW and "") or (USE_MSVC_MANUAL and "") or get_msvc_env_setup_cmd()
656 785
657print(S[[ 786print(S[[
658 787
@@ -671,11 +800,20 @@ Lua interpreter : $LUA_BINDIR\$LUA_INTERPRETER
671 includes : $LUA_INCDIR 800 includes : $LUA_INCDIR
672 architecture: $UNAME_M 801 architecture: $UNAME_M
673 binary link : $LUA_LIBNAME with runtime $LUA_RUNTIME.dll 802 binary link : $LUA_LIBNAME with runtime $LUA_RUNTIME.dll
674
675]]) 803]])
676 804
805if USE_MINGW then
806 print("Compiler : MinGW (make sure it is in your path before using LuaRocks)")
807else
808 if vars.COMPILER_ENV_CMD == "" then
809 print("Compiler : Microsoft (make sure it is in your path before using LuaRocks)")
810 else
811 print(S[[Compiler : Microsoft, using; $COMPILER_ENV_CMD]])
812 end
813end
814
677if PROMPT then 815if PROMPT then
678 print("Press <ENTER> to start installing, or press <CTRL>+<C> to abort. Use install /? for installation options.") 816 print("\nPress <ENTER> to start installing, or press <CTRL>+<C> to abort. Use install /? for installation options.")
679 io.read() 817 io.read()
680end 818end
681 819
@@ -758,7 +896,8 @@ for _, c in ipairs{"luarocks", "luarocks-admin"} do
758 local f = io.open(vars.BINDIR.."\\"..c..".bat", "w") 896 local f = io.open(vars.BINDIR.."\\"..c..".bat", "w")
759 f:write(S[[ 897 f:write(S[[
760@ECHO OFF 898@ECHO OFF
761SETLOCAL 899SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
900$COMPILER_ENV_CMD
762SET "LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%" 901SET "LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%"
763IF NOT "%LUA_PATH_5_2%"=="" ( 902IF NOT "%LUA_PATH_5_2%"=="" (
764 SET "LUA_PATH_5_2=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH_5_2%" 903 SET "LUA_PATH_5_2=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH_5_2%"
@@ -835,7 +974,6 @@ else
835end 974end
836f:write(S[=[ 975f:write(S[=[
837site_config.LUAROCKS_UNAME_M=[[$UNAME_M]] 976site_config.LUAROCKS_UNAME_M=[[$UNAME_M]]
838site_config.LUAROCKS_SYSCONFIG=[[$CONFIG_FILE]]
839site_config.LUAROCKS_ROCKS_TREE=[[$TREE_ROOT]] 977site_config.LUAROCKS_ROCKS_TREE=[[$TREE_ROOT]]
840site_config.LUAROCKS_PREFIX=[[$PREFIX]] 978site_config.LUAROCKS_PREFIX=[[$PREFIX]]
841site_config.LUAROCKS_DOWNLOADER=[[wget]] 979site_config.LUAROCKS_DOWNLOADER=[[wget]]
@@ -844,6 +982,9 @@ site_config.LUAROCKS_MD5CHECKER=[[md5sum]]
844if FORCE_CONFIG then 982if FORCE_CONFIG then
845 f:write("site_config.LUAROCKS_FORCE_CONFIG=true\n") 983 f:write("site_config.LUAROCKS_FORCE_CONFIG=true\n")
846end 984end
985if vars.SYSCONFFORCE then -- only write this value when explcitly given, otherwise rely on defaults
986 f:write("site_config.LUAROCKS_SYSCONFIG=[[$CONFIG_FILE]]\n")
987end
847f:write("return site_config\n") 988f:write("return site_config\n")
848f:close() 989f:close()
849print(S([[Created LuaRocks site-config file: $LUADIR\luarocks\]]..site_config..[[.lua]])) 990print(S([[Created LuaRocks site-config file: $LUADIR\luarocks\]]..site_config..[[.lua]]))
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua
index 6706468c..af30417c 100644
--- a/src/luarocks/cfg.lua
+++ b/src/luarocks/cfg.lua
@@ -149,7 +149,7 @@ local sys_config_file_default, home_config_file_default
149local sys_config_dir, home_config_dir 149local sys_config_dir, home_config_dir
150local sys_config_ok, home_config_ok = false, false 150local sys_config_ok, home_config_ok = false, false
151local extra_luarocks_module_dir 151local extra_luarocks_module_dir
152sys_config_dir = site_config.LUAROCKS_SYSCONFDIR 152sys_config_dir = site_config.LUAROCKS_SYSCONFDIR or site_config.LUAROCKS_PREFIX
153if cfg.platforms.windows then 153if cfg.platforms.windows then
154 cfg.home = os.getenv("APPDATA") or "c:" 154 cfg.home = os.getenv("APPDATA") or "c:"
155 sys_config_dir = sys_config_dir or "c:/luarocks" 155 sys_config_dir = sys_config_dir or "c:/luarocks"
@@ -665,7 +665,7 @@ function cfg.init_package_paths()
665end 665end
666 666
667function cfg.which_config() 667function cfg.which_config()
668 return { 668 local ret = {
669 system = { 669 system = {
670 file = sys_config_file or sys_config_file_default, 670 file = sys_config_file or sys_config_file_default,
671 ok = sys_config_ok, 671 ok = sys_config_ok,
@@ -675,6 +675,8 @@ function cfg.which_config()
675 ok = home_config_ok, 675 ok = home_config_ok,
676 } 676 }
677 } 677 }
678 ret.nearest = (ret.user.ok and ret.user.file) or ret.system.file
679 return ret
678end 680end
679 681
680cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch 682cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua
index dbf64b9c..e1c9f492 100644
--- a/src/luarocks/command_line.lua
+++ b/src/luarocks/command_line.lua
@@ -31,12 +31,17 @@ end
31local function replace_tree(flags, args, tree) 31local function replace_tree(flags, args, tree)
32 tree = dir.normalize(tree) 32 tree = dir.normalize(tree)
33 flags["tree"] = tree 33 flags["tree"] = tree
34 local added = false
34 for i = 1, #args do 35 for i = 1, #args do
35 if args[i]:match("%-%-tree=") then 36 if args[i]:match("%-%-tree=") then
36 args[i] = "--tree="..tree 37 args[i] = "--tree="..tree
38 added = true
37 break 39 break
38 end 40 end
39 end 41 end
42 if not added then
43 args[#args + 1] = "--tree="..tree
44 end
40 path.use_tree(tree) 45 path.use_tree(tree)
41end 46end
42 47
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index 3f7eb4d2..764116a2 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -558,10 +558,11 @@ function deps.check_external_deps(rockspec, mode)
558 subdirs = cfg.runtime_external_deps_subdirs 558 subdirs = cfg.runtime_external_deps_subdirs
559 end 559 end
560 if rockspec.external_dependencies then 560 if rockspec.external_dependencies then
561 for name, files in pairs(rockspec.external_dependencies) do 561 for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do
562 local ok = true 562 local ok = true
563 local failed_file = nil 563 local failed_files = {program = {}, header = {}, library = {}}
564 local failed_dirname = nil 564 local failed_dirname
565 local failed_testfile
565 for _, extdir in ipairs(cfg.external_deps_dirs) do 566 for _, extdir in ipairs(cfg.external_deps_dirs) do
566 ok = true 567 ok = true
567 local prefix = vars[name.."_DIR"] 568 local prefix = vars[name.."_DIR"]
@@ -590,7 +591,7 @@ function deps.check_external_deps(rockspec, mode)
590 end 591 end
591 prefix = prefix.prefix 592 prefix = prefix.prefix
592 end 593 end
593 for dirname, dirdata in pairs(dirs) do 594 for dirname, dirdata in util.sortedpairs(dirs) do
594 local paths 595 local paths
595 local path_var_value = vars[name.."_"..dirname] 596 local path_var_value = vars[name.."_"..dirname]
596 if path_var_value then 597 if path_var_value then
@@ -604,7 +605,7 @@ function deps.check_external_deps(rockspec, mode)
604 paths = { dir.path(prefix, dirdata.subdir) } 605 paths = { dir.path(prefix, dirdata.subdir) }
605 end 606 end
606 dirdata.dir = paths[1] 607 dirdata.dir = paths[1]
607 local file = files[dirdata.testfile] 608 local file = ext_files[dirdata.testfile]
608 if file then 609 if file then
609 local files = {} 610 local files = {}
610 if not file:match("%.") then 611 if not file:match("%.") then
@@ -619,19 +620,23 @@ function deps.check_external_deps(rockspec, mode)
619 table.insert(files, file) 620 table.insert(files, file)
620 end 621 end
621 local found = false 622 local found = false
622 failed_file = nil 623 for _, f in ipairs(files) do
623 for _, f in pairs(files) do 624
624
625 -- small convenience hack 625 -- small convenience hack
626 if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then 626 if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
627 f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) 627 f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
628 end 628 end
629 629
630 local pattern
631 if f:match("%*") then
632 pattern = f:gsub("%.", "%%."):gsub("%*", ".*")
633 f = "matching "..f
634 end
635
630 for _, d in ipairs(paths) do 636 for _, d in ipairs(paths) do
631 if f:match("%*") then 637 if pattern then
632 local replaced = f:gsub("%.", "%%."):gsub("%*", ".*")
633 for entry in fs.dir(d) do 638 for entry in fs.dir(d) do
634 if entry:match(replaced) then 639 if entry:match(pattern) then
635 found = true 640 found = true
636 break 641 break
637 end 642 end
@@ -642,21 +647,18 @@ function deps.check_external_deps(rockspec, mode)
642 if found then 647 if found then
643 dirdata.dir = d 648 dirdata.dir = d
644 break 649 break
650 else
651 table.insert(failed_files[dirdata.testfile], f.." in "..d)
645 end 652 end
646 end 653 end
647 if found then 654 if found then
648 break 655 break
649 else
650 if failed_file then
651 failed_file = failed_file .. ", or " .. f
652 else
653 failed_file = f
654 end
655 end 656 end
656 end 657 end
657 if not found then 658 if not found then
658 ok = false 659 ok = false
659 failed_dirname = dirname 660 failed_dirname = dirname
661 failed_testfile = dirdata.testfile
660 break 662 break
661 end 663 end
662 end 664 end
@@ -670,7 +672,20 @@ function deps.check_external_deps(rockspec, mode)
670 end 672 end
671 end 673 end
672 if not ok then 674 if not ok then
673 return nil, "Could not find expected file "..failed_file.." for "..name.." -- you may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_dirname.." to the luarocks command. Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local", "dependency" 675 local lines = {"Could not find "..failed_testfile.." file for "..name}
676
677 local failed_paths = {}
678 for _, failed_file in ipairs(failed_files[failed_testfile]) do
679 if not failed_paths[failed_file] then
680 failed_paths[failed_file] = true
681 table.insert(lines, " No file "..failed_file)
682 end
683 end
684
685 table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_dirname.." to the luarocks command.")
686 table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local")
687
688 return nil, table.concat(lines, "\n"), "dependency"
674 end 689 end
675 end 690 end
676 end 691 end
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index 73ae2698..a444f014 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -134,10 +134,10 @@ function fs_lua.is_tool_available(tool_cmd, tool_name, arg)
134 arg = arg or "--version" 134 arg = arg or "--version"
135 assert(type(arg) == "string") 135 assert(type(arg) == "string")
136 136
137 if not fs.execute_quiet(tool_cmd, arg) then 137 if not fs.execute_quiet(fs.Q(tool_cmd), arg) then
138 local msg = "'%s' program not found. Make sure %s is installed and is available in your PATH " .. 138 local msg = "'%s' program not found. Make sure %s is installed and is available in your PATH " ..
139 "(or you may want to edit the 'variables.%s' value in file 'config.lua')" 139 "(or you may want to edit the 'variables.%s' value in file '%s')"
140 return nil, msg:format(tool_cmd, tool_name, tool_cmd:upper()) 140 return nil, msg:format(tool_cmd, tool_name, tool_name:upper(), cfg.which_config().nearest)
141 else 141 else
142 return true 142 return true
143 end 143 end
@@ -833,10 +833,19 @@ function fs_lua.check_command_permissions(flags)
833 break 833 break
834 end 834 end
835 end 835 end
836 local root_parent = dir.dir_name(root_dir) 836 if ok and not fs.exists(root_dir) then
837 if ok and not fs.exists(root_dir) and not fs.is_writable(root_parent) then 837 local root = fs.root_of(root_dir)
838 ok = false 838 local parent = root_dir
839 err = root_dir.." does not exist and your user does not have write permissions in " .. root_parent 839 repeat
840 parent = dir.dir_name(parent)
841 if parent == "" then
842 parent = root
843 end
844 until parent == root or fs.exists(parent)
845 if not fs.is_writable(parent) then
846 ok = false
847 err = root_dir.." does not exist and your user does not have write permissions in " .. parent
848 end
840 end 849 end
841 if ok then 850 if ok then
842 return true 851 return true
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua
index 6ad5a678..8eb3386a 100644
--- a/src/luarocks/fs/unix.lua
+++ b/src/luarocks/fs/unix.lua
@@ -36,6 +36,14 @@ function unix.absolute_name(pathname, relative_to)
36 end 36 end
37end 37end
38 38
39--- Return the root directory for the given path.
40-- In Unix, root is always "/".
41-- @param pathname string: pathname to use.
42-- @return string: The root of the given pathname.
43function unix.root_of(_)
44 return "/"
45end
46
39--- Create a wrapper to make a script executable from the command-line. 47--- Create a wrapper to make a script executable from the command-line.
40-- @param file string: Pathname of script to be made executable. 48-- @param file string: Pathname of script to be made executable.
41-- @param dest string: Directory where to put the wrapper. 49-- @param dest string: Directory where to put the wrapper.
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua
index 32766e53..0c8cc9e9 100644
--- a/src/luarocks/fs/win32.lua
+++ b/src/luarocks/fs/win32.lua
@@ -18,7 +18,6 @@ local _popen, _execute = io.popen, os.execute
18io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end 18io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
19os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end 19os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
20 20
21
22--- Annotate command string for quiet execution. 21--- Annotate command string for quiet execution.
23-- @param cmd string: A command-line string. 22-- @param cmd string: A command-line string.
24-- @return string: The command-line, with silencing annotation. 23-- @return string: The command-line, with silencing annotation.
@@ -26,6 +25,7 @@ function win32.quiet(cmd)
26 return cmd.." 2> NUL 1> NUL" 25 return cmd.." 2> NUL 1> NUL"
27end 26end
28 27
28local drive_letter = "[%.a-zA-Z]?:?[\\/]"
29 29
30local win_escape_chars = { 30local win_escape_chars = {
31 ["%"] = "%%", 31 ["%"] = "%%",
@@ -47,7 +47,7 @@ end
47function win32.Q(arg) 47function win32.Q(arg)
48 assert(type(arg) == "string") 48 assert(type(arg) == "string")
49 -- Quote DIR for Windows 49 -- Quote DIR for Windows
50 if arg:match("^[%.a-zA-Z]?:?[\\/]") then 50 if arg:match("^"..drive_letter) then
51 arg = arg:gsub("/", "\\") 51 arg = arg:gsub("/", "\\")
52 end 52 end
53 if arg == "\\" then 53 if arg == "\\" then
@@ -68,7 +68,7 @@ end
68function win32.Qb(arg) 68function win32.Qb(arg)
69 assert(type(arg) == "string") 69 assert(type(arg) == "string")
70 -- Quote DIR for Windows 70 -- Quote DIR for Windows
71 if arg:match("^[%.a-zA-Z]?:?[\\/]") then 71 if arg:match("^"..drive_letter) then
72 arg = arg:gsub("/", "\\") 72 arg = arg:gsub("/", "\\")
73 end 73 end
74 if arg == "\\" then 74 if arg == "\\" then
@@ -92,15 +92,21 @@ function win32.absolute_name(pathname, relative_to)
92 assert(type(relative_to) == "string" or not relative_to) 92 assert(type(relative_to) == "string" or not relative_to)
93 93
94 relative_to = relative_to or fs.current_dir() 94 relative_to = relative_to or fs.current_dir()
95 -- FIXME I'm not sure this first \\ should be there at all. 95 if pathname:match("^"..drive_letter) then
96 -- What are the Windows rules for drive letters?
97 if pathname:match("^[\\.a-zA-Z]?:?[\\/]") then
98 return pathname 96 return pathname
99 else 97 else
100 return relative_to .. "/" .. pathname 98 return relative_to .. "/" .. pathname
101 end 99 end
102end 100end
103 101
102--- Return the root directory for the given path.
103-- For example, for "c:\hello", returns "c:\"
104-- @param pathname string: pathname to use.
105-- @return string: The root of the given pathname.
106function win32.root_of(pathname)
107 return (fs.absolute_name(pathname):match("^("..drive_letter..")"))
108end
109
104--- Create a wrapper to make a script executable from the command-line. 110--- Create a wrapper to make a script executable from the command-line.
105-- @param file string: Pathname of script to be made executable. 111-- @param file string: Pathname of script to be made executable.
106-- @param dest string: Directory where to put the wrapper. 112-- @param dest string: Directory where to put the wrapper.