aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor/build.bat111
-rw-r--r--.appveyor/install.bat154
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml5
-rw-r--r--Makefile41
-rw-r--r--Makefile.install.inc22
-rw-r--r--Makefile.luarocks15
-rw-r--r--Makefile.setup.inc20
-rw-r--r--README.md17
-rw-r--r--appveyor.yml30
-rwxr-xr-xconfigure87
-rw-r--r--install.bat332
-rwxr-xr-xmakedist40
-rw-r--r--rockspec16
-rwxr-xr-xsrc/bin/luarocks4
-rwxr-xr-xsrc/bin/luarocks-admin3
-rw-r--r--src/luarocks/add.lua2
-rw-r--r--src/luarocks/admin_remove.lua2
-rw-r--r--src/luarocks/build.lua57
-rw-r--r--src/luarocks/build/builtin.lua25
-rw-r--r--src/luarocks/build/cmake.lua25
-rw-r--r--src/luarocks/cache.lua15
-rw-r--r--src/luarocks/cfg.lua434
-rw-r--r--src/luarocks/command_line.lua44
-rw-r--r--src/luarocks/config_cmd.lua73
-rw-r--r--src/luarocks/deps.lua75
-rw-r--r--src/luarocks/doc.lua6
-rw-r--r--src/luarocks/download.lua45
-rw-r--r--src/luarocks/fetch.lua33
-rw-r--r--src/luarocks/fetch/cvs.lua8
-rw-r--r--src/luarocks/fetch/git.lua7
-rw-r--r--src/luarocks/fetch/git_https.lua7
-rw-r--r--src/luarocks/fetch/git_ssh.lua32
-rw-r--r--src/luarocks/fetch/hg.lua9
-rw-r--r--src/luarocks/fetch/hg_http.lua24
-rw-r--r--src/luarocks/fetch/hg_https.lua8
-rw-r--r--src/luarocks/fetch/hg_ssh.lua8
-rw-r--r--src/luarocks/fetch/svn.lua5
-rw-r--r--src/luarocks/fs.lua3
-rw-r--r--src/luarocks/fs/lua.lua122
-rw-r--r--src/luarocks/fs/unix.lua14
-rw-r--r--src/luarocks/fs/unix/tools.lua55
-rw-r--r--src/luarocks/fs/win32.lua42
-rw-r--r--src/luarocks/fs/win32/tools.lua14
-rw-r--r--src/luarocks/help.lua16
-rw-r--r--src/luarocks/install.lua65
-rw-r--r--src/luarocks/list.lua70
-rw-r--r--src/luarocks/loader.lua58
-rw-r--r--src/luarocks/make.lua67
-rw-r--r--src/luarocks/manif.lua22
-rw-r--r--src/luarocks/manif_core.lua50
-rw-r--r--src/luarocks/new_version.lua84
-rw-r--r--src/luarocks/path.lua22
-rw-r--r--src/luarocks/path_cmd.lua12
-rw-r--r--src/luarocks/persist.lua151
-rw-r--r--src/luarocks/remove.lua2
-rw-r--r--src/luarocks/search.lua114
-rw-r--r--src/luarocks/show.lua36
-rw-r--r--src/luarocks/tools/patch.lua63
-rw-r--r--src/luarocks/tools/tar.lua8
-rw-r--r--src/luarocks/tools/zip.lua60
-rw-r--r--src/luarocks/type_check.lua276
-rw-r--r--src/luarocks/unpack.lua6
-rw-r--r--src/luarocks/upload.lua8
-rw-r--r--src/luarocks/upload/api.lua144
-rw-r--r--src/luarocks/upload/multipart.lua16
-rw-r--r--src/luarocks/util.lua129
-rw-r--r--src/luarocks/write_rockspec.lua53
-rw-r--r--test/testfiles/invalid_patch-0.1-1.rockspec29
-rw-r--r--test/testfiles/no_build_table-0.1-1.rockspec12
-rw-r--r--test/testfiles/not_a_zipfile-1.0-1.src.rock1
-rw-r--r--test/testfiles/type_mismatch_string-1.0-1.rockspec4
-rw-r--r--test/testfiles/type_mismatch_table-1.0-1.rockspec5
-rw-r--r--test/testfiles/type_mismatch_version-1.0-1.rockspec4
-rw-r--r--test/testing.bat9
-rw-r--r--test/testing.lua464
-rwxr-xr-xtest/testing.sh250
-rw-r--r--win32/pe-parser.lua15
78 files changed, 3354 insertions, 1064 deletions
diff --git a/.appveyor/build.bat b/.appveyor/build.bat
new file mode 100644
index 00000000..a4ff6378
--- /dev/null
+++ b/.appveyor/build.bat
@@ -0,0 +1,111 @@
1@echo off
2Setlocal EnableDelayedExpansion EnableExtensions
3
4cd %APPVEYOR_BUILD_FOLDER%
5
6:: =========================================================
7:: Make sure some environment variables are set
8if not defined LUA_VER call :die LUA_VER is not defined
9if not defined LUA call :die LUA is not defined
10if not defined LUA_SHORTV call :die LUA_SHORTV is not defined
11if not defined LUA_DIR call :die LUA_DIR is not defined
12
13:: =========================================================
14:: Set some defaults. Infer some variables.
15::
16if not defined LUAROCKS_VER set LUAROCKS_VER=2.2.1
17
18set LUAROCKS_SHORTV=%LUAROCKS_VER:~0,3%
19
20if not defined LR_EXTERNAL set LR_EXTERNAL=c:\external
21if not defined LR_ROOT set LR_ROOT=%LUA_DIR%\LuaRocks
22if not defined LR_SYSTREE set LR_SYSTREE=%LR_ROOT%\systree
23
24::
25:: =========================================================
26
27
28if not exist %LUA_DIR%\bin\%LUA%.exe call :die "Missing Lua interpreter at %LUA_DIR%\bin\%LUA%.exe"
29
30
31
32:: =========================================================
33:: LuaRocks
34:: =========================================================
35
36cd %APPVEYOR_BUILD_FOLDER%
37call install.bat /LUA %LUA_DIR% /Q /LV %LUA_SHORTV% /P "%LR_ROOT%" /TREE "%LR_SYSTREE%"
38
39if not exist "%LR_ROOT%" call :die "LuaRocks not found at %LR_ROOT%"
40
41set PATH=%LR_ROOT%;%LR_SYSTREE%\bin;%PATH%
42
43:: Lua will use just the system rocks
44set LUA_PATH=%LR_ROOT%\lua\?.lua;%LR_ROOT%\lua\?\init.lua
45set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?.lua
46set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?\init.lua
47set LUA_CPATH=%LR_SYSTREE%\lib\lua\%LUA_SHORTV%\?.dll
48
49call luarocks --version || call :die "Error with LuaRocks installation"
50call luarocks list
51
52
53if not exist "%LR_EXTERNAL%" (
54 mkdir "%LR_EXTERNAL%"
55 mkdir "%LR_EXTERNAL%\lib"
56 mkdir "%LR_EXTERNAL%\include"
57)
58
59set PATH=%LR_EXTERNAL%;%PATH%
60
61:: Exports the following variables:
62:: (beware of whitespace between & and ^ below)
63endlocal & set PATH=%PATH%&^
64set LR_SYSTREE=%LR_SYSTREE%&^
65set LUA_PATH=%LUA_PATH%&^
66set LUA_CPATH=%LUA_CPATH%&^
67set LR_EXTERNAL=%LR_EXTERNAL%
68
69echo.
70echo ======================================================
71echo Installation of LuaRocks %LUAROCKS_VER% done.
72echo .
73echo LUA_PATH - %LUA_PATH%
74echo LUA_CPATH - %LUA_CPATH%
75echo.
76echo LR_EXTERNAL - %LR_EXTERNAL%
77echo ======================================================
78echo.
79
80goto :eof
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99:: This blank space is intentional. If you see errors like "The system cannot find the batch label specified 'foo'"
100:: then try adding or removing blank lines lines above.
101:: Yes, really.
102:: http://stackoverflow.com/questions/232651/why-the-system-cannot-find-the-batch-label-specified-is-thrown-even-if-label-e
103
104:: helper functions:
105
106:: for bailing out when an error occurred
107:die %1
108echo %1
109exit /B 1
110goto :eof
111
diff --git a/.appveyor/install.bat b/.appveyor/install.bat
new file mode 100644
index 00000000..a2aefdd2
--- /dev/null
+++ b/.appveyor/install.bat
@@ -0,0 +1,154 @@
1@echo off
2
3cd %APPVEYOR_BUILD_FOLDER%
4
5:: =========================================================
6:: Set some defaults. Infer some variables.
7::
8:: These are set globally
9if "%LUA_VER%" NEQ "" (
10 set LUA=lua
11 set LUA_SHORTV=%LUA_VER:~0,3%
12) else (
13 set LUA=luajit
14 set LJ_SHORTV=%LJ_VER:~0,3%
15 set LUA_SHORTV=5.1
16)
17
18:: unless we specify a platform on appveyor.yaml, we won't get this variable
19if not defined platform set platform=x86
20
21:: defines LUA_DIR so Cmake can find this Lua install
22if "%LUA%"=="luajit" (
23 set LUA_DIR=c:\lua\%platform%\lj%LJ_SHORTV%
24) else (
25 set LUA_DIR=c:\lua\%platform%\%LUA_VER%
26)
27
28:: Now we declare a scope
29Setlocal EnableDelayedExpansion EnableExtensions
30
31if not defined LUA_URL set LUA_URL=http://www.lua.org/ftp
32if not defined LUAJIT_GIT_REPO set LUAJIT_GIT_REPO=http://luajit.org/git/luajit-2.0.git
33if not defined LUAJIT_URL set LUAJIT_URL=http://luajit.org/download
34
35if not defined SEVENZIP set SEVENZIP=7z
36::
37:: =========================================================
38
39:: first create some necessary directories:
40mkdir downloads 2>NUL
41
42:: Download and compile Lua (or LuaJIT)
43if "%LUA%"=="luajit" (
44 if not exist %LUA_DIR% (
45 if "%LJ_SHORTV%"=="2.1" (
46 :: Clone repository and checkout 2.1 branch
47 set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER%
48 if not exist !lj_source_folder! (
49 echo Cloning git repo %LUAJIT_GIT_REPO% !lj_source_folder!
50 git clone %LUAJIT_GIT_REPO% !lj_source_folder! || call :die "Failed to clone repository"
51 )
52 cd !lj_source_folder!\src
53 git checkout v2.1 || call :die
54 ) else (
55 set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER%
56 if not exist !lj_source_folder! (
57 echo Downloading... %LUAJIT_URL%/LuaJIT-%LJ_VER%.tar.gz
58 curl --silent --fail --max-time 120 --connect-timeout 30 %LUAJIT_URL%/LuaJIT-%LJ_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads
59 )
60 cd !lj_source_folder!\src
61 )
62 :: Compiles LuaJIT
63 call msvcbuild.bat
64
65 mkdir %LUA_DIR% 2> NUL
66 for %%a in (bin include lib) do ( mkdir "%LUA_DIR%\%%a" )
67
68 for %%a in (luajit.exe lua51.dll) do ( move "!lj_source_folder!\src\%%a" "%LUA_DIR%\bin" )
69
70 move "!lj_source_folder!\src\lua51.lib" "%LUA_DIR%\lib"
71 for %%a in (lauxlib.h lua.h lua.hpp luaconf.h lualib.h luajit.h) do (
72 copy "!lj_source_folder!\src\%%a" "%LUA_DIR%\include"
73 )
74
75 ) else (
76 echo LuaJIT %LJ_VER% already installed at %LUA_DIR%
77 )
78) else (
79 if not exist %LUA_DIR% (
80 :: Download and compile Lua
81 if not exist downloads\lua-%LUA_VER% (
82 curl --silent --fail --max-time 120 --connect-timeout 30 %LUA_URL%/lua-%LUA_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads
83 )
84
85 mkdir downloads\lua-%LUA_VER%\etc 2> NUL
86 if not exist downloads\lua-%LUA_VER%\etc\winmake.bat (
87 curl --silent --location --insecure --fail --max-time 120 --connect-timeout 30 https://github.com/Tieske/luawinmake/archive/master.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% e -si -ttar -aoa -odownloads\lua-%LUA_VER%\etc luawinmake-master\etc\winmake.bat
88 )
89
90 cd downloads\lua-%LUA_VER%
91 call etc\winmake
92 call etc\winmake install %LUA_DIR%
93 ) else (
94 echo Lua %LUA_VER% already installed at %LUA_DIR%
95 )
96)
97
98if not exist %LUA_DIR%\bin\%LUA%.exe call :die "Missing Lua interpreter at %LUA_DIR%\bin\%LUA%.exe"
99
100set PATH=%LUA_DIR%\bin;%PATH%
101call %LUA% -v
102
103
104
105:: Exports the following variables:
106endlocal & set PATH=%PATH%
107
108echo.
109echo ======================================================
110if "%LUA%"=="luajit" (
111 echo Installation of LuaJIT %LJ_VER% done.
112) else (
113 echo Installation of Lua %LUA_VER% done.
114)
115echo Platform - %platform%
116echo LUA - %LUA%
117echo LUA_SHORTV - %LUA_SHORTV%
118echo LJ_SHORTV - %LJ_SHORTV%
119echo.
120echo ======================================================
121echo.
122
123goto :eof
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142:: This blank space is intentional. If you see errors like "The system cannot find the batch label specified 'foo'"
143:: then try adding or removing blank lines lines above.
144:: Yes, really.
145:: http://stackoverflow.com/questions/232651/why-the-system-cannot-find-the-batch-label-specified-is-thrown-even-if-label-e
146
147:: helper functions:
148
149:: for bailing out when an error occurred
150:die %1
151echo %1
152exit /B 1
153goto :eof
154
diff --git a/.gitignore b/.gitignore
index 13a07720..f74b9549 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
1/config.* 1/config.*
2/src/luarocks/site_config.lua 2/src/luarocks/site_config.lua
3/test/testing_*
4/test/luacov.*
diff --git a/.travis.yml b/.travis.yml
index cf2b1e6b..69ec28f3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,9 +2,12 @@ language: c
2 2
3compiler: gcc 3compiler: gcc
4 4
5sudo: false
6
5env: 7env:
6 matrix: 8 matrix:
7 - LUA_VER=5.1.5 9 - LUA_VER=5.1.5
8 - LUA_VER=5.2.3 10 - LUA_VER=5.2.4
11 - LUA_VER=5.3.1
9 12
10script: cd test && ./testing.sh --travis --lua $LUA_VER 13script: cd test && ./testing.sh --travis --lua $LUA_VER
diff --git a/Makefile b/Makefile
index 1f9d0e2d..81d24d24 100644
--- a/Makefile
+++ b/Makefile
@@ -2,31 +2,13 @@
2include config.unix 2include config.unix
3 3
4.PHONY: all build dev build_bins luadoc check_makefile cleanup_bins clean \ 4.PHONY: all build dev build_bins luadoc check_makefile cleanup_bins clean \
5 install_bins install_luas install_site_config write_sysconfig \ 5 install_site_config write_sysconfig install bootstrap install_rock
6 install bootstrap install_rock
7 6
8DESTDIR =
9PREFIX ?= /usr/local
10ROCKS_TREE ?= $(PREFIX) 7ROCKS_TREE ?= $(PREFIX)
11SYSCONFDIR ?= $(PREFIX)/etc/luarocks 8SYSCONFDIR ?= $(PREFIX)/etc/luarocks
12BINDIR ?= $(PREFIX)/bin
13LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)/
14LUA_DIR ?= /usr/local 9LUA_DIR ?= /usr/local
15LUA_BINDIR ?= $(LUA_DIR)/bin 10LUA_BINDIR ?= $(LUA_DIR)/bin
16 11
17BIN_FILES = luarocks luarocks-admin
18LUAROCKS_FILES = fs/unix/tools.lua fs/unix.lua fs/win32/tools.lua fs/win32.lua \
19fs/lua.lua persist.lua list.lua require.lua repos.lua dir.lua make_manifest.lua \
20command_line.lua install.lua build/command.lua build/cmake.lua build/make.lua \
21build/builtin.lua fetch/cvs.lua fetch/git.lua fetch/sscm.lua tools/patch.lua \
22fetch/svn.lua tools/zip.lua tools/tar.lua pack.lua type_check.lua make.lua \
23remove.lua fs.lua manif.lua add.lua deps.lua build.lua search.lua show.lua \
24manif_core.lua fetch.lua unpack.lua validate.lua cfg.lua download.lua \
25help.lua util.lua index.lua cache.lua refresh_cache.lua loader.lua \
26admin_remove.lua fetch/hg.lua fetch/git_file.lua new_version.lua lint.lua \
27purge.lua path.lua path_cmd.lua write_rockspec.lua doc.lua upload.lua \
28upload/api.lua upload/multipart.lua fetch/git_http.lua
29
30CONFIG_FILE = $(SYSCONFDIR)/config-$(LUA_VERSION).lua 12CONFIG_FILE = $(SYSCONFDIR)/config-$(LUA_VERSION).lua
31 13
32SAFEPWD=`echo "$$PWD" | sed -e 's/\([][]\)\1/]]..'\''\1\1'\''..[[/g'` 14SAFEPWD=`echo "$$PWD" | sed -e 's/\([][]\)\1/]]..'\''\1\1'\''..[[/g'`
@@ -38,6 +20,9 @@ all:
38 @echo " to install LuaRocks in $(PREFIX) as a rock." 20 @echo " to install LuaRocks in $(PREFIX) as a rock."
39 @echo 21 @echo
40 22
23include Makefile.setup.inc
24include Makefile.install.inc
25
41build: src/luarocks/site_config.lua build_bins 26build: src/luarocks/site_config.lua build_bins
42 @echo 27 @echo
43 @echo "Done. Type 'make install' to install into $(PREFIX)." 28 @echo "Done. Type 'make install' to install into $(PREFIX)."
@@ -139,23 +124,6 @@ cleanup_bins:
139clean: cleanup_bins 124clean: cleanup_bins
140 rm -f src/luarocks/site_config.lua 125 rm -f src/luarocks/site_config.lua
141 126
142install_bins:
143 mkdir -p "$(DESTDIR)$(BINDIR)"
144 cd src/bin && for f in $(BIN_FILES); \
145 do \
146 cp "$$f" "$(DESTDIR)$(BINDIR)/$$f-$(LUA_VERSION)"; \
147 ln -nfs "$$f-$(LUA_VERSION)" "$(DESTDIR)$(BINDIR)/$$f"; \
148 done
149
150install_luas:
151 mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
152 cd src/luarocks && for f in $(LUAROCKS_FILES); \
153 do \
154 d="$(DESTDIR)$(LUADIR)/luarocks"/`dirname "$$f"` && \
155 mkdir -p "$$d" && \
156 cp "$$f" "$$d" || exit 1; \
157 done
158
159install_site_config: src/luarocks/site_config.lua 127install_site_config: src/luarocks/site_config.lua
160 mkdir -p "$(DESTDIR)$(LUADIR)/luarocks" 128 mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
161 cp src/luarocks/site_config.lua "$(DESTDIR)$(LUADIR)/luarocks" 129 cp src/luarocks/site_config.lua "$(DESTDIR)$(LUADIR)/luarocks"
@@ -180,3 +148,4 @@ bootstrap: src/luarocks/site_config.lua install_site_config write_sysconfig clea
180 '$(LUA_BINDIR)/lua$(LUA_SUFFIX)' -e "package.path=[[$(SAFEPWD)/src/?.lua;]]..package.path" src/bin/luarocks make rockspec --tree="$(PREFIX)" 148 '$(LUA_BINDIR)/lua$(LUA_SUFFIX)' -e "package.path=[[$(SAFEPWD)/src/?.lua;]]..package.path" src/bin/luarocks make rockspec --tree="$(PREFIX)"
181 149
182install_rock: install_bins install_luas 150install_rock: install_bins install_luas
151
diff --git a/Makefile.install.inc b/Makefile.install.inc
new file mode 100644
index 00000000..20d96a12
--- /dev/null
+++ b/Makefile.install.inc
@@ -0,0 +1,22 @@
1
2.PHONY: install_bins install_luas
3
4install_bins:
5 mkdir -p "$(DESTDIR)$(BINDIR)"
6 cd src/bin && \
7 luaver="$(LUA_VERSION)" && [ -n "$$luaver" ] || luaver=`$(LUA) -e 'print(_VERSION:sub(5))'`; \
8 for f in $(BIN_FILES); \
9 do \
10 cp "$$f" "$(DESTDIR)$(BINDIR)/$$f-$$luaver"; \
11 ln -nfs "$$f-$$luaver" "$(DESTDIR)$(BINDIR)/$$f"; \
12 done
13
14install_luas:
15 mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
16 cd src/luarocks && for f in $(LUAROCKS_FILES); \
17 do \
18 d="$(DESTDIR)$(LUADIR)/luarocks"/`dirname "$$f"` && \
19 mkdir -p "$$d" && \
20 cp "$$f" "$$d" || exit 1; \
21 done
22
diff --git a/Makefile.luarocks b/Makefile.luarocks
new file mode 100644
index 00000000..1eecfeae
--- /dev/null
+++ b/Makefile.luarocks
@@ -0,0 +1,15 @@
1
2include Makefile.setup.inc
3include Makefile.install.inc
4
5.PHONY: all install copy_site_config
6
7all:
8 @echo This Makefile is used by the LuaRocks rockspec for upgrading itself.
9
10install: install_bins install_luas copy_site_config
11
12copy_site_config:
13 luaver="$(LUA_VERSION)" && [ -n "$$luaver" ] || luaver=`$(LUA) -e 'print(_VERSION:sub(5))'`; \
14 mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"; \
15 cp $(LUAROCKS_PREFIX)/share/lua/$$luaver/luarocks/site_config.lua "$(DESTDIR)$(LUADIR)/luarocks"
diff --git a/Makefile.setup.inc b/Makefile.setup.inc
new file mode 100644
index 00000000..0a049bc4
--- /dev/null
+++ b/Makefile.setup.inc
@@ -0,0 +1,20 @@
1
2DESTDIR =
3PREFIX ?= /usr/local
4BINDIR ?= $(PREFIX)/bin
5LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)/
6
7BIN_FILES = luarocks luarocks-admin
8LUAROCKS_FILES = fs/unix/tools.lua fs/unix.lua fs/win32/tools.lua fs/win32.lua \
9fs/lua.lua persist.lua list.lua require.lua repos.lua dir.lua make_manifest.lua \
10command_line.lua config_cmd.lua install.lua build/command.lua build/cmake.lua \
11build/make.lua build/builtin.lua fetch/cvs.lua fetch/git.lua fetch/sscm.lua \
12tools/patch.lua fetch/svn.lua tools/zip.lua tools/tar.lua pack.lua type_check.lua \
13make.lua remove.lua fs.lua manif.lua add.lua deps.lua build.lua search.lua \
14show.lua manif_core.lua fetch.lua unpack.lua validate.lua cfg.lua download.lua \
15help.lua util.lua index.lua cache.lua refresh_cache.lua loader.lua \
16admin_remove.lua fetch/hg.lua fetch/git_file.lua new_version.lua lint.lua \
17purge.lua path.lua path_cmd.lua write_rockspec.lua doc.lua upload.lua \
18upload/api.lua upload/multipart.lua fetch/git_http.lua fetch/hg_http.lua \
19fetch/hg_https.lua fetch/hg_ssh.lua fetch/git_https.lua fetch/git_ssh.lua
20
diff --git a/README.md b/README.md
index c779c3d6..02543ef3 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,23 @@
1LuaRocks 1<p align="center"><a href="http://luarocks.org"><img border="0" src="http://keplerproject.github.io/luarocks/luarocks.png" alt="LuaRocks" width="500px"></a></p>
2========
3 2
4A package manager for Lua modules. 3A package manager for Lua modules.
5 4
6[![Build Status](https://travis-ci.org/keplerproject/luarocks.png?branch=master)](https://travis-ci.org/keplerproject/luarocks) 5[![Build Status](https://travis-ci.org/keplerproject/luarocks.png?branch=master)](https://travis-ci.org/keplerproject/luarocks)
6[![Build status](https://ci.appveyor.com/api/projects/status/4x4630tcf64da48i/branch/master?svg=true)](https://ci.appveyor.com/project/hishamhm/luarocks/branch/master)
7[![Coverage Status](https://coveralls.io/repos/keplerproject/luarocks/badge.svg?branch=master)](https://coveralls.io/r/keplerproject/luarocks?branch=master)
7 8
8Main website: [luarocks.org](http://www.luarocks.org) 9Main website: [luarocks.org](http://www.luarocks.org)
9 10
10It allows you to install Lua modules as self-contained packages called 11It allows you to install Lua modules as self-contained packages called
11[*rocks*][1], which also contain version [dependency][2] information. This 12[*rocks*][1], which also contain version [dependency][2] information. This
12information is used both during installation, so that when one rock is 13information can be used both during installation, so that when one rock is
13requested all rocks it depends on are installed as well, and at run time, so 14requested all rocks it depends on are installed as well, and also optionally
14that when a module is required, the correct version is loaded. LuaRocks 15at run time, so that when a module is required, the correct version is loaded.
15supports both local and [remote][3] repositories, and multiple local rocks 16LuaRocks supports both local and [remote][3] repositories, and multiple local
16trees. You can [download][4] and install LuaRocks on [Unix][5] and 17rocks trees. You can [download][4] and install LuaRocks on [Unix][5] and
17[Windows][6]. 18[Windows][6].
18 19
19LuaRocks is free software and uses the same [license][7] as Lua 5.1. 20LuaRocks is free software and uses the same [license][7] as Lua 5.x.
20 21
21[1]: http://luarocks.org/en/Types_of_rocks 22[1]: http://luarocks.org/en/Types_of_rocks
22[2]: http://luarocks.org/en/Dependencies 23[2]: http://luarocks.org/en/Dependencies
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..d7fc7cc2
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,30 @@
1version: 2.2.1.{build}-test
2
3shallow_clone: true
4
5environment:
6 LUAROCKS_VER: 2.2.1
7
8 matrix:
9 - LUA_VER: 5.1.5
10 - LUA_VER: 5.2.4
11 - LUA_VER: 5.3.1
12 - LJ_VER: 2.0.4
13 - LJ_VER: 2.1
14
15init:
16# Setup Lua development/build environment
17# Make VS 2015 command line tools available
18- call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %platform%
19
20install:
21# Setup Lua development/build environment
22- call .appveyor\install.bat
23
24build_script:
25- call .appveyor\build.bat
26
27test_script:
28- echo "Testing..."
29- cd test
30- call testing.bat
diff --git a/configure b/configure
index bbdbb5c9..665d52bc 100755
--- a/configure
+++ b/configure
@@ -40,17 +40,20 @@ system's package manager.
40 Default is \$PREFIX 40 Default is \$PREFIX
41 41
42--lua-version=VERSION Use specific Lua version: 5.1, 5.2, or 5.3 42--lua-version=VERSION Use specific Lua version: 5.1, 5.2, or 5.3
43 Default is "$LUA_VERSION" 43 Default is auto-detected.
44--lua-suffix=SUFFIX Versioning suffix to use in Lua filenames. 44--lua-suffix=SUFFIX Versioning suffix to use in Lua filenames.
45 Default is "$LUA_SUFFIX" (lua$LUA_SUFFIX...) 45 Default is "$LUA_SUFFIX" (lua$LUA_SUFFIX...)
46--with-lua=PREFIX Use Lua from given prefix. 46--with-lua=PREFIX Use Lua from given prefix.
47 Default is $LUA_DIR 47 Default is auto-detected (the parent directory of \$LUA_BINDIR).
48--with-lua-bin=DIR You can also specify Lua's bin dir.
49 Default is the directory of the auto-detected Lua interpreter,
50 or \$LUA_DIR/bin if --with-lua is used.
48--with-lua-include=DIR You can also specify Lua's includes dir. 51--with-lua-include=DIR You can also specify Lua's includes dir.
49 Default is \$LUA_DIR/include 52 Default is \$LUA_DIR/include
50--with-lua-lib=DIR You can also specify Lua's libraries dir. 53--with-lua-lib=DIR You can also specify Lua's libraries dir.
51 Default is \$LUA_DIR/lib 54 Default is \$LUA_DIR/lib
52--with-downloader=TOOL Which tool to use as a downloader. 55--with-downloader=TOOL Which tool to use as a downloader.
53 Valid options are: wget, curl. 56 Valid options are: curl, wget.
54 Default is to auto-detect. 57 Default is to auto-detect.
55--with-md5-checker=TOOL Which tool to use as a downloader. 58--with-md5-checker=TOOL Which tool to use as a downloader.
56 Valid options are: md5sum, openssl 59 Valid options are: md5sum, openssl
@@ -68,25 +71,10 @@ EOF
68# Helper functions 71# Helper functions
69 72
70find_program() { 73find_program() {
71 path="$PATH" 74 prog=`command -v "$1" 2>/dev/null`
72 item="`echo "$path" | sed 's/\([^:]*\):.*/\1/'`" 75 if [ -n "$prog" ]
73 path="`echo "$path" | sed -n 's/[^:]*::*\(.*\)/\1/p'`"
74 found="no"
75 while [ -n "$item" ]
76 do
77 if [ -f "$item/$1" ]
78 then
79 found="yes"
80 break
81 fi
82 item="`echo "$path" | sed 's/\([^:]*\):.*/\1/'`"
83 path="`echo "$path" | sed -n 's/[^:]*::*\(.*\)/\1/p'`"
84 done
85 if [ "$found" = "yes" ]
86 then 76 then
87 echo "$item" 77 dirname "$prog"
88 else
89 echo ""
90 fi 78 fi
91} 79}
92 80
@@ -113,7 +101,7 @@ find_helper() {
113 fi 101 fi
114 shift 102 shift
115 done 103 done
116 echo "Could not find a $explanation. Tried: $tried." 104 echo "Could not find $explanation. Tried: $tried."
117 die "Make sure one of them is installed and available in your PATH." 105 die "Make sure one of them is installed and available in your PATH."
118} 106}
119 107
@@ -174,7 +162,7 @@ do
174 LUA_SUFFIX="$value" 162 LUA_SUFFIX="$value"
175 LUA_SUFFIX_SET=yes 163 LUA_SUFFIX_SET=yes
176 ;; 164 ;;
177 --lua-version) 165 --lua-version|--with-lua-version)
178 [ -n "$value" ] || die "Missing value in flag $key." 166 [ -n "$value" ] || die "Missing value in flag $key."
179 LUA_VERSION="$value" 167 LUA_VERSION="$value"
180 [ "$LUA_VERSION" = "5.1" -o "$LUA_VERSION" = "5.2" -o "$LUA_VERSION" = "5.3" ] || die "Invalid Lua version in flag $key." 168 [ "$LUA_VERSION" = "5.1" -o "$LUA_VERSION" = "5.2" -o "$LUA_VERSION" = "5.3" ] || die "Invalid Lua version in flag $key."
@@ -185,6 +173,11 @@ do
185 LUA_DIR="$value" 173 LUA_DIR="$value"
186 LUA_DIR_SET=yes 174 LUA_DIR_SET=yes
187 ;; 175 ;;
176 --with-lua-bin)
177 [ -n "$value" ] || die "Missing value in flag $key."
178 LUA_BINDIR="$value"
179 LUA_BINDIR_SET=yes
180 ;;
188 --with-lua-include) 181 --with-lua-include)
189 [ -n "$value" ] || die "Missing value in flag $key." 182 [ -n "$value" ] || die "Missing value in flag $key."
190 LUA_INCDIR="$value" 183 LUA_INCDIR="$value"
@@ -242,14 +235,17 @@ detect_lua_version() {
242 LUA_VERSION=$detected_lua 235 LUA_VERSION=$detected_lua
243 elif [ "$LUA_VERSION" != "$detected_lua" ] 236 elif [ "$LUA_VERSION" != "$detected_lua" ]
244 then 237 then
245 die "This clashes with the value of --with-lua-version. Please check your configuration." 238 die "This clashes with the value of --lua-version. Please check your configuration."
246 fi 239 fi
247 fi 240 fi
248} 241}
249 242
250search_interpreter() { 243search_interpreter() {
251 LUA_SUFFIX="$1" 244 suffix="$1"
252 if [ "$LUA_DIR_SET" = "yes" ] 245 if [ "$LUA_BINDIR_SET" = "yes" ]
246 then
247 find_lua="$LUA_BINDIR"
248 elif [ "$LUA_DIR_SET" = "yes" ]
253 then 249 then
254 if [ -f "$LUA_DIR/bin/lua$suffix" ] 250 if [ -f "$LUA_DIR/bin/lua$suffix" ]
255 then 251 then
@@ -258,10 +254,11 @@ search_interpreter() {
258 else 254 else
259 find_lua=`find_program lua$suffix` 255 find_lua=`find_program lua$suffix`
260 fi 256 fi
261 if [ -n "$find_lua" ] 257 if [ -n "$find_lua" -a -x "$find_lua/lua$suffix" ]
262 then 258 then
263 echo "Lua interpreter found: $find_lua/lua$suffix..." 259 echo "Lua interpreter found: $find_lua/lua$suffix..."
264 detect_lua_version "$find_lua/lua$suffix" 260 LUA_SUFFIX=$suffix
261 detect_lua_version "$find_lua/lua$LUA_SUFFIX"
265 return 0 262 return 0
266 fi 263 fi
267 return 1 264 return 1
@@ -281,9 +278,13 @@ then
281 else 278 else
282 suffixes="5.3 53 -5.3 -53 5.2 52 -5.2 -52 5.1 51 -5.1 -51" 279 suffixes="5.3 53 -5.3 -53 5.2 52 -5.2 -52 5.1 51 -5.1 -51"
283 fi 280 fi
284 for suffix in `echo $suffixes` "" 281 lua_interp_found=no
282 for suffix in "" `echo $suffixes`
285 do 283 do
286 search_interpreter "$suffix" && break 284 search_interpreter "$suffix" && {
285 lua_interp_found=yes
286 break
287 }
287 done 288 done
288fi 289fi
289 290
@@ -302,7 +303,7 @@ then
302 echo "lua$LUA_SUFFIX found in \$PATH: $find_lua" 303 echo "lua$LUA_SUFFIX found in \$PATH: $find_lua"
303 else 304 else
304 echo "lua$LUA_SUFFIX not found in \$PATH." 305 echo "lua$LUA_SUFFIX not found in \$PATH."
305 die "You may want to use the flags --with-lua and/or --lua-suffix. See --help." 306 die "You may want to use the flags --with-lua, --with-lua-bin and/or --lua-suffix. See --help."
306 fi 307 fi
307fi 308fi
308 309
@@ -316,11 +317,23 @@ then
316 LUA_LIBDIR="$LUA_DIR/lib" 317 LUA_LIBDIR="$LUA_DIR/lib"
317fi 318fi
318 319
319if [ "$LUA_DIR_SET" = "yes" ] 320if [ "$LUA_DIR_SET" = "yes" -a "$LUA_BINDIR_SET" != "yes" ]
320then 321then
321 LUA_BINDIR="$LUA_DIR/bin" 322 LUA_BINDIR="$LUA_DIR/bin"
322fi 323fi
323 324
325if [ "$lua_interp_found" != "yes" ]
326then
327 echo_n "Checking Lua interpreter... "
328 if [ -x "$LUA_BINDIR/lua$LUA_SUFFIX" ]
329 then
330 echo "lua$LUA_SUFFIX found in $LUA_BINDIR"
331 else
332 echo "lua$LUA_SUFFIX not found (looked in $LUA_BINDIR)"
333 die "You may want to use the flag --with-lua or --with-lua-bin. See --help."
334 fi
335fi
336
324echo_n "Checking Lua includes... " 337echo_n "Checking Lua includes... "
325lua_h="$LUA_INCDIR/lua.h" 338lua_h="$LUA_INCDIR/lua.h"
326if [ -f "$lua_h" ] 339if [ -f "$lua_h" ]
@@ -349,16 +362,18 @@ fi
349 362
350if [ "$LUAROCKS_DOWNLOADER_SET" != "yes" ] 363if [ "$LUAROCKS_DOWNLOADER_SET" != "yes" ]
351then 364then
352 find_helper "downloader helper program" wget curl fetch 365 find_helper "a downloader helper program" curl wget fetch
353 LUAROCKS_DOWNLOADER=$HELPER 366 LUAROCKS_DOWNLOADER=$HELPER
354fi 367fi
355 368
356if [ "$LUAROCKS_MD5CHECKER_SET" != "yes" ] 369if [ "$LUAROCKS_MD5CHECKER_SET" != "yes" ]
357then 370then
358 find_helper "MD5 checksum calculator" md5sum openssl md5 371 find_helper "a MD5 checksum calculator" md5sum openssl md5
359 LUAROCKS_MD5CHECKER=$HELPER 372 LUAROCKS_MD5CHECKER=$HELPER
360fi 373fi
361 374
375find_helper "an 'unzip' program" unzip
376
362echo_n "Configuring for system... " 377echo_n "Configuring for system... "
363if uname -s 378if uname -s
364then 379then
@@ -408,6 +423,10 @@ then
408 if [ -n "$GCC_ARCH" -a -d "/usr/lib/$GCC_ARCH" ] 423 if [ -n "$GCC_ARCH" -a -d "/usr/lib/$GCC_ARCH" ]
409 then 424 then
410 MULTIARCH_SUBDIR="lib/$GCC_ARCH" 425 MULTIARCH_SUBDIR="lib/$GCC_ARCH"
426 elif [ -d "/usr/lib64" ]
427 then
428 # Useful for Fedora systems
429 MULTIARCH_SUBDIR="lib64"
411 fi 430 fi
412fi 431fi
413 432
diff --git a/install.bat b/install.bat
index ddcbc71a..053fdfd6 100644
--- a/install.bat
+++ b/install.bat
@@ -6,8 +6,12 @@ local vars = {}
6 6
7 7
8vars.PREFIX = nil 8vars.PREFIX = nil
9vars.VERSION = "2.1" 9vars.VERSION = "2.2"
10vars.SYSCONFDIR = nil 10vars.SYSCONFDIR = nil
11vars.SYSCONFFORCE = nil
12vars.CONFBACKUPDIR = nil
13vars.SYSCONFFILENAME = nil
14vars.CONFIG_FILE = nil
11vars.TREE_ROOT = nil 15vars.TREE_ROOT = nil
12vars.TREE_BIN = nil 16vars.TREE_BIN = nil
13vars.TREE_LMODULE = nil 17vars.TREE_LMODULE = nil
@@ -26,11 +30,13 @@ vars.LUA_SHORTV = nil -- "51"
26vars.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"
27vars.LUA_RUNTIME = nil 31vars.LUA_RUNTIME = nil
28vars.UNAME_M = nil 32vars.UNAME_M = nil
33vars.COMPILER_ENV_CMD = nil
29 34
30local FORCE = false 35local FORCE = false
31local FORCE_CONFIG = false 36local FORCE_CONFIG = false
32local INSTALL_LUA = false 37local INSTALL_LUA = false
33local USE_MINGW = false 38local USE_MINGW = false
39local USE_MSVC_MANUAL = false
34local REGISTRY = true 40local REGISTRY = true
35local NOADMIN = false 41local NOADMIN = false
36local PROMPT = true 42local PROMPT = true
@@ -77,7 +83,7 @@ end
77 83
78local function exec(cmd) 84local function exec(cmd)
79 --print(cmd) 85 --print(cmd)
80 local status = os.execute(cmd) 86 local status = os.execute("type NUL && "..cmd)
81 return (status == 0 or status == true) -- compat 5.1/5.2 87 return (status == 0 or status == true) -- compat 5.1/5.2
82end 88end
83 89
@@ -90,12 +96,12 @@ local function mkdir (dir)
90 return exec([[.\win32\tools\mkdir -p "]]..dir..[[" >NUL]]) 96 return exec([[.\win32\tools\mkdir -p "]]..dir..[[" >NUL]])
91end 97end
92 98
93-- does the current user have admin priviledges ( = elevated) 99-- does the current user have admin privileges ( = elevated)
94local function permission() 100local function permission()
95 return exec("net session >NUL 2>&1") -- fails if not admin 101 return exec("net session >NUL 2>&1") -- fails if not admin
96end 102end
97 103
98-- rename file (full path) to backup (name only), appending number if required 104-- rename filename (full path) to backupname (name only), appending number if required
99-- returns the new name (name only) 105-- returns the new name (name only)
100local function backup(filename, backupname) 106local function backup(filename, backupname)
101 local path = filename:match("(.+)%\\.-$").."\\" 107 local path = filename:match("(.+)%\\.-$").."\\"
@@ -119,14 +125,12 @@ local function print_help()
119Installs LuaRocks. 125Installs LuaRocks.
120 126
121/P [dir] Where to install LuaRocks. 127/P [dir] Where to install LuaRocks.
122 Note that version; $VERSION, will be appended to this
123 path, so "/P c:\luarocks\" will install in
124 "c:\luarocks\$VERSION\"
125 Default is %PROGRAMFILES%\LuaRocks 128 Default is %PROGRAMFILES%\LuaRocks
126 129
127Configuring the destinations: 130Configuring the destinations:
128/TREE [dir] Root of the local tree of installed rocks. 131/TREE [dir] Root of the local system tree of installed rocks.
129 Default is %PROGRAMFILES%\LuaRocks\systree 132 Default is {BIN}\..\ if {BIN} ends with '\bin'
133 otherwise it is {BIN}\systree.
130/SCRIPTS [dir] Where to install commandline scripts installed by 134/SCRIPTS [dir] Where to install commandline scripts installed by
131 rocks. Default is {TREE}\bin. 135 rocks. Default is {TREE}\bin.
132/LUAMOD [dir] Where to install Lua modules installed by rocks. 136/LUAMOD [dir] Where to install Lua modules installed by rocks.
@@ -165,7 +169,14 @@ Configuring the Lua interpreter:
165 (/LUA, /INC, /LIB, /BIN cannot be used with /L) 169 (/LUA, /INC, /LIB, /BIN cannot be used with /L)
166 170
167Compiler configuration: 171Compiler configuration:
168/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)
169 180
170Other options: 181Other options:
171/FORCECONFIG Use a single config location. Do not use the 182/FORCECONFIG Use a single config location. Do not use the
@@ -175,7 +186,7 @@ Other options:
175/F Remove installation directory if it already exists. 186/F Remove installation directory if it already exists.
176/NOREG Do not load registry info to register '.rockspec' 187/NOREG Do not load registry info to register '.rockspec'
177 extension with LuaRocks commands (right-click). 188 extension with LuaRocks commands (right-click).
178/NOADMIN The installer requires admin priviledges. If not 189/NOADMIN The installer requires admin privileges. If not
179 available it will elevate a new process. Use this 190 available it will elevate a new process. Use this
180 switch to prevent elevation, but make sure the 191 switch to prevent elevation, but make sure the
181 destination paths are all accessible for the current 192 destination paths are all accessible for the current
@@ -198,6 +209,7 @@ local function parse_options(args)
198 vars.PREFIX = option.value 209 vars.PREFIX = option.value
199 elseif name == "/CONFIG" then 210 elseif name == "/CONFIG" then
200 vars.SYSCONFDIR = option.value 211 vars.SYSCONFDIR = option.value
212 vars.SYSCONFFORCE = true
201 elseif name == "/TREE" then 213 elseif name == "/TREE" then
202 vars.TREE_ROOT = option.value 214 vars.TREE_ROOT = option.value
203 elseif name == "/SCRIPTS" then 215 elseif name == "/SCRIPTS" then
@@ -212,6 +224,8 @@ local function parse_options(args)
212 INSTALL_LUA = true 224 INSTALL_LUA = true
213 elseif name == "/MW" then 225 elseif name == "/MW" then
214 USE_MINGW = true 226 USE_MINGW = true
227 elseif name == "/MSVC" then
228 USE_MSVC_MANUAL = true
215 elseif name == "/LUA" then 229 elseif name == "/LUA" then
216 vars.LUA_PREFIX = option.value 230 vars.LUA_PREFIX = option.value
217 elseif name == "/LIB" then 231 elseif name == "/LIB" then
@@ -253,7 +267,7 @@ local function check_flags()
253 die("Cannot combine option /L with any of /LUA /BIN /LIB /INC") 267 die("Cannot combine option /L with any of /LUA /BIN /LIB /INC")
254 end 268 end
255 if vars.LUA_VERSION ~= "5.1" then 269 if vars.LUA_VERSION ~= "5.1" then
256 die("Bundled Lua version is 5.1, cannot install 5.2") 270 die("Bundled Lua version is 5.1, cannot install "..vars.LUA_VERSION)
257 end 271 end
258 end 272 end
259 if vars.LUA_VERSION ~= "5.1" then 273 if vars.LUA_VERSION ~= "5.1" then
@@ -265,6 +279,9 @@ local function check_flags()
265 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")
266 end 280 end
267 end 281 end
282 if USE_MSVC_MANUAL and USE_MINGW then
283 die("Cannot combine option /MSVC and /MW")
284 end
268end 285end
269 286
270-- *********************************************************** 287-- ***********************************************************
@@ -319,7 +336,7 @@ local function look_for_interpreter (directory)
319 return true 336 return true
320 end 337 end
321 end 338 end
322 print(" No Lua interpreter found") 339 --print(" No Lua interpreter found")
323 return false 340 return false
324end 341end
325 342
@@ -360,7 +377,14 @@ local function look_for_headers (directory)
360 die(S"lua.h not found in $LUA_INCDIR") 377 die(S"lua.h not found in $LUA_INCDIR")
361 end 378 end
362 379
363 for _, e in ipairs{ [[\]], [[\include\]]} do 380 for _, e in ipairs{
381 S([[\include\lua\$LUA_VERSION]]),
382 S([[\include\lua$LUA_SHORTV]]),
383 S([[\include\lua$LUA_VERSION]]),
384 S([[\include\$LUA_VERSION]]),
385 [[\include\]],
386 [[\]],
387 } do
364 print(" checking for "..directory..e.."\\lua.h") 388 print(" checking for "..directory..e.."\\lua.h")
365 if exists(directory..e.."\\lua.h") then 389 if exists(directory..e.."\\lua.h") then
366 vars.LUA_INCDIR = directory..e 390 vars.LUA_INCDIR = directory..e
@@ -400,6 +424,117 @@ local function get_architecture()
400 return proc 424 return proc
401end 425end
402 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
403local function look_for_lua_install () 538local function look_for_lua_install ()
404 print("Looking for Lua interpreter") 539 print("Looking for Lua interpreter")
405 local directories 540 local directories
@@ -470,6 +605,28 @@ local function look_for_lua_install ()
470 return false 605 return false
471end 606end
472 607
608-- backup config[x.x].lua[.bak] and site_config[_x_x].lua
609local function backup_config_files()
610 local temppath
611 while not temppath do
612 temppath = os.getenv("temp").."\\LR-config-backup-"..tostring(math.random(10000))
613 if exists(temppath) then temppath = nil end
614 end
615 vars.CONFBACKUPDIR = temppath
616 mkdir(vars.CONFBACKUPDIR)
617 exec(S[[COPY "$PREFIX\config*.*" "$CONFBACKUPDIR" >NUL]])
618 exec(S[[COPY "$PREFIX\lua\luarocks\site_config*.*" "$CONFBACKUPDIR" >NUL]])
619end
620
621-- restore previously backed up config files
622local function restore_config_files()
623 if not vars.CONFBACKUPDIR then return end -- there is no backup to restore
624 exec(S[[COPY "$CONFBACKUPDIR\config*.*" "$PREFIX" >NUL]])
625 exec(S[[COPY "$CONFBACKUPDIR\site_config*.*" "$PREFIX\lua\luarocks" >NUL]])
626 -- cleanup
627 exec(S[[RD /S /Q "$CONFBACKUPDIR"]])
628 vars.CONFBACKUPDIR = nil
629end
473 630
474-- *********************************************************** 631-- ***********************************************************
475-- Installer script start 632-- Installer script start
@@ -550,12 +707,12 @@ check_flags()
550 707
551if not permission() then 708if not permission() then
552 if not NOADMIN then 709 if not NOADMIN then
553 -- must elevate the process with admin priviledges 710 -- must elevate the process with admin privileges
554 if not exec("PowerShell /? >NUL 2>&1") then 711 if not exec("PowerShell /? >NUL 2>&1") then
555 -- powershell is not available, so error out 712 -- powershell is not available, so error out
556 die("No administrative priviledges detected and cannot auto-elevate. Please run with admin priviledges or use the /NOADMIN switch") 713 die("No administrative privileges detected and cannot auto-elevate. Please run with admin privileges or use the /NOADMIN switch")
557 end 714 end
558 print("Need admin priviledges, now elevating a new process to continue installing...") 715 print("Need admin privileges, now elevating a new process to continue installing...")
559 local runner = os.getenv("TEMP").."\\".."LuaRocks_Installer.bat" 716 local runner = os.getenv("TEMP").."\\".."LuaRocks_Installer.bat"
560 local f = io.open(runner, "w") 717 local f = io.open(runner, "w")
561 f:write("@echo off\n") 718 f:write("@echo off\n")
@@ -567,21 +724,20 @@ if not permission() then
567 f:close() 724 f:close()
568 -- run the created temp batch file in elevated mode 725 -- run the created temp batch file in elevated mode
569 exec("PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('"..runner.."', '', '', 'runas')\n") 726 exec("PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('"..runner.."', '', '', 'runas')\n")
570 print("Now exiting unpriviledged installer") 727 print("Now exiting unprivileged installer")
571 os.exit() -- exit here, the newly created elevated process will do the installing 728 os.exit() -- exit here, the newly created elevated process will do the installing
572 else 729 else
573 print("Attempting to install without admin priviledges...") 730 print("Attempting to install without admin privileges...")
574 end 731 end
575else 732else
576 print("Admin priviledges available for installing") 733 print("Admin privileges available for installing")
577end 734end
578 735
579vars.PREFIX = vars.PREFIX or os.getenv("PROGRAMFILES")..[[\LuaRocks]] 736vars.PREFIX = vars.PREFIX or os.getenv("PROGRAMFILES")..[[\LuaRocks]]
580vars.FULL_PREFIX = S"$PREFIX\\$VERSION" 737vars.BINDIR = vars.PREFIX
581vars.BINDIR = vars.FULL_PREFIX 738vars.LIBDIR = vars.PREFIX
582vars.LIBDIR = vars.FULL_PREFIX 739vars.LUADIR = S"$PREFIX\\lua"
583vars.LUADIR = S"$FULL_PREFIX\\lua" 740vars.INCDIR = S"$PREFIX\\include"
584vars.INCDIR = S"$FULL_PREFIX\\include"
585vars.LUA_SHORTV = vars.LUA_VERSION:gsub("%.", "") 741vars.LUA_SHORTV = vars.LUA_VERSION:gsub("%.", "")
586 742
587if INSTALL_LUA then 743if INSTALL_LUA then
@@ -602,20 +758,30 @@ else
602 vars.UNAME_M = get_architecture() -- can only do when installation was found 758 vars.UNAME_M = get_architecture() -- can only do when installation was found
603end 759end
604 760
605local datapath 761-- check location of system tree
606if vars.UNAME_M == "x86" then 762if not vars.TREE_ROOT then
607 datapath = os.getenv("PROGRAMFILES") .. [[\LuaRocks]] 763 -- no system tree location given, so we need to construct a default value
608else 764 if vars.LUA_BINDIR:lower():match([[([\/]+bin[\/]*)$]]) then
609 -- our target interpreter is 64bit, so the tree (with binaries) should go into 64bit program files 765 -- lua binary is located in a 'bin' subdirectory, so assume
610 datapath = os.getenv("ProgramW6432") .. [[\LuaRocks]] 766 -- default Lua layout and match rocktree on top
767 vars.TREE_ROOT = vars.LUA_BINDIR:lower():gsub([[[\/]+bin[\/]*$]], [[\]])
768 else
769 -- no 'bin', so use a named tree next to the Lua executable
770 vars.TREE_ROOT = vars.LUA_BINDIR .. [[\systree]]
771 end
611end 772end
773
774local datapath
612vars.SYSCONFDIR = vars.SYSCONFDIR or vars.PREFIX 775vars.SYSCONFDIR = vars.SYSCONFDIR or vars.PREFIX
613vars.TREE_ROOT = vars.TREE_ROOT or datapath..[[\systree]] 776vars.SYSCONFFILENAME = S"config-$LUA_VERSION.lua"
777vars.CONFIG_FILE = vars.SYSCONFDIR.."\\"..vars.SYSCONFFILENAME
614if SELFCONTAINED then 778if SELFCONTAINED then
615 vars.SYSCONFDIR = vars.PREFIX 779 vars.SYSCONFDIR = vars.PREFIX
780 vars.SYSCONFFORCE = true
616 vars.TREE_ROOT = vars.PREFIX..[[\systree]] 781 vars.TREE_ROOT = vars.PREFIX..[[\systree]]
617 REGISTRY = false 782 REGISTRY = false
618end 783end
784vars.COMPILER_ENV_CMD = (USE_MINGW and "") or (USE_MSVC_MANUAL and "") or get_msvc_env_setup_cmd()
619 785
620print(S[[ 786print(S[[
621 787
@@ -624,8 +790,8 @@ print(S[[
624========================== 790==========================
625 791
626Will configure LuaRocks with the following paths: 792Will configure LuaRocks with the following paths:
627LuaRocks : $FULL_PREFIX 793LuaRocks : $PREFIX
628Config file : $SYSCONFDIR\config.lua 794Config file : $CONFIG_FILE
629Rocktree : $TREE_ROOT 795Rocktree : $TREE_ROOT
630 796
631Lua interpreter : $LUA_BINDIR\$LUA_INTERPRETER 797Lua interpreter : $LUA_BINDIR\$LUA_INTERPRETER
@@ -634,11 +800,20 @@ Lua interpreter : $LUA_BINDIR\$LUA_INTERPRETER
634 includes : $LUA_INCDIR 800 includes : $LUA_INCDIR
635 architecture: $UNAME_M 801 architecture: $UNAME_M
636 binary link : $LUA_LIBNAME with runtime $LUA_RUNTIME.dll 802 binary link : $LUA_LIBNAME with runtime $LUA_RUNTIME.dll
637
638]]) 803]])
639 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
640if PROMPT then 815if PROMPT then
641 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.")
642 io.read() 817 io.read()
643end 818end
644 819
@@ -653,17 +828,19 @@ print([[
653-- *********************************************************** 828-- ***********************************************************
654-- Install LuaRocks files 829-- Install LuaRocks files
655-- *********************************************************** 830-- ***********************************************************
656if FORCE then
657 print(S"Removing $FULL_PREFIX...")
658 exec(S[[RD /S /Q "$FULL_PREFIX"]])
659 print()
660end
661 831
662if exists(vars.FULL_PREFIX) then 832if exists(vars.PREFIX) then
663 die(S"$FULL_PREFIX exists. Use /F to force removal and reinstallation.") 833 if not FORCE then
834 die(S"$PREFIX exists. Use /F to force removal and reinstallation.")
835 else
836 backup_config_files()
837 print(S"Removing $PREFIX...")
838 exec(S[[RD /S /Q "$PREFIX"]])
839 print()
840 end
664end 841end
665 842
666print(S"Installing LuaRocks in $FULL_PREFIX...") 843print(S"Installing LuaRocks in $PREFIX...")
667if not exists(vars.BINDIR) then 844if not exists(vars.BINDIR) then
668 if not mkdir(vars.BINDIR) then 845 if not mkdir(vars.BINDIR) then
669 die() 846 die()
@@ -719,7 +896,8 @@ for _, c in ipairs{"luarocks", "luarocks-admin"} do
719 local f = io.open(vars.BINDIR.."\\"..c..".bat", "w") 896 local f = io.open(vars.BINDIR.."\\"..c..".bat", "w")
720 f:write(S[[ 897 f:write(S[[
721@ECHO OFF 898@ECHO OFF
722SETLOCAL 899SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
900$COMPILER_ENV_CMD
723SET "LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%" 901SET "LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%"
724IF NOT "%LUA_PATH_5_2%"=="" ( 902IF NOT "%LUA_PATH_5_2%"=="" (
725 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%"
@@ -729,7 +907,8 @@ IF NOT "%LUA_PATH_5_3%"=="" (
729) 907)
730SET "PATH=$BINDIR;%PATH%" 908SET "PATH=$BINDIR;%PATH%"
731"$LUA_BINDIR\$LUA_INTERPRETER" "$BINDIR\]]..c..[[.lua" %* 909"$LUA_BINDIR\$LUA_INTERPRETER" "$BINDIR\]]..c..[[.lua" %*
732IF NOT "%ERRORLEVEL%"=="2" GOTO EXITLR 910SET EXITCODE=%ERRORLEVEL%
911IF NOT "%EXITCODE%"=="2" GOTO EXITLR
733 912
734REM Permission denied error, try and auto elevate... 913REM Permission denied error, try and auto elevate...
735REM already an admin? (checking to prevent loops) 914REM already an admin? (checking to prevent loops)
@@ -754,48 +933,33 @@ ECHO ECHO Press any key to close this window... >> "%TMPFILE%"
754ECHO PAUSE ^> NUL >> "%TMPFILE%" 933ECHO PAUSE ^> NUL >> "%TMPFILE%"
755ECHO DEL "%TMPFILE%" >> "%TMPFILE%" 934ECHO DEL "%TMPFILE%" >> "%TMPFILE%"
756 935
757ECHO Now retrying as a priviledged user... 936ECHO Now retrying as a privileged user...
758PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('%TMPFILE%', '', '', 'runas') 937PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('%TMPFILE%', '', '', 'runas')
759 938
760:EXITLR 939:EXITLR
761ENDLOCAL 940exit /b %EXITCODE%
762]]) 941]])
763 f:close() 942 f:close()
764 print(S"Created LuaRocks command: $BINDIR\\"..c..".bat") 943 print(S"Created LuaRocks command: $BINDIR\\"..c..".bat")
765end 944end
766 945
767-- part below was commented out as its purpose was unclear
768-- see https://github.com/keplerproject/luarocks/pull/197#issuecomment-30176548
769
770-- configure 'scripts' directory
771-- if vars.TREE_BIN then
772-- mkdir(vars.TREE_BIN)
773-- if not USE_MINGW then
774-- -- definitly not for MinGW because of conflicting runtimes
775-- -- but is it ok to do it for others???
776-- exec(S[[COPY lua5.1\bin\*.dll "$TREE_BIN" >NUL]])
777-- end
778-- else
779-- if not USE_MINGW then
780-- mkdir(S[[$TREE_ROOT\bin]])
781-- -- definitly not for MinGW because of conflicting runtimes
782-- -- but is it ok to do it for others???
783-- exec(S[[COPY lua5.1\bin\*.dll "$TREE_ROOT"\bin >NUL]])
784-- end
785-- end
786
787-- *********************************************************** 946-- ***********************************************************
788-- Configure LuaRocks 947-- Configure LuaRocks
789-- *********************************************************** 948-- ***********************************************************
790 949
950restore_config_files()
791print() 951print()
792print("Configuring LuaRocks...") 952print("Configuring LuaRocks...")
793 953
794-- Create a site-config file 954-- Create a site-config file
795if exists(S[[$LUADIR\luarocks\site_config.lua]]) then 955local site_config = S("site_config_$LUA_VERSION"):gsub("%.","_")
796 exec(S[[RENAME "$LUADIR\luarocks\site_config.lua" site_config.lua.bak]]) 956if exists(S([[$LUADIR\luarocks\]]..site_config..[[.lua]])) then
957 local nname = backup(S([[$LUADIR\luarocks\]]..site_config..[[.lua]]), site_config..".lua.bak")
958 print("***************")
959 print("*** WARNING *** LuaRocks site_config file already exists: '"..site_config..".lua'. The old file has been renamed to '"..nname.."'")
960 print("***************")
797end 961end
798local f = io.open(vars.LUADIR.."\\luarocks\\site_config.lua", "w") 962local f = io.open(vars.LUADIR.."\\luarocks\\"..site_config..".lua", "w")
799f:write(S[=[ 963f:write(S[=[
800local site_config = {} 964local site_config = {}
801site_config.LUA_INCDIR=[[$LUA_INCDIR]] 965site_config.LUA_INCDIR=[[$LUA_INCDIR]]
@@ -810,7 +974,6 @@ else
810end 974end
811f:write(S[=[ 975f:write(S[=[
812site_config.LUAROCKS_UNAME_M=[[$UNAME_M]] 976site_config.LUAROCKS_UNAME_M=[[$UNAME_M]]
813site_config.LUAROCKS_SYSCONFIG=[[$SYSCONFDIR\config.lua]]
814site_config.LUAROCKS_ROCKS_TREE=[[$TREE_ROOT]] 977site_config.LUAROCKS_ROCKS_TREE=[[$TREE_ROOT]]
815site_config.LUAROCKS_PREFIX=[[$PREFIX]] 978site_config.LUAROCKS_PREFIX=[[$PREFIX]]
816site_config.LUAROCKS_DOWNLOADER=[[wget]] 979site_config.LUAROCKS_DOWNLOADER=[[wget]]
@@ -819,24 +982,19 @@ site_config.LUAROCKS_MD5CHECKER=[[md5sum]]
819if FORCE_CONFIG then 982if FORCE_CONFIG then
820 f:write("site_config.LUAROCKS_FORCE_CONFIG=true\n") 983 f:write("site_config.LUAROCKS_FORCE_CONFIG=true\n")
821end 984end
822if exists(vars.LUADIR.."\\luarocks\\site_config.lua.bak") then 985if vars.SYSCONFFORCE then -- only write this value when explcitly given, otherwise rely on defaults
823 for line in io.lines(vars.LUADIR.."\\luarocks\\site_config.lua.bak", "r") do 986 f:write(S("site_config.LUAROCKS_SYSCONFIG=[[$CONFIG_FILE]]\n"))
824 f:write(line)
825 f:write("\n")
826 end
827 exec(S[[DEL /F /Q "$LUADIR\luarocks\site_config.lua.bak"]])
828end 987end
829f:write("return site_config\n") 988f:write("return site_config\n")
830f:close() 989f:close()
831print(S[[Created LuaRocks site-config file: $LUADIR\luarocks\site_config.lua]]) 990print(S([[Created LuaRocks site-config file: $LUADIR\luarocks\]]..site_config..[[.lua]]))
832 991
833-- create config file 992-- create config file
834vars.CONFIG_FILE = vars.SYSCONFDIR.."\\config.lua"
835if not exists(vars.SYSCONFDIR) then 993if not exists(vars.SYSCONFDIR) then
836 mkdir(vars.SYSCONFDIR) 994 mkdir(vars.SYSCONFDIR)
837end 995end
838if exists(vars.CONFIG_FILE) then 996if exists(vars.CONFIG_FILE) then
839 local nname = backup(vars.CONFIG_FILE, "config.bak") 997 local nname = backup(vars.CONFIG_FILE, vars.SYSCONFFILENAME..".bak")
840 print("***************") 998 print("***************")
841 print(S"*** WARNING *** LuaRocks config file already exists: '$CONFIG_FILE'. The old file has been renamed to '"..nname.."'") 999 print(S"*** WARNING *** LuaRocks config file already exists: '$CONFIG_FILE'. The old file has been renamed to '"..nname.."'")
842 print("***************") 1000 print("***************")
@@ -901,17 +1059,17 @@ if REGISTRY then
901 -- expand template with correct path information 1059 -- expand template with correct path information
902 print() 1060 print()
903 print([[Loading registry information for ".rockspec" files]]) 1061 print([[Loading registry information for ".rockspec" files]])
904 exec( S[[win32\lua5.1\bin\lua5.1.exe "$FULL_PREFIX\LuaRocks.reg.lua" "$FULL_PREFIX\LuaRocks.reg.template"]] ) 1062 exec( S[[win32\lua5.1\bin\lua5.1.exe "$PREFIX\LuaRocks.reg.lua" "$PREFIX\LuaRocks.reg.template"]] )
905 exec( S[[regedit /S "$FULL_PREFIX\\LuaRocks.reg"]] ) 1063 exec( S[[regedit /S "$PREFIX\\LuaRocks.reg"]] )
906end 1064end
907 1065
908-- *********************************************************** 1066-- ***********************************************************
909-- Cleanup 1067-- Cleanup
910-- *********************************************************** 1068-- ***********************************************************
911-- remove regsitry related files, no longer needed 1069-- remove regsitry related files, no longer needed
912exec( S[[del "$FULL_PREFIX\LuaRocks.reg.*" >NUL]] ) 1070exec( S[[del "$PREFIX\LuaRocks.reg.*" >NUL]] )
913-- remove pe-parser module 1071-- remove pe-parser module
914exec( S[[del "$FULL_PREFIX\pe-parser.lua" >NUL]] ) 1072exec( S[[del "$PREFIX\pe-parser.lua" >NUL]] )
915 1073
916-- *********************************************************** 1074-- ***********************************************************
917-- Exit handlers 1075-- Exit handlers
@@ -931,8 +1089,8 @@ Lua interpreter;
931 PATH : $LUA_BINDIR 1089 PATH : $LUA_BINDIR
932 PATHEXT : .LUA 1090 PATHEXT : .LUA
933LuaRocks; 1091LuaRocks;
934 PATH : $FULL_PREFIX 1092 PATH : $PREFIX
935 LUA_PATH : $FULL_PREFIX\lua\?.lua;$FULL_PREFIX\lua\?\init.lua 1093 LUA_PATH : $PREFIX\lua\?.lua;$PREFIX\lua\?\init.lua
936Local user rocktree (Note: %APPDATA% is user dependent); 1094Local user rocktree (Note: %APPDATA% is user dependent);
937 PATH : %APPDATA%\LuaRocks\bin 1095 PATH : %APPDATA%\LuaRocks\bin
938 LUA_PATH : %APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?.lua;%APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?\init.lua 1096 LUA_PATH : %APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?.lua;%APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?\init.lua
diff --git a/makedist b/makedist
index d6d46a19..fb41b981 100755
--- a/makedist
+++ b/makedist
@@ -16,13 +16,40 @@ make clean || exit 1
16 16
17grep -q "\"$1\"" rockspec || { 17grep -q "\"$1\"" rockspec || {
18 echo 18 echo
19 echo "Version in rockspec is incorrect. Please fix it." 19 echo "version in rockspec is incorrect. Please fix it."
20 exit 1 20 exit 1
21} 21}
22 22
23grep -q "program_version = \"$1\"" src/luarocks/cfg.lua || { 23grep -q "program_version = \"$1\"" src/luarocks/cfg.lua || {
24 echo 24 echo
25 echo "Version in src/luarocks/cfg.lua is incorrect. Please fix it." 25 echo "program_version in src/luarocks/cfg.lua is incorrect. Please fix it."
26 exit 1
27}
28
29grep -q "version: $1\\." appveyor.yml || {
30 echo
31 echo "version in appveyor.yml is incorrect. Please fix it."
32 exit 1
33}
34
35grep -q "LUAROCKS_VER: $1" appveyor.yml || {
36 echo
37 echo "LUAROCKS_VER in appveyor.yml is incorrect. Please fix it."
38 exit 1
39}
40
41# e.g. if $1 is "2.3.0", $program_series is "2.3"
42program_series=${1%.*}
43
44grep -q "program_series = \"$program_series\"" src/luarocks/cfg.lua || {
45 echo
46 echo "program_series in src/luarocks/cfg.lua is incorrect. Please fix it."
47 exit 1
48}
49
50grep -q "vars.VERSION = \"$program_series\"" install.bat || {
51 echo
52 echo "vars.VERSION in install.bat is incorrect. Please fix it."
26 exit 1 53 exit 1
27} 54}
28 55
@@ -39,8 +66,8 @@ do
39 cp "$i" "$out/$dir" 66 cp "$i" "$out/$dir"
40 if echo "$i" | grep -v "/bin/" | grep -q "^src/" 67 if echo "$i" | grep -v "/bin/" | grep -q "^src/"
41 then 68 then
42 grep -qw `basename "$i"` Makefile || { 69 grep -qw `basename "$i"` Makefile.setup.inc || {
43 echo "Missing ref in makefile: $i" 70 echo "Missing ref in Makefile.setup.inc: $i"
44 touch "missing_ref" 71 touch "missing_ref"
45 exit 1 72 exit 1
46 } 73 }
@@ -61,15 +88,14 @@ mkdir "release-windows"
61mv "$out" "release-windows/$out-win32" 88mv "$out" "release-windows/$out-win32"
62 89
63cd "release-unix/$out" 90cd "release-unix/$out"
64rm -rf makedist install.bat COPYING_lua COPYING_7z COPYING_win win32 lfw 91rm -rf makedist install.bat COPYING_lua COPYING_7z COPYING_win win32 lfw .travis.yml .gitignore appveyor* .appveyor
65cd .. 92cd ..
66tar czvpf ../"$out.tar.gz" "$out" 93tar czvpf ../"$out.tar.gz" "$out"
67cd .. 94cd ..
68rm -rf "release-unix" 95rm -rf "release-unix"
69 96
70cd "release-windows/$out-win32" 97cd "release-windows/$out-win32"
71cp -va win32/* . 98rm -rf makedist Makefile* configure lfw .travis.yml .gitignore test appveyor* .appveyor
72rm -rf makedist Makefile configure lfw win32
73cd .. 99cd ..
74zip -r ../"$out-win32.zip" "$out-win32" 100zip -r ../"$out-win32.zip" "$out-win32"
75cd .. 101cd ..
diff --git a/rockspec b/rockspec
index 16ac635c..bb7645f9 100644
--- a/rockspec
+++ b/rockspec
@@ -1,7 +1,10 @@
1package = "LuaRocks" 1package = "LuaRocks"
2local VER = "2.2.0beta1" 2local VER = "scm"
3local REV = "1" 3version = VER .. "-1"
4version = VER.."-"..REV 4
5source = {
6 url = "--this rockspec is used by `make bootstrap` only--",
7}
5 8
6description = { 9description = {
7 summary = "A deployment and management system for Lua modules.", 10 summary = "A deployment and management system for Lua modules.",
@@ -23,16 +26,13 @@ dependencies = {
23 "lua >= 5.1" 26 "lua >= 5.1"
24} 27}
25 28
26source = {
27 url = "http://luarocks.org/releases/luarocks-"..VER..".tar.gz",
28}
29
30build = { 29build = {
31 type = "make", 30 type = "make",
32 install_target = "install_rock", 31 install_target = "install_rock",
33 build_pass=false, 32 build_pass=false,
34 install_variables = { 33 install_variables = {
35 BINDIR="$(BINDIR)", 34 BINDIR="$(BINDIR)",
36 LUADIR="$(LUADIR)" 35 LUADIR="$(LUADIR)",
36 LUA="$(LUA)",
37 } 37 }
38} 38}
diff --git a/src/bin/luarocks b/src/bin/luarocks
index 3c9e1b74..be6c2b81 100755
--- a/src/bin/luarocks
+++ b/src/bin/luarocks
@@ -1,5 +1,8 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3-- this should be loaded first.
4local cfg = require("luarocks.cfg")
5
3local loader = require("luarocks.loader") 6local loader = require("luarocks.loader")
4local command_line = require("luarocks.command_line") 7local command_line = require("luarocks.command_line")
5 8
@@ -24,6 +27,7 @@ commands = {
24 purge = "luarocks.purge", 27 purge = "luarocks.purge",
25 doc = "luarocks.doc", 28 doc = "luarocks.doc",
26 upload = "luarocks.upload", 29 upload = "luarocks.upload",
30 config = "luarocks.config_cmd",
27} 31}
28 32
29command_line.run_command(...) 33command_line.run_command(...)
diff --git a/src/bin/luarocks-admin b/src/bin/luarocks-admin
index e7f49c25..2890d1f1 100755
--- a/src/bin/luarocks-admin
+++ b/src/bin/luarocks-admin
@@ -1,5 +1,8 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3-- this should be loaded first.
4local cfg = require("luarocks.cfg")
5
3local loader = require("luarocks.loader") 6local loader = require("luarocks.loader")
4local command_line = require("luarocks.command_line") 7local command_line = require("luarocks.command_line")
5 8
diff --git a/src/luarocks/add.lua b/src/luarocks/add.lua
index fc913c95..81adff9b 100644
--- a/src/luarocks/add.lua
+++ b/src/luarocks/add.lua
@@ -50,7 +50,7 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server)
50 if not ok then return nil, err end 50 if not ok then return nil, err end
51 51
52 local files = {} 52 local files = {}
53 for i, rockfile in ipairs(rockfiles) do 53 for _, rockfile in ipairs(rockfiles) do
54 if fs.exists(rockfile) then 54 if fs.exists(rockfile) then
55 util.printout("Copying file "..rockfile.." to "..local_cache.."...") 55 util.printout("Copying file "..rockfile.." to "..local_cache.."...")
56 local absolute = fs.absolute_name(rockfile) 56 local absolute = fs.absolute_name(rockfile)
diff --git a/src/luarocks/admin_remove.lua b/src/luarocks/admin_remove.lua
index 839121d1..5a1cf20b 100644
--- a/src/luarocks/admin_remove.lua
+++ b/src/luarocks/admin_remove.lua
@@ -46,7 +46,7 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve
46 if not ok then return nil, err end 46 if not ok then return nil, err end
47 47
48 local nr_files = 0 48 local nr_files = 0
49 for i, rockfile in ipairs(rockfiles) do 49 for _, rockfile in ipairs(rockfiles) do
50 local basename = dir.base_name(rockfile) 50 local basename = dir.base_name(rockfile)
51 local file = dir.path(local_cache, basename) 51 local file = dir.path(local_cache, basename)
52 util.printout("Removing file "..file.."...") 52 util.printout("Removing file "..file.."...")
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index cc56c782..68f20264 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -37,6 +37,8 @@ or the name of a rock to be fetched from a repository.
37 rockspec. Allows to specify a different branch to 37 rockspec. Allows to specify a different branch to
38 fetch. Particularly for SCM rocks. 38 fetch. Particularly for SCM rocks.
39 39
40--only-deps Installs only the dependencies of the rock.
41
40]]..util.deps_mode_help() 42]]..util.deps_mode_help()
41 43
42--- Install files to a given location. 44--- Install files to a given location.
@@ -130,17 +132,17 @@ function build.apply_patches(rockspec)
130end 132end
131 133
132local function install_default_docs(name, version) 134local function install_default_docs(name, version)
133 local patterns = { "readme", "license", "copying" } 135 local patterns = { "readme", "license", "copying", ".*%.md" }
134 local dest = dir.path(path.install_dir(name, version), "doc") 136 local dest = dir.path(path.install_dir(name, version), "doc")
135 local has_dir = false 137 local has_dir = false
136 for name in fs.dir() do 138 for file in fs.dir() do
137 for _, pattern in ipairs(patterns) do 139 for _, pattern in ipairs(patterns) do
138 if name:lower():match("^"..pattern) then 140 if file:lower():match("^"..pattern) then
139 if not has_dir then 141 if not has_dir then
140 fs.make_dir(dest) 142 fs.make_dir(dest)
141 has_dir = true 143 has_dir = true
142 end 144 end
143 fs.copy(name, dest) 145 fs.copy(file, dest)
144 break 146 break
145 end 147 end
146 end 148 end
@@ -157,9 +159,10 @@ end
157-- @param deps_mode string: Dependency mode: "one" for the current default tree, 159-- @param deps_mode string: Dependency mode: "one" for the current default tree,
158-- "all" for all trees, "order" for all trees with priority >= the current default, 160-- "all" for all trees, "order" for all trees with priority >= the current default,
159-- "none" for no trees. 161-- "none" for no trees.
162-- @param build_only_deps boolean: true to build the listed dependencies only.
160-- @return (string, string) or (nil, string, [string]): Name and version of 163-- @return (string, string) or (nil, string, [string]): Name and version of
161-- installed rock if succeeded or nil and an error message followed by an error code. 164-- installed rock if succeeded or nil and an error message followed by an error code.
162function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode) 165function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode, build_only_deps)
163 assert(type(rockspec_file) == "string") 166 assert(type(rockspec_file) == "string")
164 assert(type(need_to_fetch) == "boolean") 167 assert(type(need_to_fetch) == "boolean")
165 168
@@ -181,12 +184,19 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m
181 end 184 end
182 end 185 end
183 186
184 local ok, err, errcode = deps.check_external_deps(rockspec, "build") 187 local name, version = rockspec.name, rockspec.version
188 if build_only_deps then
189 util.printout("Stopping after installing dependencies for " ..name.." "..version)
190 util.printout()
191 return name, version
192 end
193
194 local ok
195 ok, err, errcode = deps.check_external_deps(rockspec, "build")
185 if err then 196 if err then
186 return nil, err, errcode 197 return nil, err, errcode
187 end 198 end
188 199
189 local name, version = rockspec.name, rockspec.version
190 if repos.is_installed(name, version) then 200 if repos.is_installed(name, version) then
191 repos.delete_version(name, version) 201 repos.delete_version(name, version)
192 end 202 end
@@ -326,8 +336,8 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m
326 end 336 end
327 337
328 local root_dir = path.root_dir(cfg.rocks_dir) 338 local root_dir = path.root_dir(cfg.rocks_dir)
329 util.printout()
330 util.printout(name.." "..version.." is now built and installed in "..root_dir.." "..license) 339 util.printout(name.." "..version.." is now built and installed in "..root_dir.." "..license)
340 util.printout()
331 341
332 util.remove_scheduled_function(rollback) 342 util.remove_scheduled_function(rollback)
333 return name, version 343 return name, version
@@ -340,37 +350,41 @@ end
340-- @param deps_mode: string: Which trees to check dependencies for: 350-- @param deps_mode: string: Which trees to check dependencies for:
341-- "one" for the current default tree, "all" for all trees, 351-- "one" for the current default tree, "all" for all trees,
342-- "order" for all trees with priority >= the current default, "none" for no trees. 352-- "order" for all trees with priority >= the current default, "none" for no trees.
353-- @param build_only_deps boolean: true to build the listed dependencies only.
343-- @return boolean or (nil, string, [string]): True if build was successful, 354-- @return boolean or (nil, string, [string]): True if build was successful,
344-- or false and an error message and an optional error code. 355-- or false and an error message and an optional error code.
345function build.build_rock(rock_file, need_to_fetch, deps_mode) 356function build.build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps)
346 assert(type(rock_file) == "string") 357 assert(type(rock_file) == "string")
347 assert(type(need_to_fetch) == "boolean") 358 assert(type(need_to_fetch) == "boolean")
348 359
349 local unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file) 360 local ok, err, errcode
361 local unpack_dir
362 unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file)
350 if not unpack_dir then 363 if not unpack_dir then
351 return nil, err, errcode 364 return nil, err, errcode
352 end 365 end
353 local rockspec_file = path.rockspec_name_from_rock(rock_file) 366 local rockspec_file = path.rockspec_name_from_rock(rock_file)
354 local ok, err = fs.change_dir(unpack_dir) 367 ok, err = fs.change_dir(unpack_dir)
355 if not ok then return nil, err end 368 if not ok then return nil, err end
356 local ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode) 369 ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps)
357 fs.pop_dir() 370 fs.pop_dir()
358 return ok, err, errcode 371 return ok, err, errcode
359end 372end
360 373
361local function do_build(name, version, deps_mode) 374local function do_build(name, version, deps_mode, build_only_deps)
362 if name:match("%.rockspec$") then 375 if name:match("%.rockspec$") then
363 return build.build_rockspec(name, true, false, deps_mode) 376 return build.build_rockspec(name, true, false, deps_mode, build_only_deps)
364 elseif name:match("%.src%.rock$") then 377 elseif name:match("%.src%.rock$") then
365 return build.build_rock(name, false, deps_mode) 378 return build.build_rock(name, false, deps_mode, build_only_deps)
366 elseif name:match("%.all%.rock$") then 379 elseif name:match("%.all%.rock$") then
367 local install = require("luarocks.install") 380 local install = require("luarocks.install")
368 return install.install_binary_rock(name, deps_mode) 381 local install_fun = build_only_deps and install.install_binary_rock_deps or install.install_binary_rock
382 return install_fun(name, deps_mode)
369 elseif name:match("%.rock$") then 383 elseif name:match("%.rock$") then
370 return build.build_rock(name, true, deps_mode) 384 return build.build_rock(name, true, deps_mode, build_only_deps)
371 elseif not name:match(dir.separator) then 385 elseif not name:match(dir.separator) then
372 local search = require("luarocks.search") 386 local search = require("luarocks.search")
373 return search.act_on_src_or_rockspec(build.run, name:lower(), version, deps.deps_mode_to_flag(deps_mode)) 387 return search.act_on_src_or_rockspec(build.run, name:lower(), version, deps.deps_mode_to_flag(deps_mode), build_only_deps and "--only-deps")
374 end 388 end
375 return nil, "Don't know what to do with "..name 389 return nil, "Don't know what to do with "..name
376end 390end
@@ -395,9 +409,12 @@ function build.run(...)
395 else 409 else
396 local ok, err = fs.check_command_permissions(flags) 410 local ok, err = fs.check_command_permissions(flags)
397 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end 411 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
398 ok, err = do_build(name, version, deps.get_deps_mode(flags)) 412 ok, err = do_build(name, version, deps.get_deps_mode(flags), flags["only-deps"])
399 if not ok then return nil, err end 413 if not ok then return nil, err end
400 local name, version = ok, err 414 local name, version = ok, err
415 if flags["only-deps"] then
416 return name, version
417 end
401 if (not flags["keep"]) and not cfg.keep_other_versions then 418 if (not flags["keep"]) and not cfg.keep_other_versions then
402 local ok, err = remove.remove_other_versions(name, version, flags["force"]) 419 local ok, err = remove.remove_other_versions(name, version, flags["force"])
403 if not ok then util.printerr(err) end 420 if not ok then util.printerr(err) end
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua
index c855f48a..938262ef 100644
--- a/src/luarocks/build/builtin.lua
+++ b/src/luarocks/build/builtin.lua
@@ -74,7 +74,7 @@ function builtin.run(rockspec)
74 add_flags(extras, "-I%s", incdirs) 74 add_flags(extras, "-I%s", incdirs)
75 return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras)) 75 return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
76 end 76 end
77 compile_library = function(library, objects, libraries, libdirs, name) 77 compile_library = function(library, objects, libraries, libdirs)
78 local extras = { unpack(objects) } 78 local extras = { unpack(objects) }
79 add_flags(extras, "-L%s", libdirs) 79 add_flags(extras, "-L%s", libdirs)
80 add_flags(extras, "-l%s", libraries) 80 add_flags(extras, "-l%s", libraries)
@@ -149,7 +149,7 @@ function builtin.run(rockspec)
149 local resname = basename..".res" 149 local resname = basename..".res"
150 local wrapname = basename..".exe" 150 local wrapname = basename..".exe"
151 make_rc(fullname, fullbasename..".rc") 151 make_rc(fullname, fullbasename..".rc")
152 local ok = execute(variables.RC, "-r", "-fo"..resname, rcname) 152 local ok = execute(variables.RC, "-nologo", "-r", "-fo"..resname, rcname)
153 if not ok then return ok end 153 if not ok then return ok end
154 ok = execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, 154 ok = execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object,
155 "-I"..variables.LUA_INCDIR, variables.WRAPPER) 155 "-I"..variables.LUA_INCDIR, variables.WRAPPER)
@@ -188,11 +188,11 @@ function builtin.run(rockspec)
188 end 188 end
189 return ok 189 return ok
190 end 190 end
191 compile_wrapper_binary = function(fullname, name) return true, name end 191 compile_wrapper_binary = function(_, name) return true, name end
192 --TODO EXEWRAPPER 192 --TODO EXEWRAPPER
193 end 193 end
194 194
195 local ok = true 195 local ok, err
196 local built_modules = {} 196 local built_modules = {}
197 local luadir = path.lua_dir(rockspec.name, rockspec.version) 197 local luadir = path.lua_dir(rockspec.name, rockspec.version)
198 local libdir = path.lib_dir(rockspec.name, rockspec.version) 198 local libdir = path.lib_dir(rockspec.name, rockspec.version)
@@ -214,11 +214,13 @@ function builtin.run(rockspec)
214 end 214 end
215 end 215 end
216 216
217 217 if not build.modules then
218 return nil, "Missing build.modules table"
219 end
218 for name, info in pairs(build.modules) do 220 for name, info in pairs(build.modules) do
219 local moddir = path.module_to_path(name) 221 local moddir = path.module_to_path(name)
220 if type(info) == "string" then 222 if type(info) == "string" then
221 local ext = info:match(".([^.]+)$") 223 local ext = info:match("%.([^.]+)$")
222 if ext == "lua" then 224 if ext == "lua" then
223 local filename = dir.base_name(info) 225 local filename = dir.base_name(info)
224 if info:match("init%.lua$") and not name:match("%.init$") then 226 if info:match("init%.lua$") and not name:match("%.init$") then
@@ -242,7 +244,7 @@ function builtin.run(rockspec)
242 if info[1] then sources = info end 244 if info[1] then sources = info end
243 if type(sources) == "string" then sources = {sources} end 245 if type(sources) == "string" then sources = {sources} end
244 for _, source in ipairs(sources) do 246 for _, source in ipairs(sources) do
245 local object = source:gsub(".[^.]*$", "."..cfg.obj_extension) 247 local object = source:gsub("%.[^.]*$", "."..cfg.obj_extension)
246 if not object then 248 if not object then
247 object = source.."."..cfg.obj_extension 249 object = source.."."..cfg.obj_extension
248 end 250 end
@@ -252,11 +254,10 @@ function builtin.run(rockspec)
252 end 254 end
253 table.insert(objects, object) 255 table.insert(objects, object)
254 end 256 end
255 if not ok then break end
256 local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension) 257 local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension)
257 if moddir ~= "" then 258 if moddir ~= "" then
258 module_name = dir.path(moddir, module_name) 259 module_name = dir.path(moddir, module_name)
259 local ok, err = fs.make_dir(moddir) 260 ok, err = fs.make_dir(moddir)
260 if not ok then return nil, err end 261 if not ok then return nil, err end
261 end 262 end
262 built_modules[module_name] = dir.path(libdir, module_name) 263 built_modules[module_name] = dir.path(libdir, module_name)
@@ -277,13 +278,13 @@ function builtin.run(rockspec)
277 end 278 end
278 for name, dest in pairs(built_modules) do 279 for name, dest in pairs(built_modules) do
279 fs.make_dir(dir.dir_name(dest)) 280 fs.make_dir(dir.dir_name(dest))
280 ok = fs.copy(name, dest) 281 ok, err = fs.copy(name, dest)
281 if not ok then 282 if not ok then
282 return nil, "Failed installing "..name.." in "..dest 283 return nil, "Failed installing "..name.." in "..dest..": "..err
283 end 284 end
284 end 285 end
285 if fs.is_dir("lua") then 286 if fs.is_dir("lua") then
286 local ok, err = fs.copy_contents("lua", luadir) 287 ok, err = fs.copy_contents("lua", luadir)
287 if not ok then 288 if not ok then
288 return nil, "Failed copying contents of 'lua' directory: "..err 289 return nil, "Failed copying contents of 'lua' directory: "..err
289 end 290 end
diff --git a/src/luarocks/build/cmake.lua b/src/luarocks/build/cmake.lua
index ed2af3ff..7b16fa51 100644
--- a/src/luarocks/build/cmake.lua
+++ b/src/luarocks/build/cmake.lua
@@ -15,7 +15,7 @@ function cmake.run(rockspec)
15 assert(type(rockspec) == "table") 15 assert(type(rockspec) == "table")
16 local build = rockspec.build 16 local build = rockspec.build
17 local variables = build.variables or {} 17 local variables = build.variables or {}
18 18
19 -- Pass Env variables 19 -- Pass Env variables
20 variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH") 20 variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH")
21 variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH") 21 variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH")
@@ -23,10 +23,11 @@ function cmake.run(rockspec)
23 23
24 util.variable_substitutions(variables, rockspec.variables) 24 util.variable_substitutions(variables, rockspec.variables)
25 25
26 if not fs.execute_quiet(rockspec.variables.CMAKE, "--help") then 26 local ok, err_msg = fs.is_tool_available(rockspec.variables.CMAKE, "CMake")
27 return nil, "'"..rockspec.variables.CMAKE.."' program not found. Is cmake installed? You may want to edit variables.CMAKE" 27 if not ok then
28 return nil, err_msg
28 end 29 end
29 30
30 -- If inline cmake is present create CMakeLists.txt from it. 31 -- If inline cmake is present create CMakeLists.txt from it.
31 if type(build.cmake) == "string" then 32 if type(build.cmake) == "string" then
32 local cmake_handler = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w")) 33 local cmake_handler = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w"))
@@ -34,25 +35,29 @@ function cmake.run(rockspec)
34 cmake_handler:close() 35 cmake_handler:close()
35 end 36 end
36 37
37
38 -- Execute cmake with variables. 38 -- Execute cmake with variables.
39 local args = "" 39 local args = ""
40
41 -- Try to pick the best generator. With msvc and x64, CMake does not select it by default so we need to be explicit.
40 if cfg.cmake_generator then 42 if cfg.cmake_generator then
41 args = args .. ' -G"'..cfg.cmake_generator.. '"' 43 args = args .. ' -G"'..cfg.cmake_generator.. '"'
44 elseif cfg.is_platform("windows") and cfg.target_cpu:match("x86_64$") then
45 args = args .. " -DCMAKE_GENERATOR_PLATFORM=x64"
42 end 46 end
47
43 for k,v in pairs(variables) do 48 for k,v in pairs(variables) do
44 args = args .. ' -D' ..k.. '="' ..v.. '"' 49 args = args .. ' -D' ..k.. '="' ..tostring(v).. '"'
45 end 50 end
46 51
47 if not fs.execute_string(rockspec.variables.CMAKE.." . " ..args) then 52 if not fs.execute_string(rockspec.variables.CMAKE.." -H. -Bbuild.luarocks "..args) then
48 return nil, "Failed cmake." 53 return nil, "Failed cmake."
49 end 54 end
50 55
51 if not fs.execute_string(rockspec.variables.MAKE.." -fMakefile") then 56 if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --config Release") then
52 return nil, "Failed building." 57 return nil, "Failed building."
53 end 58 end
54 59
55 if not fs.execute_string(rockspec.variables.MAKE.." -fMakefile install") then 60 if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --target install --config Release") then
56 return nil, "Failed installing." 61 return nil, "Failed installing."
57 end 62 end
58 return true 63 return true
diff --git a/src/luarocks/cache.lua b/src/luarocks/cache.lua
index dbea8405..fb6344d8 100644
--- a/src/luarocks/cache.lua
+++ b/src/luarocks/cache.lua
@@ -45,25 +45,12 @@ function cache.split_server_url(server, url, user, password)
45 user = credentials 45 user = credentials
46 end 46 end
47 end 47 end
48 local local_cache 48 local local_cache = cfg.local_cache .. "/" .. server
49 if cfg.local_cache then
50 local_cache = cfg.local_cache .. "/" .. server
51 end
52 return local_cache, protocol, server_path, user, password 49 return local_cache, protocol, server_path, user, password
53end 50end
54 51
55function cache.refresh_local_cache(server, url, user, password) 52function cache.refresh_local_cache(server, url, user, password)
56 local local_cache, protocol, server_path, user, password = cache.split_server_url(server, url, user, password) 53 local local_cache, protocol, server_path, user, password = cache.split_server_url(server, url, user, password)
57
58 local ok, err = fs.make_dir(cfg.local_cache)
59 if not ok then return nil, err end
60
61 local tmp_cache = false
62 if not local_cache then
63 local err
64 local_cache, err = fs.make_temp_dir("local_cache")
65 tmp_cache = true
66 end
67 local ok, err = fs.make_dir(local_cache) 54 local ok, err = fs.make_dir(local_cache)
68 if not ok then 55 if not ok then
69 return nil, "Failed creating local cache dir: "..err 56 return nil, "Failed creating local cache dir: "..err
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua
index 8f73bec1..898b0854 100644
--- a/src/luarocks/cfg.lua
+++ b/src/luarocks/cfg.lua
@@ -17,6 +17,8 @@ local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs,
17local cfg = {} 17local cfg = {}
18package.loaded["luarocks.cfg"] = cfg 18package.loaded["luarocks.cfg"] = cfg
19 19
20local util = require("luarocks.util")
21
20cfg.lua_version = _VERSION:sub(5) 22cfg.lua_version = _VERSION:sub(5)
21local version_suffix = cfg.lua_version:gsub("%.", "_") 23local version_suffix = cfg.lua_version:gsub("%.", "_")
22 24
@@ -30,10 +32,12 @@ if not ok then
30 site_config = {} 32 site_config = {}
31end 33end
32 34
33cfg.site_config = site_config 35cfg.program_version = "scm"
34 36cfg.program_series = "2.2"
35cfg.program_version = "2.2.0beta1" 37cfg.major_version = (cfg.program_version:match("([^.]%.[^.])")) or cfg.program_series
36cfg.major_version = cfg.program_version:match("([^.]%.[^.])") 38cfg.variables = {}
39cfg.rocks_trees = {}
40cfg.platforms = {}
37 41
38local persist = require("luarocks.persist") 42local persist = require("luarocks.persist")
39 43
@@ -41,6 +45,8 @@ cfg.errorcodes = setmetatable({
41 OK = 0, 45 OK = 0,
42 UNSPECIFIED = 1, 46 UNSPECIFIED = 1,
43 PERMISSIONDENIED = 2, 47 PERMISSIONDENIED = 2,
48 CONFIGFILE = 3,
49 CRASH = 99
44},{ 50},{
45 __index = function(t, key) 51 __index = function(t, key)
46 local val = rawget(t, key) 52 local val = rawget(t, key)
@@ -65,67 +71,94 @@ end
65 71
66-- System detection: 72-- System detection:
67 73
68local detected = {}
69local system,proc
70
71-- A proper installation of LuaRocks will hardcode the system 74-- A proper installation of LuaRocks will hardcode the system
72-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M, 75-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M,
73-- so that this detection does not run every time. When it is 76-- so that this detection does not run every time. When it is
74-- performed, we use the Unix way to identify the system, 77-- performed, we use the Unix way to identify the system,
75-- even on Windows (assuming UnxUtils or Cygwin). 78-- even on Windows (assuming UnxUtils or Cygwin).
76system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l") 79local system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
77proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l") 80local proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l")
78if proc:match("i[%d]86") then 81if proc:match("i[%d]86") then
79 proc = "x86" 82 cfg.target_cpu = "x86"
80elseif proc:match("amd64") or proc:match("x86_64") then 83elseif proc:match("amd64") or proc:match("x86_64") then
81 proc = "x86_64" 84 cfg.target_cpu = "x86_64"
82elseif proc:match("Power Macintosh") then 85elseif proc:match("Power Macintosh") then
83 proc = "powerpc" 86 cfg.target_cpu = "powerpc"
87 else
88 cfg.target_cpu = proc
84end 89end
85 90
86if system == "FreeBSD" then 91if system == "FreeBSD" then
87 detected.unix = true 92 cfg.platforms.unix = true
88 detected.freebsd = true 93 cfg.platforms.freebsd = true
89 detected.bsd = true 94 cfg.platforms.bsd = true
90elseif system == "OpenBSD" then 95elseif system == "OpenBSD" then
91 detected.unix = true 96 cfg.platforms.unix = true
92 detected.openbsd = true 97 cfg.platforms.openbsd = true
93 detected.bsd = true 98 cfg.platforms.bsd = true
94elseif system == "NetBSD" then 99elseif system == "NetBSD" then
95 detected.unix = true 100 cfg.platforms.unix = true
96 detected.netbsd = true 101 cfg.platforms.netbsd = true
97 detected.bsd = true 102 cfg.platforms.bsd = true
98elseif system == "Darwin" then 103elseif system == "Darwin" then
99 detected.unix = true 104 cfg.platforms.unix = true
100 detected.macosx = true 105 cfg.platforms.macosx = true
101 detected.bsd = true 106 cfg.platforms.bsd = true
102elseif system == "Linux" then 107elseif system == "Linux" then
103 detected.unix = true 108 cfg.platforms.unix = true
104 detected.linux = true 109 cfg.platforms.linux = true
105elseif system == "SunOS" then 110elseif system == "SunOS" then
106 detected.unix = true 111 cfg.platforms.unix = true
107 detected.solaris = true 112 cfg.platforms.solaris = true
108elseif system and system:match("^CYGWIN") then 113elseif system and system:match("^CYGWIN") then
109 detected.unix = true 114 cfg.platforms.unix = true
110 detected.cygwin = true 115 cfg.platforms.cygwin = true
116elseif system and system:match("^MSYS") then
117 cfg.platforms.unix = true
118 cfg.platforms.msys = true
119 cfg.platforms.cygwin = true
111elseif system and system:match("^Windows") then 120elseif system and system:match("^Windows") then
112 detected.windows = true 121 cfg.platforms.windows = true
122 cfg.platforms.win32 = true
113elseif system and system:match("^MINGW") then 123elseif system and system:match("^MINGW") then
114 detected.windows = true 124 cfg.platforms.windows = true
115 detected.mingw32 = true 125 cfg.platforms.mingw32 = true
126 cfg.platforms.win32 = true
127elseif system == "Haiku" then
128 cfg.platforms.unix = true
129 cfg.platforms.haiku = true
116else 130else
117 detected.unix = true 131 cfg.platforms.unix = true
118 -- Fall back to Unix in unknown systems. 132 -- Fall back to Unix in unknown systems.
119end 133end
120 134
121-- Path configuration: 135-- Set order for platform overrides
136local platform_order = {
137 -- Unixes
138 unix = 1,
139 bsd = 2,
140 solaris = 3,
141 netbsd = 4,
142 openbsd = 5,
143 freebsd = 6,
144 linux = 7,
145 macosx = 8,
146 cygwin = 9,
147 msys = 10,
148 haiku = 11,
149 -- Windows
150 win32 = 12,
151 mingw32 = 13,
152 windows = 14 }
122 153
154-- Path configuration:
123local sys_config_file, home_config_file 155local sys_config_file, home_config_file
156local sys_config_file_default, home_config_file_default
124local sys_config_dir, home_config_dir 157local sys_config_dir, home_config_dir
125local sys_config_ok, home_config_ok = false, false 158local sys_config_ok, home_config_ok = false, false
126local extra_luarocks_module_dir 159local extra_luarocks_module_dir
127sys_config_dir = site_config.LUAROCKS_SYSCONFDIR 160sys_config_dir = site_config.LUAROCKS_SYSCONFDIR or site_config.LUAROCKS_PREFIX
128if detected.windows then 161if cfg.platforms.windows then
129 cfg.home = os.getenv("APPDATA") or "c:" 162 cfg.home = os.getenv("APPDATA") or "c:"
130 sys_config_dir = sys_config_dir or "c:/luarocks" 163 sys_config_dir = sys_config_dir or "c:/luarocks"
131 home_config_dir = cfg.home.."/luarocks" 164 home_config_dir = cfg.home.."/luarocks"
@@ -134,55 +167,105 @@ else
134 cfg.home = os.getenv("HOME") or "" 167 cfg.home = os.getenv("HOME") or ""
135 sys_config_dir = sys_config_dir or "/etc/luarocks" 168 sys_config_dir = sys_config_dir or "/etc/luarocks"
136 home_config_dir = cfg.home.."/.luarocks" 169 home_config_dir = cfg.home.."/.luarocks"
137 cfg.home_tree = cfg.home.."/.luarocks/" 170 cfg.home_tree = (os.getenv("USER") ~= "root") and cfg.home.."/.luarocks/"
138end 171end
139 172
140cfg.variables = {} 173-- Create global environment for the config files;
141cfg.rocks_trees = {} 174local env_for_config_file = function()
175 local e
176 e = {
177 home = cfg.home,
178 lua_version = cfg.lua_version,
179 platforms = util.make_shallow_copy(cfg.platforms),
180 processor = cfg.target_cpu, -- remains for compat reasons
181 target_cpu = cfg.target_cpu, -- replaces `processor`
182 os_getenv = os.getenv,
183 dump_env = function()
184 -- debug function, calling it from a config file will show all
185 -- available globals to that config file
186 print(util.show_table(e, "global environment"))
187 end,
188 }
189 return e
190end
142 191
143sys_config_file = site_config.LUAROCKS_SYSCONFIG or sys_config_dir.."/config-"..cfg.lua_version..".lua" 192-- Merge values from config files read into the `cfg` table
144local err 193local merge_overrides = function(overrides)
145sys_config_ok, err = persist.load_into_table(sys_config_file, cfg) 194 -- remove some stuff we do not want to integrate
195 overrides.os_getenv = nil
196 overrides.dump_env = nil
197 -- remove tables to be copied verbatim instead of deeply merged
198 if overrides.rocks_trees then cfg.rocks_trees = nil end
199 if overrides.rocks_servers then cfg.rocks_servers = nil end
200 -- perform actual merge
201 util.deep_merge(cfg, overrides)
202end
146 203
147if not sys_config_ok then 204-- load config file from a list until first succesful one. Info is
148 sys_config_file = sys_config_dir.."/config.lua" 205-- added to `cfg` module table, returns filepath of succesfully loaded
149 sys_config_ok, err = persist.load_into_table(sys_config_file, cfg) 206-- file or nil if it failed
207local load_config_file = function(list)
208 for _, filepath in ipairs(list) do
209 local result, err, errcode = persist.load_into_table(filepath, env_for_config_file())
210 if (not result) and errcode ~= "open" then
211 -- errcode is either "load" or "run"; bad config file, so error out
212 io.stderr:write(err.."\n")
213 os.exit(cfg.errorcodes.CONFIGFILE)
214 end
215 if result then
216 -- succes in loading and running, merge contents and exit
217 merge_overrides(result)
218 return filepath
219 end
220 end
221 return nil -- nothing was loaded
150end 222end
151if err and sys_config_ok == nil then 223
152 io.stderr:write(err.."\n") 224
225-- Load system configuration file
226do
227 sys_config_file_default = sys_config_dir.."/config-"..cfg.lua_version..".lua"
228 sys_config_file = load_config_file({
229 site_config.LUAROCKS_SYSCONFIG or sys_config_file_default,
230 sys_config_dir.."/config.lua",
231 })
232 sys_config_ok = (sys_config_file ~= nil)
153end 233end
154 234
235-- Load user configuration file (if allowed)
155if not site_config.LUAROCKS_FORCE_CONFIG then 236if not site_config.LUAROCKS_FORCE_CONFIG then
156 local home_overrides, err 237
157 home_config_file = os.getenv("LUAROCKS_CONFIG_" .. version_suffix) or os.getenv("LUAROCKS_CONFIG") 238 home_config_file_default = home_config_dir.."/config-"..cfg.lua_version..".lua"
158 if home_config_file then 239
159 home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version }) 240 local config_env_var = "LUAROCKS_CONFIG_" .. version_suffix
160 else 241 local config_env_value = os.getenv(config_env_var)
161 home_config_file = home_config_dir.."/config-"..cfg.lua_version..".lua" 242 if not config_env_value then
162 home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version }) 243 config_env_var = "LUAROCKS_CONFIG"
163 if not home_overrides then 244 config_env_value = os.getenv(config_env_var)
164 home_config_file = home_config_dir.."/config.lua"
165 home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version })
166 end
167 end 245 end
168 if home_overrides then 246
169 home_config_ok = true 247 -- first try environment provided file, so we can explicitly warn when it is missing
170 local util = require("luarocks.util") 248 if config_env_value then
171 if home_overrides.rocks_trees then 249 local list = { config_env_value }
172 cfg.rocks_trees = nil 250 home_config_file = load_config_file(list)
173 end 251 home_config_ok = (home_config_file ~= nil)
174 if home_overrides.rocks_servers then 252 if not home_config_ok then
175 cfg.rocks_servers = nil 253 io.stderr:write("Warning: could not load configuration file `"..config_env_value.."` given in environment variable "..config_env_var.."\n")
176 end
177 util.deep_merge(cfg, home_overrides)
178 else -- nil or false
179 home_config_ok = home_overrides
180 if err and home_config_ok == nil then
181 io.stderr:write(err.."\n")
182 end 254 end
183 end 255 end
256
257 -- try the alternative defaults if there was no environment specified file or it didn't work
258 if not home_config_ok then
259 local list = {
260 home_config_file_default,
261 home_config_dir.."/config.lua",
262 }
263 home_config_file = load_config_file(list)
264 home_config_ok = (home_config_file ~= nil)
265 end
184end 266end
185 267
268
186if not next(cfg.rocks_trees) then 269if not next(cfg.rocks_trees) then
187 if cfg.home_tree then 270 if cfg.home_tree then
188 table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } ) 271 table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } )
@@ -192,17 +275,37 @@ if not next(cfg.rocks_trees) then
192 end 275 end
193end 276end
194 277
195-- Configure defaults:
196 278
197local root = cfg.rocks_trees[#cfg.rocks_trees] 279-- update platforms list; keyed -> array
280do
281 local lst = {} -- use temp array to not confuse `pairs` in loop
282 for plat in pairs(cfg.platforms) do
283 if cfg.platforms[plat] then -- entries set to 'false' skipped
284 if not platform_order[plat] then
285 local pl = ""
286 for k,_ in pairs(platform_order) do pl = pl .. ", " .. k end
287 io.stderr:write("Bad platform given; "..tostring(plat)..". Valid entries are: "..pl:sub(3,-1) ..".\n")
288 os.exit(cfg.errorcodes.CONFIGFILE)
289 end
290 table.insert(lst, plat)
291 else
292 cfg.platforms[plat] = nil
293 end
294 end
295 -- platform overrides depent on the order, so set priorities
296 table.sort(lst, function(key1, key2) return platform_order[key1] < platform_order[key2] end)
297 util.deep_merge(cfg.platforms, lst)
298end
299
300-- Configure defaults:
198local defaults = { 301local defaults = {
199 302
200 local_by_default = false, 303 local_by_default = false,
201 use_extensions = false,
202 accept_unknown_fields = false, 304 accept_unknown_fields = false,
203 fs_use_modules = true, 305 fs_use_modules = true,
204 hooks_enabled = true, 306 hooks_enabled = true,
205 deps_mode = "one", 307 deps_mode = "one",
308 check_certificates = false,
206 309
207 lua_modules_path = "/share/lua/"..cfg.lua_version, 310 lua_modules_path = "/share/lua/"..cfg.lua_version,
208 lib_modules_path = "/lib/lua/"..cfg.lua_version, 311 lib_modules_path = "/lib/lua/"..cfg.lua_version,
@@ -214,15 +317,17 @@ local defaults = {
214 317
215 rocks_servers = { 318 rocks_servers = {
216 { 319 {
217 "http://rocks.moonscript.org", 320 "https://luarocks.org",
218 "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/", 321 "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",
322 "http://luafr.org/moonrocks/",
323 "http://luarocks.logiceditor.com/rocks",
219 } 324 }
220 }, 325 },
221 disabled_servers = {}, 326 disabled_servers = {},
222 327
223 upload = { 328 upload = {
224 server = "rocks.moonscript.org", 329 server = "https://luarocks.org",
225 tool_version = "0.0.1", 330 tool_version = "1.0.0",
226 api_version = "1", 331 api_version = "1",
227 }, 332 },
228 333
@@ -259,7 +364,7 @@ local defaults = {
259 FIND = "find", 364 FIND = "find",
260 TEST = "test", 365 TEST = "test",
261 CHMOD = "chmod", 366 CHMOD = "chmod",
262 PATCH = "patch", 367 MKTEMP = "mktemp",
263 368
264 ZIP = "zip", 369 ZIP = "zip",
265 UNZIP = "unzip -n", 370 UNZIP = "unzip -n",
@@ -271,12 +376,15 @@ local defaults = {
271 OPENSSL = "openssl", 376 OPENSSL = "openssl",
272 MD5 = "md5", 377 MD5 = "md5",
273 STAT = "stat", 378 STAT = "stat",
379 TOUCH = "touch",
274 380
275 CMAKE = "cmake", 381 CMAKE = "cmake",
276 SEVENZ = "7z", 382 SEVENZ = "7z",
277 383
278 RSYNCFLAGS = "--exclude=.git -Oavz", 384 RSYNCFLAGS = "--exclude=.git -Oavz",
279 STATFLAG = "-c '%a'", 385 STATFLAG = "-c '%a'",
386 CURLNOCERTFLAG = "",
387 WGETNOCERTFLAG = "",
280 }, 388 },
281 389
282 external_deps_subdirs = site_config.LUAROCKS_EXTERNAL_DEPS_SUBDIRS or { 390 external_deps_subdirs = site_config.LUAROCKS_EXTERNAL_DEPS_SUBDIRS or {
@@ -293,14 +401,13 @@ local defaults = {
293 rocks_provided = {} 401 rocks_provided = {}
294} 402}
295 403
296if detected.windows then 404if cfg.platforms.windows then
297 local full_prefix = site_config.LUAROCKS_PREFIX.."\\"..cfg.major_version 405 local full_prefix = (site_config.LUAROCKS_PREFIX or (os.getenv("PROGRAMFILES")..[[\LuaRocks]]))
298 extra_luarocks_module_dir = full_prefix.."\\lua\\?.lua" 406 extra_luarocks_module_dir = full_prefix.."\\lua\\?.lua"
299 407
300 home_config_file = home_config_file and home_config_file:gsub("\\","/") 408 home_config_file = home_config_file and home_config_file:gsub("\\","/")
301 defaults.fs_use_modules = false 409 defaults.fs_use_modules = false
302 defaults.arch = "win32-"..proc 410 defaults.arch = "win32-"..cfg.target_cpu
303 defaults.platforms = {"win32", "windows" }
304 defaults.lib_extension = "dll" 411 defaults.lib_extension = "dll"
305 defaults.external_lib_extension = "dll" 412 defaults.external_lib_extension = "dll"
306 defaults.static_lib_extension = "lib" 413 defaults.static_lib_extension = "lib"
@@ -309,7 +416,7 @@ if detected.windows then
309 defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin" 416 defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin"
310 defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/include" 417 defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/include"
311 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/lib" 418 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/lib"
312 defaults.cmake_generator = "MinGW Makefiles" 419
313 defaults.makefile = "Makefile.win" 420 defaults.makefile = "Makefile.win"
314 defaults.variables.MAKE = "nmake" 421 defaults.variables.MAKE = "nmake"
315 defaults.variables.CC = "cl" 422 defaults.variables.CC = "cl"
@@ -319,8 +426,8 @@ if detected.windows then
319 defaults.variables.MT = "mt" 426 defaults.variables.MT = "mt"
320 defaults.variables.AR = "lib" 427 defaults.variables.AR = "lib"
321 defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib" 428 defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib"
322 defaults.variables.CFLAGS = "/MD /O2" 429 defaults.variables.CFLAGS = "/nologo /MD /O2"
323 defaults.variables.LIBFLAG = "/dll" 430 defaults.variables.LIBFLAG = "/nologo /dll"
324 431
325 local bins = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", 432 local bins = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM",
326 "MKDIR", "MV", "PWD", "RMDIR", "TEST", "UNAME", "WGET" } 433 "MKDIR", "MV", "PWD", "RMDIR", "TEST", "UNAME", "WGET" }
@@ -355,8 +462,7 @@ if detected.windows then
355 defaults.web_browser = "start" 462 defaults.web_browser = "start"
356end 463end
357 464
358if detected.mingw32 then 465if cfg.platforms.mingw32 then
359 defaults.platforms = { "win32", "mingw32", "windows" }
360 defaults.obj_extension = "o" 466 defaults.obj_extension = "o"
361 defaults.static_lib_extension = "a" 467 defaults.static_lib_extension = "a"
362 defaults.cmake_generator = "MinGW Makefiles" 468 defaults.cmake_generator = "MinGW Makefiles"
@@ -383,7 +489,7 @@ if detected.mingw32 then
383 489
384end 490end
385 491
386if detected.unix then 492if cfg.platforms.unix then
387 defaults.lib_extension = "so" 493 defaults.lib_extension = "so"
388 defaults.static_lib_extension = "a" 494 defaults.static_lib_extension = "a"
389 defaults.external_lib_extension = "so" 495 defaults.external_lib_extension = "so"
@@ -394,7 +500,6 @@ if detected.unix then
394 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib" 500 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib"
395 defaults.variables.CFLAGS = "-O2" 501 defaults.variables.CFLAGS = "-O2"
396 defaults.cmake_generator = "Unix Makefiles" 502 defaults.cmake_generator = "Unix Makefiles"
397 defaults.platforms = { "unix" }
398 defaults.variables.CC = "gcc" 503 defaults.variables.CC = "gcc"
399 defaults.variables.LD = "gcc" 504 defaults.variables.LD = "gcc"
400 defaults.gcc_rpath = true 505 defaults.gcc_rpath = true
@@ -421,63 +526,80 @@ if detected.unix then
421 defaults.web_browser = "xdg-open" 526 defaults.web_browser = "xdg-open"
422end 527end
423 528
424if detected.cygwin then 529if cfg.platforms.cygwin then
425 defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds 530 defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
426 defaults.arch = "cygwin-"..proc 531 defaults.arch = "cygwin-"..cfg.target_cpu
427 defaults.platforms = {"unix", "cygwin"}
428 defaults.cmake_generator = "Unix Makefiles" 532 defaults.cmake_generator = "Unix Makefiles"
429 defaults.variables.CC = "echo -llua | xargs gcc" 533 defaults.variables.CC = "echo -llua | xargs gcc"
430 defaults.variables.LD = "echo -llua | xargs gcc" 534 defaults.variables.LD = "echo -llua | xargs gcc"
431 defaults.variables.LIBFLAG = "-shared" 535 defaults.variables.LIBFLAG = "-shared"
432end 536end
433 537
434if detected.bsd then 538if cfg.platforms.msys then
539 -- msys is basically cygwin made out of mingw, meaning the subsytem is unixish
540 -- enough, yet we can freely mix with native win32
541 defaults.external_deps_patterns = {
542 bin = { "?.exe", "?.bat", "?" },
543 lib = { "lib?.so", "lib?.so.*", "lib?.dll.a", "?.dll.a",
544 "lib?.a", "lib?.dll", "?.dll", "?.lib" },
545 include = { "?.h" }
546 }
547 defaults.runtime_external_deps_patterns = {
548 bin = { "?.exe", "?.bat" },
549 lib = { "lib?.so", "?.dll", "lib?.dll" },
550 include = { "?.h" }
551 }
552end
553
554
555if cfg.platforms.bsd then
435 defaults.variables.MAKE = "gmake" 556 defaults.variables.MAKE = "gmake"
436 defaults.variables.STATFLAG = "-f '%OLp'" 557 defaults.variables.STATFLAG = "-f '%OLp'"
437end 558end
438 559
439if detected.macosx then 560if cfg.platforms.macosx then
440 defaults.variables.MAKE = "make" 561 defaults.variables.MAKE = "make"
441 defaults.external_lib_extension = "dylib" 562 defaults.external_lib_extension = "dylib"
442 defaults.arch = "macosx-"..proc 563 defaults.arch = "macosx-"..cfg.target_cpu
443 defaults.platforms = {"unix", "bsd", "macosx"}
444 defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load" 564 defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
565 defaults.variables.STAT = "/usr/bin/stat"
445 defaults.variables.STATFLAG = "-f '%A'" 566 defaults.variables.STATFLAG = "-f '%A'"
446 local version = io.popen("sw_vers -productVersion"):read("*l") 567 local version = io.popen("sw_vers -productVersion"):read("*l")
447 version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3 568 version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3
448 if version >= 5 then 569 if version >= 10 then
570 version = 8
571 elseif version >= 5 then
449 version = 5 572 version = 5
450 else 573 else
451 defaults.gcc_rpath = false 574 defaults.gcc_rpath = false
452 end 575 end
453 defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc" 576 defaults.variables.CC = "env MACOSX_DEPLOYMENT_TARGET=10."..version.." gcc"
454 defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc" 577 defaults.variables.LD = "env MACOSX_DEPLOYMENT_TARGET=10."..version.." gcc"
455 defaults.web_browser = "open" 578 defaults.web_browser = "open"
456end 579end
457 580
458if detected.linux then 581if cfg.platforms.linux then
459 defaults.arch = "linux-"..proc 582 defaults.arch = "linux-"..cfg.target_cpu
460 defaults.platforms = {"unix", "linux"}
461end 583end
462 584
463if detected.freebsd then 585if cfg.platforms.freebsd then
464 defaults.arch = "freebsd-"..proc 586 defaults.arch = "freebsd-"..cfg.target_cpu
465 defaults.platforms = {"unix", "bsd", "freebsd"} 587 defaults.gcc_rpath = false
588 defaults.variables.CC = "cc"
589 defaults.variables.LD = "cc"
466end 590end
467 591
468if detected.openbsd then 592if cfg.platforms.openbsd then
469 defaults.arch = "openbsd-"..proc 593 defaults.arch = "openbsd-"..cfg.target_cpu
470 defaults.platforms = {"unix", "bsd", "openbsd"}
471end 594end
472 595
473if detected.netbsd then 596if cfg.platforms.netbsd then
474 defaults.arch = "netbsd-"..proc 597 defaults.arch = "netbsd-"..cfg.target_cpu
475 defaults.platforms = {"unix", "bsd", "netbsd"}
476end 598end
477 599
478if detected.solaris then 600if cfg.platforms.solaris then
479 defaults.arch = "solaris-"..proc 601 defaults.arch = "solaris-"..cfg.target_cpu
480 defaults.platforms = {"unix", "solaris"} 602 --defaults.platforms = {"unix", "solaris"}
481 defaults.variables.MAKE = "gmake" 603 defaults.variables.MAKE = "gmake"
482end 604end
483 605
@@ -490,13 +612,11 @@ defaults.variables.LUA = site_config.LUA_DIR_SET and (defaults.variables.LUA_BIN
490-- Add built-in modules to rocks_provided 612-- Add built-in modules to rocks_provided
491defaults.rocks_provided["lua"] = cfg.lua_version.."-1" 613defaults.rocks_provided["lua"] = cfg.lua_version.."-1"
492 614
493if cfg.lua_version >= "5.2" then 615if bit32 then -- Lua 5.2+
494 -- Lua 5.2+
495 defaults.rocks_provided["bit32"] = cfg.lua_version.."-1" 616 defaults.rocks_provided["bit32"] = cfg.lua_version.."-1"
496end 617end
497 618
498if cfg.lua_version >= "5.3" then 619if utf8 then -- Lua 5.3+
499 -- Lua 5.3+
500 defaults.rocks_provided["utf8"] = cfg.lua_version.."-1" 620 defaults.rocks_provided["utf8"] = cfg.lua_version.."-1"
501end 621end
502 622
@@ -534,33 +654,73 @@ local cfg_mt = {
534} 654}
535setmetatable(cfg, cfg_mt) 655setmetatable(cfg, cfg_mt)
536 656
537function cfg.package_paths() 657if not cfg.check_certificates then
658 cfg.variables.CURLNOCERTFLAG = "-k"
659 cfg.variables.WGETNOCERTFLAG = "--no-check-certificate"
660end
661
662function cfg.make_paths_from_tree(tree)
663 local lua_path, lib_path, bin_path
664 if type(tree) == "string" then
665 lua_path = tree..cfg.lua_modules_path
666 lib_path = tree..cfg.lib_modules_path
667 bin_path = tree.."/bin"
668 else
669 lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path
670 lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path
671 bin_path = tree.bin_dir or tree.root.."/bin"
672 end
673 return lua_path, lib_path, bin_path
674end
675
676function cfg.package_paths(current)
538 local new_path, new_cpath, new_bin = {}, {}, {} 677 local new_path, new_cpath, new_bin = {}, {}, {}
678 local function add_tree_to_paths(tree)
679 local lua_path, lib_path, bin_path = cfg.make_paths_from_tree(tree)
680 table.insert(new_path, lua_path.."/?.lua")
681 table.insert(new_path, lua_path.."/?/init.lua")
682 table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension)
683 table.insert(new_bin, bin_path)
684 end
685 if current then
686 add_tree_to_paths(current)
687 end
539 for _,tree in ipairs(cfg.rocks_trees) do 688 for _,tree in ipairs(cfg.rocks_trees) do
540 if type(tree) == "string" then 689 add_tree_to_paths(tree)
541 table.insert(new_path, tree..cfg.lua_modules_path.."/?.lua")
542 table.insert(new_path, tree..cfg.lua_modules_path.."/?/init.lua")
543 table.insert(new_cpath, tree..cfg.lib_modules_path.."/?."..cfg.lib_extension)
544 table.insert(new_bin, tree.."/bin")
545 else
546 table.insert(new_path, (tree.lua_dir or tree.root..cfg.lua_modules_path).."/?.lua")
547 table.insert(new_path, (tree.lua_dir or tree.root..cfg.lua_modules_path).."/?/init.lua")
548 table.insert(new_cpath, (tree.lib_dir or tree.root..cfg.lib_modules_path).."/?."..cfg.lib_extension)
549 table.insert(new_bin, (tree.bin_dir or tree.root.."/bin"))
550 end
551 end 690 end
552 if extra_luarocks_module_dir then 691 if extra_luarocks_module_dir then
553 table.insert(new_path, extra_luarocks_module_dir) 692 table.insert(new_path, extra_luarocks_module_dir)
554 end 693 end
555 return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, ";") 694 return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
695end
696
697function cfg.init_package_paths()
698 local lr_path, lr_cpath, lr_bin = cfg.package_paths()
699 package.path = util.remove_path_dupes(package.path .. ";" .. lr_path, ";")
700 package.cpath = util.remove_path_dupes(package.cpath .. ";" .. lr_cpath, ";")
556end 701end
557 702
558function cfg.which_config() 703function cfg.which_config()
559 return sys_config_file, sys_config_ok, home_config_file, home_config_ok 704 local ret = {
705 system = {
706 file = sys_config_file or sys_config_file_default,
707 ok = sys_config_ok,
708 },
709 user = {
710 file = home_config_file or home_config_file_default,
711 ok = home_config_ok,
712 }
713 }
714 ret.nearest = (ret.user.ok and ret.user.file) or ret.system.file
715 return ret
560end 716end
561 717
562cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch 718cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
563 719
720cfg.http_proxy = os.getenv("http_proxy")
721cfg.https_proxy = os.getenv("https_proxy")
722cfg.no_proxy = os.getenv("no_proxy")
723
564--- Check if platform was detected 724--- Check if platform was detected
565-- @param query string: The platform name to check. 725-- @param query string: The platform name to check.
566-- @return boolean: true if LuaRocks is currently running on queried platform. 726-- @return boolean: true if LuaRocks is currently running on queried platform.
diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua
index cc2e1683..a016fc72 100644
--- a/src/luarocks/command_line.lua
+++ b/src/luarocks/command_line.lua
@@ -10,6 +10,7 @@ local cfg = require("luarocks.cfg")
10local path = require("luarocks.path") 10local path = require("luarocks.path")
11local dir = require("luarocks.dir") 11local dir = require("luarocks.dir")
12local deps = require("luarocks.deps") 12local deps = require("luarocks.deps")
13local fs = require("luarocks.fs")
13 14
14local program = util.this_program("luarocks") 15local program = util.this_program("luarocks")
15 16
@@ -21,7 +22,7 @@ local function die(message, exitcode)
21 22
22 local ok, err = pcall(util.run_scheduled_functions) 23 local ok, err = pcall(util.run_scheduled_functions)
23 if not ok then 24 if not ok then
24 util.printerr("\nLuaRocks "..cfg.program_version.." internal bug (please report at luarocks-developers@lists.sourceforge.net):\n"..err) 25 util.printerr("\nLuaRocks "..cfg.program_version.." internal bug (please report at https://github.com/keplerproject/luarocks/issues):\n"..err)
25 end 26 end
26 util.printerr("\nError: "..message) 27 util.printerr("\nError: "..message)
27 os.exit(exitcode or cfg.errorcodes.UNSPECIFIED) 28 os.exit(exitcode or cfg.errorcodes.UNSPECIFIED)
@@ -30,12 +31,17 @@ end
30local function replace_tree(flags, args, tree) 31local function replace_tree(flags, args, tree)
31 tree = dir.normalize(tree) 32 tree = dir.normalize(tree)
32 flags["tree"] = tree 33 flags["tree"] = tree
34 local added = false
33 for i = 1, #args do 35 for i = 1, #args do
34 if args[i]:match("%-%-tree=") then 36 if args[i]:match("%-%-tree=") then
35 args[i] = "--tree="..tree 37 args[i] = "--tree="..tree
38 added = true
36 break 39 break
37 end 40 end
38 end 41 end
42 if not added then
43 args[#args + 1] = "--tree="..tree
44 end
39 path.use_tree(tree) 45 path.use_tree(tree)
40end 46end
41 47
@@ -63,6 +69,9 @@ function command_line.run_command(...)
63 end 69 end
64 local nonflags = { util.parse_flags(unpack(args)) } 70 local nonflags = { util.parse_flags(unpack(args)) }
65 local flags = table.remove(nonflags, 1) 71 local flags = table.remove(nonflags, 1)
72 if flags.ERROR then
73 die(flags.ERROR.." See --help.")
74 end
66 75
67 if flags["from"] then flags["server"] = flags["from"] end 76 if flags["from"] then flags["server"] = flags["from"] end
68 if flags["only-from"] then flags["only-server"] = flags["only-from"] end 77 if flags["only-from"] then flags["only-server"] = flags["only-from"] end
@@ -79,7 +88,6 @@ function command_line.run_command(...)
79 88
80 if flags["verbose"] then -- setting it in the config file will kick-in earlier in the process 89 if flags["verbose"] then -- setting it in the config file will kick-in earlier in the process
81 cfg.verbose = true 90 cfg.verbose = true
82 local fs = require("luarocks.fs")
83 fs.verbose() 91 fs.verbose()
84 end 92 end
85 93
@@ -110,12 +118,6 @@ function command_line.run_command(...)
110 end 118 end
111 end 119 end
112 command = command:gsub("-", "_") 120 command = command:gsub("-", "_")
113
114 if flags["extensions"] then
115 cfg.use_extensions = true
116 local type_check = require("luarocks.type_check")
117 type_check.load_extensions()
118 end
119 121
120 if cfg.local_by_default then 122 if cfg.local_by_default then
121 flags["local"] = true 123 flags["local"] = true
@@ -126,16 +128,10 @@ function command_line.run_command(...)
126 end 128 end
127 129
128 if flags["branch"] then 130 if flags["branch"] then
129 if flags["branch"] == true or flags["branch"] == "" then
130 die("Argument error: use --branch=<branch-name>")
131 end
132 cfg.branch = flags["branch"] 131 cfg.branch = flags["branch"]
133 end 132 end
134 133
135 if flags["tree"] then 134 if flags["tree"] then
136 if flags["tree"] == true or flags["tree"] == "" then
137 die("Argument error: use --tree=<path>")
138 end
139 local named = false 135 local named = false
140 for _, tree in ipairs(cfg.rocks_trees) do 136 for _, tree in ipairs(cfg.rocks_trees) do
141 if type(tree) == "table" and flags["tree"] == tree.name then 137 if type(tree) == "table" and flags["tree"] == tree.name then
@@ -148,11 +144,15 @@ function command_line.run_command(...)
148 end 144 end
149 end 145 end
150 if not named then 146 if not named then
151 local fs = require("luarocks.fs")
152 local root_dir = fs.absolute_name(flags["tree"]) 147 local root_dir = fs.absolute_name(flags["tree"])
153 replace_tree(flags, args, root_dir) 148 replace_tree(flags, args, root_dir)
154 end 149 end
155 elseif flags["local"] then 150 elseif flags["local"] then
151 if not cfg.home_tree then
152 die("The --local flag is meant for operating in a user's home directory.\n"..
153 "You are running as a superuser, which is intended for system-wide operation.\n"..
154 "To force using the superuser's home, use --tree explicitly.")
155 end
156 replace_tree(flags, args, cfg.home_tree) 156 replace_tree(flags, args, cfg.home_tree)
157 else 157 else
158 local trees = cfg.rocks_trees 158 local trees = cfg.rocks_trees
@@ -173,17 +173,11 @@ function command_line.run_command(...)
173 cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir 173 cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
174 174
175 if flags["server"] then 175 if flags["server"] then
176 if flags["server"] == true then
177 die("Argument error: use --server=<url>")
178 end
179 local protocol, path = dir.split_url(flags["server"]) 176 local protocol, path = dir.split_url(flags["server"])
180 table.insert(cfg.rocks_servers, 1, protocol.."://"..path) 177 table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
181 end 178 end
182 179
183 if flags["only-server"] then 180 if flags["only-server"] then
184 if flags["only-server"] == true then
185 die("Argument error: use --only-server=<url>")
186 end
187 cfg.rocks_servers = { flags["only-server"] } 181 cfg.rocks_servers = { flags["only-server"] }
188 end 182 end
189 183
@@ -196,6 +190,10 @@ function command_line.run_command(...)
196 cfg.variables[k] = v 190 cfg.variables[k] = v
197 end 191 end
198 end 192 end
193
194 if not fs.current_dir() or fs.current_dir() == "" then
195 die("Current directory does not exist. Please run LuaRocks from an existing directory.")
196 end
199 197
200 if commands[command] then 198 if commands[command] then
201 -- TODO the interface of run should be modified, to receive the 199 -- TODO the interface of run should be modified, to receive the
@@ -207,8 +205,8 @@ function command_line.run_command(...)
207 local cmd = require(commands[command]) 205 local cmd = require(commands[command])
208 local xp, ok, err, exitcode = xpcall(function() return cmd.run(unpack(args)) end, function(err) 206 local xp, ok, err, exitcode = xpcall(function() return cmd.run(unpack(args)) end, function(err)
209 die(debug.traceback("LuaRocks "..cfg.program_version 207 die(debug.traceback("LuaRocks "..cfg.program_version
210 .." bug (please report at luarocks-developers@lists.sourceforge.net).\n" 208 .." bug (please report at https://github.com/keplerproject/luarocks/issues).\n"
211 ..err, 2)) 209 ..err, 2), cfg.errorcodes.CRASH)
212 end) 210 end)
213 if xp and (not ok) then 211 if xp and (not ok) then
214 die(err, exitcode) 212 die(err, exitcode)
diff --git a/src/luarocks/config_cmd.lua b/src/luarocks/config_cmd.lua
new file mode 100644
index 00000000..bf282a7a
--- /dev/null
+++ b/src/luarocks/config_cmd.lua
@@ -0,0 +1,73 @@
1--- Module implementing the LuaRocks "config" command.
2-- Queries information about the LuaRocks configuration.
3local config_cmd = {}
4
5local cfg = require("luarocks.cfg")
6local util = require("luarocks.util")
7local dir = require("luarocks.dir")
8
9config_cmd.help_summary = "Query information about the LuaRocks configuration."
10config_cmd.help_arguments = "<flag>"
11config_cmd.help = [[
12--lua-incdir Path to Lua header files.
13
14--lua-libdir Path to Lua library files.
15
16--lua-ver Lua version (in major.minor format). e.g. 5.1
17
18--system-config Location of the system config file.
19
20--user-config Location of the user config file.
21
22--rock-trees Rocks trees in use. First the user tree, then the system tree.
23]]
24
25local function config_file(conf)
26 print(dir.normalize(conf.file))
27 if conf.ok then
28 return true
29 else
30 return nil, "file not found"
31 end
32end
33
34--- Driver function for "config" command.
35-- @return boolean: True if succeeded, nil on errors.
36function config_cmd.run(...)
37 local flags = util.parse_flags(...)
38
39 if flags["lua-incdir"] then
40 print(cfg.variables.LUA_INCDIR)
41 return true
42 end
43 if flags["lua-libdir"] then
44 print(cfg.variables.LUA_LIBDIR)
45 return true
46 end
47 if flags["lua-ver"] then
48 print(cfg.lua_version)
49 return true
50 end
51 local conf = cfg.which_config()
52 if flags["system-config"] then
53 return config_file(conf.system)
54 end
55 if flags["user-config"] then
56 return config_file(conf.user)
57 end
58 if flags["rock-trees"] then
59 for _, tree in ipairs(cfg.rocks_trees) do
60 if type(tree) == "string" then
61 util.printout(dir.normalize(tree))
62 else
63 local name = tree.name and "\t"..tree.name or ""
64 util.printout(dir.normalize(tree.root)..name)
65 end
66 end
67 return true
68 end
69
70 return nil, "Please provide a flag for querying configuration values. "..util.see_help("config")
71end
72
73return config_cmd
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index 3f75f9be..812e6d18 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -247,12 +247,16 @@ end
247function deps.show_dep(dep, internal) 247function deps.show_dep(dep, internal)
248 assert(type(dep) == "table") 248 assert(type(dep) == "table")
249 assert(type(internal) == "boolean" or not internal) 249 assert(type(internal) == "boolean" or not internal)
250 250
251 local pretty = {} 251 if #dep.constraints > 0 then
252 for _, c in ipairs(dep.constraints) do 252 local pretty = {}
253 table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal)) 253 for _, c in ipairs(dep.constraints) do
254 table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal))
255 end
256 return dep.name.." "..table.concat(pretty, ", ")
257 else
258 return dep.name
254 end 259 end
255 return dep.name.." "..table.concat(pretty, ", ")
256end 260end
257 261
258--- A more lenient check for equivalence between versions. 262--- A more lenient check for equivalence between versions.
@@ -480,13 +484,13 @@ function deps.fulfill_dependencies(rockspec, deps_mode)
480 for _, dep in pairs(missing) do 484 for _, dep in pairs(missing) do
481 -- Double-check in case dependency was filled during recursion. 485 -- Double-check in case dependency was filled during recursion.
482 if not match_dep(dep, nil, deps_mode) then 486 if not match_dep(dep, nil, deps_mode) then
483 local rock = search.find_suitable_rock(dep) 487 local url, err = search.find_suitable_rock(dep)
484 if not rock then 488 if not url then
485 return nil, "Could not satisfy dependency: "..deps.show_dep(dep) 489 return nil, "Could not satisfy dependency "..deps.show_dep(dep)..": "..err
486 end 490 end
487 local ok, err, errcode = install.run(rock) 491 local ok, err, errcode = install.run(url, deps.deps_mode_to_flag(deps_mode))
488 if not ok then 492 if not ok then
489 return nil, "Failed installing dependency: "..rock.." - "..err, errcode 493 return nil, "Failed installing dependency: "..url.." - "..err, errcode
490 end 494 end
491 end 495 end
492 end 496 end
@@ -545,10 +549,11 @@ function deps.check_external_deps(rockspec, mode)
545 subdirs = cfg.runtime_external_deps_subdirs 549 subdirs = cfg.runtime_external_deps_subdirs
546 end 550 end
547 if rockspec.external_dependencies then 551 if rockspec.external_dependencies then
548 for name, files in pairs(rockspec.external_dependencies) do 552 for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do
549 local ok = true 553 local ok = true
550 local failed_file = nil 554 local failed_files = {program = {}, header = {}, library = {}}
551 local failed_dirname = nil 555 local failed_dirname
556 local failed_testfile
552 for _, extdir in ipairs(cfg.external_deps_dirs) do 557 for _, extdir in ipairs(cfg.external_deps_dirs) do
553 ok = true 558 ok = true
554 local prefix = vars[name.."_DIR"] 559 local prefix = vars[name.."_DIR"]
@@ -577,7 +582,7 @@ function deps.check_external_deps(rockspec, mode)
577 end 582 end
578 prefix = prefix.prefix 583 prefix = prefix.prefix
579 end 584 end
580 for dirname, dirdata in pairs(dirs) do 585 for dirname, dirdata in util.sortedpairs(dirs) do
581 local paths 586 local paths
582 local path_var_value = vars[name.."_"..dirname] 587 local path_var_value = vars[name.."_"..dirname]
583 if path_var_value then 588 if path_var_value then
@@ -591,7 +596,7 @@ function deps.check_external_deps(rockspec, mode)
591 paths = { dir.path(prefix, dirdata.subdir) } 596 paths = { dir.path(prefix, dirdata.subdir) }
592 end 597 end
593 dirdata.dir = paths[1] 598 dirdata.dir = paths[1]
594 local file = files[dirdata.testfile] 599 local file = ext_files[dirdata.testfile]
595 if file then 600 if file then
596 local files = {} 601 local files = {}
597 if not file:match("%.") then 602 if not file:match("%.") then
@@ -606,17 +611,23 @@ function deps.check_external_deps(rockspec, mode)
606 table.insert(files, file) 611 table.insert(files, file)
607 end 612 end
608 local found = false 613 local found = false
609 failed_file = nil 614 for _, f in ipairs(files) do
610 for _, f in pairs(files) do 615
611 -- small convenience hack 616 -- small convenience hack
612 if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then 617 if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
613 f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) 618 f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
614 end 619 end
620
621 local pattern
622 if f:match("%*") then
623 pattern = f:gsub("%.", "%%."):gsub("%*", ".*")
624 f = "matching "..f
625 end
626
615 for _, d in ipairs(paths) do 627 for _, d in ipairs(paths) do
616 if f:match("%*") then 628 if pattern then
617 local replaced = f:gsub("%.", "%%."):gsub("%*", ".*")
618 for entry in fs.dir(d) do 629 for entry in fs.dir(d) do
619 if entry:match(replaced) then 630 if entry:match(pattern) then
620 found = true 631 found = true
621 break 632 break
622 end 633 end
@@ -627,21 +638,18 @@ function deps.check_external_deps(rockspec, mode)
627 if found then 638 if found then
628 dirdata.dir = d 639 dirdata.dir = d
629 break 640 break
641 else
642 table.insert(failed_files[dirdata.testfile], f.." in "..d)
630 end 643 end
631 end 644 end
632 if found then 645 if found then
633 break 646 break
634 else
635 if failed_file then
636 failed_file = failed_file .. ", or " .. f
637 else
638 failed_file = f
639 end
640 end 647 end
641 end 648 end
642 if not found then 649 if not found then
643 ok = false 650 ok = false
644 failed_dirname = dirname 651 failed_dirname = dirname
652 failed_testfile = dirdata.testfile
645 break 653 break
646 end 654 end
647 end 655 end
@@ -655,7 +663,20 @@ function deps.check_external_deps(rockspec, mode)
655 end 663 end
656 end 664 end
657 if not ok then 665 if not ok then
658 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" 666 local lines = {"Could not find "..failed_testfile.." file for "..name}
667
668 local failed_paths = {}
669 for _, failed_file in ipairs(failed_files[failed_testfile]) do
670 if not failed_paths[failed_file] then
671 failed_paths[failed_file] = true
672 table.insert(lines, " No file "..failed_file)
673 end
674 end
675
676 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.")
677 table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local")
678
679 return nil, table.concat(lines, "\n"), "dependency"
659 end 680 end
660 end 681 end
661 end 682 end
diff --git a/src/luarocks/doc.lua b/src/luarocks/doc.lua
index 6dee1069..53ed0116 100644
--- a/src/luarocks/doc.lua
+++ b/src/luarocks/doc.lua
@@ -13,7 +13,7 @@ local fetch = require("luarocks.fetch")
13local fs = require("luarocks.fs") 13local fs = require("luarocks.fs")
14local download = require("luarocks.download") 14local download = require("luarocks.download")
15 15
16doc.help_summary = "Shows documentation for an installed rock." 16doc.help_summary = "Show documentation for an installed rock."
17 17
18doc.help = [[ 18doc.help = [[
19<argument> is an existing package name. 19<argument> is an existing package name.
@@ -21,7 +21,7 @@ Without any flags, tries to load the documentation
21using a series of heuristics. 21using a series of heuristics.
22With these flags, return only the desired information: 22With these flags, return only the desired information:
23 23
24--homepage Open the home page of project. 24--home Open the home page of project.
25--list List documentation files only. 25--list List documentation files only.
26 26
27For more information about a rock, see the 'show' command. 27For more information about a rock, see the 'show' command.
@@ -75,7 +75,7 @@ function doc.run(...)
75 if not rockspec then return nil,err end 75 if not rockspec then return nil,err end
76 local descript = rockspec.description or {} 76 local descript = rockspec.description or {}
77 77
78 if flags["homepage"] then 78 if flags["home"] then
79 return show_homepage(descript.homepage, name, version) 79 return show_homepage(descript.homepage, name, version)
80 end 80 end
81 81
diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua
index 74ed40e9..090f49aa 100644
--- a/src/luarocks/download.lua
+++ b/src/luarocks/download.lua
@@ -37,25 +37,23 @@ local function get_file(filename)
37end 37end
38 38
39function download.download(arch, name, version, all) 39function download.download(arch, name, version, all)
40 local results, err
41 local query = search.make_query(name, version) 40 local query = search.make_query(name, version)
42 if arch then query.arch = arch end 41 if arch then query.arch = arch end
42 local search_err
43
43 if all then 44 if all then
44 if name == "" then query.exact_name = false end 45 if name == "" then query.exact_name = false end
45 results = search.search_repos(query) 46 local results = search.search_repos(query)
46 else 47 local has_result = false
47 results, err = search.find_suitable_rock(query) 48 local all_ok = true
48 end 49 local any_err = ""
49 if type(results) == "string" then 50 for name, result in pairs(results) do
50 return get_file(results) 51 for version, items in pairs(result) do
51 elseif type(results) == "table" and next(results) then 52 for _, item in ipairs(items) do
52 if all then 53 -- Ignore provided rocks.
53 local all_ok = true 54 if item.arch ~= "installed" then
54 local any_err = "" 55 has_result = true
55 for name, result in pairs(results) do 56 local filename = path.make_url(item.repo, name, version, item.arch)
56 for version, versions in pairs(result) do
57 for _,items in pairs(versions) do
58 local filename = path.make_url(items.repo, name, version, items.arch)
59 local ok, err = get_file(filename) 57 local ok, err = get_file(filename)
60 if not ok then 58 if not ok then
61 all_ok = false 59 all_ok = false
@@ -64,15 +62,20 @@ function download.download(arch, name, version, all)
64 end 62 end
65 end 63 end
66 end 64 end
65 end
66
67 if has_result then
67 return all_ok, any_err 68 return all_ok, any_err
68 else 69 end
69 util.printerr("Multiple search results were returned.") 70 else
70 util.title("Search results:") 71 local url
71 search.print_results(results) 72 url, search_err = search.find_suitable_rock(query)
72 return nil, "Please narrow your query or use --all." 73 if url then
74 return get_file(url)
73 end 75 end
74 end 76 end
75 return nil, "Could not find a result named "..name..(version and " "..version or "").."." 77 return nil, "Could not find a result named "..name..(version and " "..version or "")..
78 (search_err and ": "..search_err or ".")
76end 79end
77 80
78--- Driver function for the "download" command. 81--- Driver function for the "download" command.
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua
index 1d84b480..2c028771 100644
--- a/src/luarocks/fetch.lua
+++ b/src/luarocks/fetch.lua
@@ -37,11 +37,11 @@ function fetch.fetch_url(url, filename, cache)
37 if protocol == "file" then 37 if protocol == "file" then
38 return fs.absolute_name(pathname) 38 return fs.absolute_name(pathname)
39 elseif fetch.is_basic_protocol(protocol, true) then 39 elseif fetch.is_basic_protocol(protocol, true) then
40 local ok, filename = fs.download(url, filename, cache) 40 local ok, name = fs.download(url, filename, cache)
41 if not ok then 41 if not ok then
42 return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network" 42 return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network"
43 end 43 end
44 return filename 44 return name
45 else 45 else
46 return nil, "Unsupported protocol "..protocol 46 return nil, "Unsupported protocol "..protocol
47 end 47 end
@@ -111,9 +111,15 @@ function fetch.find_base_dir(file, temp_dir, src_url, src_dir)
111 else 111 else
112 util.printerr("Directory "..inferred_dir.." not found") 112 util.printerr("Directory "..inferred_dir.." not found")
113 local files = fs.list_dir() 113 local files = fs.list_dir()
114 if files[1] and fs.is_dir(files[1]) then 114 if files then
115 util.printerr("Found "..files[1]) 115 table.sort(files)
116 found_dir = files[1] 116 for i,filename in ipairs(files) do
117 if fs.is_dir(filename) then
118 util.printerr("Found "..filename)
119 found_dir = filename
120 break
121 end
122 end
117 end 123 end
118 end 124 end
119 fs.pop_dir() 125 fs.pop_dir()
@@ -164,8 +170,13 @@ function fetch.fetch_and_unpack_rock(rock_file, dest)
164end 170end
165 171
166function fetch.url_to_base_dir(url) 172function fetch.url_to_base_dir(url)
173 -- for extensions like foo.tar.gz, "gz" is stripped first
174 local known_exts = {}
175 for _, ext in ipairs{"zip", "git", "tgz", "tar", "gz", "bz2"} do
176 known_exts[ext] = ""
177 end
167 local base = dir.base_name(url) 178 local base = dir.base_name(url)
168 return base:gsub("%.[^.]*$", ""):gsub("%.tar$", "") 179 return (base:gsub("%.([^.]*)$", known_exts):gsub("%.tar", ""))
169end 180end
170 181
171--- Back-end function that actually loads the local rockspec. 182--- Back-end function that actually loads the local rockspec.
@@ -187,9 +198,8 @@ function fetch.load_local_rockspec(filename, quick)
187 end 198 end
188 local globals = err 199 local globals = err
189 200
190 local ok, err = true, nil
191 if not quick then 201 if not quick then
192 ok, err = type_check.type_check_rockspec(rockspec, globals) 202 local ok, err = type_check.type_check_rockspec(rockspec, globals)
193 if not ok then 203 if not ok then
194 return nil, filename..": "..err 204 return nil, filename..": "..err
195 end 205 end
@@ -313,9 +323,10 @@ function fetch.get_sources(rockspec, extract, dest_dir)
313 local url = rockspec.source.url 323 local url = rockspec.source.url
314 local name = rockspec.name.."-"..rockspec.version 324 local name = rockspec.name.."-"..rockspec.version
315 local filename = rockspec.source.file 325 local filename = rockspec.source.file
316 local source_file, store_dir, err, errcode 326 local source_file, store_dir
327 local ok, err, errcode
317 if dest_dir then 328 if dest_dir then
318 local ok, err = fs.change_dir(dest_dir) 329 ok, err = fs.change_dir(dest_dir)
319 if not ok then return nil, err, "dest_dir" end 330 if not ok then return nil, err, "dest_dir" end
320 source_file, err, errcode = fetch.fetch_url(url, filename) 331 source_file, err, errcode = fetch.fetch_url(url, filename)
321 fs.pop_dir() 332 fs.pop_dir()
@@ -360,7 +371,7 @@ function fetch.fetch_sources(rockspec, extract, dest_dir)
360 local protocol = rockspec.source.protocol 371 local protocol = rockspec.source.protocol
361 local ok, proto 372 local ok, proto
362 if fetch.is_basic_protocol(protocol) then 373 if fetch.is_basic_protocol(protocol) then
363 proto = require("luarocks.fetch") 374 proto = fetch
364 else 375 else
365 ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_")) 376 ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_"))
366 if not ok then 377 if not ok then
diff --git a/src/luarocks/fetch/cvs.lua b/src/luarocks/fetch/cvs.lua
index cc9fd655..ccf928c4 100644
--- a/src/luarocks/fetch/cvs.lua
+++ b/src/luarocks/fetch/cvs.lua
@@ -20,9 +20,15 @@ function cvs.get_sources(rockspec, extract, dest_dir)
20 assert(type(rockspec) == "table") 20 assert(type(rockspec) == "table")
21 assert(type(dest_dir) == "string" or not dest_dir) 21 assert(type(dest_dir) == "string" or not dest_dir)
22 22
23 local cvs_cmd = rockspec.variables.CVS
24 local ok, err_msg = fs.is_tool_available(cvs_cmd, "CVS")
25 if not ok then
26 return nil, err_msg
27 end
28
23 local name_version = rockspec.name .. "-" .. rockspec.version 29 local name_version = rockspec.name .. "-" .. rockspec.version
24 local module = rockspec.source.module or dir.base_name(rockspec.source.url) 30 local module = rockspec.source.module or dir.base_name(rockspec.source.url)
25 local command = {rockspec.variables.CVS, "-d"..rockspec.source.pathname, "export", module} 31 local command = {cvs_cmd, "-d"..rockspec.source.pathname, "export", module}
26 if rockspec.source.tag then 32 if rockspec.source.tag then
27 table.insert(command, 4, "-r") 33 table.insert(command, 4, "-r")
28 table.insert(command, 5, rockspec.source.tag) 34 table.insert(command, 5, rockspec.source.tag)
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua
index 53fd4445..a635f190 100644
--- a/src/luarocks/fetch/git.lua
+++ b/src/luarocks/fetch/git.lua
@@ -40,6 +40,11 @@ function git.get_sources(rockspec, extract, dest_dir, depth)
40 -- Strip off .git from base name if present 40 -- Strip off .git from base name if present
41 module = module:gsub("%.git$", "") 41 module = module:gsub("%.git$", "")
42 42
43 local ok, err_msg = fs.is_tool_available(git_cmd, "Git")
44 if not ok then
45 return nil, err_msg
46 end
47
43 local store_dir 48 local store_dir
44 if not dest_dir then 49 if not dest_dir then
45 store_dir = fs.make_temp_dir(name_version) 50 store_dir = fs.make_temp_dir(name_version)
@@ -63,7 +68,7 @@ function git.get_sources(rockspec, extract, dest_dir, depth)
63 if git_can_clone_by_tag(git_cmd) then 68 if git_can_clone_by_tag(git_cmd) then
64 -- The argument to `--branch` can actually be a branch or a tag as of 69 -- The argument to `--branch` can actually be a branch or a tag as of
65 -- Git 1.7.10. 70 -- Git 1.7.10.
66 table.insert(command, 4, "--branch=" .. tag_or_branch) 71 table.insert(command, 3, "--branch=" .. tag_or_branch)
67 end 72 end
68 end 73 end
69 if not fs.execute(unpack(command)) then 74 if not fs.execute(unpack(command)) then
diff --git a/src/luarocks/fetch/git_https.lua b/src/luarocks/fetch/git_https.lua
new file mode 100644
index 00000000..67f8ad6c
--- /dev/null
+++ b/src/luarocks/fetch/git_https.lua
@@ -0,0 +1,7 @@
1--- Fetch back-end for retrieving sources from Git repositories
2-- that use https:// transport. For example, for fetching a repository
3-- that requires the following command line:
4-- `git clone https://example.com/foo.git`
5-- you can use this in the rockspec:
6-- source = { url = "git+https://example.com/foo.git" }
7return require "luarocks.fetch.git_http"
diff --git a/src/luarocks/fetch/git_ssh.lua b/src/luarocks/fetch/git_ssh.lua
new file mode 100644
index 00000000..0c2c0750
--- /dev/null
+++ b/src/luarocks/fetch/git_ssh.lua
@@ -0,0 +1,32 @@
1--- Fetch back-end for retrieving sources from Git repositories
2-- that use ssh:// transport. For example, for fetching a repository
3-- that requires the following command line:
4-- `git clone ssh://git@example.com/path/foo.git
5-- you can use this in the rockspec:
6-- source = { url = "git+ssh://git@example.com/path/foo.git" }
7-- It also handles scp-style ssh urls: git@example.com:path/foo.git,
8-- but you have to prepend the "git+ssh://" and why not use the "newer"
9-- style anyway?
10local git_ssh = {}
11
12local git = require("luarocks.fetch.git")
13
14--- Fetch sources for building a rock from a local Git repository.
15-- @param rockspec table: The rockspec table
16-- @param extract boolean: Unused in this module (required for API purposes.)
17-- @param dest_dir string or nil: If set, will extract to the given directory.
18-- @return (string, string) or (nil, string): The absolute pathname of
19-- the fetched source tarball and the temporary directory created to
20-- store it; or nil and an error message.
21function git_ssh.get_sources(rockspec, extract, dest_dir)
22 rockspec.source.url = rockspec.source.url:gsub("^git.", "")
23
24 -- Handle old-style scp-like git ssh urls
25 if rockspec.source.url:match("^ssh://[^/]+:[^%d]") then
26 rockspec.source.url = rockspec.source.url:gsub("^ssh://", "")
27 end
28
29 return git.get_sources(rockspec, extract, dest_dir, "--")
30end
31
32return git_ssh
diff --git a/src/luarocks/fetch/hg.lua b/src/luarocks/fetch/hg.lua
index b2ba56e9..518130b4 100644
--- a/src/luarocks/fetch/hg.lua
+++ b/src/luarocks/fetch/hg.lua
@@ -21,16 +21,21 @@ function hg.get_sources(rockspec, extract, dest_dir)
21 assert(type(dest_dir) == "string" or not dest_dir) 21 assert(type(dest_dir) == "string" or not dest_dir)
22 22
23 local hg_cmd = rockspec.variables.HG 23 local hg_cmd = rockspec.variables.HG
24 local ok, err_msg = fs.is_tool_available(hg_cmd, "Mercurial")
25 if not ok then
26 return nil, err_msg
27 end
28
24 local name_version = rockspec.name .. "-" .. rockspec.version 29 local name_version = rockspec.name .. "-" .. rockspec.version
25 -- Strip off special hg:// protocol type 30 -- Strip off special hg:// protocol type
26 local url = rockspec.source.url:gsub("^hg://", "") 31 local url = rockspec.source.url:gsub("^hg://", "")
27 32
28 local module = dir.base_name(url) 33 local module = dir.base_name(url)
29 34
30 local command = {hg_cmd, "clone", url, module} 35 local command = {hg_cmd, "clone", url, module}
31 local tag_or_branch = rockspec.source.tag or rockspec.source.branch 36 local tag_or_branch = rockspec.source.tag or rockspec.source.branch
32 if tag_or_branch then 37 if tag_or_branch then
33 command = {hg_cmd, "clone", "--rev", url, module} 38 command = {hg_cmd, "clone", "--rev", tag_or_branch, url, module}
34 end 39 end
35 local store_dir 40 local store_dir
36 if not dest_dir then 41 if not dest_dir then
diff --git a/src/luarocks/fetch/hg_http.lua b/src/luarocks/fetch/hg_http.lua
new file mode 100644
index 00000000..8f506daf
--- /dev/null
+++ b/src/luarocks/fetch/hg_http.lua
@@ -0,0 +1,24 @@
1
2--- Fetch back-end for retrieving sources from hg repositories
3-- that use http:// transport. For example, for fetching a repository
4-- that requires the following command line:
5-- `hg clone http://example.com/foo`
6-- you can use this in the rockspec:
7-- source = { url = "hg+http://example.com/foo" }
8local hg_http = {}
9
10local hg = require("luarocks.fetch.hg")
11
12--- Download sources for building a rock, using hg over http.
13-- @param rockspec table: The rockspec table
14-- @param extract boolean: Unused in this module (required for API purposes.)
15-- @param dest_dir string or nil: If set, will extract to the given directory.
16-- @return (string, string) or (nil, string): The absolute pathname of
17-- the fetched source tarball and the temporary directory created to
18-- store it; or nil and an error message.
19function hg_http.get_sources(rockspec, extract, dest_dir)
20 rockspec.source.url = rockspec.source.url:gsub("^hg.", "")
21 return hg.get_sources(rockspec, extract, dest_dir)
22end
23
24return hg_http
diff --git a/src/luarocks/fetch/hg_https.lua b/src/luarocks/fetch/hg_https.lua
new file mode 100644
index 00000000..e67417fe
--- /dev/null
+++ b/src/luarocks/fetch/hg_https.lua
@@ -0,0 +1,8 @@
1
2--- Fetch back-end for retrieving sources from hg repositories
3-- that use https:// transport. For example, for fetching a repository
4-- that requires the following command line:
5-- `hg clone https://example.com/foo`
6-- you can use this in the rockspec:
7-- source = { url = "hg+https://example.com/foo" }
8return require "luarocks.fetch.hg_http"
diff --git a/src/luarocks/fetch/hg_ssh.lua b/src/luarocks/fetch/hg_ssh.lua
new file mode 100644
index 00000000..0c365fab
--- /dev/null
+++ b/src/luarocks/fetch/hg_ssh.lua
@@ -0,0 +1,8 @@
1
2--- Fetch back-end for retrieving sources from hg repositories
3-- that use ssh:// transport. For example, for fetching a repository
4-- that requires the following command line:
5-- `hg clone ssh://example.com/foo`
6-- you can use this in the rockspec:
7-- source = { url = "hg+ssh://example.com/foo" }
8return require "luarocks.fetch.hg_http"
diff --git a/src/luarocks/fetch/svn.lua b/src/luarocks/fetch/svn.lua
index abeacf9a..755e5e32 100644
--- a/src/luarocks/fetch/svn.lua
+++ b/src/luarocks/fetch/svn.lua
@@ -21,6 +21,11 @@ function svn.get_sources(rockspec, extract, dest_dir)
21 assert(type(dest_dir) == "string" or not dest_dir) 21 assert(type(dest_dir) == "string" or not dest_dir)
22 22
23 local svn_cmd = rockspec.variables.SVN 23 local svn_cmd = rockspec.variables.SVN
24 local ok, err_msg = fs.is_tool_available(svn_cmd, "--version", "Subversion")
25 if not ok then
26 return nil, err_msg
27 end
28
24 local name_version = rockspec.name .. "-" .. rockspec.version 29 local name_version = rockspec.name .. "-" .. rockspec.version
25 local module = rockspec.source.module or dir.base_name(rockspec.source.url) 30 local module = rockspec.source.module or dir.base_name(rockspec.source.url)
26 local url = rockspec.source.url:gsub("^svn://", "") 31 local url = rockspec.source.url:gsub("^svn://", "")
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua
index 72e11c09..57302c7f 100644
--- a/src/luarocks/fs.lua
+++ b/src/luarocks/fs.lua
@@ -31,7 +31,8 @@ fs.verbose = function() -- patch io.popen and os.execute to display commands
31 31
32 old_exec = os.execute 32 old_exec = os.execute
33 os.execute = function(cmd) 33 os.execute = function(cmd)
34 print("\nos.execute: ", cmd) 34 -- redact api keys if present
35 print("\nos.execute: ", (cmd:gsub("(/api/[^/]+/)([^/]+)/", function(cap, key) return cap.."<redacted>/" end)) )
35 local code = pack(old_exec(cmd)) 36 local code = pack(old_exec(cmd))
36 print("Results: "..tostring(code.n)) 37 print("Results: "..tostring(code.n))
37 for i = 1,code.n do 38 for i = 1,code.n do
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index f18deac3..483b3e3c 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -28,8 +28,6 @@ local patch = require("luarocks.tools.patch")
28 28
29local dir_stack = {} 29local dir_stack = {}
30 30
31math.randomseed(os.time())
32
33local dir_separator = "/" 31local dir_separator = "/"
34 32
35--- Quote argument for shell processing. 33--- Quote argument for shell processing.
@@ -67,23 +65,6 @@ function fs_lua.is_writable(file)
67 return result 65 return result
68end 66end
69 67
70--- Create a temporary directory.
71-- @param name string: name pattern to use for avoiding conflicts
72-- when creating temporary directory.
73-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
74function fs_lua.make_temp_dir(name)
75 assert(type(name) == "string")
76 name = dir.normalize(name)
77
78 local temp_dir = (os.getenv("TMP") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000))
79 local ok, err = fs.make_dir(temp_dir)
80 if ok then
81 return temp_dir
82 else
83 return nil, err
84 end
85end
86
87local function quote_args(command, ...) 68local function quote_args(command, ...)
88 local out = { command } 69 local out = { command }
89 for _, arg in ipairs({...}) do 70 for _, arg in ipairs({...}) do
@@ -122,6 +103,27 @@ function fs_lua.execute_quiet(command, ...)
122 end 103 end
123end 104end
124 105
106--- Checks if the given tool is available.
107-- The tool is executed using a flag, usually just to ask its version.
108-- @param tool_cmd string: The command to be used to check the tool's presence (e.g. hg in case of Mercurial)
109-- @param tool_name string: The actual name of the tool (e.g. Mercurial)
110-- @param arg string: The flag to pass to the tool. '--version' by default.
111function fs_lua.is_tool_available(tool_cmd, tool_name, arg)
112 assert(type(tool_cmd) == "string")
113 assert(type(tool_name) == "string")
114
115 arg = arg or "--version"
116 assert(type(arg) == "string")
117
118 if not fs.execute_quiet(fs.Q(tool_cmd), arg) then
119 local msg = "'%s' program not found. Make sure %s is installed and is available in your PATH " ..
120 "(or you may want to edit the 'variables.%s' value in file '%s')"
121 return nil, msg:format(tool_cmd, tool_name, tool_name:upper(), cfg.which_config().nearest)
122 else
123 return true
124 end
125end
126
125--- Check the MD5 checksum for a file. 127--- Check the MD5 checksum for a file.
126-- @param file string: The file to be checked. 128-- @param file string: The file to be checked.
127-- @param md5sum string: The string with the expected MD5 checksum. 129-- @param md5sum string: The string with the expected MD5 checksum.
@@ -207,8 +209,13 @@ end
207-- Allows leaving a directory (e.g. for deleting it) in 209-- Allows leaving a directory (e.g. for deleting it) in
208-- a crossplatform way. 210-- a crossplatform way.
209function fs_lua.change_dir_to_root() 211function fs_lua.change_dir_to_root()
210 table.insert(dir_stack, lfs.currentdir()) 212 local current = lfs.currentdir()
213 if not current or current == "" then
214 return false
215 end
216 table.insert(dir_stack, current)
211 lfs.chdir("/") -- works on Windows too 217 lfs.chdir("/") -- works on Windows too
218 return true
212end 219end
213 220
214--- Change working directory to the previous in the dir stack. 221--- Change working directory to the previous in the dir stack.
@@ -540,7 +547,7 @@ local redirect_protocols = {
540local function request(url, method, http, loop_control) 547local function request(url, method, http, loop_control)
541 local result = {} 548 local result = {}
542 549
543 local proxy = cfg.proxy 550 local proxy = cfg.http_proxy
544 if type(proxy) ~= "string" then proxy = nil end 551 if type(proxy) ~= "string" then proxy = nil end
545 -- LuaSocket's http.request crashes when given URLs missing the scheme part. 552 -- LuaSocket's http.request crashes when given URLs missing the scheme part.
546 if proxy and not proxy:find("://") then 553 if proxy and not proxy:find("://") then
@@ -592,7 +599,7 @@ local function request(url, method, http, loop_control)
592 loop_control[url] = true 599 loop_control[url] = true
593 return request(location, method, redirect_protocols[protocol], loop_control) 600 return request(location, method, redirect_protocols[protocol], loop_control)
594 else 601 else
595 return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support." 602 return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support.", "https"
596 end 603 end
597 end 604 end
598 return nil, err 605 return nil, err
@@ -614,7 +621,7 @@ local function http_request(url, http, cached)
614 return true 621 return true
615 end 622 end
616 if not result then 623 if not result then
617 return nil, status 624 return nil, status, headers
618 end 625 end
619 end 626 end
620 end 627 end
@@ -629,10 +636,12 @@ local function http_request(url, http, cached)
629 end 636 end
630 return table.concat(result) 637 return table.concat(result)
631 else 638 else
632 return nil, status 639 return nil, status, headers
633 end 640 end
634end 641end
635 642
643local downloader_warning = false
644
636--- Download a remote file. 645--- Download a remote file.
637-- @param url string: URL to be fetched. 646-- @param url string: URL to be fetched.
638-- @param filename string or nil: this function attempts to detect the 647-- @param filename string or nil: this function attempts to detect the
@@ -646,21 +655,34 @@ function fs_lua.download(url, filename, cache)
646 assert(type(filename) == "string" or not filename) 655 assert(type(filename) == "string" or not filename)
647 656
648 filename = fs.absolute_name(filename or dir.base_name(url)) 657 filename = fs.absolute_name(filename or dir.base_name(url))
658
659 -- delegate to the configured downloader so we don't have to deal with whitelists
660 if cfg.no_proxy then
661 return fs.use_downloader(url, filename, cache)
662 end
649 663
650 local content, err 664 local content, err, https_err
651 if util.starts_with(url, "http:") then 665 if util.starts_with(url, "http:") then
652 content, err = http_request(url, http, cache and filename) 666 content, err, https_err = http_request(url, http, cache and filename)
653 elseif util.starts_with(url, "ftp:") then 667 elseif util.starts_with(url, "ftp:") then
654 content, err = ftp.get(url) 668 content, err = ftp.get(url)
655 elseif util.starts_with(url, "https:") then 669 elseif util.starts_with(url, "https:") then
656 if luasec_ok then 670 -- skip LuaSec when proxy is enabled since it is not supported
671 if luasec_ok and not cfg.https_proxy then
657 content, err = http_request(url, https, cache and filename) 672 content, err = http_request(url, https, cache and filename)
658 else 673 else
659 err = "Unsupported protocol - install luasec to get HTTPS support." 674 https_err = true
660 end 675 end
661 else 676 else
662 err = "Unsupported protocol" 677 err = "Unsupported protocol"
663 end 678 end
679 if https_err then
680 if not downloader_warning then
681 util.printerr("Warning: falling back to "..cfg.downloader.." - install luasec to get native HTTPS support")
682 downloader_warning = true
683 end
684 return fs.use_downloader(url, filename, cache)
685 end
664 if cache and content == true then 686 if cache and content == true then
665 return true, filename 687 return true, filename
666 end 688 end
@@ -674,6 +696,12 @@ function fs_lua.download(url, filename, cache)
674 return true, filename 696 return true, filename
675end 697end
676 698
699else --...if socket_ok == false then
700
701function fs_lua.download(url, filename, cache)
702 return fs.use_downloader(url, filename, cache)
703end
704
677end 705end
678--------------------------------------------------------------------- 706---------------------------------------------------------------------
679-- MD5 functions 707-- MD5 functions
@@ -681,6 +709,14 @@ end
681 709
682if md5_ok then 710if md5_ok then
683 711
712-- Support the interface of lmd5 by lhf in addition to md5 by Roberto
713-- and the keplerproject.
714if not md5.sumhexa and md5.digest then
715 md5.sumhexa = function(msg)
716 return md5.digest(msg)
717 end
718end
719
684--- Get the MD5 checksum for a file. 720--- Get the MD5 checksum for a file.
685-- @param file string: The file to be computed. 721-- @param file string: The file to be computed.
686-- @return string: The MD5 checksum or nil + error 722-- @return string: The MD5 checksum or nil + error
@@ -717,7 +753,7 @@ function fs_lua.chmod(file, mode)
717 -- LuaPosix (as of 5.1.15) does not support octal notation... 753 -- LuaPosix (as of 5.1.15) does not support octal notation...
718 if mode:sub(1,1) == "0" then 754 if mode:sub(1,1) == "0" then
719 local new_mode = {} 755 local new_mode = {}
720 for c in mode:sub(2):gmatch(".") do 756 for c in mode:sub(-3):gmatch(".") do
721 table.insert(new_mode, octal_to_rwx[c]) 757 table.insert(new_mode, octal_to_rwx[c])
722 end 758 end
723 mode = table.concat(new_mode) 759 mode = table.concat(new_mode)
@@ -730,6 +766,17 @@ function fs_lua.get_permissions(file)
730 return posix.stat(file, "mode") 766 return posix.stat(file, "mode")
731end 767end
732 768
769--- Create a temporary directory.
770-- @param name string: name pattern to use for avoiding conflicts
771-- when creating temporary directory.
772-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
773function fs_lua.make_temp_dir(name)
774 assert(type(name) == "string")
775 name = dir.normalize(name)
776
777 return posix.mkdtemp((os.getenv("TMPDIR") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-XXXXXX")
778end
779
733end 780end
734 781
735--------------------------------------------------------------------- 782---------------------------------------------------------------------
@@ -786,10 +833,19 @@ function fs_lua.check_command_permissions(flags)
786 break 833 break
787 end 834 end
788 end 835 end
789 local root_parent = dir.dir_name(root_dir) 836 if ok and not fs.exists(root_dir) then
790 if ok and not fs.exists(root_dir) and not fs.is_writable(root_parent) then 837 local root = fs.root_of(root_dir)
791 ok = false 838 local parent = root_dir
792 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
793 end 849 end
794 if ok then 850 if ok then
795 return true 851 return true
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua
index a70ed116..570b26e4 100644
--- a/src/luarocks/fs/unix.lua
+++ b/src/luarocks/fs/unix.lua
@@ -9,8 +9,6 @@ local cfg = require("luarocks.cfg")
9local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11 11
12math.randomseed(os.time())
13
14--- Annotate command string for quiet execution. 12--- Annotate command string for quiet execution.
15-- @param cmd string: A command-line string. 13-- @param cmd string: A command-line string.
16-- @return string: The command-line, with silencing annotation. 14-- @return string: The command-line, with silencing annotation.
@@ -36,6 +34,14 @@ function unix.absolute_name(pathname, relative_to)
36 end 34 end
37end 35end
38 36
37--- Return the root directory for the given path.
38-- In Unix, root is always "/".
39-- @param pathname string: pathname to use.
40-- @return string: The root of the given pathname.
41function unix.root_of(_)
42 return "/"
43end
44
39--- Create a wrapper to make a script executable from the command-line. 45--- Create a wrapper to make a script executable from the command-line.
40-- @param file string: Pathname of script to be made executable. 46-- @param file string: Pathname of script to be made executable.
41-- @param dest string: Directory where to put the wrapper. 47-- @param dest string: Directory where to put the wrapper.
@@ -107,4 +113,8 @@ function unix.replace_file(old_file, new_file)
107 return os.rename(new_file, old_file) 113 return os.rename(new_file, old_file)
108end 114end
109 115
116function unix.tmpname()
117 return os.tmpname()
118end
119
110return unix 120return unix
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
index 69466931..ab55897e 100644
--- a/src/luarocks/fs/unix/tools.lua
+++ b/src/luarocks/fs/unix/tools.lua
@@ -12,7 +12,7 @@ local dir_stack = {}
12local vars = cfg.variables 12local vars = cfg.variables
13 13
14local function command_at(directory, cmd) 14local function command_at(directory, cmd)
15 return "cd " .. fs.Q(directory) .. " && " .. cmd 15 return "cd " .. fs.Q(fs.absolute_name(directory)) .. " && " .. cmd
16end 16end
17 17
18--- Obtain current directory. 18--- Obtain current directory.
@@ -21,7 +21,7 @@ end
21function tools.current_dir() 21function tools.current_dir()
22 local current = cfg.cache_pwd 22 local current = cfg.cache_pwd
23 if not current then 23 if not current then
24 local pipe = io.popen(fs.Q(vars.PWD)) 24 local pipe = io.popen(fs.Q(vars.PWD).." 2> /dev/null")
25 current = pipe:read("*l") 25 current = pipe:read("*l")
26 pipe:close() 26 pipe:close()
27 cfg.cache_pwd = current 27 cfg.cache_pwd = current
@@ -38,7 +38,9 @@ end
38-- @return boolean: true if command succeeds (status code 0), false 38-- @return boolean: true if command succeeds (status code 0), false
39-- otherwise. 39-- otherwise.
40function tools.execute_string(cmd) 40function tools.execute_string(cmd)
41 local code, err = os.execute(command_at(fs.current_dir(), cmd)) 41 local current = fs.current_dir()
42 if not current then return false end
43 local code, err = os.execute(command_at(current, cmd))
42 if code == 0 or code == true then 44 if code == 0 or code == true then
43 return true 45 return true
44 else 46 else
@@ -238,7 +240,7 @@ end
238-- filename can be given explicitly as this second argument. 240-- filename can be given explicitly as this second argument.
239-- @return (boolean, string): true and the filename on success, 241-- @return (boolean, string): true and the filename on success,
240-- false and the error message on failure. 242-- false and the error message on failure.
241function tools.download(url, filename, cache) 243function tools.use_downloader(url, filename, cache)
242 assert(type(url) == "string") 244 assert(type(url) == "string")
243 assert(type(filename) == "string" or not filename) 245 assert(type(filename) == "string" or not filename)
244 246
@@ -246,7 +248,7 @@ function tools.download(url, filename, cache)
246 248
247 local ok 249 local ok
248 if cfg.downloader == "wget" then 250 if cfg.downloader == "wget" then
249 local wget_cmd = fs.Q(vars.WGET).." --no-check-certificate --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet " 251 local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet "
250 if cfg.connection_timeout and cfg.connection_timeout > 0 then 252 if cfg.connection_timeout and cfg.connection_timeout > 0 then
251 wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 " 253 wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 "
252 end 254 end
@@ -262,7 +264,7 @@ function tools.download(url, filename, cache)
262 ok = fs.execute_quiet(wget_cmd, url) 264 ok = fs.execute_quiet(wget_cmd, url)
263 end 265 end
264 elseif cfg.downloader == "curl" then 266 elseif cfg.downloader == "curl" then
265 local curl_cmd = fs.Q(vars.CURL).." -f -k -L --user-agent '"..cfg.user_agent.." via curl' " 267 local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent '"..cfg.user_agent.." via curl' "
266 if cfg.connection_timeout and cfg.connection_timeout > 0 then 268 if cfg.connection_timeout and cfg.connection_timeout > 0 then
267 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." " 269 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
268 end 270 end
@@ -283,12 +285,6 @@ function tools.chmod(pathname, mode)
283 end 285 end
284end 286end
285 287
286--- Apply a patch.
287-- @param patchname string: The filename of the patch.
288function tools.apply_patch(patchname)
289 return fs.execute(vars.PATCH.." -p1 -f -i ", patchname)
290end
291
292--- Unpack an archive. 288--- Unpack an archive.
293-- Extract the contents of an archive, detecting its format by 289-- Extract the contents of an archive, detecting its format by
294-- filename extension. 290-- filename extension.
@@ -297,13 +293,19 @@ end
297function tools.unpack_archive(archive) 293function tools.unpack_archive(archive)
298 assert(type(archive) == "string") 294 assert(type(archive) == "string")
299 295
296 local pipe_to_tar = " | "..vars.TAR.." -xf -"
297
298 if not cfg.verbose then
299 pipe_to_tar = " 2> /dev/null"..fs.quiet(pipe_to_tar)
300 end
301
300 local ok 302 local ok
301 if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then 303 if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then
302 ok = fs.execute_string(vars.GUNZIP.." -c "..archive.."|"..vars.TAR.." -xf -") 304 ok = fs.execute_string(vars.GUNZIP.." -c "..fs.Q(archive)..pipe_to_tar)
303 elseif archive:match("%.tar%.bz2$") then 305 elseif archive:match("%.tar%.bz2$") then
304 ok = fs.execute_string(vars.BUNZIP2.." -c "..archive.."|tar -xf -") 306 ok = fs.execute_string(vars.BUNZIP2.." -c "..fs.Q(archive)..pipe_to_tar)
305 elseif archive:match("%.zip$") then 307 elseif archive:match("%.zip$") then
306 ok = fs.execute(vars.UNZIP, archive) 308 ok = fs.execute_quiet(vars.UNZIP, archive)
307 elseif archive:match("%.lua$") or archive:match("%.c$") then 309 elseif archive:match("%.lua$") or archive:match("%.c$") then
308 -- Ignore .lua and .c files; they don't need to be extracted. 310 -- Ignore .lua and .c files; they don't need to be extracted.
309 return true 311 return true
@@ -350,4 +352,27 @@ function tools.browser(url)
350 return fs.execute(cfg.web_browser, url) 352 return fs.execute(cfg.web_browser, url)
351end 353end
352 354
355function tools.set_time(file, time)
356 file = dir.normalize(file)
357 return fs.execute(vars.TOUCH, "-d", "@"..tostring(time), file)
358end
359
360--- Create a temporary directory.
361-- @param name string: name pattern to use for avoiding conflicts
362-- when creating temporary directory.
363-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
364function tools.make_temp_dir(name)
365 assert(type(name) == "string")
366 name = dir.normalize(name)
367
368 local template = (os.getenv("TMPDIR") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-XXXXXX"
369 local pipe = io.popen(vars.MKTEMP.." -d "..fs.Q(template))
370 local dirname = pipe:read("*l")
371 pipe:close()
372 if dirname and dirname:match("^/") then
373 return dirname
374 end
375 return nil, "Failed to create temporary directory "..tostring(dirname)
376end
377
353return tools 378return tools
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua
index 238a25e9..c14c421b 100644
--- a/src/luarocks/fs/win32.lua
+++ b/src/luarocks/fs/win32.lua
@@ -10,6 +10,8 @@ local cfg = require("luarocks.cfg")
10local dir = require("luarocks.dir") 10local dir = require("luarocks.dir")
11local util = require("luarocks.util") 11local util = require("luarocks.util")
12 12
13math.randomseed(os.time())
14
13-- Monkey patch io.popen and os.execute to make sure quoting 15-- Monkey patch io.popen and os.execute to make sure quoting
14-- works as expected. 16-- works as expected.
15-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html 17-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html
@@ -18,7 +20,6 @@ local _popen, _execute = io.popen, os.execute
18io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end 20io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
19os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end 21os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
20 22
21
22--- Annotate command string for quiet execution. 23--- Annotate command string for quiet execution.
23-- @param cmd string: A command-line string. 24-- @param cmd string: A command-line string.
24-- @return string: The command-line, with silencing annotation. 25-- @return string: The command-line, with silencing annotation.
@@ -26,6 +27,7 @@ function win32.quiet(cmd)
26 return cmd.." 2> NUL 1> NUL" 27 return cmd.." 2> NUL 1> NUL"
27end 28end
28 29
30local drive_letter = "[%.a-zA-Z]?:?[\\/]"
29 31
30local win_escape_chars = { 32local win_escape_chars = {
31 ["%"] = "%%", 33 ["%"] = "%%",
@@ -47,7 +49,7 @@ end
47function win32.Q(arg) 49function win32.Q(arg)
48 assert(type(arg) == "string") 50 assert(type(arg) == "string")
49 -- Quote DIR for Windows 51 -- Quote DIR for Windows
50 if arg:match("^[%.a-zA-Z]?:?[\\/]") then 52 if arg:match("^"..drive_letter) then
51 arg = arg:gsub("/", "\\") 53 arg = arg:gsub("/", "\\")
52 end 54 end
53 if arg == "\\" then 55 if arg == "\\" then
@@ -68,7 +70,7 @@ end
68function win32.Qb(arg) 70function win32.Qb(arg)
69 assert(type(arg) == "string") 71 assert(type(arg) == "string")
70 -- Quote DIR for Windows 72 -- Quote DIR for Windows
71 if arg:match("^[%.a-zA-Z]?:?[\\/]") then 73 if arg:match("^"..drive_letter) then
72 arg = arg:gsub("/", "\\") 74 arg = arg:gsub("/", "\\")
73 end 75 end
74 if arg == "\\" then 76 if arg == "\\" then
@@ -92,15 +94,21 @@ function win32.absolute_name(pathname, relative_to)
92 assert(type(relative_to) == "string" or not relative_to) 94 assert(type(relative_to) == "string" or not relative_to)
93 95
94 relative_to = relative_to or fs.current_dir() 96 relative_to = relative_to or fs.current_dir()
95 -- FIXME I'm not sure this first \\ should be there at all. 97 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 98 return pathname
99 else 99 else
100 return relative_to .. "/" .. pathname 100 return relative_to .. "/" .. pathname
101 end 101 end
102end 102end
103 103
104--- Return the root directory for the given path.
105-- For example, for "c:\hello", returns "c:\"
106-- @param pathname string: pathname to use.
107-- @return string: The root of the given pathname.
108function win32.root_of(pathname)
109 return (fs.absolute_name(pathname):match("^("..drive_letter..")"))
110end
111
104--- Create a wrapper to make a script executable from the command-line. 112--- Create a wrapper to make a script executable from the command-line.
105-- @param file string: Pathname of script to be made executable. 113-- @param file string: Pathname of script to be made executable.
106-- @param dest string: Directory where to put the wrapper. 114-- @param dest string: Directory where to put the wrapper.
@@ -125,6 +133,7 @@ function win32.wrap_script(file, dest, name, version)
125 local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath" 133 local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath"
126 local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")" 134 local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
127 wrapper:write(fs.Qb(lua)..' -e '..fs.Qb(ppaths)..' -e '..fs.Qb(addctx)..' '..fs.Qb(file)..' %*\n') 135 wrapper:write(fs.Qb(lua)..' -e '..fs.Qb(ppaths)..' -e '..fs.Qb(addctx)..' '..fs.Qb(file)..' %*\n')
136 wrapper:write("exit /b %ERRORLEVEL%\n")
128 wrapper:close() 137 wrapper:close()
129 return true 138 return true
130end 139end
@@ -214,4 +223,25 @@ function win32.is_writable(file)
214 return result 223 return result
215end 224end
216 225
226--- Create a temporary directory.
227-- @param name string: name pattern to use for avoiding conflicts
228-- when creating temporary directory.
229-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
230function win32.make_temp_dir(name)
231 assert(type(name) == "string")
232 name = dir.normalize(name)
233
234 local temp_dir = os.getenv("TMP") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000))
235 local ok, err = fs.make_dir(temp_dir)
236 if ok then
237 return temp_dir
238 else
239 return nil, err
240 end
241end
242
243function win32.tmpname()
244 return os.getenv("TMP")..os.tmpname()
245end
246
217return win32 247return win32
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
index a8b2a1db..b9dce85c 100644
--- a/src/luarocks/fs/win32/tools.lua
+++ b/src/luarocks/fs/win32/tools.lua
@@ -39,7 +39,7 @@ end
39function tools.current_dir() 39function tools.current_dir()
40 local current = cfg.cache_pwd 40 local current = cfg.cache_pwd
41 if not current then 41 if not current then
42 local pipe = io.popen(fs.Q(vars.PWD)) 42 local pipe = io.popen(fs.Q(vars.PWD).. " 2> NUL")
43 current = pipe:read("*l") 43 current = pipe:read("*l")
44 pipe:close() 44 pipe:close()
45 cfg.cache_pwd = current 45 cfg.cache_pwd = current
@@ -56,7 +56,9 @@ end
56-- @return boolean: true if command succeeds (status code 0), false 56-- @return boolean: true if command succeeds (status code 0), false
57-- otherwise. 57-- otherwise.
58function tools.execute_string(cmd) 58function tools.execute_string(cmd)
59 cmd = command_at(fs.current_dir(), cmd) 59 local current = fs.current_dir()
60 if not current then return false end
61 cmd = command_at(current, cmd)
60 local code = os.execute(cmd) 62 local code = os.execute(cmd)
61 if code == 0 or code == true then 63 if code == 0 or code == true then
62 return true 64 return true
@@ -149,7 +151,7 @@ end
149-- plus an error message. 151-- plus an error message.
150function tools.copy_contents(src, dest) 152function tools.copy_contents(src, dest)
151 assert(src and dest) 153 assert(src and dest)
152 if fs.execute_quiet(fs.Q(vars.CP).." -dR "..src.."\\*.* "..fs.Q(dest)) then 154 if fs.execute_quiet(fs.Q(vars.CP), "-dR", src.."\\*.*", dest) then
153 return true 155 return true
154 else 156 else
155 return false, "Failed copying "..src.." to "..dest 157 return false, "Failed copying "..src.." to "..dest
@@ -248,7 +250,7 @@ end
248-- filename can be given explicitly as this second argument. 250-- filename can be given explicitly as this second argument.
249-- @return (boolean, string): true and the filename on success, 251-- @return (boolean, string): true and the filename on success,
250-- false and the error message on failure. 252-- false and the error message on failure.
251function tools.download(url, filename, cache) 253function tools.use_downloader(url, filename, cache)
252 assert(type(url) == "string") 254 assert(type(url) == "string")
253 assert(type(filename) == "string" or not filename) 255 assert(type(filename) == "string" or not filename)
254 256
@@ -256,7 +258,7 @@ function tools.download(url, filename, cache)
256 258
257 local ok 259 local ok
258 if cfg.downloader == "wget" then 260 if cfg.downloader == "wget" then
259 local wget_cmd = fs.Q(vars.WGET).." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet " 261 local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet "
260 if cfg.connection_timeout and cfg.connection_timeout > 0 then 262 if cfg.connection_timeout and cfg.connection_timeout > 0 then
261 wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 " 263 wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 "
262 end 264 end
@@ -272,7 +274,7 @@ function tools.download(url, filename, cache)
272 ok = fs.execute_quiet(wget_cmd, url) 274 ok = fs.execute_quiet(wget_cmd, url)
273 end 275 end
274 elseif cfg.downloader == "curl" then 276 elseif cfg.downloader == "curl" then
275 local curl_cmd = vars.CURL.." -f -k -L --user-agent \""..cfg.user_agent.." via curl\" " 277 local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent \""..cfg.user_agent.." via curl\" "
276 if cfg.connection_timeout and cfg.connection_timeout > 0 then 278 if cfg.connection_timeout and cfg.connection_timeout > 0 then
277 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." " 279 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
278 end 280 end
diff --git a/src/luarocks/help.lua b/src/luarocks/help.lua
index 0a155509..5a2681a3 100644
--- a/src/luarocks/help.lua
+++ b/src/luarocks/help.lua
@@ -31,10 +31,8 @@ end
31local function get_status(status) 31local function get_status(status)
32 if status then 32 if status then
33 return "ok" 33 return "ok"
34 elseif status == false then
35 return "not found"
36 else 34 else
37 return "failed" 35 return "not found"
38 end 36 end
39end 37end
40 38
@@ -47,7 +45,7 @@ function help.run(...)
47 local flags, command = util.parse_flags(...) 45 local flags, command = util.parse_flags(...)
48 46
49 if not command then 47 if not command then
50 local sys_file, sys_ok, home_file, home_ok = cfg.which_config() 48 local conf = cfg.which_config()
51 print_banner() 49 print_banner()
52 print_section("NAME") 50 print_section("NAME")
53 util.printout("\t"..program..[[ - ]]..program_description) 51 util.printout("\t"..program..[[ - ]]..program_description)
@@ -83,9 +81,9 @@ function help.run(...)
83 print_section("CONFIGURATION") 81 print_section("CONFIGURATION")
84 util.printout("\tLua version: " .. cfg.lua_version) 82 util.printout("\tLua version: " .. cfg.lua_version)
85 util.printout("\tConfiguration files:") 83 util.printout("\tConfiguration files:")
86 util.printout("\t\tSystem: ".. dir.normalize(sys_file) .. " (" .. get_status(sys_ok) ..")") 84 util.printout("\t\tSystem: ".. dir.normalize(conf.system.file) .. " (" .. get_status(conf.system.ok) ..")")
87 if home_file then 85 if conf.user.file then
88 util.printout("\t\tUser : ".. dir.normalize(home_file) .. " (" .. get_status(home_ok) ..")\n") 86 util.printout("\t\tUser : ".. dir.normalize(conf.user.file) .. " (" .. get_status(conf.user.ok) ..")\n")
89 else 87 else
90 util.printout("\t\tUser : disabled in this LuaRocks installation.\n") 88 util.printout("\t\tUser : disabled in this LuaRocks installation.\n")
91 end 89 end
@@ -100,7 +98,7 @@ function help.run(...)
100 end 98 end
101 else 99 else
102 command = command:gsub("-", "_") 100 command = command:gsub("-", "_")
103 local cmd = require(commands[command]) 101 local cmd = commands[command] and require(commands[command])
104 if cmd then 102 if cmd then
105 local arguments = cmd.help_arguments or "<argument>" 103 local arguments = cmd.help_arguments or "<argument>"
106 print_banner() 104 print_banner()
@@ -113,7 +111,7 @@ function help.run(...)
113 print_section("SEE ALSO") 111 print_section("SEE ALSO")
114 util.printout("","'"..program.." help' for general options and configuration.\n") 112 util.printout("","'"..program.." help' for general options and configuration.\n")
115 else 113 else
116 return nil, "Unknown command '"..command.."'" 114 return nil, "Unknown command: "..command
117 end 115 end
118 end 116 end
119 return true 117 return true
diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua
index 7678c0cc..c938aa9f 100644
--- a/src/luarocks/install.lua
+++ b/src/luarocks/install.lua
@@ -26,6 +26,8 @@ or a filename of a locally available rock.
26 rock after installing a new one. This behavior can 26 rock after installing a new one. This behavior can
27 be made permanent by setting keep_other_versions=true 27 be made permanent by setting keep_other_versions=true
28 in the configuration file. 28 in the configuration file.
29
30--only-deps Installs only the dependencies of the rock.
29]]..util.deps_mode_help() 31]]..util.deps_mode_help()
30 32
31 33
@@ -109,6 +111,43 @@ function install.install_binary_rock(rock_file, deps_mode)
109 return name, version 111 return name, version
110end 112end
111 113
114--- Installs the dependencies of a binary rock.
115-- @param rock_file string: local or remote filename of a rock.
116-- @param deps_mode: string: Which trees to check dependencies for:
117-- "one" for the current default tree, "all" for all trees,
118-- "order" for all trees with priority >= the current default, "none" for no trees.
119-- @return (string, string) or (nil, string, [string]): Name and version of
120-- the rock whose dependencies were installed if succeeded or nil and an error message
121-- followed by an error code.
122function install.install_binary_rock_deps(rock_file, deps_mode)
123 assert(type(rock_file) == "string")
124
125 local name, version, arch = path.parse_name(rock_file)
126 if not name then
127 return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
128 end
129
130 if arch ~= "all" and arch ~= cfg.arch then
131 return nil, "Incompatible architecture "..arch, "arch"
132 end
133
134 local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version))
135 if not ok then return nil, err, errcode end
136
137 local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
138 if err then
139 return nil, "Failed loading rockspec for installed package: "..err, errcode
140 end
141
142 ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
143 if err then return nil, err, errcode end
144
145 util.printout()
146 util.printout("Succesfully installed dependencies for " ..name.." "..version)
147
148 return name, version
149end
150
112--- Driver function for the "install" command. 151--- Driver function for the "install" command.
113-- @param name string: name of a binary rock. If an URL or pathname 152-- @param name string: name of a binary rock. If an URL or pathname
114-- to a binary rock is given, fetches and installs it. If a rockspec or a 153-- to a binary rock is given, fetches and installs it. If a rockspec or a
@@ -131,32 +170,28 @@ function install.run(...)
131 if name:match("%.rockspec$") or name:match("%.src%.rock$") then 170 if name:match("%.rockspec$") or name:match("%.src%.rock$") then
132 util.printout("Using "..name.."... switching to 'build' mode") 171 util.printout("Using "..name.."... switching to 'build' mode")
133 local build = require("luarocks.build") 172 local build = require("luarocks.build")
134 return build.run(name, util.forward_flags(flags, "local", "keep", "deps-mode")) 173 return build.run(name, util.forward_flags(flags, "local", "keep", "deps-mode", "only-deps"))
135 elseif name:match("%.rock$") then 174 elseif name:match("%.rock$") then
136 ok, err = install.install_binary_rock(name, deps.get_deps_mode(flags)) 175 if flags["only-deps"] then
176 ok, err = install.install_binary_rock_deps(name, deps.get_deps_mode(flags))
177 else
178 ok, err = install.install_binary_rock(name, deps.get_deps_mode(flags))
179 end
137 if not ok then return nil, err end 180 if not ok then return nil, err end
138 local name, version = ok, err 181 local name, version = ok, err
139 if (not flags["keep"]) and not cfg.keep_other_versions then 182 if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then
140 local ok, err = remove.remove_other_versions(name, version, flags["force"]) 183 local ok, err = remove.remove_other_versions(name, version, flags["force"])
141 if not ok then util.printerr(err) end 184 if not ok then util.printerr(err) end
142 end 185 end
143 return name, version 186 return name, version
144 else 187 else
145 local search = require("luarocks.search") 188 local search = require("luarocks.search")
146 local results, err = search.find_suitable_rock(search.make_query(name:lower(), version)) 189 local url, err = search.find_suitable_rock(search.make_query(name:lower(), version))
147 if err then 190 if not url then
148 return nil, err 191 return nil, err
149 elseif type(results) == "string" then
150 local url = results
151 util.printout("Installing "..url.."...")
152 return install.run(url, util.forward_flags(flags))
153 else
154 util.printout()
155 util.printerr("Could not determine which rock to install.")
156 util.title("Search results:")
157 search.print_results(results)
158 return nil, (next(results) and "Please narrow your query." or "No results found.")
159 end 192 end
193 util.printout("Installing "..url.."...")
194 return install.run(url, util.forward_flags(flags))
160 end 195 end
161end 196end
162 197
diff --git a/src/luarocks/list.lua b/src/luarocks/list.lua
index 319909d3..99868028 100644
--- a/src/luarocks/list.lua
+++ b/src/luarocks/list.lua
@@ -6,33 +6,97 @@ local list = {}
6package.loaded["luarocks.list"] = list 6package.loaded["luarocks.list"] = list
7 7
8local search = require("luarocks.search") 8local search = require("luarocks.search")
9local deps = require("luarocks.deps")
9local cfg = require("luarocks.cfg") 10local cfg = require("luarocks.cfg")
10local util = require("luarocks.util") 11local util = require("luarocks.util")
11local path = require("luarocks.path") 12local path = require("luarocks.path")
12 13
13list.help_summary = "Lists currently installed rocks." 14list.help_summary = "List currently installed rocks."
14list.help_arguments = "[--porcelain] <filter>" 15list.help_arguments = "[--porcelain] <filter>"
15list.help = [[ 16list.help = [[
16<filter> is a substring of a rock name to filter by. 17<filter> is a substring of a rock name to filter by.
17 18
19--outdated List only rocks for which there is a
20 higher version available in the rocks server.
21
18--porcelain Produce machine-friendly output. 22--porcelain Produce machine-friendly output.
19]] 23]]
20 24
25local function check_outdated(trees, query)
26 local results_installed = {}
27 for _, tree in ipairs(trees) do
28 search.manifest_search(results_installed, path.rocks_dir(tree), query)
29 end
30 local outdated = {}
31 for name, versions in util.sortedpairs(results_installed) do
32 local latest_installed
33 local latest_available, latest_available_repo
34
35 for version, _ in util.sortedpairs(versions) do
36 latest_installed = version
37 break
38 end
39
40 local query_available = search.make_query(name:lower())
41 query.exact_name = true
42 local results_available, err = search.search_repos(query_available)
43
44 if results_available[name] then
45 for version, repos in util.sortedpairs(results_available[name], deps.compare_versions) do
46 latest_available = version
47 for _, repo in ipairs(repos) do
48 latest_available_repo = repo.repo
49 break
50 end
51 break
52 end
53
54 if deps.compare_versions(latest_available, latest_installed) then
55 table.insert(outdated, { name = name, installed = latest_installed, available = latest_available, repo = latest_available_repo })
56 end
57 end
58 end
59 return outdated
60end
61
62local function list_outdated(trees, query, porcelain)
63 util.title("Outdated rocks:", porcelain)
64 local outdated = check_outdated(trees, query)
65 for _, item in ipairs(outdated) do
66 if porcelain then
67 util.printout(item.name, item.installed, item.available, item.repo)
68 else
69 util.printout(item.name)
70 util.printout(" "..item.installed.." < "..item.available.." at "..item.repo)
71 util.printout()
72 end
73 end
74 return true
75end
76
21--- Driver function for "list" command. 77--- Driver function for "list" command.
22-- @param filter string or nil: A substring of a rock name to filter by. 78-- @param filter string or nil: A substring of a rock name to filter by.
23-- @param version string or nil: a version may also be passed. 79-- @param version string or nil: a version may also be passed.
24-- @return boolean: True if succeeded, nil on errors. 80-- @return boolean: True if succeeded, nil on errors.
25function list.run(...) 81function list.run(...)
26 local flags, filter, version = util.parse_flags(...) 82 local flags, filter, version = util.parse_flags(...)
27 local results = {}
28 local query = search.make_query(filter and filter:lower() or "", version) 83 local query = search.make_query(filter and filter:lower() or "", version)
29 query.exact_name = false 84 query.exact_name = false
30 local trees = cfg.rocks_trees 85 local trees = cfg.rocks_trees
31 if flags["tree"] then 86 if flags["tree"] then
32 trees = { flags["tree"] } 87 trees = { flags["tree"] }
33 end 88 end
89
90 if flags["outdated"] then
91 return list_outdated(trees, query, flags["porcelain"])
92 end
93
94 local results = {}
34 for _, tree in ipairs(trees) do 95 for _, tree in ipairs(trees) do
35 search.manifest_search(results, path.rocks_dir(tree), query) 96 local ok, err, errcode = search.manifest_search(results, path.rocks_dir(tree), query)
97 if not ok and errcode ~= "open" then
98 util.warning(err)
99 end
36 end 100 end
37 util.title("Installed rocks:", flags["porcelain"]) 101 util.title("Installed rocks:", flags["porcelain"])
38 search.print_results(results, flags["porcelain"]) 102 search.print_results(results, flags["porcelain"])
diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua
index 3d36723f..26280e94 100644
--- a/src/luarocks/loader.lua
+++ b/src/luarocks/loader.lua
@@ -6,18 +6,21 @@
6-- used to load previous modules, so that the loader chooses versions 6-- used to load previous modules, so that the loader chooses versions
7-- that are declared to be compatible with the ones loaded earlier. 7-- that are declared to be compatible with the ones loaded earlier.
8local loaders = package.loaders or package.searchers 8local loaders = package.loaders or package.searchers
9local package, require, ipairs, pairs, table, type, next, tostring, error = 9local package, require, ipairs, table, type, next, tostring, error =
10 package, require, ipairs, pairs, table, type, next, tostring, error 10 package, require, ipairs, table, type, next, tostring, error
11local unpack = unpack or table.unpack 11local unpack = unpack or table.unpack
12 12
13--module("luarocks.loader") 13--module("luarocks.loader")
14local loader = {} 14local loader = {}
15package.loaded["luarocks.loader"] = loader 15package.loaded["luarocks.loader"] = loader
16 16
17local cfg = require("luarocks.cfg")
18cfg.init_package_paths()
19
17local path = require("luarocks.path") 20local path = require("luarocks.path")
18local manif_core = require("luarocks.manif_core") 21local manif_core = require("luarocks.manif_core")
19local deps = require("luarocks.deps") 22local deps = require("luarocks.deps")
20local cfg = require("luarocks.cfg") 23local util = require("luarocks.util")
21 24
22loader.context = {} 25loader.context = {}
23 26
@@ -77,7 +80,7 @@ function loader.add_context(name, version)
77 for _, tree in ipairs(loader.rocks_trees) do 80 for _, tree in ipairs(loader.rocks_trees) do
78 local entries = tree.manifest.repository[pkg] 81 local entries = tree.manifest.repository[pkg]
79 if entries then 82 if entries then
80 for version, pkgs in pairs(entries) do 83 for version, pkgs in util.sortedpairs(entries, deps.compare_versions) do
81 if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then 84 if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
82 loader.add_context(pkg, version) 85 loader.add_context(pkg, version)
83 end 86 end
@@ -123,16 +126,17 @@ end
123 126
124--- Search for a module in the rocks trees 127--- Search for a module in the rocks trees
125-- @param module string: module name (eg. "socket.core") 128-- @param module string: module name (eg. "socket.core")
126-- @param filter_module_name function(string, string, string, string, number): 129-- @param filter_file_name function(string, string, string, string, number):
127-- a function that takes the module name (eg "socket.core"), the rock name 130-- a function that takes the module file name (eg "socket/core.so"), the rock name
128-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree 131-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree
129-- (eg "/usr/local"), and the numeric index of the matching entry, so the 132-- (eg "/usr/local"), and the numeric index of the matching entry, so the
130-- filter function can know if the matching module was the first entry or not. 133-- filter function can know if the matching module was the first entry or not.
131-- @return string, string, string: name of the rock containing the module 134-- @return string, string, string, (string or table):
132-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), 135-- * name of the rock containing the module (eg. "luasocket")
133-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is 136-- * version of the rock (eg. "2.0.2-1")
134-- stored versioned). 137-- * return value of filter_file_name
135local function select_module(module, filter_module_name) 138-- * tree of the module (string or table in `rocks_trees` format)
139local function select_module(module, filter_file_name)
136 --assert(type(module) == "string") 140 --assert(type(module) == "string")
137 --assert(type(filter_module_name) == "function") 141 --assert(type(filter_module_name) == "function")
138 142
@@ -146,16 +150,16 @@ local function select_module(module, filter_module_name)
146 if entries then 150 if entries then
147 for i, entry in ipairs(entries) do 151 for i, entry in ipairs(entries) do
148 local name, version = entry:match("^([^/]*)/(.*)$") 152 local name, version = entry:match("^([^/]*)/(.*)$")
149 local module_name = tree.manifest.repository[name][version][1].modules[module] 153 local file_name = tree.manifest.repository[name][version][1].modules[module]
150 if type(module_name) ~= "string" then 154 if type(file_name) ~= "string" then
151 error("Invalid data in manifest file for module "..tostring(module).." (invalid data for "..tostring(name).." "..tostring(version)..")") 155 error("Invalid data in manifest file for module "..tostring(module).." (invalid data for "..tostring(name).." "..tostring(version)..")")
152 end 156 end
153 module_name = filter_module_name(module_name, name, version, tree.tree, i) 157 file_name = filter_file_name(file_name, name, version, tree.tree, i)
154 if loader.context[name] == version then 158 if loader.context[name] == version then
155 return name, version, module_name 159 return name, version, file_name
156 end 160 end
157 version = deps.parse_version(version) 161 version = deps.parse_version(version)
158 table.insert(providers, {name = name, version = version, module_name = module_name}) 162 table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree})
159 end 163 end
160 end 164 end
161 end 165 end
@@ -163,24 +167,24 @@ local function select_module(module, filter_module_name)
163 if next(providers) then 167 if next(providers) then
164 table.sort(providers, sort_versions) 168 table.sort(providers, sort_versions)
165 local first = providers[1] 169 local first = providers[1]
166 return first.name, first.version.string, first.module_name 170 return first.name, first.version.string, first.module_name, first.tree
167 end 171 end
168end 172end
169 173
170--- Search for a module 174--- Search for a module
171-- @param module string: module name (eg. "socket.core") 175-- @param module string: module name (eg. "socket.core")
172-- @return string, string, string: name of the rock containing the module 176-- @return string, string, string, (string or table):
173-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), 177-- * name of the rock containing the module (eg. "luasocket")
174-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is 178-- * version of the rock (eg. "2.0.2-1")
175-- stored versioned). 179-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
180-- * tree of the module (string or table in `rocks_trees` format)
176local function pick_module(module) 181local function pick_module(module)
177 return 182 return
178 select_module(module, function(module_name, name, version, tree, i) 183 select_module(module, function(file_name, name, version, tree, i)
179 if i > 1 then 184 if i > 1 then
180 module_name = path.versioned_name(module_name, "", name, version) 185 file_name = path.versioned_name(file_name, "", name, version)
181 end 186 end
182 module_name = path.path_to_module(module_name) 187 return path.path_to_module(file_name)
183 return module_name
184 end) 188 end)
185end 189end
186 190
@@ -188,8 +192,8 @@ end
188-- @param module string: module name (eg. "socket.core") 192-- @param module string: module name (eg. "socket.core")
189-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") 193-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
190function loader.which(module) 194function loader.which(module)
191 local name, version, module_name = select_module(module, path.which_i) 195 local _, _, file_name = select_module(module, path.which_i)
192 return module_name 196 return file_name
193end 197end
194 198
195--- Package loader for LuaRocks support. 199--- Package loader for LuaRocks support.
diff --git a/src/luarocks/make.lua b/src/luarocks/make.lua
index 1dfe6473..94cf4414 100644
--- a/src/luarocks/make.lua
+++ b/src/luarocks/make.lua
@@ -9,6 +9,8 @@ package.loaded["luarocks.make"] = make
9 9
10local build = require("luarocks.build") 10local build = require("luarocks.build")
11local fs = require("luarocks.fs") 11local fs = require("luarocks.fs")
12local dir = require("luarocks.dir")
13local path = require("luarocks.path")
12local util = require("luarocks.util") 14local util = require("luarocks.util")
13local cfg = require("luarocks.cfg") 15local cfg = require("luarocks.cfg")
14local fetch = require("luarocks.fetch") 16local fetch = require("luarocks.fetch")
@@ -22,8 +24,11 @@ make.help = [[
22Builds sources in the current directory, but unlike "build", 24Builds sources in the current directory, but unlike "build",
23it does not fetch sources, etc., assuming everything is 25it does not fetch sources, etc., assuming everything is
24available in the current directory. If no argument is given, 26available in the current directory. If no argument is given,
25look for a rockspec in the current directory. If more than one 27it looks for a rockspec in the current directory and in "rockspec/"
26is found, you must specify which to use, through the command-line. 28and "rockspecs/" subdirectories, picking the rockspec with newest version
29or without version name. If rockspecs for different rocks are found
30or there are several rockspecs without version, you must specify which to use,
31through the command-line.
27 32
28This command is useful as a tool for debugging rockspecs. 33This command is useful as a tool for debugging rockspecs.
29To install rocks, you'll normally want to use the "install" and 34To install rocks, you'll normally want to use the "install" and
@@ -44,6 +49,33 @@ To install rocks, you'll normally want to use the "install" and
44 49
45]] 50]]
46 51
52--- Collect rockspecs located in a subdirectory.
53-- @param versions table: A table mapping rock names to newest rockspec versions.
54-- @param paths table: A table mapping rock names to newest rockspec paths.
55-- @param unnamed_paths table: An array of rockspec paths that don't contain rock
56-- name and version in regular format.
57-- @param subdir string: path to subdirectory.
58local function collect_rockspecs(versions, paths, unnamed_paths, subdir)
59 if fs.is_dir(subdir) then
60 for file in fs.dir(subdir) do
61 file = dir.path(subdir, file)
62
63 if file:match("rockspec$") and fs.is_file(file) then
64 local rock, version = path.parse_name(file)
65
66 if rock then
67 if not versions[rock] or deps.compare_versions(version, versions[rock]) then
68 versions[rock] = version
69 paths[rock] = file
70 end
71 else
72 table.insert(unnamed_paths, file)
73 end
74 end
75 end
76 end
77end
78
47--- Driver function for "make" command. 79--- Driver function for "make" command.
48-- @param name string: A local rockspec. 80-- @param name string: A local rockspec.
49-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an 81-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
@@ -53,18 +85,35 @@ function make.run(...)
53 assert(type(rockspec) == "string" or not rockspec) 85 assert(type(rockspec) == "string" or not rockspec)
54 86
55 if not rockspec then 87 if not rockspec then
56 for file in fs.dir() do 88 -- Try to infer default rockspec name.
57 if file:match("rockspec$") then 89 local versions, paths, unnamed_paths = {}, {}, {}
58 if rockspec then 90 -- Look for rockspecs in some common locations.
91 collect_rockspecs(versions, paths, unnamed_paths, ".")
92 collect_rockspecs(versions, paths, unnamed_paths, "rockspec")
93 collect_rockspecs(versions, paths, unnamed_paths, "rockspecs")
94
95 if #unnamed_paths > 0 then
96 -- There are rockspecs not following "name-version.rockspec" format.
97 -- More than one are ambiguous.
98 if #unnamed_paths > 1 then
99 return nil, "Please specify which rockspec file to use."
100 else
101 rockspec = unnamed_paths[1]
102 end
103 else
104 local rock = next(versions)
105
106 if rock then
107 -- If there are rockspecs for multiple rocks it's ambiguous.
108 if next(versions, rock) then
59 return nil, "Please specify which rockspec file to use." 109 return nil, "Please specify which rockspec file to use."
60 else 110 else
61 rockspec = file 111 rockspec = paths[rock]
62 end 112 end
113 else
114 return nil, "Argument missing: please specify a rockspec to use on current directory."
63 end 115 end
64 end 116 end
65 if not rockspec then
66 return nil, "Argument missing: please specify a rockspec to use on current directory."
67 end
68 end 117 end
69 if not rockspec:match("rockspec$") then 118 if not rockspec:match("rockspec$") then
70 return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make") 119 return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make")
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua
index f1d1629c..05621315 100644
--- a/src/luarocks/manif.lua
+++ b/src/luarocks/manif.lua
@@ -105,18 +105,22 @@ end
105-- All functions that use manifest tables assume they were obtained 105-- All functions that use manifest tables assume they were obtained
106-- through either this function or load_local_manifest. 106-- through either this function or load_local_manifest.
107-- @param repo_url string: URL or pathname for the repository. 107-- @param repo_url string: URL or pathname for the repository.
108-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
108-- @return table or (nil, string, [string]): A table representing the manifest, 109-- @return table or (nil, string, [string]): A table representing the manifest,
109-- or nil followed by an error message and an optional error code. 110-- or nil followed by an error message and an optional error code.
110function manif.load_manifest(repo_url) 111function manif.load_manifest(repo_url, lua_version)
111 assert(type(repo_url) == "string") 112 assert(type(repo_url) == "string")
113 assert(type(lua_version) == "string" or not lua_version)
114 lua_version = lua_version or cfg.lua_version
112 115
113 if manif_core.manifest_cache[repo_url] then 116 local cached_manifest = manif_core.get_cached_manifest(repo_url, lua_version)
114 return manif_core.manifest_cache[repo_url] 117 if cached_manifest then
118 return cached_manifest
115 end 119 end
116 120
117 local filenames = { 121 local filenames = {
118 "manifest-"..cfg.lua_version..".zip", 122 "manifest-"..lua_version..".zip",
119 "manifest-"..cfg.lua_version, 123 "manifest-"..lua_version,
120 "manifest", 124 "manifest",
121 } 125 }
122 126
@@ -156,7 +160,7 @@ function manif.load_manifest(repo_url)
156 end 160 end
157 pathname = nozip 161 pathname = nozip
158 end 162 end
159 return manif_core.manifest_loader(pathname, repo_url) 163 return manif_core.manifest_loader(pathname, repo_url, lua_version)
160end 164end
161 165
162--- Output a table listing items of a package. 166--- Output a table listing items of a package.
@@ -381,7 +385,7 @@ function manif.make_manifest(repo, deps_mode, remote)
381 local results = search.disk_search(repo, query) 385 local results = search.disk_search(repo, query)
382 local manifest = { repository = {}, modules = {}, commands = {} } 386 local manifest = { repository = {}, modules = {}, commands = {} }
383 387
384 manif_core.manifest_cache[repo] = manifest 388 manif_core.cache_manifest(repo, nil, manifest)
385 389
386 local dep_handler = nil 390 local dep_handler = nil
387 if not remote then 391 if not remote then
@@ -414,7 +418,7 @@ end
414-- @param name string: Name of a package from the repository. 418-- @param name string: Name of a package from the repository.
415-- @param version string: Version of a package from the repository. 419-- @param version string: Version of a package from the repository.
416-- @param repo string or nil: Pathname of a local repository. If not given, 420-- @param repo string or nil: Pathname of a local repository. If not given,
417-- the default local repository configured as cfg.rocks_dir is used. 421-- the default local repository is used.
418-- @param deps_mode string: Dependency mode: "one" for the current default tree, 422-- @param deps_mode string: Dependency mode: "one" for the current default tree,
419-- "all" for all trees, "order" for all trees with priority >= the current default, 423-- "all" for all trees, "order" for all trees with priority >= the current default,
420-- "none" for using the default dependency mode from the configuration. 424-- "none" for using the default dependency mode from the configuration.
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua
index 1a2c111f..610f9860 100644
--- a/src/luarocks/manif_core.lua
+++ b/src/luarocks/manif_core.lua
@@ -7,32 +7,56 @@ package.loaded["luarocks.manif_core"] = manif_core
7 7
8local persist = require("luarocks.persist") 8local persist = require("luarocks.persist")
9local type_check = require("luarocks.type_check") 9local type_check = require("luarocks.type_check")
10local cfg = require("luarocks.cfg")
10local dir = require("luarocks.dir") 11local dir = require("luarocks.dir")
11local util = require("luarocks.util") 12local util = require("luarocks.util")
12local cfg = require("luarocks.cfg")
13local path = require("luarocks.path") 13local path = require("luarocks.path")
14 14
15manif_core.manifest_cache = {} 15-- Table with repository identifiers as keys and tables mapping
16-- Lua versions to cached loaded manifests as values.
17local manifest_cache = {}
18
19--- Cache a loaded manifest.
20-- @param repo_url string: The repository identifier.
21-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
22-- @param manifest table: the manifest to be cached.
23function manif_core.cache_manifest(repo_url, lua_version, manifest)
24 lua_version = lua_version or cfg.lua_version
25 manifest_cache[repo_url] = manifest_cache[repo_url] or {}
26 manifest_cache[repo_url][lua_version] = manifest
27end
28
29--- Attempt to get cached loaded manifest.
30-- @param repo_url string: The repository identifier.
31-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
32-- @return table or nil: loaded manifest or nil if cache is empty.
33function manif_core.get_cached_manifest(repo_url, lua_version)
34 lua_version = lua_version or cfg.lua_version
35 return manifest_cache[repo_url] and manifest_cache[repo_url][lua_version]
36end
16 37
17--- Back-end function that actually loads the manifest 38--- Back-end function that actually loads the manifest
18-- and stores it in the manifest cache. 39-- and stores it in the manifest cache.
19-- @param file string: The local filename of the manifest file. 40-- @param file string: The local filename of the manifest file.
20-- @param repo_url string: The repository identifier. 41-- @param repo_url string: The repository identifier.
42-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
21-- @param quick boolean: If given, skips type checking. 43-- @param quick boolean: If given, skips type checking.
22function manif_core.manifest_loader(file, repo_url, quick) 44-- @return table or (nil, string, string): the manifest or nil,
23 local manifest, err = persist.load_into_table(file) 45-- error message and error code ("open", "load", "run" or "type").
46function manif_core.manifest_loader(file, repo_url, lua_version, quick)
47 local manifest, err, errcode = persist.load_into_table(file)
24 if not manifest then 48 if not manifest then
25 return nil, "Failed loading manifest for "..repo_url..": "..err 49 return nil, "Failed loading manifest for "..repo_url..": "..err, errcode
26 end 50 end
27 local globals = err 51 local globals = err
28 if not quick then 52 if not quick then
29 local ok, err = type_check.type_check_manifest(manifest, globals) 53 local ok, err = type_check.type_check_manifest(manifest, globals)
30 if not ok then 54 if not ok then
31 return nil, "Error checking manifest: "..err 55 return nil, "Error checking manifest: "..err, "type"
32 end 56 end
33 end 57 end
34 58
35 manif_core.manifest_cache[repo_url] = manifest 59 manif_core.cache_manifest(repo_url, lua_version, manifest)
36 return manifest 60 return manifest
37end 61end
38 62
@@ -40,18 +64,18 @@ end
40-- All functions that use manifest tables assume they were obtained 64-- All functions that use manifest tables assume they were obtained
41-- through either this function or load_manifest. 65-- through either this function or load_manifest.
42-- @param repo_url string: URL or pathname for the repository. 66-- @param repo_url string: URL or pathname for the repository.
43-- @return table or (nil, string): A table representing the manifest, 67-- @return table or (nil, string, string): A table representing the manifest,
44-- or nil followed by an error message. 68-- or nil followed by an error message and an error code, see manifest_loader.
45function manif_core.load_local_manifest(repo_url) 69function manif_core.load_local_manifest(repo_url)
46 assert(type(repo_url) == "string") 70 assert(type(repo_url) == "string")
47 71
48 if manif_core.manifest_cache[repo_url] then 72 local cached_manifest = manif_core.get_cached_manifest(repo_url)
49 return manif_core.manifest_cache[repo_url] 73 if cached_manifest then
74 return cached_manifest
50 end 75 end
51 76
52 local pathname = dir.path(repo_url, "manifest") 77 local pathname = dir.path(repo_url, "manifest")
53 78 return manif_core.manifest_loader(pathname, repo_url, nil, true)
54 return manif_core.manifest_loader(pathname, repo_url, true)
55end 79end
56 80
57--- Get all versions of a package listed in a manifest file. 81--- Get all versions of a package listed in a manifest file.
diff --git a/src/luarocks/new_version.lua b/src/luarocks/new_version.lua
index 9ef0cfbb..6969d4b2 100644
--- a/src/luarocks/new_version.lua
+++ b/src/luarocks/new_version.lua
@@ -1,9 +1,7 @@
1 1
2--- Module implementing the LuaRocks "new_version" command. 2--- Module implementing the LuaRocks "new_version" command.
3-- Utility function that writes a new rockspec, updating data from a previous one. 3-- Utility function that writes a new rockspec, updating data from a previous one.
4--module("luarocks.new_version", package.seeall)
5local new_version = {} 4local new_version = {}
6package.loaded["luarocks.new_version"] = new_version
7 5
8local util = require("luarocks.util") 6local util = require("luarocks.util")
9local download = require("luarocks.download") 7local download = require("luarocks.download")
@@ -13,7 +11,7 @@ local fs = require("luarocks.fs")
13local type_check = require("luarocks.type_check") 11local type_check = require("luarocks.type_check")
14 12
15new_version.help_summary = "Auto-write a rockspec for a new version of a rock." 13new_version.help_summary = "Auto-write a rockspec for a new version of a rock."
16new_version.help_arguments = "{<package>|<rockspec>} [<new_version>] [<new_url>]" 14new_version.help_arguments = "[--tag=<tag>] {<package>|<rockspec>} [<new_version>] [<new_url>]"
17new_version.help = [[ 15new_version.help = [[
18This is a utility function that writes a new rockspec, updating data 16This is a utility function that writes a new rockspec, updating data
19from a previous one. 17from a previous one.
@@ -21,8 +19,10 @@ from a previous one.
21If a package name is given, it downloads the latest rockspec from the 19If a package name is given, it downloads the latest rockspec from the
22default server. If a rockspec is given, it uses it instead. 20default server. If a rockspec is given, it uses it instead.
23 21
24If the version number is not given, it only increments the revision 22If the version number is not given and tag is passed using --tag,
25number of the given (or downloaded) rockspec. 23it is used as the version, with 'v' removed from beginning.
24Otherwise, it only increments the revision number of the given
25(or downloaded) rockspec.
26 26
27If a URL is given, it replaces the one from the old rockspec with the 27If a URL is given, it replaces the one from the old rockspec with the
28given URL. If a URL is not given and a new version is given, it tries 28given URL. If a URL is not given and a new version is given, it tries
@@ -30,6 +30,9 @@ to guess the new URL by replacing occurrences of the version number
30in the URL or tag. It also tries to download the new URL to determine 30in the URL or tag. It also tries to download the new URL to determine
31the new MD5 checksum. 31the new MD5 checksum.
32 32
33If a tag is given, it replaces the one from the old rockspec. If there is
34an old tag but no new one passed, it is guessed in the same way URL is.
35
33WARNING: it writes the new rockspec to the current directory, 36WARNING: it writes the new rockspec to the current directory,
34overwriting the file if it already exists. 37overwriting the file if it already exists.
35]] 38]]
@@ -48,58 +51,73 @@ local function try_replace(tbl, field, old, new)
48 return false 51 return false
49end 52end
50 53
51local function check_url_and_update_md5(out_rs, out_name) 54-- Try to download source file using URL from a rockspec.
52 local old_md5 = out_rs.source.md5 55-- If it specified MD5, update it.
53 out_rs.source.md5 = nil 56-- @return (true, false) if MD5 was not specified or it stayed same,
54 local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_name) 57-- (true, true) if MD5 changed, (nil, string) on error.
58local function check_url_and_update_md5(out_rs)
59 local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_rs.package)
55 if not file then 60 if not file then
56 util.printerr("Warning: invalid URL - "..temp_dir) 61 util.printerr("Warning: invalid URL - "..temp_dir)
57 return true 62 return true, false
58 end 63 end
59 util.printout("File successfully downloaded. Updating MD5 checksum...") 64
60 out_rs.source.md5 = fs.get_md5(file)
61 local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir) 65 local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir)
62 if not inferred_dir then 66 if not inferred_dir then
63 return nil, found_dir 67 return nil, found_dir
64 end 68 end
69
65 if found_dir and found_dir ~= inferred_dir then 70 if found_dir and found_dir ~= inferred_dir then
66 out_rs.source.dir = found_dir 71 out_rs.source.dir = found_dir
67 end 72 end
68 return out_rs.source.md5 ~= old_md5 73
74 if file then
75 if out_rs.source.md5 then
76 util.printout("File successfully downloaded. Updating MD5 checksum...")
77 local new_md5, err = fs.get_md5(file)
78 if not new_md5 then
79 return nil, err
80 end
81 local old_md5 = out_rs.source.md5
82 out_rs.source.md5 = new_md5
83 return true, new_md5 ~= old_md5
84 else
85 util.printout("File successfully downloaded.")
86 return true, false
87 end
88 end
69end 89end
70 90
71local function update_source_section(out_rs, out_name, url, old_ver, new_ver) 91local function update_source_section(out_rs, url, tag, old_ver, new_ver)
92 if tag then
93 out_rs.source.tag = tag
94 end
72 if url then 95 if url then
73 out_rs.source.url = url 96 out_rs.source.url = url
74 check_url_and_update_md5(out_rs, out_name) 97 return check_url_and_update_md5(out_rs)
75 return true
76 end 98 end
77 if new_ver == old_ver then 99 if new_ver == old_ver then
78 return true 100 return true
79 end 101 end
80 if not out_rs.source then
81 return nil, "'source' table is missing. Invalid rockspec?"
82 end
83 if out_rs.source.dir then 102 if out_rs.source.dir then
84 try_replace(out_rs.source, "dir", old_ver, new_ver) 103 try_replace(out_rs.source, "dir", old_ver, new_ver)
85 end 104 end
86 if out_rs.source.file then 105 if out_rs.source.file then
87 try_replace(out_rs.source, "file", old_ver, new_ver) 106 try_replace(out_rs.source, "file", old_ver, new_ver)
88 end 107 end
89 local ok = try_replace(out_rs.source, "url", old_ver, new_ver) 108 if try_replace(out_rs.source, "url", old_ver, new_ver) then
90 if ok then 109 return check_url_and_update_md5(out_rs)
91 check_url_and_update_md5(out_rs, out_name) 110 end
111 if tag or try_replace(out_rs.source, "tag", old_ver, new_ver) then
92 return true 112 return true
93 end 113 end
94 ok = try_replace(out_rs.source, "tag", old_ver, new_ver) 114 -- Couldn't replace anything significant, use the old URL.
115 local ok, md5_changed = check_url_and_update_md5(out_rs)
95 if not ok then 116 if not ok then
96 ok = check_url_and_update_md5(out_rs, out_name) 117 return nil, md5_changed
97 if ok then
98 util.printerr("Warning: URL is the same, but MD5 has changed. Old rockspec is broken.")
99 end
100 end 118 end
101 if not ok then 119 if md5_changed then
102 return nil, "Failed to determine the location of the new version." 120 util.printerr("Warning: URL is the same, but MD5 has changed. Old rockspec is broken.")
103 end 121 end
104 return true 122 return true
105end 123end
@@ -107,7 +125,7 @@ end
107function new_version.run(...) 125function new_version.run(...)
108 local flags, input, version, url = util.parse_flags(...) 126 local flags, input, version, url = util.parse_flags(...)
109 if not input then 127 if not input then
110 return nil, "Missing arguments: expected program or rockspec. "..util.see_help("new_version") 128 return nil, "Missing argument: expected package or rockspec. "..util.see_help("new_version")
111 end 129 end
112 assert(type(input) == "string") 130 assert(type(input) == "string")
113 131
@@ -127,6 +145,10 @@ function new_version.run(...)
127 145
128 local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$") 146 local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$")
129 local new_ver, new_rev 147 local new_ver, new_rev
148
149 if flags.tag and not version then
150 version = flags.tag:gsub("^v", "")
151 end
130 152
131 if version then 153 if version then
132 new_ver, new_rev = version:match("(.*)%-(%d+)$") 154 new_ver, new_rev = version:match("(.*)%-(%d+)$")
@@ -145,7 +167,7 @@ function new_version.run(...)
145 local out_name = out_rs.package:lower() 167 local out_name = out_rs.package:lower()
146 out_rs.version = new_rockver.."-"..new_rev 168 out_rs.version = new_rockver.."-"..new_rev
147 169
148 local ok, err = update_source_section(out_rs, out_name, url, old_ver, new_ver) 170 local ok, err = update_source_section(out_rs, url, flags.tag, old_ver, new_ver)
149 if not ok then return nil, err end 171 if not ok then return nil, err end
150 172
151 if out_rs.build and out_rs.build.type == "module" then 173 if out_rs.build and out_rs.build.type == "module" then
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua
index 519f32b0..37ff846a 100644
--- a/src/luarocks/path.lua
+++ b/src/luarocks/path.lua
@@ -344,44 +344,48 @@ function path.map_trees(deps_mode, fn, ...)
344 return result 344 return result
345end 345end
346 346
347local is_src_extension = { [".lua"] = true, [".tl"] = true, [".tld"] = true, [".moon"] = true }
348
347--- Return the pathname of the file that would be loaded for a module, indexed. 349--- Return the pathname of the file that would be loaded for a module, indexed.
348-- @param module_name string: module name (eg. "socket.core") 350-- @param file_name string: module file name as in manifest (eg. "socket/core.so")
349-- @param name string: name of the package (eg. "luasocket") 351-- @param name string: name of the package (eg. "luasocket")
350-- @param version string: version number (eg. "2.0.2-1") 352-- @param version string: version number (eg. "2.0.2-1")
351-- @param tree string: repository path (eg. "/usr/local") 353-- @param tree string: repository path (eg. "/usr/local")
352-- @param i number: the index, 1 if version is the current default, > 1 otherwise. 354-- @param i number: the index, 1 if version is the current default, > 1 otherwise.
353-- This is done this way for use by select_module in luarocks.loader. 355-- This is done this way for use by select_module in luarocks.loader.
354-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") 356-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
355function path.which_i(module_name, name, version, tree, i) 357function path.which_i(file_name, name, version, tree, i)
356 local deploy_dir 358 local deploy_dir
357 if module_name:match("%.lua$") then 359 local extension = file_name:match("%.[a-z]+$")
360 if is_src_extension[extension] then
358 deploy_dir = path.deploy_lua_dir(tree) 361 deploy_dir = path.deploy_lua_dir(tree)
359 module_name = dir.path(deploy_dir, module_name) 362 file_name = dir.path(deploy_dir, file_name)
360 else 363 else
361 deploy_dir = path.deploy_lib_dir(tree) 364 deploy_dir = path.deploy_lib_dir(tree)
362 module_name = dir.path(deploy_dir, module_name) 365 file_name = dir.path(deploy_dir, file_name)
363 end 366 end
364 if i > 1 then 367 if i > 1 then
365 module_name = path.versioned_name(module_name, deploy_dir, name, version) 368 file_name = path.versioned_name(file_name, deploy_dir, name, version)
366 end 369 end
367 return module_name 370 return file_name
368end 371end
369 372
370--- Return the pathname of the file that would be loaded for a module, 373--- Return the pathname of the file that would be loaded for a module,
371-- returning the versioned pathname if given version is not the default version 374-- returning the versioned pathname if given version is not the default version
372-- in the given manifest. 375-- in the given manifest.
373-- @param module_name string: module name (eg. "socket.core") 376-- @param module_name string: module name (eg. "socket.core")
377-- @param file_name string: module file name as in manifest (eg. "socket/core.so")
374-- @param name string: name of the package (eg. "luasocket") 378-- @param name string: name of the package (eg. "luasocket")
375-- @param version string: version number (eg. "2.0.2-1") 379-- @param version string: version number (eg. "2.0.2-1")
376-- @param tree string: repository path (eg. "/usr/local") 380-- @param tree string: repository path (eg. "/usr/local")
377-- @param manifest table: the manifest table for the tree. 381-- @param manifest table: the manifest table for the tree.
378-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") 382-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
379function path.which(module_name, filename, name, version, tree, manifest) 383function path.which(module_name, file_name, name, version, tree, manifest)
380 local versions = manifest.modules[module_name] 384 local versions = manifest.modules[module_name]
381 assert(versions) 385 assert(versions)
382 for i, name_version in ipairs(versions) do 386 for i, name_version in ipairs(versions) do
383 if name_version == name.."/"..version then 387 if name_version == name.."/"..version then
384 return path.which_i(filename, name, version, tree, i):gsub("//", "/") 388 return path.which_i(file_name, name, version, tree, i):gsub("//", "/")
385 end 389 end
386 end 390 end
387 assert(false) 391 assert(false)
diff --git a/src/luarocks/path_cmd.lua b/src/luarocks/path_cmd.lua
index 4aeba41c..ecd6d4b1 100644
--- a/src/luarocks/path_cmd.lua
+++ b/src/luarocks/path_cmd.lua
@@ -6,7 +6,6 @@ local path_cmd = {}
6local util = require("luarocks.util") 6local util = require("luarocks.util")
7local deps = require("luarocks.deps") 7local deps = require("luarocks.deps")
8local cfg = require("luarocks.cfg") 8local cfg = require("luarocks.cfg")
9local path = require("luarocks.path")
10 9
11path_cmd.help_summary = "Return the currently configured package path." 10path_cmd.help_summary = "Return the currently configured package path."
12path_cmd.help_arguments = "" 11path_cmd.help_arguments = ""
@@ -38,7 +37,8 @@ function path_cmd.run(...)
38 local flags = util.parse_flags(...) 37 local flags = util.parse_flags(...)
39 local deps_mode = deps.get_deps_mode(flags) 38 local deps_mode = deps.get_deps_mode(flags)
40 39
41 local lr_path, lr_cpath, lr_bin = cfg.package_paths() 40 local lr_path, lr_cpath, lr_bin = cfg.package_paths(flags["tree"])
41 local path_sep = cfg.export_path_separator
42 42
43 if flags["lr-path"] then 43 if flags["lr-path"] then
44 util.printout(util.remove_path_dupes(lr_path, ';')) 44 util.printout(util.remove_path_dupes(lr_path, ';'))
@@ -47,24 +47,24 @@ function path_cmd.run(...)
47 util.printout(util.remove_path_dupes(lr_cpath, ';')) 47 util.printout(util.remove_path_dupes(lr_cpath, ';'))
48 return true 48 return true
49 elseif flags["lr-bin"] then 49 elseif flags["lr-bin"] then
50 util.printout(util.remove_path_dupes(lr_bin, ';')) 50 util.printout(util.remove_path_dupes(lr_bin, path_sep))
51 return true 51 return true
52 end 52 end
53 53
54 if flags["append"] then 54 if flags["append"] then
55 lr_path = package.path .. ";" .. lr_path 55 lr_path = package.path .. ";" .. lr_path
56 lr_cpath = package.cpath .. ";" .. lr_cpath 56 lr_cpath = package.cpath .. ";" .. lr_cpath
57 lr_bin = os.getenv("PATH") .. ";" .. lr_bin 57 lr_bin = os.getenv("PATH") .. path_sep .. lr_bin
58 else 58 else
59 lr_path = lr_path.. ";" .. package.path 59 lr_path = lr_path.. ";" .. package.path
60 lr_cpath = lr_cpath .. ";" .. package.cpath 60 lr_cpath = lr_cpath .. ";" .. package.cpath
61 lr_bin = lr_bin .. ";" .. os.getenv("PATH") 61 lr_bin = lr_bin .. path_sep .. os.getenv("PATH")
62 end 62 end
63 63
64 util.printout(cfg.export_lua_path:format(util.remove_path_dupes(lr_path, ';'))) 64 util.printout(cfg.export_lua_path:format(util.remove_path_dupes(lr_path, ';')))
65 util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(lr_cpath, ';'))) 65 util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(lr_cpath, ';')))
66 if flags["bin"] then 66 if flags["bin"] then
67 util.printout(cfg.export_path:format(util.remove_path_dupes(lr_bin,';'))) 67 util.printout(cfg.export_path:format(util.remove_path_dupes(lr_bin, path_sep)))
68 end 68 end
69 return true 69 return true
70end 70end
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua
index 9d601a43..354b17c3 100644
--- a/src/luarocks/persist.lua
+++ b/src/luarocks/persist.lua
@@ -9,60 +9,85 @@ package.loaded["luarocks.persist"] = persist
9 9
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11 11
12--- Load and run a Lua file in an environment.
13-- @param filename string: the name of the file.
14-- @param env table: the environment table.
15-- @return (true, any) or (nil, string, string): true and the return value
16-- of the file, or nil, an error message and an error code ("open", "load"
17-- or "run") in case of errors.
18local function run_file(filename, env)
19 local fd, err = io.open(filename)
20 if not fd then
21 return nil, err, "open"
22 end
23 local str, err = fd:read("*a")
24 fd:close()
25 if not str then
26 return nil, err, "open"
27 end
28 str = str:gsub("^#![^\n]*\n", "")
29 local chunk, ran
30 if _VERSION == "Lua 5.1" then -- Lua 5.1
31 chunk, err = loadstring(str, filename)
32 if chunk then
33 setfenv(chunk, env)
34 ran, err = pcall(chunk)
35 end
36 else -- Lua 5.2
37 chunk, err = load(str, filename, "t", env)
38 if chunk then
39 ran, err = pcall(chunk)
40 end
41 end
42 if not chunk then
43 return nil, "Error loading file: "..err, "load"
44 end
45 if not ran then
46 return nil, "Error running file: "..err, "run"
47 end
48 return true, err
49end
50
12--- Load a Lua file containing assignments, storing them in a table. 51--- Load a Lua file containing assignments, storing them in a table.
13-- The global environment is not propagated to the loaded file. 52-- The global environment is not propagated to the loaded file.
14-- @param filename string: the name of the file. 53-- @param filename string: the name of the file.
15-- @param tbl table or nil: if given, this table is used to store 54-- @param tbl table or nil: if given, this table is used to store
16-- loaded values. 55-- loaded values.
17-- @return table or (nil, string): a table with the file's assignments 56-- @return (table, table) or (nil, string, string): a table with the file's assignments
18-- as fields, or nil and a message in case of errors. 57-- as fields and set of undefined globals accessed in file,
58-- or nil, an error message and an error code ("open"; couldn't open the file,
59-- "load"; compile-time error, or "run"; run-time error)
60-- in case of errors.
19function persist.load_into_table(filename, tbl) 61function persist.load_into_table(filename, tbl)
20 assert(type(filename) == "string") 62 assert(type(filename) == "string")
21 assert(type(tbl) == "table" or not tbl) 63 assert(type(tbl) == "table" or not tbl)
22 64
23 local result, chunk, ran, err 65 local result = tbl or {}
24 result = tbl or {}
25 local globals = {} 66 local globals = {}
26 local globals_mt = { 67 local globals_mt = {
27 __index = function(t, n) 68 __index = function(t, k)
28 globals[n] = true 69 globals[k] = true
29 return rawget(t, n)
30 end 70 end
31 } 71 }
32 local save_mt = getmetatable(result) 72 local save_mt = getmetatable(result)
33 setmetatable(result, globals_mt) 73 setmetatable(result, globals_mt)
34 if _VERSION == "Lua 5.1" then -- Lua 5.1
35 chunk, err = loadfile(filename)
36 if chunk then
37 setfenv(chunk, result)
38 ran, err = pcall(chunk)
39 end
40 else -- Lua 5.2
41 chunk, err = loadfile(filename, "t", result)
42 if chunk then
43 ran, err = pcall(chunk)
44 end
45 end
46 setmetatable(result, save_mt)
47 74
48 if not chunk then 75 local ok, err, errcode = run_file(filename, result)
49 if err:sub(1,5) ~= filename:sub(1,5) then 76
50 return false, err 77 setmetatable(result, save_mt)
51 end 78
52 return nil, "Error loading file: "..err 79 if not ok then
53 end 80 return nil, err, errcode
54 if not ran then
55 return nil, "Error running file: "..err
56 end 81 end
57 return result, globals 82 return result, globals
58end 83end
59 84
60local write_table 85local write_table
61 86
62--- Write a value as Lua code, invoking write_table. 87--- Write a value as Lua code.
63-- This function handles only numbers, strings and tables 88-- This function handles only numbers and strings, invoking write_table
64-- are keys (tables are handled recursively). 89-- to write tables.
65-- @param out userdata: a file object, open for writing. 90-- @param out table or userdata: a writer object supporting :write() method.
66-- @param v: the value to be written. 91-- @param v: the value to be written.
67-- @param level number: the indentation level 92-- @param level number: the indentation level
68-- @param sub_order table: optional prioritization table 93-- @param sub_order table: optional prioritization table
@@ -71,28 +96,27 @@ local function write_value(out, v, level, sub_order)
71 if type(v) == "table" then 96 if type(v) == "table" then
72 write_table(out, v, level + 1, sub_order) 97 write_table(out, v, level + 1, sub_order)
73 elseif type(v) == "string" then 98 elseif type(v) == "string" then
74 if v:match("\n") then 99 if v:match("[\r\n]") then
75 local open, close = "[[", "]]" 100 local open, close = "[[", "]]"
76 local equals = 0 101 local equals = 0
77 while v:find(open,1,true) or v:find(close,1,true) do 102 while v:find(close, 1, true) do
78 equals = equals + 1 103 equals = equals + 1
79 local eqs = ("="):rep(equals) 104 local eqs = ("="):rep(equals)
80 open, close = "["..eqs.."[", "]"..eqs.."]" 105 open, close = "["..eqs.."[", "]"..eqs.."]"
81 end 106 end
82 out:write(open.."\n"..v..close) 107 out:write(open.."\n"..v..close)
83 else 108 else
84 out:write("\""..v:gsub("\"", "\\\"").."\"") 109 out:write("\""..v:gsub("\\", "\\\\"):gsub("\"", "\\\"").."\"")
85 end 110 end
86 else 111 else
87 out:write(tostring(v)) 112 out:write(tostring(v))
88 end 113 end
89end 114end
90 115
91--- Write a table as Lua code representing a table to disk 116--- Write a table as Lua code in curly brackets notation to a writer object.
92-- (that is, in curly brackets notation). 117-- Only numbers, strings and tables (containing numbers, strings
93-- This function handles only numbers, strings and tables 118-- or other recursively processed tables) are supported.
94-- are keys (tables are handled recursively). 119-- @param out table or userdata: a writer object supporting :write() method.
95-- @param out userdata: a file object, open for writing.
96-- @param tbl table: the table to be written. 120-- @param tbl table: the table to be written.
97-- @param level number: the indentation level 121-- @param level number: the indentation level
98-- @param field_order table: optional prioritization table 122-- @param field_order table: optional prioritization table
@@ -107,28 +131,29 @@ write_table = function(out, tbl, level, field_order)
107 if indent then 131 if indent then
108 for n = 1,level do out:write(indentation) end 132 for n = 1,level do out:write(indentation) end
109 end 133 end
110 sep = ",\n" 134
111 indent = true 135 if k == i then
112 if type(k) == "number" then 136 i = i + 1
113 if k ~= i then
114 out:write("["..tostring(k).."]=")
115 else
116 i = i + 1
117 end
118 indent = false
119 sep = ", "
120 elseif type(k) == "table" then
121 out:write("[")
122 write_table(out, k, level + 1)
123 out:write("] = ")
124 else 137 else
125 if k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then 138 if type(k) == "string" and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
126 out:write(k.." = ") 139 out:write(k)
127 else 140 else
128 out:write("['"..k:gsub("'", "\\'").."'] = ") 141 out:write("[")
142 write_value(out, k, level)
143 out:write("]")
129 end 144 end
145
146 out:write(" = ")
130 end 147 end
148
131 write_value(out, v, level, sub_order) 149 write_value(out, v, level, sub_order)
150 if type(k) == "number" then
151 sep = ", "
152 indent = false
153 else
154 sep = ",\n"
155 indent = true
156 end
132 end 157 end
133 if sep ~= "\n" then 158 if sep ~= "\n" then
134 out:write("\n") 159 out:write("\n")
@@ -137,18 +162,16 @@ write_table = function(out, tbl, level, field_order)
137 out:write("}") 162 out:write("}")
138end 163end
139 164
140--- Writes a table to an io-like object. 165--- Write a table as series of assignments to a writer object.
141-- @param out userdata: a file object, open for writing. 166-- @param out table or userdata: a writer object supporting :write() method.
142-- @param tbl table: the table to be written. 167-- @param tbl table: the table to be written.
143-- @param field_order table: optional prioritization table 168-- @param field_order table: optional prioritization table
144-- @return userdata The file object originally passed in as the `out` parameter. 169local function write_table_as_assignments(out, tbl, field_order)
145local function write_table(out, tbl, field_order)
146 for k, v, sub_order in util.sortedpairs(tbl, field_order) do 170 for k, v, sub_order in util.sortedpairs(tbl, field_order) do
147 out:write(k.." = ") 171 out:write(k.." = ")
148 write_value(out, v, 0, sub_order) 172 write_value(out, v, 0, sub_order)
149 out:write("\n") 173 out:write("\n")
150 end 174 end
151 return out
152end 175end
153 176
154--- Save the contents of a table to a string. 177--- Save the contents of a table to a string.
@@ -161,7 +184,7 @@ end
161function persist.save_from_table_to_string(tbl, field_order) 184function persist.save_from_table_to_string(tbl, field_order)
162 local out = {buffer = {}} 185 local out = {buffer = {}}
163 function out:write(data) table.insert(self.buffer, data) end 186 function out:write(data) table.insert(self.buffer, data) end
164 write_table(out, tbl, field_order) 187 write_table_as_assignments(out, tbl, field_order)
165 return table.concat(out.buffer) 188 return table.concat(out.buffer)
166end 189end
167 190
@@ -179,7 +202,7 @@ function persist.save_from_table(filename, tbl, field_order)
179 if not out then 202 if not out then
180 return nil, "Cannot create file at "..filename 203 return nil, "Cannot create file at "..filename
181 end 204 end
182 write_table(out, tbl, field_order) 205 write_table_as_assignments(out, tbl, field_order)
183 out:close() 206 out:close()
184 return true 207 return true
185end 208end
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua
index 595df8f4..5d419817 100644
--- a/src/luarocks/remove.lua
+++ b/src/luarocks/remove.lua
@@ -159,7 +159,7 @@ function remove.run(...)
159 local results = {} 159 local results = {}
160 search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version)) 160 search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
161 if not results[name] then 161 if not results[name] then
162 return nil, "Could not find rock '"..name..(version and " "..version or "").."' in local tree." 162 return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir)
163 end 163 end
164 164
165 return remove.remove_search_results(results, name, deps_mode, flags["force"]) 165 return remove.remove_search_results(results, name, deps_mode, flags["force"])
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 53439386..6c0020c0 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -48,7 +48,8 @@ end
48 48
49--- Store a search result (a rock or rockspec) in the results table. 49--- Store a search result (a rock or rockspec) in the results table.
50-- @param results table: The results table, where keys are package names and 50-- @param results table: The results table, where keys are package names and
51-- versions are tables matching version strings to an array of servers. 51-- values are tables matching version strings to arrays of
52-- tables with fields "arch" and "repo".
52-- @param name string: Package name. 53-- @param name string: Package name.
53-- @param version string: Package version. 54-- @param version string: Package version.
54-- @param arch string: Architecture of rock ("all", "src" or platform 55-- @param arch string: Architecture of rock ("all", "src" or platform
@@ -92,7 +93,8 @@ end
92-- table, optionally checking if version and arch (if given) match 93-- table, optionally checking if version and arch (if given) match
93-- a query. 94-- a query.
94-- @param results table: The results table, where keys are package names and 95-- @param results table: The results table, where keys are package names and
95-- versions are tables matching version strings to an array of servers. 96-- values are tables matching version strings to arrays of
97-- tables with fields "arch" and "repo".
96-- @param repo string: URL or pathname of the repository. 98-- @param repo string: URL or pathname of the repository.
97-- @param name string: The name of the package being tested. 99-- @param name string: The name of the package being tested.
98-- @param version string: The version of the package being tested. 100-- @param version string: The version of the package being tested.
@@ -123,8 +125,9 @@ end
123-- matches regardless of architecture. 125-- matches regardless of architecture.
124-- @param results table or nil: If given, this table will store the 126-- @param results table or nil: If given, this table will store the
125-- results; if not given, a new table will be created. 127-- results; if not given, a new table will be created.
126-- @param table: The results table, where keys are package names and 128-- @return table: The results table, where keys are package names and
127-- versions are tables matching version strings to an array of servers. 129-- values are tables matching version strings to arrays of
130-- tables with fields "arch" and "repo".
128-- If a table was given in the "results" parameter, that is the result value. 131-- If a table was given in the "results" parameter, that is the result value.
129function search.disk_search(repo, query, results) 132function search.disk_search(repo, query, results)
130 assert(type(repo) == "string") 133 assert(type(repo) == "string")
@@ -155,24 +158,27 @@ function search.disk_search(repo, query, results)
155 return results 158 return results
156end 159end
157 160
158--- Perform search on a rocks server. 161--- Perform search on a rocks server or tree.
159-- @param results table: The results table, where keys are package names and 162-- @param results table: The results table, where keys are package names and
160-- versions are tables matching version strings to an array of servers. 163-- values are tables matching version strings to arrays of
161-- @param repo string: The URL of the rocks server. 164-- tables with fields "arch" and "repo".
165-- @param repo string: The URL of a rocks server or
166-- the pathname of a rocks tree (as returned by path.rocks_dir()).
162-- @param query table: A table describing the query in dependency 167-- @param query table: A table describing the query in dependency
163-- format (for example, {name = "filesystem", exact_name = false, 168-- format (for example, {name = "filesystem", exact_name = false,
164-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec"). 169-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
165-- If the arch field is omitted, the local architecture (cfg.arch) 170-- If the arch field is omitted, the local architecture (cfg.arch)
166-- is used. The special value "any" is also recognized, returning all 171-- is used. The special value "any" is also recognized, returning all
167-- matches regardless of architecture. 172-- matches regardless of architecture.
168-- @return true or, in case of errors, nil and an error message. 173-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
169function search.manifest_search(results, repo, query) 174-- @return true or, in case of errors, nil, an error message and an optional error code.
175function search.manifest_search(results, repo, query, lua_version)
170 assert(type(results) == "table") 176 assert(type(results) == "table")
171 assert(type(repo) == "string") 177 assert(type(repo) == "string")
172 assert(type(query) == "table") 178 assert(type(query) == "table")
173 179
174 query_arch_as_table(query) 180 query_arch_as_table(query)
175 local manifest, err, errcode = manif.load_manifest(repo) 181 local manifest, err, errcode = manif.load_manifest(repo, lua_version)
176 if not manifest then 182 if not manifest then
177 return nil, err, errcode 183 return nil, err, errcode
178 end 184 end
@@ -188,10 +194,11 @@ end
188 194
189--- Search on all configured rocks servers. 195--- Search on all configured rocks servers.
190-- @param query table: A dependency query. 196-- @param query table: A dependency query.
197-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
191-- @return table: A table where keys are package names 198-- @return table: A table where keys are package names
192-- and values are tables matching version strings to an array of 199-- and values are tables matching version strings to arrays of
193-- rocks servers; if no results are found, an empty table is returned. 200-- tables with fields "arch" and "repo".
194function search.search_repos(query) 201function search.search_repos(query, lua_version)
195 assert(type(query) == "table") 202 assert(type(query) == "table")
196 203
197 local results = {} 204 local results = {}
@@ -205,7 +212,7 @@ function search.search_repos(query)
205 if protocol == "file" then 212 if protocol == "file" then
206 mirror = pathname 213 mirror = pathname
207 end 214 end
208 local ok, err, errcode = search.manifest_search(results, mirror, query) 215 local ok, err, errcode = search.manifest_search(results, mirror, query, lua_version)
209 if errcode == "network" then 216 if errcode == "network" then
210 cfg.disabled_servers[repo] = true 217 cfg.disabled_servers[repo] = true
211 end 218 end
@@ -273,28 +280,66 @@ local function pick_latest_version(name, versions)
273 return nil 280 return nil
274end 281end
275 282
276--- Attempt to get a single URL for a given search. 283-- Find out which other Lua versions provide rock versions matching a query,
277-- @param query table: A dependency query. 284-- @param query table: A dependency query matching a single rock.
278-- @return string or table or (nil, string): URL for matching rock if 285-- @return table: array of Lua versions supported, in "5.x" format.
279-- a single one was found, a table of candidates if it could not narrow to 286local function supported_lua_versions(query)
280-- a single result, or nil followed by an error message. 287 local results = {}
288
289 for lua_version in util.lua_versions() do
290 if lua_version ~= cfg.lua_version then
291 if search.search_repos(query, lua_version)[query.name] then
292 table.insert(results, lua_version)
293 end
294 end
295 end
296
297 return results
298end
299
300--- Attempt to get a single URL for a given search for a rock.
301-- @param query table: A dependency query matching a single rock.
302-- @return string or (nil, string): URL for latest matching version
303-- of the rock if it was found, or nil followed by an error message.
281function search.find_suitable_rock(query) 304function search.find_suitable_rock(query)
282 assert(type(query) == "table") 305 assert(type(query) == "table")
283 306
284 local results = search.search_repos(query) 307 local results = search.search_repos(query)
285 local first = next(results) 308 local first_rock = next(results)
286 if not first then 309 if not first_rock then
287 return nil, "No results matching query were found." 310 if cfg.rocks_provided[query.name] == nil then
288 elseif not next(results, first) then 311 -- Check if constraints are satisfiable with other Lua versions.
289 if cfg.rocks_provided[query.name] ~= nil then 312 local lua_versions = supported_lua_versions(query)
290 -- do not install versions that listed in cfg.rocks_provided 313
291 return nil, "Rock "..query.name.. 314 if #lua_versions ~= 0 then
292 " "..cfg.rocks_provided[query.name].. 315 -- Build a nice message in "only Lua 5.x and 5.y but not 5.z." format
293 " was found but it is provided by VM or 'rocks_provided' in the config file." 316 for i, lua_version in ipairs(lua_versions) do
317 lua_versions[i] = "Lua "..lua_version
318 end
319
320 local versions_message = "only "..table.concat(lua_versions, " and ")..
321 " but not Lua "..cfg.lua_version.."."
322
323 if #query.constraints == 0 then
324 return nil, query.name.." supports "..versions_message
325 elseif #query.constraints == 1 and query.constraints[1].op == "==" then
326 return nil, query.name.." "..query.constraints[1].version.string.." supports "..versions_message
327 else
328 return nil, "Matching "..query.name.." versions support "..versions_message
329 end
330 end
294 end 331 end
295 return pick_latest_version(query.name, results[first]) 332
333 return nil, "No results matching query were found."
334 elseif next(results, first_rock) then
335 -- Shouldn't happen as query must match only one package.
336 return nil, "Several rocks matched query."
337 elseif cfg.rocks_provided[query.name] ~= nil then
338 -- Do not install versions listed in cfg.rocks_provided.
339 return nil, "Rock "..query.name.." "..cfg.rocks_provided[query.name]..
340 " was found but it is provided by VM or 'rocks_provided' in the config file."
296 else 341 else
297 return results 342 return pick_latest_version(query.name, results[first_rock])
298 end 343 end
299end 344end
300 345
@@ -364,12 +409,11 @@ function search.act_on_src_or_rockspec(action, name, version, ...)
364 409
365 local query = search.make_query(name, version) 410 local query = search.make_query(name, version)
366 query.arch = "src|rockspec" 411 query.arch = "src|rockspec"
367 local results, err = search.find_suitable_rock(query) 412 local url, err = search.find_suitable_rock(query)
368 if type(results) == "string" then 413 if not url then
369 return action(results, ...) 414 return nil, "Could not find a result named "..name..(version and " "..version or "")..": "..err
370 else
371 return nil, "Could not find a result named "..name..(version and " "..version or "").."."
372 end 415 end
416 return action(url, ...)
373end 417end
374 418
375--- Driver function for "search" command. 419--- Driver function for "search" command.
diff --git a/src/luarocks/show.lua b/src/luarocks/show.lua
index 3243c0ce..ae41a513 100644
--- a/src/luarocks/show.lua
+++ b/src/luarocks/show.lua
@@ -11,7 +11,7 @@ local path = require("luarocks.path")
11local deps = require("luarocks.deps") 11local deps = require("luarocks.deps")
12local fetch = require("luarocks.fetch") 12local fetch = require("luarocks.fetch")
13local manif = require("luarocks.manif") 13local manif = require("luarocks.manif")
14show.help_summary = "Shows information about an installed rock." 14show.help_summary = "Show information about an installed rock."
15 15
16show.help = [[ 16show.help = [[
17<argument> is an existing package name. 17<argument> is an existing package name.
@@ -28,7 +28,9 @@ With these flags, return only the desired information:
28]] 28]]
29 29
30local function keys_as_string(t, sep) 30local function keys_as_string(t, sep)
31 return table.concat(util.keys(t), sep or " ") 31 local keys = util.keys(t)
32 table.sort(keys)
33 return table.concat(keys, sep or " ")
32end 34end
33 35
34local function word_wrap(line) 36local function word_wrap(line)
@@ -88,6 +90,16 @@ function show.pick_installed_rock(name, version, tree)
88 return name, version, repo, repo_url 90 return name, version, repo, repo_url
89end 91end
90 92
93local function installed_rock_label(name, tree)
94 local installed, version
95 if cfg.rocks_provided[name] then
96 installed, version = true, cfg.rocks_provided[name]
97 else
98 installed, version = show.pick_installed_rock(name, nil, tree)
99 end
100 return installed and "(using "..version..")" or "(missing)"
101end
102
91--- Driver function for "show" command. 103--- Driver function for "show" command.
92-- @param name or nil: an existing package name. 104-- @param name or nil: an existing package name.
93-- @param version string or nil: a version may also be passed. 105-- @param version string or nil: a version may also be passed.
@@ -143,10 +155,26 @@ function show.run(...)
143 util.printout("\t"..mod.." ("..path.which(mod, filename, name, version, repo, manifest)..")") 155 util.printout("\t"..mod.." ("..path.which(mod, filename, name, version, repo, manifest)..")")
144 end 156 end
145 end 157 end
146 if next(minfo.dependencies) then 158 local direct_deps = {}
159 if #rockspec.dependencies > 0 then
147 util.printout() 160 util.printout()
148 util.printout("Depends on:") 161 util.printout("Depends on:")
149 util.printout("\t"..keys_as_string(minfo.dependencies, "\n\t")) 162 for _, dep in ipairs(rockspec.dependencies) do
163 direct_deps[dep.name] = true
164 util.printout("\t"..deps.show_dep(dep).." "..installed_rock_label(dep.name, flags["tree"]))
165 end
166 end
167 local has_indirect_deps
168 for dep_name in util.sortedpairs(minfo.dependencies) do
169 if not direct_deps[dep_name] then
170 if not has_indirect_deps then
171 util.printout()
172 util.printout("Indirectly pulling:")
173 has_indirect_deps = true
174 end
175
176 util.printout("\t"..dep_name.." "..installed_rock_label(dep_name, flags["tree"]))
177 end
150 end 178 end
151 util.printout() 179 util.printout()
152 end 180 end
diff --git a/src/luarocks/tools/patch.lua b/src/luarocks/tools/patch.lua
index 8df3093d..debaf636 100644
--- a/src/luarocks/tools/patch.lua
+++ b/src/luarocks/tools/patch.lua
@@ -22,8 +22,8 @@ local format = string.format
22 22
23-- logging 23-- logging
24local debugmode = false 24local debugmode = false
25local function debug(s) end 25local function debug(_) end
26local function info(s) end 26local function info(_) end
27local function warning(s) io.stderr:write(s .. '\n') end 27local function warning(s) io.stderr:write(s .. '\n') end
28 28
29-- Returns boolean whether string s2 starts with string s. 29-- Returns boolean whether string s2 starts with string s.
@@ -57,27 +57,30 @@ end
57local function isfile() return true end --FIX? 57local function isfile() return true end --FIX?
58 58
59local function read_file(filename) 59local function read_file(filename)
60 local fh, err, oserr = io.open(filename, 'rb') 60 local fh, data, err, oserr
61 fh, err, oserr = io.open(filename, 'rb')
61 if not fh then return fh, err, oserr end 62 if not fh then return fh, err, oserr end
62 local data, err, oserr = fh:read'*a' 63 data, err, oserr = fh:read'*a'
63 fh:close() 64 fh:close()
64 if not data then return nil, err, oserr end 65 if not data then return nil, err, oserr end
65 return data 66 return data
66end 67end
67 68
68local function write_file(filename, data) 69local function write_file(filename, data)
69 local fh, err, oserr = io.open(filename 'wb') 70 local fh, status, err, oserr
71 fh, err, oserr = io.open(filename 'wb')
70 if not fh then return fh, err, oserr end 72 if not fh then return fh, err, oserr end
71 local status, err, oserr = fh:write(data) 73 status, err, oserr = fh:write(data)
72 fh:close() 74 fh:close()
73 if not status then return nil, err, oserr end 75 if not status then return nil, err, oserr end
74 return true 76 return true
75end 77end
76 78
77local function file_copy(src, dest) 79local function file_copy(src, dest)
78 local data, err, oserr = read_file(src) 80 local data, status, err, oserr
81 data, err, oserr = read_file(src)
79 if not data then return data, err, oserr end 82 if not data then return data, err, oserr end
80 local status, err, oserr = write_file(dest) 83 status, err, oserr = write_file(dest)
81 if not status then return status, err, oserr end 84 if not status then return status, err, oserr end
82 return true 85 return true
83end 86end
@@ -197,8 +200,13 @@ function patch.read_patch(filename, data)
197 if state == 'hunkbody' then 200 if state == 'hunkbody' then
198 -- skip hunkskip and hunkbody code until definition of hunkhead read 201 -- skip hunkskip and hunkbody code until definition of hunkhead read
199 202
203 if line:match"^[\r\n]*$" then
204 -- prepend space to empty lines to interpret them as context properly
205 line = " " .. line
206 end
207
200 -- process line first 208 -- process line first
201 if line:match"^[- +\\]" or line:match"^[\r\n]*$" then 209 if line:match"^[- +\\]" then
202 -- gather stats about line endings 210 -- gather stats about line endings
203 local he = files.hunkends[nextfileno] 211 local he = files.hunkends[nextfileno]
204 if endswith(line, "\r\n") then 212 if endswith(line, "\r\n") then
@@ -420,7 +428,7 @@ local function find_hunk(file, h, hno)
420 end 428 end
421 h.startsrc = location 429 h.startsrc = location
422 h.starttgt = h.starttgt + offset 430 h.starttgt = h.starttgt + offset
423 for i=1,fuzz do 431 for _=1,fuzz do
424 table.remove(h.text, 1) 432 table.remove(h.text, 1)
425 table.remove(h.text, #h.text) 433 table.remove(h.text, #h.text)
426 end 434 end
@@ -452,16 +460,15 @@ local function find_hunks(file, hunks)
452end 460end
453 461
454local function check_patched(file, hunks) 462local function check_patched(file, hunks)
455 local matched = true
456 local lineno = 1 463 local lineno = 1
457 local ok, err = pcall(function() 464 local ok, err = pcall(function()
458 if #file == 0 then 465 if #file == 0 then
459 error 'nomatch' 466 error('nomatch', 0)
460 end 467 end
461 for hno, h in ipairs(hunks) do 468 for hno, h in ipairs(hunks) do
462 -- skip to line just before hunk starts 469 -- skip to line just before hunk starts
463 if #file < h.starttgt then 470 if #file < h.starttgt then
464 error 'nomatch' 471 error('nomatch', 0)
465 end 472 end
466 lineno = h.starttgt 473 lineno = h.starttgt
467 for _, hline in ipairs(h.text) do 474 for _, hline in ipairs(h.text) do
@@ -470,22 +477,18 @@ local function check_patched(file, hunks)
470 local line = file[lineno] 477 local line = file[lineno]
471 lineno = lineno + 1 478 lineno = lineno + 1
472 if #line == 0 then 479 if #line == 0 then
473 error 'nomatch' 480 error('nomatch', 0)
474 end 481 end
475 if endlstrip(line) ~= endlstrip(hline:sub(2)) then 482 if endlstrip(line) ~= endlstrip(hline:sub(2)) then
476 warning(format("file is not patched - failed hunk: %d", hno)) 483 warning(format("file is not patched - failed hunk: %d", hno))
477 error 'nomatch' 484 error('nomatch', 0)
478 end 485 end
479 end 486 end
480 end 487 end
481 end 488 end
482 end) 489 end)
483 if err == 'nomatch' then 490 -- todo: display failed hunk, i.e. expected/found
484 matched = false 491 return err ~= 'nomatch'
485 end
486 -- todo: display failed hunk, i.e. expected/found
487
488 return matched
489end 492end
490 493
491local function patch_hunks(srcname, tgtname, hunks) 494local function patch_hunks(srcname, tgtname, hunks)
@@ -532,7 +535,7 @@ local function patch_hunks(srcname, tgtname, hunks)
532 local line2write = hline:sub(2) 535 local line2write = hline:sub(2)
533 -- detect if line ends are consistent in source file 536 -- detect if line ends are consistent in source file
534 local sum = 0 537 local sum = 0
535 for k,v in pairs(lineends) do if v > 0 then sum=sum+1 end end 538 for _,v in pairs(lineends) do if v > 0 then sum=sum+1 end end
536 if sum == 1 then 539 if sum == 1 then
537 local newline 540 local newline
538 for k,v in pairs(lineends) do if v ~= 0 then newline = k end end 541 for k,v in pairs(lineends) do if v ~= 0 then newline = k end end
@@ -553,7 +556,7 @@ end
553 556
554local function strip_dirs(filename, strip) 557local function strip_dirs(filename, strip)
555 if strip == nil then return filename end 558 if strip == nil then return filename end
556 for i=1,strip do 559 for _=1,strip do
557 filename=filename:gsub("^[^/]*/", "") 560 filename=filename:gsub("^[^/]*/", "")
558 end 561 end
559 return filename 562 return filename
@@ -593,7 +596,6 @@ function patch.apply_patch(the_patch, strip)
593 local hunkno = 1 596 local hunkno = 1
594 local hunk = hunks[hunkno] 597 local hunk = hunks[hunkno]
595 local hunkfind = {} 598 local hunkfind = {}
596 local hunkreplace = {}
597 local validhunks = 0 599 local validhunks = 0
598 local canpatch = false 600 local canpatch = false
599 local hunklineno 601 local hunklineno
@@ -610,15 +612,10 @@ function patch.apply_patch(the_patch, strip)
610 elseif lineno == hunk.startsrc then 612 elseif lineno == hunk.startsrc then
611 hunkfind = {} 613 hunkfind = {}
612 for _,x in ipairs(hunk.text) do 614 for _,x in ipairs(hunk.text) do
613 if x:sub(1,1) == ' ' or x:sub(1,1) == '-' then 615 if x:sub(1,1) == ' ' or x:sub(1,1) == '-' then
614 hunkfind[#hunkfind+1] = endlstrip(x:sub(2)) 616 hunkfind[#hunkfind+1] = endlstrip(x:sub(2))
615 end end 617 end
616 hunkreplace = {} 618 end
617 for _,x in ipairs(hunk.text) do
618 if x:sub(1,1) == ' ' or x:sub(1,1) == '+' then
619 hunkreplace[#hunkreplace+1] = endlstrip(x:sub(2))
620 end end
621 --pprint(hunkreplace)
622 hunklineno = 1 619 hunklineno = 1
623 620
624 -- todo \ No newline at end of file 621 -- todo \ No newline at end of file
diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.lua
index 03f7de3c..b2bd930a 100644
--- a/src/luarocks/tools/tar.lua
+++ b/src/luarocks/tools/tar.lua
@@ -31,9 +31,10 @@ local function octal_to_number(octal)
31 local number = 0 31 local number = 0
32 for i = #octal,1,-1 do 32 for i = #octal,1,-1 do
33 local digit = tonumber(octal:sub(i,i)) 33 local digit = tonumber(octal:sub(i,i))
34 if not digit then break end 34 if digit then
35 number = number + (digit * 8^exp) 35 number = number + (digit * 8^exp)
36 exp = exp + 1 36 exp = exp + 1
37 end
37 end 38 end
38 return number 39 return number
39end 40end
@@ -143,6 +144,7 @@ function tar.untar(filename, destdir)
143 util.printout() 144 util.printout()
144 --]] 145 --]]
145 end 146 end
147 tar_handle:close()
146 return true 148 return true
147end 149end
148 150
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua
index 40cc089a..e6d9e36a 100644
--- a/src/luarocks/tools/zip.lua
+++ b/src/luarocks/tools/zip.lua
@@ -1,16 +1,38 @@
1 1
2--- A Lua implementation of .zip file archiving (used for creating .rock files), 2--- A Lua implementation of .zip file archiving (used for creating .rock files),
3-- using only lua-zlib. 3-- using only lzlib or lua-lzib.
4--module("luarocks.tools.zip", package.seeall)
5local zip = {} 4local zip = {}
6 5
7local zlib = require("zlib") 6local zlib = require("zlib")
8local fs = require("luarocks.fs") 7local fs = require("luarocks.fs")
9local dir = require("luarocks.dir") 8local dir = require("luarocks.dir")
10 9
10-- zlib module can be provided by both lzlib and lua-lzib packages.
11-- Create a compatibility layer.
12local zlib_compress, zlib_crc32
13if zlib._VERSION:match "^lua%-zlib" then
14 function zlib_compress(data)
15 return (zlib.deflate()(data, "finish"))
16 end
17
18 function zlib_crc32(data)
19 return zlib.crc32()(data)
20 end
21elseif zlib._VERSION:match "^lzlib" then
22 function zlib_compress(data)
23 return zlib.compress(data)
24 end
25
26 function zlib_crc32(data)
27 return zlib.crc32(zlib.crc32(), data)
28 end
29else
30 error("unknown zlib library", 0)
31end
32
11local function number_to_bytestring(number, nbytes) 33local function number_to_bytestring(number, nbytes)
12 local out = {} 34 local out = {}
13 for i = 1, nbytes do 35 for _ = 1, nbytes do
14 local byte = number % 256 36 local byte = number % 256
15 table.insert(out, string.char(byte)) 37 table.insert(out, string.char(byte))
16 number = (number - byte) / 256 38 number = (number - byte) / 256
@@ -31,32 +53,28 @@ local function zipwriter_open_new_file_in_zip(self, filename)
31 self.local_file_header = lfh 53 self.local_file_header = lfh
32 lfh.last_mod_file_time = 0 -- TODO 54 lfh.last_mod_file_time = 0 -- TODO
33 lfh.last_mod_file_date = 0 -- TODO 55 lfh.last_mod_file_date = 0 -- TODO
34 lfh.crc32 = 0 -- initial value
35 lfh.compressed_size = 0 -- unknown yet
36 lfh.uncompressed_size = 0 -- unknown yet
37 lfh.file_name_length = #filename 56 lfh.file_name_length = #filename
38 lfh.extra_field_length = 0 57 lfh.extra_field_length = 0
39 lfh.file_name = filename:gsub("\\", "/") 58 lfh.file_name = filename:gsub("\\", "/")
40 lfh.external_attr = 0 -- TODO properly store permissions 59 lfh.external_attr = 0 -- TODO properly store permissions
41 self.in_open_file = true 60 self.in_open_file = true
42 self.data = {}
43 return true 61 return true
44end 62end
45 63
46--- Write data to the file currently being stored in the zipfile. 64--- Write data to the file currently being stored in the zipfile.
47-- @param self handle of the zipfile being written. 65-- @param self handle of the zipfile being written.
48-- @param buf string containing data to be written. 66-- @param data string containing full contents of the file.
49-- @return true if succeeded, nil in case of failure. 67-- @return true if succeeded, nil in case of failure.
50local function zipwriter_write_file_in_zip(self, buf) 68local function zipwriter_write_file_in_zip(self, data)
51 if not self.in_open_file then 69 if not self.in_open_file then
52 return nil 70 return nil
53 end 71 end
54 local lfh = self.local_file_header 72 local lfh = self.local_file_header
55 local cbuf = zlib.compress(buf):sub(3, -5) 73 local compressed = zlib_compress(data):sub(3, -5)
56 lfh.crc32 = zlib.crc32(lfh.crc32, buf) 74 lfh.crc32 = zlib_crc32(data)
57 lfh.compressed_size = lfh.compressed_size + #cbuf 75 lfh.compressed_size = #compressed
58 lfh.uncompressed_size = lfh.uncompressed_size + #buf 76 lfh.uncompressed_size = #data
59 table.insert(self.data, cbuf) 77 self.data = compressed
60 return true 78 return true
61end 79end
62 80
@@ -86,10 +104,8 @@ local function zipwriter_close_file_in_zip(self)
86 zh:write(number_to_bytestring(lfh.extra_field_length, 2)) 104 zh:write(number_to_bytestring(lfh.extra_field_length, 2))
87 zh:write(lfh.file_name) 105 zh:write(lfh.file_name)
88 106
89 -- File data 107 -- File data
90 for _, cbuf in ipairs(self.data) do 108 zh:write(self.data)
91 zh:write(cbuf)
92 end
93 109
94 -- Data descriptor 110 -- Data descriptor
95 zh:write(number_to_bytestring(lfh.crc32, 4)) 111 zh:write(number_to_bytestring(lfh.crc32, 4))
@@ -117,12 +133,12 @@ local function zipwriter_add(self, file)
117 end 133 end
118 end 134 end
119 if ok then 135 if ok then
120 local buf = fin:read("*a") 136 local data = fin:read("*a")
121 if not buf then 137 if not data then
122 err = "error reading "..file 138 err = "error reading "..file
123 ok = false 139 ok = false
124 else 140 else
125 ok = self:write_file_in_zip(buf) 141 ok = self:write_file_in_zip(data)
126 if not ok then 142 if not ok then
127 err = "error in writing "..file.." in the zipfile" 143 err = "error in writing "..file.." in the zipfile"
128 end 144 end
@@ -237,7 +253,7 @@ function zip.zip(zipfile, ...)
237 end 253 end
238 end 254 end
239 255
240 local ok = zw:close() 256 ok = zw:close()
241 if not ok then 257 if not ok then
242 return false, "error closing "..zipfile 258 return false, "error closing "..zipfile
243 end 259 end
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua
index a78c4848..65b4fc15 100644
--- a/src/luarocks/type_check.lua
+++ b/src/luarocks/type_check.lua
@@ -6,72 +6,97 @@ local type_check = {}
6package.loaded["luarocks.type_check"] = type_check 6package.loaded["luarocks.type_check"] = type_check
7 7
8local cfg = require("luarocks.cfg") 8local cfg = require("luarocks.cfg")
9local deps = require("luarocks.deps")
9 10
10type_check.rockspec_format = "1.0" 11type_check.rockspec_format = "1.1"
12
13local string_1 = { _type = "string" }
14local number_1 = { _type = "number" }
15local mandatory_string_1 = { _type = "string", _mandatory = true }
16
17-- Syntax for type-checking tables:
18--
19-- A type-checking table describes typing data for a value.
20-- Any key starting with an underscore has a special meaning:
21-- _type (string) is the Lua type of the value. Default is "table".
22-- _version (string) is the minimum rockspec_version that supports this value. Default is "1.0".
23-- _mandatory (boolean) indicates if the value is a mandatory key in its container table. Default is false.
24-- For "string" types only:
25-- _pattern (string) is the string-matching pattern, valid for string types only. Default is ".*".
26-- For "table" types only:
27-- _any (table) is the type-checking table for unspecified keys, recursively checked.
28-- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them.
29-- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked.
11 30
12local rockspec_types = { 31local rockspec_types = {
13 rockspec_format = "string", 32 rockspec_format = string_1,
14 MUST_package = "string", 33 package = mandatory_string_1,
15 MUST_version = "[%w.]+-[%d]+", 34 version = { _type = "string", _pattern = "[%w.]+-[%d]+", _mandatory = true },
16 description = { 35 description = {
17 summary = "string", 36 summary = string_1,
18 detailed = "string", 37 detailed = string_1,
19 homepage = "string", 38 homepage = string_1,
20 license = "string", 39 license = string_1,
21 maintainer = "string" 40 maintainer = string_1,
22 }, 41 },
23 dependencies = { 42 dependencies = {
24 platforms = {}, 43 platforms = {}, -- recursively defined below
25 ANY = "string" 44 _any = string_1,
26 }, 45 },
27 supported_platforms = { 46 supported_platforms = {
28 ANY = "string" 47 _any = string_1,
29 }, 48 },
30 external_dependencies = { 49 external_dependencies = {
31 platforms = {}, 50 platforms = {}, -- recursively defined below
32 ANY = { 51 _any = {
33 program = "string", 52 program = string_1,
34 header = "string", 53 header = string_1,
35 library = "string" 54 library = string_1,
36 } 55 }
37 }, 56 },
38 MUST_source = { 57 source = {
39 platforms = {}, 58 _mandatory = true,
40 MUST_url = "string", 59 platforms = {}, -- recursively defined below
41 md5 = "string", 60 url = mandatory_string_1,
42 file = "string", 61 md5 = string_1,
43 dir = "string", 62 file = string_1,
44 tag = "string", 63 dir = string_1,
45 branch = "string", 64 tag = string_1,
46 module = "string", 65 branch = string_1,
47 cvs_tag = "string", 66 module = string_1,
48 cvs_module = "string" 67 cvs_tag = string_1,
68 cvs_module = string_1,
49 }, 69 },
50 build = { 70 build = {
51 platforms = {}, 71 platforms = {}, -- recursively defined below
52 type = "string", 72 type = string_1,
53 install = { 73 install = {
54 lua = { 74 lua = {
55 MORE = true 75 _more = true
56 }, 76 },
57 lib = { 77 lib = {
58 MORE = true 78 _more = true
59 }, 79 },
60 conf = { 80 conf = {
61 MORE = true 81 _more = true
62 }, 82 },
63 bin = { 83 bin = {
64 MORE = true 84 _more = true
65 } 85 }
66 }, 86 },
67 copy_directories = { 87 copy_directories = {
68 ANY = "string" 88 _any = string_1,
69 }, 89 },
70 MORE = true 90 _more = true,
91 _mandatory = true
71 }, 92 },
72 hooks = { 93 hooks = {
73 platforms = {}, 94 platforms = {}, -- recursively defined below
74 post_install = "string" 95 post_install = string_1,
96 },
97 deploy = {
98 _version = "1.1",
99 wrap_bin_scripts = { _type = "boolean", _version = "1.1" },
75 } 100 }
76} 101}
77 102
@@ -82,69 +107,61 @@ type_check.rockspec_order = {"rockspec_format", "package", "version",
82 { "build", {"type", "modules", "copy_directories", "platforms"} }, 107 { "build", {"type", "modules", "copy_directories", "platforms"} },
83 "hooks"} 108 "hooks"}
84 109
85function type_check.load_extensions() 110rockspec_types.build.platforms._any = rockspec_types.build
86 type_check.rockspec_format = "1.1" 111rockspec_types.dependencies.platforms._any = rockspec_types.dependencies
87 rockspec_types.deploy = { 112rockspec_types.external_dependencies.platforms._any = rockspec_types.external_dependencies
88 wrap_bin_scripts = true, 113rockspec_types.source.platforms._any = rockspec_types.source
89 } 114rockspec_types.hooks.platforms._any = rockspec_types.hooks
90end
91
92if cfg.use_extensions then
93 type_check.load_extensions()
94end
95
96rockspec_types.build.platforms.ANY = rockspec_types.build
97rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies
98rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies
99rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source
100rockspec_types.hooks.platforms.ANY = rockspec_types.hooks
101 115
102local manifest_types = { 116local manifest_types = {
103 MUST_repository = { 117 repository = {
118 _mandatory = true,
104 -- packages 119 -- packages
105 ANY = { 120 _any = {
106 -- versions 121 -- versions
107 ANY = { 122 _any = {
108 -- items 123 -- items
109 ANY = { 124 _any = {
110 MUST_arch = "string", 125 arch = mandatory_string_1,
111 modules = { ANY = "string" }, 126 modules = { _any = string_1 },
112 commands = { ANY = "string" }, 127 commands = { _any = string_1 },
113 dependencies = { ANY = "string" }, 128 dependencies = { _any = string_1 },
114 -- TODO: to be extended with more metadata. 129 -- TODO: to be extended with more metadata.
115 } 130 }
116 } 131 }
117 } 132 }
118 }, 133 },
119 MUST_modules = { 134 modules = {
135 _mandatory = true,
120 -- modules 136 -- modules
121 ANY = { 137 _any = {
122 -- providers 138 -- providers
123 ANY = "string" 139 _any = string_1
124 } 140 }
125 }, 141 },
126 MUST_commands = { 142 commands = {
143 _mandatory = true,
127 -- modules 144 -- modules
128 ANY = { 145 _any = {
129 -- commands 146 -- commands
130 ANY = "string" 147 _any = string_1
131 } 148 }
132 }, 149 },
133 dependencies = { 150 dependencies = {
134 -- each module 151 -- each module
135 ANY = { 152 _any = {
136 -- each version 153 -- each version
137 ANY = { 154 _any = {
138 -- each dependency 155 -- each dependency
139 ANY = { 156 _any = {
140 name = "string", 157 name = string_1,
141 constraints = { 158 constraints = {
142 ANY = { 159 _any = {
143 no_upgrade = "boolean", 160 no_upgrade = { _type = "boolean" },
144 op = "string", 161 op = string_1,
145 version = { 162 version = {
146 string = "string", 163 string = string_1,
147 ANY = 0, 164 _any = number_1,
148 } 165 }
149 } 166 }
150 } 167 }
@@ -154,54 +171,75 @@ local manifest_types = {
154 } 171 }
155} 172}
156 173
174local function check_version(version, typetbl, context)
175 local typetbl_version = typetbl._version or "1.0"
176 if deps.compare_versions(typetbl_version, version) then
177 if context == "" then
178 return nil, "Invalid rockspec_format version number in rockspec? Please fix rockspec accordingly."
179 else
180 return nil, context.." is not supported in rockspec format "..version.." (requires version "..typetbl_version.."), please fix the rockspec_format field accordingly."
181 end
182 end
183 return true
184end
185
157local type_check_table 186local type_check_table
158 187
159--- Type check an object. 188--- Type check an object.
160-- The object is compared against an archetypical value 189-- The object is compared against an archetypical value
161-- matching the expected type -- the actual values don't matter, 190-- matching the expected type -- the actual values don't matter,
162-- only their types. Tables are type checked recursively. 191-- only their types. Tables are type checked recursively.
163-- @param name any: The object name (for error messages). 192-- @param version string: The version of the item.
164-- @param item any: The object being checked. 193-- @param item any: The object being checked.
165-- @param expected any: The reference object. In case of a table, 194-- @param typetbl any: The type-checking table for the object.
166-- its is structured as a type reference table.
167-- @param context string: A string indicating the "context" where the 195-- @param context string: A string indicating the "context" where the
168-- error occurred (such as the name of the table the item is a part of), 196-- error occurred (the full table path), for error messages.
169-- to be used by error messages.
170-- @return boolean or (nil, string): true if type checking 197-- @return boolean or (nil, string): true if type checking
171-- succeeded, or nil and an error message if it failed. 198-- succeeded, or nil and an error message if it failed.
172-- @see type_check_table 199-- @see type_check_table
173local function type_check_item(name, item, expected, context) 200local function type_check_item(version, item, typetbl, context)
174 name = tostring(name) 201 assert(type(version) == "string")
175 202
176 local item_type = type(item) 203 local ok, err = check_version(version, typetbl, context)
177 local expected_type = type(expected) 204 if not ok then
205 return nil, err
206 end
207
208 local item_type = type(item) or "nil"
209 local expected_type = typetbl._type or "table"
210
178 if expected_type == "number" then 211 if expected_type == "number" then
179 if not tonumber(item) then 212 if not tonumber(item) then
180 return nil, "Type mismatch on field "..context..name..": expected a number" 213 return nil, "Type mismatch on field "..context..": expected a number"
181 end 214 end
182 elseif expected_type == "string" then 215 elseif expected_type == "string" then
183 if type(item) ~= "string" then 216 if item_type ~= "string" then
184 return nil, "Type mismatch on field "..context..name..": expected a string" 217 return nil, "Type mismatch on field "..context..": expected a string, got "..item_type
185 end 218 end
186 if expected ~= "string" then 219 if typetbl._pattern then
187 if item_type ~= "string" then 220 if not item:match("^"..typetbl._pattern.."$") then
188 return nil, "Type mismatch on field "..context..name..": expected a string, got a "..type(item) 221 return nil, "Type mismatch on field "..context..": invalid value "..item.." does not match '"..typetbl._pattern.."'"
189 elseif not item:match("^"..expected.."$") then
190 return nil, "Type mismatch on field "..context..name..": invalid value "..item.." does not match '"..expected.."'"
191 end 222 end
192 end 223 end
193 elseif expected_type == "table" then 224 elseif expected_type == "table" then
194 if item_type ~= expected_type then 225 if item_type ~= expected_type then
195 return nil, "Type mismatch on field "..context..name..": expected a table" 226 return nil, "Type mismatch on field "..context..": expected a table"
196 else 227 else
197 return type_check_table(item, expected, context..name..".") 228 return type_check_table(version, item, typetbl, context)
198 end 229 end
199 elseif item_type ~= expected_type then 230 elseif item_type ~= expected_type then
200 return nil, "Type mismatch on field "..context..name..": expected a "..expected_type 231 return nil, "Type mismatch on field "..context..": expected "..expected_type
201 end 232 end
202 return true 233 return true
203end 234end
204 235
236local function mkfield(context, field)
237 if context == "" then
238 return field
239 end
240 return context.."."..field
241end
242
205--- Type check the contents of a table. 243--- Type check the contents of a table.
206-- The table's contents are compared against a reference table, 244-- The table's contents are compared against a reference table,
207-- which contains the recognized fields, with archetypical values 245-- which contains the recognized fields, with archetypical values
@@ -215,23 +253,31 @@ end
215-- with MUST_, it is mandatory; its absence from the table is 253-- with MUST_, it is mandatory; its absence from the table is
216-- a type error. 254-- a type error.
217-- Tables are type checked recursively. 255-- Tables are type checked recursively.
256-- @param version string: The version of tbl.
218-- @param tbl table: The table to be type checked. 257-- @param tbl table: The table to be type checked.
219-- @param types table: The reference table, containing 258-- @param typetbl table: The type-checking table, containing
220-- values for recognized fields in the checked table. 259-- values for recognized fields in the checked table.
221-- @param context string: A string indicating the "context" where the 260-- @param context string: A string indicating the "context" where the
222-- error occurred (such as the name of the table the item is a part of), 261-- error occurred (such as the name of the table the item is a part of),
223-- to be used by error messages. 262-- to be used by error messages.
224-- @return boolean or (nil, string): true if type checking 263-- @return boolean or (nil, string): true if type checking
225-- succeeded, or nil and an error message if it failed. 264-- succeeded, or nil and an error message if it failed.
226type_check_table = function(tbl, types, context) 265type_check_table = function(version, tbl, typetbl, context)
266 assert(type(version) == "string")
227 assert(type(tbl) == "table") 267 assert(type(tbl) == "table")
228 assert(type(types) == "table") 268 assert(type(typetbl) == "table")
269
270 local ok, err = check_version(version, typetbl, context)
271 if not ok then
272 return nil, err
273 end
274
229 for k, v in pairs(tbl) do 275 for k, v in pairs(tbl) do
230 local t = types[k] or (type(k) == "string" and types["MUST_"..k]) or types.ANY 276 local t = typetbl[k] or typetbl._any
231 if t then 277 if t then
232 local ok, err = type_check_item(k, v, t, context) 278 local ok, err = type_check_item(version, v, t, mkfield(context, k))
233 if not ok then return nil, err end 279 if not ok then return nil, err end
234 elseif types.MORE then 280 elseif typetbl._more then
235 -- Accept unknown field 281 -- Accept unknown field
236 else 282 else
237 if not cfg.accept_unknown_fields then 283 if not cfg.accept_unknown_fields then
@@ -239,21 +285,20 @@ type_check_table = function(tbl, types, context)
239 end 285 end
240 end 286 end
241 end 287 end
242 for k, v in pairs(types) do 288 for k, v in pairs(typetbl) do
243 local mandatory_key = k:match("^MUST_(.+)") 289 if k:sub(1,1) ~= "_" and v._mandatory then
244 if mandatory_key then 290 if not tbl[k] then
245 if not tbl[mandatory_key] then 291 return nil, "Mandatory field "..mkfield(context, k).." is missing."
246 return nil, "Mandatory field "..context..mandatory_key.." is missing."
247 end 292 end
248 end 293 end
249 end 294 end
250 return true 295 return true
251end 296end
252 297
253local function check_undeclared_globals(globals, types) 298local function check_undeclared_globals(globals, typetbl)
254 local undeclared = {} 299 local undeclared = {}
255 for glob, _ in pairs(globals) do 300 for glob, _ in pairs(globals) do
256 if not (types[glob] or types["MUST_"..glob]) then 301 if not (typetbl[glob] or typetbl["MUST_"..glob]) then
257 table.insert(undeclared, glob) 302 table.insert(undeclared, glob)
258 end 303 end
259 end 304 end
@@ -273,13 +318,12 @@ end
273-- succeeded, or nil and an error message if it failed. 318-- succeeded, or nil and an error message if it failed.
274function type_check.type_check_rockspec(rockspec, globals) 319function type_check.type_check_rockspec(rockspec, globals)
275 assert(type(rockspec) == "table") 320 assert(type(rockspec) == "table")
276 if rockspec.rockspec_format then 321 if not rockspec.rockspec_format then
277 -- relies on global state 322 rockspec.rockspec_format = "1.0"
278 type_check.load_extensions()
279 end 323 end
280 local ok, err = check_undeclared_globals(globals, rockspec_types) 324 local ok, err = check_undeclared_globals(globals, rockspec_types)
281 if not ok then return nil, err end 325 if not ok then return nil, err end
282 return type_check_table(rockspec, rockspec_types, "") 326 return type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "")
283end 327end
284 328
285--- Type check a manifest table. 329--- Type check a manifest table.
@@ -292,7 +336,7 @@ function type_check.type_check_manifest(manifest, globals)
292 assert(type(manifest) == "table") 336 assert(type(manifest) == "table")
293 local ok, err = check_undeclared_globals(globals, manifest_types) 337 local ok, err = check_undeclared_globals(globals, manifest_types)
294 if not ok then return nil, err end 338 if not ok then return nil, err end
295 return type_check_table(manifest, manifest_types, "") 339 return type_check_table("1.0", manifest, manifest_types, "")
296end 340end
297 341
298return type_check 342return type_check
diff --git a/src/luarocks/unpack.lua b/src/luarocks/unpack.lua
index 9204e265..a889bac5 100644
--- a/src/luarocks/unpack.lua
+++ b/src/luarocks/unpack.lua
@@ -43,9 +43,10 @@ local function unpack_rockspec(rockspec_file, dir_name)
43 end 43 end
44 ok, err = fs.change_dir(sources_dir) 44 ok, err = fs.change_dir(sources_dir)
45 if not ok then return nil, err end 45 if not ok then return nil, err end
46 build.apply_patches(rockspec) 46 ok, err = build.apply_patches(rockspec)
47 fs.pop_dir() 47 fs.pop_dir()
48 fs.pop_dir() 48 fs.pop_dir()
49 if not ok then return nil, err end
49 return rockspec 50 return rockspec
50end 51end
51 52
@@ -79,8 +80,9 @@ local function unpack_rock(rock_file, dir_name, kind)
79 end 80 end
80 ok, err = fs.change_dir(rockspec.source.dir) 81 ok, err = fs.change_dir(rockspec.source.dir)
81 if not ok then return nil, err end 82 if not ok then return nil, err end
82 build.apply_patches(rockspec) 83 ok, err = build.apply_patches(rockspec)
83 fs.pop_dir() 84 fs.pop_dir()
85 if not ok then return nil, err end
84 end 86 end
85 end 87 end
86 return rockspec 88 return rockspec
diff --git a/src/luarocks/upload.lua b/src/luarocks/upload.lua
index 018e702d..19ddee8d 100644
--- a/src/luarocks/upload.lua
+++ b/src/luarocks/upload.lua
@@ -4,6 +4,7 @@ local upload = {}
4local util = require("luarocks.util") 4local util = require("luarocks.util")
5local fetch = require("luarocks.fetch") 5local fetch = require("luarocks.fetch")
6local pack = require("luarocks.pack") 6local pack = require("luarocks.pack")
7local cfg = require("luarocks.cfg")
7local Api = require("luarocks.upload.api") 8local Api = require("luarocks.upload.api")
8 9
9upload.help_summary = "Upload a rockspec to the public rocks repository." 10upload.help_summary = "Upload a rockspec to the public rocks repository."
@@ -29,6 +30,9 @@ function upload.run(...)
29 if not api then 30 if not api then
30 return nil, err 31 return nil, err
31 end 32 end
33 if cfg.verbose then
34 api.debug = true
35 end
32 36
33 local rockspec, err, errcode = fetch.load_rockspec(fname) 37 local rockspec, err, errcode = fetch.load_rockspec(fname)
34 if err then 38 if err then
@@ -50,7 +54,7 @@ function upload.run(...)
50 end 54 end
51 55
52 local rock_fname 56 local rock_fname
53 if not flags["skip-pack"] then 57 if not flags["skip-pack"] and not rockspec.version:match("^scm") then
54 util.printout("Packing " .. tostring(rockspec.package)) 58 util.printout("Packing " .. tostring(rockspec.package))
55 rock_fname, err = pack.pack_source_rock(fname) 59 rock_fname, err = pack.pack_source_rock(fname)
56 if not rock_fname then 60 if not rock_fname then
@@ -73,7 +77,7 @@ function upload.run(...)
73 77
74 if rock_fname then 78 if rock_fname then
75 util.printout(("Sending " .. tostring(rock_fname) .. " ...")) 79 util.printout(("Sending " .. tostring(rock_fname) .. " ..."))
76 res, err = api:method("upload_rock/" .. tostring(res.version.id), nil, { 80 res, err = api:method("upload_rock/" .. ("%d"):format(res.version.id), nil, {
77 rock_file = multipart.new_file(rock_fname) 81 rock_file = multipart.new_file(rock_fname)
78 }) 82 })
79 if not res then return nil, err end 83 if not res then return nil, err end
diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua
index 818d293e..6df24569 100644
--- a/src/luarocks/upload/api.lua
+++ b/src/luarocks/upload/api.lua
@@ -5,20 +5,20 @@ local cfg = require("luarocks.cfg")
5local fs = require("luarocks.fs") 5local fs = require("luarocks.fs")
6local util = require("luarocks.util") 6local util = require("luarocks.util")
7local persist = require("luarocks.persist") 7local persist = require("luarocks.persist")
8local multipart = require("luarocks.upload.multipart")
8 9
9local Api = {} 10local Api = {}
10 11
11local function upload_config_file() 12local function upload_config_file()
12 local _, _, home_conf, home_ok = cfg.which_config() 13 local conf = cfg.which_config()
13 if not home_conf then 14 if not conf.user.file then
14 return nil 15 return nil
15 end 16 end
16 return (home_conf:gsub("/[^/]+$", "/upload_config.lua")) 17 return (conf.user.file:gsub("/[^/]+$", "/upload_config.lua"))
17end 18end
18 19
19function Api:load_config() 20function Api:load_config()
20 local upload_conf = upload_config_file() 21 local upload_conf = upload_config_file()
21 print(upload_conf)
22 if not upload_conf then return nil end 22 if not upload_conf then return nil end
23 local cfg, err = persist.load_into_table(upload_conf) 23 local cfg, err = persist.load_into_table(upload_conf)
24 return cfg 24 return cfg
@@ -43,7 +43,7 @@ end
43function Api:check_version() 43function Api:check_version()
44 if not self._server_tool_version then 44 if not self._server_tool_version then
45 local tool_version = cfg.upload.tool_version 45 local tool_version = cfg.upload.tool_version
46 local res, err = self:request("http://" .. tostring(self.config.server) .. "/api/tool_version", { 46 local res, err = self:request(tostring(self.config.server) .. "/api/tool_version", {
47 current = tool_version 47 current = tool_version
48 }) 48 })
49 if not res then 49 if not res then
@@ -80,12 +80,11 @@ end
80 80
81function Api:raw_method(path, ...) 81function Api:raw_method(path, ...)
82 self:check_version() 82 self:check_version()
83 local url = "http://" .. tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path) 83 local url = tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path)
84 return self:request(url, ...) 84 return self:request(url, ...)
85end 85end
86 86
87local function encode_query_string(t, sep) 87local function encode_query_string(t, sep)
88 local url = require("socket.url")
89 if sep == nil then 88 if sep == nil then
90 sep = "&" 89 sep = "&"
91 end 90 end
@@ -95,9 +94,9 @@ local function encode_query_string(t, sep)
95 if type(k) == "number" and type(v) == "table" then 94 if type(k) == "number" and type(v) == "table" then
96 k, v = v[1], v[2] 95 k, v = v[1], v[2]
97 end 96 end
98 buf[i + 1] = url.escape(k) 97 buf[i + 1] = multipart.url_escape(k)
99 buf[i + 2] = "=" 98 buf[i + 2] = "="
100 buf[i + 3] = url.escape(v) 99 buf[i + 3] = multipart.url_escape(v)
101 buf[i + 4] = sep 100 buf[i + 4] = sep
102 i = i + 4 101 i = i + 4
103 end 102 end
@@ -107,21 +106,125 @@ end
107 106
108-- An ode to the multitude of JSON libraries out there... 107-- An ode to the multitude of JSON libraries out there...
109local function require_json() 108local function require_json()
110 for _, lib in ipairs({ "cjson", "dkjson", "json" }) do 109 local list = { "cjson", "dkjson", "json" }
110 for _, lib in ipairs(list) do
111 local json_ok, json = pcall(require, lib) 111 local json_ok, json = pcall(require, lib)
112 if json_ok then 112 if json_ok then
113 return json_ok, json 113 return json_ok, json
114 end 114 end
115 end 115 end
116 return nil 116 local errmsg = "Failed loading "
117 for i, name in ipairs(list) do
118 if i == #list then
119 errmsg = errmsg .."and '"..name.."'. Use 'luarocks search <partial-name>' to search for a library and 'luarocks install <name>' to install one."
120 else
121 errmsg = errmsg .."'"..name.."', "
122 end
123 end
124 return nil, errmsg
125end
126
127local function redact_api_url(url)
128 url = tostring(url)
129 return (url:gsub(".*/api/[^/]+/[^/]+", "")) or ""
117end 130end
118 131
132local ltn12_ok, ltn12 = pcall(require, "ltn12")
133if not ltn12_ok then -- If not using LuaSocket and/or LuaSec...
134
119function Api:request(url, params, post_params) 135function Api:request(url, params, post_params)
120 local http_ok, http = pcall(require, "socket.http") 136 local vars = cfg.variables
121 local ltn12_ok, ltn12 = pcall(require, "ltn12")
122 local json_ok, json = require_json() 137 local json_ok, json = require_json()
123 if not http_ok then return nil, "LuaSocket is required for this command." end 138 if not json_ok then return nil, "A JSON library is required for this command. "..json end
124 if not json_ok then return nil, "A JSON library is required for this command." end 139
140 if cfg.downloader == "wget" then
141 local curl_ok, err = fs.is_tool_available(vars.CURL, "curl")
142 if not curl_ok then
143 return nil, err
144 end
145 end
146
147 if not self.config.key then
148 return nil, "Must have API key before performing any actions."
149 end
150 local body
151 local headers = {}
152 if params and next(params) then
153 url = url .. ("?" .. encode_query_string(params))
154 end
155 local method = "GET"
156 local out
157 local tmpfile = fs.tmpname()
158 if post_params then
159 method = "POST"
160 local curl_cmd = fs.Q(vars.CURL).." -f -k -L --silent --user-agent \""..cfg.user_agent.." via curl\" "
161 for k,v in pairs(post_params) do
162 local var = v
163 if type(v) == "table" then
164 var = "@"..v.fname
165 end
166 curl_cmd = curl_cmd .. "--form \""..k.."="..var.."\" "
167 end
168 if cfg.connection_timeout and cfg.connection_timeout > 0 then
169 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
170 end
171 local ok = fs.execute_string(curl_cmd..fs.Q(url).." -o "..fs.Q(tmpfile))
172 if not ok then
173 return nil, "API failure: " .. redact_api_url(url)
174 end
175 else
176 local ok, err = fs.download(url, tmpfile)
177 if not ok then
178 return nil, "API failure: " .. tostring(err) .. " - " .. redact_api_url(url)
179 end
180 end
181
182 local tmpfd = io.open(tmpfile)
183 if not tmpfd then
184 os.remove(tmpfile)
185 return nil, "API failure reading temporary file - " .. redact_api_url(url)
186 end
187 out = tmpfd:read("*a")
188 tmpfd:close()
189 os.remove(tmpfile)
190
191 if self.debug then
192 util.printout("[" .. tostring(method) .. " via curl] " .. redact_api_url(url) .. " ... ")
193 end
194
195 return json.decode(out)
196end
197
198else -- use LuaSocket and LuaSec
199
200local warned_luasec = false
201
202function Api:request(url, params, post_params)
203 local json_ok, json = require_json()
204 if not json_ok then return nil, "A JSON library is required for this command. "..json end
205 local server = tostring(self.config.server)
206 local http_ok, http
207 local via = "luasocket"
208 if server:match("^https://") then
209 http_ok, http = pcall(require, "ssl.https")
210 if http_ok then
211 via = "luasec"
212 else
213 if not warned_luasec then
214 util.printerr("LuaSec is not available; using plain HTTP. Install 'luasec' to enable HTTPS.")
215 warned_luasec = true
216 end
217 http_ok, http = pcall(require, "socket.http")
218 server = server:gsub("^https", "http")
219 url = url:gsub("^https", "http")
220 via = "luasocket"
221 end
222 else
223 http_ok, http = pcall(require, "socket.http")
224 end
225 if not http_ok then
226 return nil, "Failed loading socket library!"
227 end
125 228
126 if not self.config.key then 229 if not self.config.key then
127 return nil, "Must have API key before performing any actions." 230 return nil, "Must have API key before performing any actions."
@@ -132,7 +235,6 @@ function Api:request(url, params, post_params)
132 url = url .. ("?" .. encode_query_string(params)) 235 url = url .. ("?" .. encode_query_string(params))
133 end 236 end
134 if post_params then 237 if post_params then
135 local multipart = require("luarocks.upload.multipart")
136 local boundary 238 local boundary
137 body, boundary = multipart.encode(post_params) 239 body, boundary = multipart.encode(post_params)
138 headers["Content-length"] = #body 240 headers["Content-length"] = #body
@@ -140,7 +242,7 @@ function Api:request(url, params, post_params)
140 end 242 end
141 local method = post_params and "POST" or "GET" 243 local method = post_params and "POST" or "GET"
142 if self.debug then 244 if self.debug then
143 util.printout("[" .. tostring(method) .. "] " .. tostring(url) .. " ... ") 245 util.printout("[" .. tostring(method) .. " via "..via.."] " .. redact_api_url(url) .. " ... ")
144 end 246 end
145 local out = {} 247 local out = {}
146 local _, status = http.request({ 248 local _, status = http.request({
@@ -154,12 +256,14 @@ function Api:request(url, params, post_params)
154 util.printout(tostring(status)) 256 util.printout(tostring(status))
155 end 257 end
156 if status ~= 200 then 258 if status ~= 200 then
157 return nil, "API returned " .. tostring(status) .. " - " .. tostring(url) 259 return nil, "API returned " .. tostring(status) .. " - " .. redact_api_url(url)
158 end 260 end
159 return json.decode(table.concat(out)) 261 return json.decode(table.concat(out))
160end 262end
161 263
162function api.new(flags, name) 264end
265
266function api.new(flags)
163 local self = {} 267 local self = {}
164 setmetatable(self, { __index = Api }) 268 setmetatable(self, { __index = Api })
165 self.config = self:load_config() or {} 269 self.config = self:load_config() or {}
@@ -169,7 +273,7 @@ function api.new(flags, name)
169 self.debug = flags["debug"] 273 self.debug = flags["debug"]
170 if not self.config.key then 274 if not self.config.key then
171 return nil, "You need an API key to upload rocks.\n" .. 275 return nil, "You need an API key to upload rocks.\n" ..
172 "Navigate to http://"..self.config.server.."/settings to get a key\n" .. 276 "Navigate to "..self.config.server.."/settings to get a key\n" ..
173 "and then pass it through the --api-key=<key> flag." 277 "and then pass it through the --api-key=<key> flag."
174 end 278 end
175 if flags["api-key"] then 279 if flags["api-key"] then
diff --git a/src/luarocks/upload/multipart.lua b/src/luarocks/upload/multipart.lua
index 95afe1b3..aad2e439 100644
--- a/src/luarocks/upload/multipart.lua
+++ b/src/luarocks/upload/multipart.lua
@@ -1,28 +1,32 @@
1 1
2local multipart = {} 2local multipart = {}
3 3
4local url = require("socket.url")
5
6local File = {} 4local File = {}
7 5
8local unpack = unpack or table.unpack 6local unpack = unpack or table.unpack
9 7
10math.randomseed(os.time()) 8math.randomseed(os.time())
11 9
10-- socket.url.escape(s) from LuaSocket 3.0rc1
11function multipart.url_escape(s)
12 return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
13 return string.format("%%%02x", string.byte(c))
14 end))
15end
16
12function File:mime() 17function File:mime()
13 if not self.mimetype then 18 if not self.mimetype then
14 local mimetypes_ok, mimetypes = pcall(require, "mimetypes") 19 local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
15 if mimetypes_ok then 20 if mimetypes_ok then
16 self.mimetype = mimetypes.guess(self.fname) 21 self.mimetype = mimetypes.guess(self.fname)
17 else
18 self.mimetype = "application/octet-stream"
19 end 22 end
23 self.mimetype = self.mimetype or "application/octet-stream"
20 end 24 end
21 return self.mimetype 25 return self.mimetype
22end 26end
23 27
24function File:content() 28function File:content()
25 local fd = io.open(self.fname) 29 local fd = io.open(self.fname, "rb")
26 if not fd then 30 if not fd then
27 return nil, "Failed to open file: "..self.fname 31 return nil, "Failed to open file: "..self.fname
28 end 32 end
@@ -64,7 +68,7 @@ function multipart.encode(params)
64 local chunks = {} 68 local chunks = {}
65 for _, tuple in ipairs(tuples) do 69 for _, tuple in ipairs(tuples) do
66 local k,v = unpack(tuple) 70 local k,v = unpack(tuple)
67 k = url.escape(k) 71 k = multipart.url_escape(k)
68 local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' } 72 local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
69 local content 73 local content
70 if type(v) == "table" and v.__class == File then 74 if type(v) == "table" and v.__class == File then
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index a70e726d..c06c8354 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -63,6 +63,76 @@ function util.matchquote(s)
63 return (s:gsub("[?%-+*%[%].%%()$^]","%%%1")) 63 return (s:gsub("[?%-+*%[%].%%()$^]","%%%1"))
64end 64end
65 65
66--- List of supported arguments.
67-- Arguments that take no parameters are marked with the boolean true.
68-- Arguments that take a parameter are marked with a descriptive string.
69-- Arguments that may take an empty string are described in quotes,
70-- (as in the value for --detailed="<text>").
71-- For all other string values, it means the parameter is mandatory.
72local supported_flags = {
73 ["all"] = true,
74 ["api-key"] = "<key>",
75 ["append"] = true,
76 ["arch"] = "<arch>",
77 ["bin"] = true,
78 ["binary"] = true,
79 ["branch"] = "<branch-name>",
80 ["debug"] = true,
81 ["deps"] = true,
82 ["deps-mode"] = "<mode>",
83 ["detailed"] = "\"<text>\"",
84 ["force"] = true,
85 ["from"] = "<server>",
86 ["help"] = true,
87 ["home"] = true,
88 ["homepage"] = "\"<url>\"",
89 ["keep"] = true,
90 ["lib"] = "<library>",
91 ["license"] = "\"<text>\"",
92 ["list"] = true,
93 ["local"] = true,
94 ["local-tree"] = true,
95 ["lr-bin"] = true,
96 ["lr-cpath"] = true,
97 ["lr-path"] = true,
98 ["lua-version"] = "<vers>",
99 ["lua-ver"] = true,
100 ["lua-incdir"] = true,
101 ["lua-libdir"] = true,
102 ["modules"] = true,
103 ["mversion"] = true,
104 ["no-refresh"] = true,
105 ["nodeps"] = true,
106 ["old-versions"] = true,
107 ["only-deps"] = true,
108 ["only-from"] = "<server>",
109 ["only-server"] = "<server>",
110 ["only-sources"] = "<url>",
111 ["only-sources-from"] = "<url>",
112 ["outdated"] = true,
113 ["output"] = "<file>",
114 ["pack-binary-rock"] = true,
115 ["porcelain"] = true,
116 ["quick"] = true,
117 ["rock-dir"] = true,
118 ["rock-tree"] = true,
119 ["rock-trees"] = true,
120 ["rockspec"] = true,
121 ["rockspec-format"] = "<ver>",
122 ["server"] = "<server>",
123 ["skip-pack"] = true,
124 ["source"] = true,
125 ["summary"] = "\"<text>\"",
126 ["system-config"] = true,
127 ["tag"] = "<tag>",
128 ["timeout"] = "<seconds>",
129 ["to"] = "<path>",
130 ["tree"] = "<path>",
131 ["user-config"] = true,
132 ["verbose"] = true,
133 ["version"] = true,
134}
135
66--- Extract flags from an arguments list. 136--- Extract flags from an arguments list.
67-- Given string arguments, extract flag arguments into a flags set. 137-- Given string arguments, extract flag arguments into a flags set.
68-- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz", 138-- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz",
@@ -71,19 +141,59 @@ end
71function util.parse_flags(...) 141function util.parse_flags(...)
72 local args = {...} 142 local args = {...}
73 local flags = {} 143 local flags = {}
74 for i = #args, 1, -1 do 144 local i = 1
145 local out = {}
146 local ignore_flags = false
147 while i <= #args do
75 local flag = args[i]:match("^%-%-(.*)") 148 local flag = args[i]:match("^%-%-(.*)")
76 if flag then 149 if flag == "--" then
150 ignore_flags = true
151 end
152 if flag and not ignore_flags then
77 local var,val = flag:match("([a-z_%-]*)=(.*)") 153 local var,val = flag:match("([a-z_%-]*)=(.*)")
78 if val then 154 if val then
79 flags[var] = val 155 local vartype = supported_flags[var]
156 if type(vartype) == "string" then
157 if val == "" and vartype:sub(1,1) ~= '"' then
158 return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." }
159 end
160 flags[var] = val
161 else
162 if vartype then
163 return { ERROR = "Invalid argument: flag --"..var.." does not take an parameter." }
164 else
165 return { ERROR = "Invalid argument: unknown flag --"..var.."." }
166 end
167 end
80 else 168 else
81 flags[flag] = true 169 local var = flag
170 local vartype = supported_flags[var]
171 if type(vartype) == "string" then
172 i = i + 1
173 local val = args[i]
174 if not val then
175 return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter." }
176 end
177 if val:match("^%-%-.*") then
178 return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter (if you really want to pass "..val.." as an argument to --"..var..", use --"..var.."="..val..")." }
179 else
180 if val == "" and vartype:sub(1,1) ~= '"' then
181 return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." }
182 end
183 flags[var] = val
184 end
185 elseif vartype == true then
186 flags[var] = true
187 else
188 return { ERROR = "Invalid argument: unknown flag --"..var.."." }
189 end
82 end 190 end
83 table.remove(args, i) 191 else
192 table.insert(out, args[i])
84 end 193 end
194 i = i + 1
85 end 195 end
86 return flags, unpack(args) 196 return flags, unpack(out)
87end 197end
88 198
89--- Build a sequence of flags for forwarding from one command to 199--- Build a sequence of flags for forwarding from one command to
@@ -177,7 +287,7 @@ local var_format_pattern = "%$%((%a[%a%d_]+)%)"
177-- the original table (ie, does not copy recursively). 287-- the original table (ie, does not copy recursively).
178-- @param tbl table: the input table 288-- @param tbl table: the input table
179-- @return table: a new table with the same contents. 289-- @return table: a new table with the same contents.
180local function make_shallow_copy(tbl) 290function util.make_shallow_copy(tbl)
181 local copy = {} 291 local copy = {}
182 for k,v in pairs(tbl) do 292 for k,v in pairs(tbl) do
183 copy[k] = v 293 copy[k] = v
@@ -196,7 +306,7 @@ end
196-- needed variables. 306-- needed variables.
197-- @param msg string: the warning message to display. 307-- @param msg string: the warning message to display.
198function util.warn_if_not_used(var_defs, needed_set, msg) 308function util.warn_if_not_used(var_defs, needed_set, msg)
199 needed_set = make_shallow_copy(needed_set) 309 needed_set = util.make_shallow_copy(needed_set)
200 for _, val in pairs(var_defs) do 310 for _, val in pairs(var_defs) do
201 for used in val:gmatch(var_format_pattern) do 311 for used in val:gmatch(var_format_pattern) do
202 needed_set[used] = nil 312 needed_set[used] = nil
@@ -392,7 +502,7 @@ function util.deps_mode_help(program)
392end 502end
393 503
394function util.see_help(command, program) 504function util.see_help(command, program)
395 return "See '"..util.this_program(program or "luarocks")..' help '..command.."'." 505 return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'."
396end 506end
397 507
398-- from http://lua-users.org/wiki/SplitJoin 508-- from http://lua-users.org/wiki/SplitJoin
@@ -432,6 +542,7 @@ function util.remove_path_dupes(list, sep)
432 local parts = util.split_string(list, sep) 542 local parts = util.split_string(list, sep)
433 local final, entries = {}, {} 543 local final, entries = {}, {}
434 for _, part in ipairs(parts) do 544 for _, part in ipairs(parts) do
545 part = part:gsub("//", "/")
435 if not entries[part] then 546 if not entries[part] then
436 table.insert(final, part) 547 table.insert(final, part)
437 entries[part] = true 548 entries[part] = true
diff --git a/src/luarocks/write_rockspec.lua b/src/luarocks/write_rockspec.lua
index 20d35701..972562c3 100644
--- a/src/luarocks/write_rockspec.lua
+++ b/src/luarocks/write_rockspec.lua
@@ -24,18 +24,19 @@ If a repository URL is given with no version, it creates an 'scm' rock.
24Note that the generated file is a _starting point_ for writing a 24Note that the generated file is a _starting point_ for writing a
25rockspec, and is not guaranteed to be complete or correct. 25rockspec, and is not guaranteed to be complete or correct.
26 26
27--output=<file> Write the rockspec with the given filename. 27--output=<file> Write the rockspec with the given filename.
28 If not given, a file is written in the current 28 If not given, a file is written in the current
29 directory with a filename based on given name and version. 29 directory with a filename based on given name and version.
30--license="<string>" A license string, such as "MIT/X11" or "GNU GPL v3". 30--license="<string>" A license string, such as "MIT/X11" or "GNU GPL v3".
31--summary="<txt>" A short one-line description summary. 31--summary="<txt>" A short one-line description summary.
32--description="<txt>" A longer description string. 32--detailed="<txt>" A longer description string.
33--homepage=<url> Project homepage. 33--homepage=<url> Project homepage.
34--lua-version=<ver> Supported Lua versions. Accepted values are "5.1", "5.2", 34--lua-version=<ver> Supported Lua versions. Accepted values are "5.1", "5.2",
35 "5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3". 35 "5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3".
36--tag=<tag> Tag to use. Will attempt to extract version number from it. 36--rockspec-format=<ver> Rockspec format version, such as "1.0" or "1.1".
37--lib=<lib>[,<lib>] A comma-separated list of libraries that C files need to 37--tag=<tag> Tag to use. Will attempt to extract version number from it.
38 link to. 38--lib=<lib>[,<lib>] A comma-separated list of libraries that C files need to
39 link to.
39]] 40]]
40 41
41local function open_file(name) 42local function open_file(name)
@@ -76,25 +77,24 @@ local function configure_lua_version(rockspec, luaver)
76 end 77 end
77end 78end
78 79
79local function detect_description(rockspec) 80local function detect_description()
80 local fd = open_file("README.md") or open_file("README") 81 local fd = open_file("README.md") or open_file("README")
81 if not fd then return end 82 if not fd then return end
82 local data = fd:read("*a") 83 local data = fd:read("*a")
83 fd:close() 84 fd:close()
84 local paragraph = data:match("\n\n([^%[].-)\n\n") 85 local paragraph = data:match("\n\n([^%[].-)\n\n")
85 if not paragraph then paragraph = data:match("\n\n(.*)") end 86 if not paragraph then paragraph = data:match("\n\n(.*)") end
87 local summary, detailed
86 if paragraph then 88 if paragraph then
89 detailed = paragraph
90
87 if #paragraph < 80 then 91 if #paragraph < 80 then
88 rockspec.description.summary = paragraph:gsub("\n", "") 92 summary = paragraph:gsub("\n", "")
89 rockspec.description.detailed = paragraph
90 else 93 else
91 local summary = paragraph:gsub("\n", " "):match("([^.]*%.) ") 94 summary = paragraph:gsub("\n", " "):match("([^.]*%.) ")
92 if summary then
93 rockspec.description.summary = summary:gsub("\n", "")
94 end
95 rockspec.description.detailed = paragraph
96 end 95 end
97 end 96 end
97 return summary, detailed
98end 98end
99 99
100local function detect_mit_license(data) 100local function detect_mit_license(data)
@@ -209,17 +209,13 @@ function write_rockspec.run(...)
209 elseif not url_or_dir then 209 elseif not url_or_dir then
210 url_or_dir = version 210 url_or_dir = version
211 end 211 end
212
213 if flags["tag"] == true then
214 return nil, "Incorrect usage: --tag requires an argument. "..util.see_help("write_rockspec")
215 end
216 212
217 if flags["tag"] then 213 if flags["tag"] then
218 if not version then 214 if not version then
219 version = flags["tag"]:gsub("^v", "") 215 version = flags["tag"]:gsub("^v", "")
220 end 216 end
221 end 217 end
222 218
223 local protocol, pathname = dir.split_url(url_or_dir) 219 local protocol, pathname = dir.split_url(url_or_dir)
224 if not fetch.is_basic_protocol(protocol) then 220 if not fetch.is_basic_protocol(protocol) then
225 if not name then 221 if not name then
@@ -251,6 +247,7 @@ function write_rockspec.run(...)
251 end 247 end
252 248
253 local rockspec = { 249 local rockspec = {
250 rockspec_format = flags["rockspec-format"],
254 package = name, 251 package = name,
255 name = name:lower(), 252 name = name:lower(),
256 version = version.."-1", 253 version = version.."-1",
@@ -316,7 +313,11 @@ function write_rockspec.run(...)
316 local ok, err = fs.change_dir(local_dir) 313 local ok, err = fs.change_dir(local_dir)
317 if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end 314 if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end
318 315
319 detect_description(rockspec) 316 if (not flags["summary"]) or (not flags["detailed"]) then
317 local summary, detailed = detect_description()
318 rockspec.description.summary = flags["summary"] or summary
319 rockspec.description.detailed = flags["detailed"] or detailed
320 end
320 321
321 local is_mit = show_license(rockspec) 322 local is_mit = show_license(rockspec)
322 323
diff --git a/test/testfiles/invalid_patch-0.1-1.rockspec b/test/testfiles/invalid_patch-0.1-1.rockspec
new file mode 100644
index 00000000..c2ecd160
--- /dev/null
+++ b/test/testfiles/invalid_patch-0.1-1.rockspec
@@ -0,0 +1,29 @@
1package = "invalid_patch"
2version = "0.1-1"
3source = {
4 -- any valid URL
5 url = "https://raw.github.com/keplerproject/luarocks/master/src/luarocks/build.lua"
6}
7description = {
8 summary = "A rockspec with an invalid patch",
9}
10dependencies = {
11 "lua >= 5.1"
12}
13build = {
14 type = "builtin",
15 modules = {
16 build = "build.lua"
17 },
18 patches = {
19 ["I_am_an_invalid_patch.patch"] =
20[[
21diff -Naur luadoc-3.0.1/src/luadoc/doclet/html.lua luadoc-3.0.1-new/src/luadoc/doclet/html.lua
22--- luadoc-3.0.1/src/luadoc/doclet/html.lua2007-12-21 15:50:48.000000000 -0200
23+++ luadoc-3.0.1-new/src/luadoc/doclet/html.lua2008-02-28 01:59:53.000000000 -0300
24@@ -18,6 +18,7 @@
25- gabba gabba gabba
26+ gobo gobo gobo
27]]
28 }
29}
diff --git a/test/testfiles/no_build_table-0.1-1.rockspec b/test/testfiles/no_build_table-0.1-1.rockspec
new file mode 100644
index 00000000..5d79e9a0
--- /dev/null
+++ b/test/testfiles/no_build_table-0.1-1.rockspec
@@ -0,0 +1,12 @@
1package = "no_build_table"
2version = "0.1-1"
3source = {
4 -- any valid URL
5 url = "https://raw.github.com/keplerproject/luarocks/master/src/luarocks/build.lua"
6}
7description = {
8 summary = "A rockspec with no build field",
9}
10dependencies = {
11 "lua >= 5.1"
12}
diff --git a/test/testfiles/not_a_zipfile-1.0-1.src.rock b/test/testfiles/not_a_zipfile-1.0-1.src.rock
new file mode 100644
index 00000000..e36f8bbe
--- /dev/null
+++ b/test/testfiles/not_a_zipfile-1.0-1.src.rock
@@ -0,0 +1 @@
I am not a .zip file!
diff --git a/test/testfiles/type_mismatch_string-1.0-1.rockspec b/test/testfiles/type_mismatch_string-1.0-1.rockspec
new file mode 100644
index 00000000..7a607cfd
--- /dev/null
+++ b/test/testfiles/type_mismatch_string-1.0-1.rockspec
@@ -0,0 +1,4 @@
1
2package="type_mismatch_version"
3version=1.0
4
diff --git a/test/testfiles/type_mismatch_table-1.0-1.rockspec b/test/testfiles/type_mismatch_table-1.0-1.rockspec
new file mode 100644
index 00000000..f348b798
--- /dev/null
+++ b/test/testfiles/type_mismatch_table-1.0-1.rockspec
@@ -0,0 +1,5 @@
1
2package="type_mismatch_table"
3version="1.0-1"
4
5source = "not a table"
diff --git a/test/testfiles/type_mismatch_version-1.0-1.rockspec b/test/testfiles/type_mismatch_version-1.0-1.rockspec
new file mode 100644
index 00000000..5e30dae6
--- /dev/null
+++ b/test/testfiles/type_mismatch_version-1.0-1.rockspec
@@ -0,0 +1,4 @@
1
2package="type_mismatch_version"
3version="1.0"
4
diff --git a/test/testing.bat b/test/testing.bat
new file mode 100644
index 00000000..7083678b
--- /dev/null
+++ b/test/testing.bat
@@ -0,0 +1,9 @@
1@echo off
2Setlocal EnableDelayedExpansion EnableExtensions
3
4if not defined LUAROCKS_REPO set LUAROCKS_REPO=https://luarocks.org
5
6appveyor DownloadFile %LUAROCKS_REPO%/stdlib-41.0.0-1.src.rock
7luarocks build stdlib
8
9endlocal
diff --git a/test/testing.lua b/test/testing.lua
new file mode 100644
index 00000000..c37293ee
--- /dev/null
+++ b/test/testing.lua
@@ -0,0 +1,464 @@
1
2local variables = {}
3
4-- Expand variables in the format $foo or ${foo} according
5-- to the variables table.
6local function expand_variables(str)
7 return str:gsub("%$({?)([A-Za-z0-9_]+)(}?)", function(o, v, c)
8 return #o <= #c and (variables[v] or "") .. (#o < #c and c or "")
9 end)
10end
11
12-- @param cmd command to run
13-- @param envtable optional table of temporary environment variables
14local function run(cmd, envtable)
15 cmd = expand_variables(cmd)
16 local env = {}
17 for var, val in pairs(envtable) do
18 table.insert(env, var.."='"..expand_variables(val).."' ")
19 end
20 local code = os.execute(table.concat(env)..cmd)
21 return (code == 0 or code == true)
22end
23
24local function cd_run(dir, cmd, envtable)
25 return run("cd "..dir.." && "..cmd, envtable)
26end
27
28local function run_get_contents(cmd)
29end
30
31local function mkdir(dirname)
32 cmd = expand_variables(dirname)
33 -- TODO
34end
35
36local function rm_rf(...)
37 -- TODO
38end
39
40local function mv(src, dst)
41 -- TODO
42end
43
44local function exists(filename)
45 filename = expand_variables(filename)
46 -- TODO
47end
48
49local function glob(patt)
50 -- TODO
51end
52
53local function touch(filename)
54 -- TODO
55end
56
57local function rm(...)
58 for _, filename in ipairs {...} do
59 filename = expand_variables(filename)
60 -- TODO
61 end
62 return true
63end
64
65local function file_set_contents(filename, contents)
66 filename = expand_variables(filename)
67
68 local fd, err = io.open(filename, "w")
69 if not fd then return nil, err end
70 fd:write(contents)
71 fd:close()
72 return true
73end
74
75local function need_luasocket()
76 -- TODO
77end
78
79local tests = {
80
81 test_version = function() return run "$luarocks --version" end,
82 fail_unknown_command = function() return run "$luarocks unknown_command" end,
83 fail_arg_boolean_parameter = function() return run "$luarocks --porcelain=invalid" end,
84 fail_arg_boolean_unknown = function() return run "$luarocks --invalid-flag" end,
85 fail_arg_string_no_parameter = function() return run "$luarocks --server" end,
86 fail_arg_string_followed_by_flag = function() return run "$luarocks --server --porcelain" end,
87 fail_arg_string_unknown = function() return run "$luarocks --invalid-flag=abc" end,
88 test_empty_list = function() return run "$luarocks list" end,
89 test_list_outdated = function () return run "$luarocks list --outdated" end,
90 fail_sysconfig_err = function()
91 mkdir "$testing_lrprefix/etc/luarocks"
92 file_set_contents("$testing_lrprefix/etc/luarocks/config.lua", "aoeui")
93 return run "$luarocks list"
94 and rm "$testing_lrprefix/etc/luarocks/config.lua"
95 end,
96 fail_sysconfig_default_err = function()
97 mkdir "$testing_lrprefix/etc/luarocks"
98 file_set_contents("$testing_lrprefix/etc/luarocks/config-$luashortversion.lua", "aoeui")
99 return run "$luarocks list"
100 and rm "$testing_lrprefix/etc/luarocks/config-$luashortversion.lua"
101 end,
102 fail_build_noarg = function() return run "$luarocks build" end,
103 fail_download_noarg = function() return run "$luarocks download" end,
104 fail_install_noarg = function() return run "$luarocks install" end,
105 fail_lint_noarg = function() return run "$luarocks lint" end,
106 fail_search_noarg = function() return run "$luarocks search" end,
107 fail_show_noarg = function() return run "$luarocks show" end,
108 fail_unpack_noarg = function() return run "$luarocks unpack" end,
109 fail_upload_noarg = function() return run "$luarocks upload" end,
110 fail_remove_noarg = function() return run "$luarocks remove" end,
111 fail_doc_noarg = function() return run "$luarocks doc" end,
112 fail_new_version_noarg = function() return run "$luarocks new_version" end,
113 fail_write_rockspec_noarg = function() return run "$luarocks write_rockspec" end,
114 fail_build_invalid = function() return run "$luarocks build invalid" end,
115 fail_download_invalid = function() return run "$luarocks download invalid" end,
116 fail_install_invalid = function() return run "$luarocks install invalid" end,
117 fail_lint_invalid = function() return run "$luarocks lint invalid" end,
118 fail_show_invalid = function() return run "$luarocks show invalid" end,
119 fail_new_version_invalid = function() return run "$luarocks new_version invalid" end,
120 test_list_invalidtree = function() return run "$luarocks --tree=/some/invalid/tree list" end,
121 fail_inexistent_dir = function()
122 -- Unix only?
123 return run "mkdir idontexist; cd idontexist; rmdir ../idontexist; $luarocks; err=$?; cd ..; return $err"
124 end,
125 fail_make_norockspec = function() return run "$luarocks make" end,
126 fail_build_permissions = function() return run "$luarocks build --tree=/usr lpeg" end,
127 fail_build_permissions_parent = function() return run "$luarocks build --tree=/usr/invalid lpeg" end,
128 test_build_verbose = function() return run "$luarocks build --verbose lpeg" end,
129 fail_build_blank_arg = function() return run "$luarocks build --tree="" lpeg" end,
130 test_build_withpatch = function() need_luasocket(); return run "$luarocks build luadoc" end,
131 test_build_diffversion = function() return run "$luarocks build luacov ${version_luacov}" end,
132 test_build_command = function() return run "$luarocks build stdlib" end,
133 test_build_install_bin = function() return run "$luarocks build luarepl" end,
134 test_build_nohttps = function()
135 need_luasocket()
136 return run "$luarocks download --rockspec validate-args ${verrev_validate_args}"
137 and run "$luarocks build ./validate-args-${version_validate_args}-1.rockspec"
138 and rm "./validate-args-${version_validate_args}-1.rockspec"
139 end,
140 test_build_https = function()
141 need_luasocket()
142 return run "$luarocks download --rockspec validate-args ${verrev_validate_args}"
143 and run "$luarocks install luasec"
144 and run "$luarocks build ./validate-args-${verrev_validate_args}.rockspec"
145 and rm "./validate-args-${verrev_validate_args}.rockspec"
146 end,
147 test_build_supported_platforms = function() return run "$luarocks build lpty" end,
148 test_build_only_deps_rockspec = function()
149 return run "$luarocks download --rockspec lxsh ${verrev_lxsh}"
150 and run "$luarocks build ./lxsh-${verrev_lxsh}.rockspec --only-deps"
151 and (not run "$luarocks show lxsh")
152 end,
153 test_build_only_deps_src_rock = function()
154 return run "$luarocks download --source lxsh ${verrev_lxsh}"
155 and run "$luarocks build ./lxsh-${verrev_lxsh}.src.rock --only-deps"
156 and (not run "$luarocks show lxsh")
157 end,
158 test_build_only_deps = function() return run "$luarocks build luasec --only-deps" and (not run "$luarocks show luasec") end,
159 test_install_only_deps = function() return run "$luarocks install lxsh ${verrev_lxsh} --only-deps" and (not run "$luarocks show lxsh") end,
160 fail_build_missing_external = function() return run '$luarocks build "$testing_dir/testfiles/missing_external-0.1-1.rockspec" INEXISTENT_INCDIR="/invalid/dir"' end,
161 fail_build_invalidpatch = function()
162 need_luasocket()
163 return run '$luarocks build "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"'
164 end,
165 test_build_deps_partial_match = function() return run "$luarocks build lmathx" end,
166 test_build_show_downloads = function()
167 return run("$luarocks build alien", { LUAROCKS_CONFIG="$testing_dir/testing_config_show_downloads.lua" })
168 end,
169 test_download_all = function()
170 return run "$luarocks download --all validate-args"
171 and rm(glob("validate-args-*"))
172 end,
173 test_download_rockspecversion = function()
174 return run "$luarocks download --rockspec validate-args ${verrev_validate_args}"
175 and rm(glob("validate-args-*"))
176 end,
177 test_help = function() return run "$luarocks help" end,
178 fail_help_invalid = function() return run "$luarocks help invalid" end,
179 test_install_binaryrock = function()
180 return run "$luarocks build --pack-binary-rock cprint"
181 and run "$luarocks install ./cprint-${verrev_cprint}.${platform}.rock"
182 and rm "./cprint-${verrev_cprint}.${platform}.rock"
183 end,
184 test_install_with_bin = function() return run "$luarocks install wsapi" end,
185 fail_install_notazipfile = function() return run '$luarocks install "$testing_dir/testfiles/not_a_zipfile-1.0-1.src.rock"' end,
186 fail_install_invalidpatch = function()
187 need_luasocket()
188 return run '$luarocks install "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"'
189 end,
190 fail_install_invalid_filename = function() return run '$luarocks install "invalid.rock"' end,
191 fail_install_invalid_arch = function() return run '$luarocks install "foo-1.0-1.impossible-x86.rock"' end,
192 test_install_reinstall = function()
193 return run '$luarocks install "$testing_cache/luasocket-$verrev_luasocket.$platform.rock"'
194 and run '$luarocks install --deps-mode=none "$testing_cache/luasocket-$verrev_luasocket.$platform.rock"'
195 end,
196 fail_local_root = function() return run("$luarocks install --local luasocket", { USER="root" }) end,
197 test_site_config = function()
198 mv("../src/luarocks/site_config.lua", "../src/luarocks/site_config.lua.tmp")
199 local ok = run "$luarocks"
200 mv("../src/luarocks/site_config.lua.tmp", "../src/luarocks/site_config.lua")
201 return ok
202 end,
203 test_lint_ok = function()
204 return run "$luarocks download --rockspec validate-args ${verrev_validate_args}"
205 and run "$luarocks lint ./validate-args-${verrev_validate_args}.rockspec"
206 and rm "./validate-args-${verrev_validate_args}.rockspec"
207 end,
208 fail_lint_type_mismatch_string = function() return run '$luarocks lint "$testing_dir/testfiles/type_mismatch_string-1.0-1.rockspec"' end,
209 fail_lint_type_mismatch_version = function() return run '$luarocks lint "$testing_dir/testfiles/type_mismatch_version-1.0-1.rockspec"' end,
210 fail_lint_type_mismatch_table = function() return run '$luarocks lint "$testing_dir/testfiles/type_mismatch_table-1.0-1.rockspec"' end,
211 fail_lint_no_build_table = function() return run '$luarocks lint "$testing_dir/testfiles/no_build_table-0.1-1.rockspec"' end,
212 test_list = function() return run "$luarocks list" end,
213 test_list_porcelain = function() return run "$luarocks list --porcelain" end,
214 test_make_with_rockspec = function()
215 return rm_rf "./luasocket-${verrev_luasocket}"
216 and run "$luarocks download --source luasocket"
217 and run "$luarocks unpack ./luasocket-${verrev_luasocket}.src.rock"
218 and cd_run("luasocket-${verrev_luasocket}/${srcdir_luasocket}", "$luarocks make luasocket-${verrev_luasocket}.rockspec")
219 and rm_rf "./luasocket-${verrev_luasocket}"
220 end,
221 test_make_default_rockspec = function()
222 return rm_rf "./lxsh-${verrev_lxsh}"
223 and run "$luarocks download --source lxsh ${verrev_lxsh}"
224 and run "$luarocks unpack ./lxsh-${verrev_lxsh}.src.rock"
225 and cd_run("lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1", "$luarocks make")
226 and rm_rf "./lxsh-${verrev_lxsh}"
227 end,
228 test_make_pack_binary_rock = function()
229 return rm_rf "./lxsh-${verrev_lxsh}"
230 and run "$luarocks download --source lxsh ${verrev_lxsh}"
231 and run "$luarocks unpack ./lxsh-${verrev_lxsh}.src.rock"
232 and cd_run("lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1", "$luarocks make --deps-mode=none --pack-binary-rock")
233 and exists "lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1/lxsh-${verrev_lxsh}.all.rock"
234 and rm_rf "./lxsh-${verrev_lxsh}"
235 end,
236 fail_make_which_rockspec = function()
237 rm_rf "./luasocket-${verrev_luasocket}"
238 run "$luarocks download --source luasocket"
239 run "$luarocks unpack ./luasocket-${verrev_luasocket}.src.rock"
240 local ok = cd_run("luasocket-${verrev_luasocket}/${srcdir_luasocket}", "$luarocks make")
241 rm_rf "./luasocket-${verrev_luasocket}"
242 return ok
243 end,
244 test_new_version = function()
245 return run "$luarocks download --rockspec luacov ${version_luacov}"
246 and run "$luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2"
247 and rm(glob("./luacov-0.*"))
248 end,
249 test_new_version_url = function()
250 return run "$luarocks download --rockspec abelhas 1.0"
251 and run "$luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz"
252 and rm(glob("./abelhas-*"))
253 end,
254 test_pack = function()
255 return run "$luarocks list"
256 and run "$luarocks pack luacov"
257 and rm(glob("./luacov-*.rock"))
258 end,
259 test_pack_src = function()
260 return run "$luarocks install luasec"
261 and run "$luarocks download --rockspec luasocket"
262 and run "$luarocks pack ./luasocket-${verrev_luasocket}.rockspec"
263 and rm(glob("./luasocket-${version_luasocket}-*.rock"))
264 end,
265 test_path = function() return run "$luarocks path --bin" end,
266 test_path_lr_path = function() return run "$luarocks path --lr-path" end,
267 test_path_lr_cpath = function() return run "$luarocks path --lr-cpath" end,
268 test_path_lr_bin = function() return run "$luarocks path --lr-bin" end,
269 test_path_with_tree = function() return run "$luarocks path --tree=lua_modules" end,
270 fail_purge_missing_tree = function() return run '$luarocks purge --tree="$testing_tree"' end,
271 test_purge = function() return run '$luarocks purge --tree="$testing_sys_tree"' end,
272 test_remove = function()
273 return run "$luarocks build abelhas ${version_abelhas}"
274 and run "$luarocks remove abelhas ${version_abelhas}"
275 end,
276 test_remove_force = function()
277 need_luasocket()
278 return run "$luarocks build lualogging"
279 and run "$luarocks remove --force luasocket"
280 end,
281 fail_remove_deps = function()
282 need_luasocket()
283 return run "$luarocks build lualogging"
284 and run "$luarocks remove luasocket"
285 end,
286 fail_remove_missing = function() return run "$luarocks remove missing_rock" end,
287 fail_remove_invalid_name = function() return run "$luarocks remove invalid.rock" end,
288 test_search_found = function() return run "$luarocks search zlib" end,
289 test_search_missing = function() return run "$luarocks search missing_rock" end,
290 test_show = function() return run "$luarocks show luacov" end,
291 test_show_modules = function() return run "$luarocks show --modules luacov" end,
292 test_show_home = function() return run "$luarocks show --home luacov" end,
293 test_show_depends = function()
294 need_luasocket()
295 return run "$luarocks install luasec"
296 and run "$luarocks show luasec"
297 end,
298 test_show_oldversion = function()
299 return run "$luarocks install luacov ${version_luacov}"
300 and run "$luarocks show luacov ${version_luacov}"
301 end,
302 test_unpack_download = function()
303 return rm_rf "./cprint-${verrev_cprint}"
304 and run "$luarocks unpack cprint"
305 and rm_rf "./cprint-${verrev_cprint}"
306 end,
307 test_unpack_src = function()
308 return rm_rf "./cprint-${verrev_cprint}"
309 and run "$luarocks download --source cprint"
310 and run "$luarocks unpack ./cprint-${verrev_cprint}.src.rock"
311 and rm_rf "./cprint-${verrev_cprint}"
312 end,
313 test_unpack_rockspec = function()
314 return rm_rf "./cprint-${verrev_cprint}"
315 and run "$luarocks download --rockspec cprint"
316 and run "$luarocks unpack ./cprint-${verrev_cprint}.rockspec"
317 and rm_rf "./cprint-${verrev_cprint}"
318 end,
319 test_unpack_binary = function()
320 return rm_rf "./cprint-${verrev_cprint}"
321 and run "$luarocks build cprint"
322 and run "$luarocks pack cprint"
323 and run "$luarocks unpack ./cprint-${verrev_cprint}.${platform}.rock"
324 and rm_rf "./cprint-${verrev_cprint}"
325 end,
326 fail_unpack_invalidpatch = function()
327 need_luasocket()
328 return run '$luarocks unpack "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"'
329 end,
330 fail_unpack_invalidrockspec = function()
331 need_luasocket()
332 return run '$luarocks unpack "invalid.rockspec"'
333 end,
334 fail_upload_invalidrockspec = function() return run '$luarocks upload "invalid.rockspec"' end,
335 fail_upload_invalidkey = function() return run '$luarocks upload --api-key="invalid" "invalid.rockspec"' end,
336 test_admin_help = function() return run "$luarocks_admin help" end,
337 test_admin_make_manifest = function() return run "$luarocks_admin make_manifest" end,
338 test_admin_add_rsync = function() return run '$luarocks_admin --server=testing add "$testing_server/luasocket-${verrev_luasocket}.src.rock"' end,
339 test_admin_add_sftp = function()
340 return run("$luarocks_admin --server=testing add ./luasocket-${verrev_luasocket}.src.rock", { LUAROCKS_CONFIG="$testing_dir/testing_config_sftp.lua" })
341 end,
342 fail_admin_add_missing = function() return run "$luarocks_admin --server=testing add" end,
343 fail_admin_invalidserver = function() return run '$luarocks_admin --server=invalid add "$testing_server/luasocket-${verrev_luasocket}.src.rock"' end,
344 fail_admin_invalidrock = function() return run "$luarocks_admin --server=testing add invalid" end,
345 test_admin_refresh_cache = function() return run "$luarocks_admin --server=testing refresh_cache" end,
346 test_admin_remove = function() return run "$luarocks_admin --server=testing remove luasocket-${verrev_luasocket}.src.rock" end,
347 fail_admin_remove_missing = function() return run "$luarocks_admin --server=testing remove" end,
348 fail_deps_mode_invalid_arg = function() return run "$luarocks remove luacov --deps-mode" end,
349
350 test_deps_mode_one = function()
351 return run '$luarocks build --tree="system" lpeg'
352 and run '$luarocks list'
353 and run '$luarocks build --deps-mode=one --tree="$testing_tree" lxsh'
354 and run_get_contents '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg' ~= ""
355 end,
356 test_deps_mode_order = function()
357 return run '$luarocks build --tree="system" lpeg'
358 and run '$luarocks build --deps-mode=order --tree="$testing_tree" lxsh'
359 and run '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg'
360 and run_get_contents '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg' == ""
361 end,
362 test_deps_mode_order_sys = function()
363 return run '$luarocks build --tree="$testing_tree" lpeg'
364 and run '$luarocks build --deps-mode=order --tree="$testing_sys_tree" lxsh'
365 and run_get_contents '$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg' ~= ""
366 end,
367 test_deps_mode_all_sys = function()
368 return run '$luarocks build --tree="$testing_tree" lpeg'
369 and run '$luarocks build --deps-mode=all --tree="$testing_sys_tree" lxsh'
370 and run_get_contents '$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg' == ""
371 end,
372
373 test_deps_mode_none = function()
374 return run '$luarocks build --tree="$testing_tree" --deps-mode=none lxsh'
375 and run_get_contents '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg' == ""
376 end,
377 test_deps_mode_nodeps_alias = function()
378 return run '$luarocks build --tree="$testing_tree" --nodeps lxsh'
379 and run_get_contents '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg' == ""
380 end,
381 test_deps_mode_make_order = function()
382 local ok = run '$luarocks build --tree="$testing_sys_tree" lpeg'
383 and rm_rf "./lxsh-${verrev_lxsh}"
384 and run "$luarocks download --source lxsh ${verrev_lxsh}"
385 and run "$luarocks unpack ./lxsh-${verrev_lxsh}.src.rock"
386 and cd_run("lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1", '$luarocks make --tree="$testing_tree" --deps-mode=order')
387 if not ok then
388 return false
389 end
390 local found = run_get_contents '$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg'
391 rm_rf "./lxsh-${verrev_lxsh}"
392 return found == ""
393 end,
394 test_deps_mode_make_order_sys = function()
395 local ok = run '$luarocks build --tree="$testing_tree" lpeg'
396 and rm_rf "./lxsh-${verrev_lxsh}"
397 and run "$luarocks download --source lxsh ${verrev_lxsh}"
398 and run "$luarocks unpack ./lxsh-${verrev_lxsh}.src.rock"
399 and cd_run("lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1", '$luarocks make --tree="$testing_sys_tree" --deps-mode=order')
400 if not ok then
401 return false
402 end
403 local found = run_get_contents '$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg'
404 rm_rf "./lxsh-${verrev_lxsh}"
405 return found ~= ""
406 end,
407 test_write_rockspec = function() return run "$luarocks write_rockspec git://github.com/keplerproject/luarocks" end,
408 test_write_rockspec_lib = function() return run '$luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2' end,
409 test_write_rockspec_format = function() return run '$luarocks write_rockspec git://github.com/keplerproject/luarocks --rockspec-format=1.1 --lua-version=5.1,5.2' end,
410 test_write_rockspec_fullargs = function() return run '$luarocks write_rockspec git://github.com/keplerproject/luarocks --lua-version=5.1,5.2 --license="MIT/X11" --homepage="http://www.luarocks.org" --summary="A package manager for Lua modules"' end,
411 fail_write_rockspec_args = function() return run "$luarocks write_rockspec invalid" end,
412 fail_write_rockspec_args_url = function() return run "$luarocks write_rockspec http://example.com/invalid.zip" end,
413 test_write_rockspec_http = function() return run "$luarocks write_rockspec http://luarocks.org/releases/luarocks-2.1.0.tar.gz --lua-version=5.1" end,
414 test_write_rockspec_basedir = function() return run "$luarocks write_rockspec https://github.com/downloads/Olivine-Labs/luassert/luassert-1.2.tar.gz --lua-version=5.1" end,
415
416 fail_config_noflags = function() return run "$luarocks config; " end,
417 test_config_lua_incdir = function() return run "$luarocks config --lua-incdir; " end,
418 test_config_lua_libdir = function() return run "$luarocks config --lua-libdir; " end,
419 test_config_lua_ver = function() return run "$luarocks config --lua-ver; " end,
420 fail_config_system_config = function()
421 return rm "$testing_lrprefix/etc/luarocks/config.lua"
422 and run "$luarocks config --system-config; "
423 end,
424 test_config_system_config = function()
425 local ok = mkdir "$testing_lrprefix/etc/luarocks"
426 and touch "$testing_lrprefix/etc/luarocks/config.lua"
427 and run "$luarocks config --system-config; "
428 rm "$testing_lrprefix/etc/luarocks/config.lua"
429 return ok
430 end,
431 fail_config_system_config_invalid = function()
432 local ok = mkdir "$testing_lrprefix/etc/luarocks"
433 and run "echo 'if if if' > '$testing_lrprefix/etc/luarocks/config.lua' ;"
434 and run "$luarocks config --system-config"
435 rm "$testing_lrprefix/etc/luarocks/config.lua"
436 return ok
437 end,
438 test_config_user_config = function() return run "$luarocks config --user-config; " end,
439 fail_config_user_config = function() return run "LUAROCKS_CONFIG='/missing_file.lua' $luarocks config --user-config; " end,
440 test_config_rock_trees = function() return run "$luarocks config --rock-trees;" end,
441 test_config_help = function() return run "$luarocks help config;" end,
442 test_doc = function()
443 return run "$luarocks install luarepl"
444 and run "$luarocks doc luarepl"
445 end,
446 test_doc_home = function()
447 return run "$luarocks install luacov"
448 and run "$luarocks doc luacov --home"
449 end,
450 fail_doc_invalid = function () return run "$luarocks doc invalid" end,
451
452 -- Tests for https://github.com/keplerproject/luarocks/issues/375
453 test_fetch_base_dir = function()
454 local fetch = require "luarocks.fetch"
455
456 return assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3.zip"))
457 and assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.zip"))
458 and assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.gz"))
459 and assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.bz2"))
460 and assert("parser.moon" == fetch.url_to_base_dir("git://github.com/Cirru/parser.moon"))
461 and assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3"))
462 end
463
464}
diff --git a/test/testing.sh b/test/testing.sh
index e3aee55f..305168c8 100755
--- a/test/testing.sh
+++ b/test/testing.sh
@@ -30,8 +30,11 @@ then
30 shift 30 shift
31fi 31fi
32 32
33luashortversion=`echo $luaversion | cut -d. -f 1-2`
34
33testing_dir="$PWD" 35testing_dir="$PWD"
34 36
37testing_lrprefix="$testing_dir/testing_lrprefix-$luaversion"
35testing_tree="$testing_dir/testing-$luaversion" 38testing_tree="$testing_dir/testing-$luaversion"
36testing_sys_tree="$testing_dir/testing_sys-$luaversion" 39testing_sys_tree="$testing_dir/testing_sys-$luaversion"
37testing_tree_copy="$testing_dir/testing_copy-$luaversion" 40testing_tree_copy="$testing_dir/testing_copy-$luaversion"
@@ -39,7 +42,6 @@ testing_sys_tree_copy="$testing_dir/testing_sys_copy-$luaversion"
39testing_cache="$testing_dir/testing_cache-$luaversion" 42testing_cache="$testing_dir/testing_cache-$luaversion"
40testing_server="$testing_dir/testing_server-$luaversion" 43testing_server="$testing_dir/testing_server-$luaversion"
41 44
42
43if [ "$1" == "--clean" ] 45if [ "$1" == "--clean" ]
44then 46then
45 shift 47 shift
@@ -51,6 +53,7 @@ fi
51rm -f luacov.report.out 53rm -f luacov.report.out
52rm -rf /tmp/luarocks_testing 54rm -rf /tmp/luarocks_testing
53mkdir /tmp/luarocks_testing 55mkdir /tmp/luarocks_testing
56rm -rf "$testing_lrprefix"
54rm -rf "$testing_tree" 57rm -rf "$testing_tree"
55rm -rf "$testing_sys_tree" 58rm -rf "$testing_sys_tree"
56rm -rf "$testing_tree_copy" 59rm -rf "$testing_tree_copy"
@@ -77,7 +80,7 @@ rocks_servers = {
77} 80}
78local_cache = "$testing_cache" 81local_cache = "$testing_cache"
79upload_server = "testing" 82upload_server = "testing"
80upload_user = "hisham" 83upload_user = "$USER"
81upload_servers = { 84upload_servers = {
82 testing = { 85 testing = {
83 rsync = "localhost/tmp/luarocks_testing", 86 rsync = "localhost/tmp/luarocks_testing",
@@ -107,7 +110,7 @@ rocks_trees = {
107} 110}
108local_cache = "$testing_cache" 111local_cache = "$testing_cache"
109upload_server = "testing" 112upload_server = "testing"
110upload_user = "hisham" 113upload_user = "$USER"
111upload_servers = { 114upload_servers = {
112 testing = { 115 testing = {
113 sftp = "localhost/tmp/luarocks_testing", 116 sftp = "localhost/tmp/luarocks_testing",
@@ -116,20 +119,15 @@ upload_servers = {
116EOF 119EOF
117cat <<EOF > $testing_dir/luacov.config 120cat <<EOF > $testing_dir/luacov.config
118return { 121return {
119 ["configfile"] = ".luacov", 122 statsfile = "$testing_dir/luacov.stats.out",
120 ["statsfile"] = "$testing_dir/luacov.stats.out", 123 reportfile = "$testing_dir/luacov.report.out",
121 ["reportfile"] = "$testing_dir/luacov.report.out", 124 modules = {
122 runreport = false, 125 ["luarocks"] = "src/bin/luarocks",
123 deletestats = false, 126 ["luarocks-admin"] = "src/bin/luarocks-admin",
124 ["include"] = {}, 127 ["luarocks.*"] = "src",
125 ["exclude"] = { 128 ["luarocks.*.*"] = "src",
126 "luacov$", 129 ["luarocks.*.*.*"] = "src"
127 "luacov%.reporter$", 130 }
128 "luacov%.defaults$",
129 "luacov%.runner$",
130 "luacov%.stats$",
131 "luacov%.tick$",
132 },
133} 131}
134EOF 132EOF
135 133
@@ -153,8 +151,16 @@ then
153 make install INSTALL_TOP="$luadir" &> /dev/null 151 make install INSTALL_TOP="$luadir" &> /dev/null
154 fi 152 fi
155 popd 153 popd
154 [ -e ~/.ssh/id_rsa.pub ] || ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
155 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
156 chmod og-wx ~/.ssh/authorized_keys
157 ssh-keyscan localhost >> ~/.ssh/known_hosts
156else 158else
157 luadir="/Programs/Lua/Current" 159 luadir="/Programs/Lua/Current"
160 if [ ! -e "$luadir" ]
161 then
162 luadir="/usr/local"
163 fi
158fi 164fi
159 165
160if [ `uname -m` = i686 ] 166if [ `uname -m` = i686 ]
@@ -171,19 +177,21 @@ verrev_luasocket=${version_luasocket}-1
171srcdir_luasocket=luasocket-3.0-rc1 177srcdir_luasocket=luasocket-3.0-rc1
172 178
173version_cprint=0.1 179version_cprint=0.1
174verrev_cprint=0.1-1 180verrev_cprint=0.1-2
175 181
176version_luacov=0.5 182version_luacov=0.11.0
177verrev_luacov=0.5-1 183verrev_luacov=${version_luacov}-1
178version_lxsh=0.8.6 184version_lxsh=0.8.6
179version_validate_args=1.5.4 185version_validate_args=1.5.4
180verrev_validate_args=1.5.4-1 186verrev_validate_args=1.5.4-1
181verrev_lxsh=${version_lxsh}-2 187verrev_lxsh=${version_lxsh}-2
188version_abelhas=1.0
189verrev_abelhas=${version_abelhas}-1
182 190
183luasec=luasec 191luasec=luasec
184 192
185cd .. 193cd ..
186./configure --with-lua="$luadir" 194./configure --with-lua="$luadir" --prefix="$testing_lrprefix"
187make clean 195make clean
188make src/luarocks/site_config.lua 196make src/luarocks/site_config.lua
189make dev 197make dev
@@ -217,8 +225,7 @@ luarocks_admin_nocov="run_lua --nocov luarocks-admin"
217mkdir -p "$testing_server" 225mkdir -p "$testing_server"
218( 226(
219 cd "$testing_server" 227 cd "$testing_server"
220 luarocks_repo="http://luarocks.org/repositories/rocks" 228 luarocks_repo="https://luarocks.org"
221 luarocks_scm_repo="http://luarocks.org/repositories/rocks-scm"
222 get() { [ -e `basename "$1"` ] || wget -c "$1"; } 229 get() { [ -e `basename "$1"` ] || wget -c "$1"; }
223 get "$luarocks_repo/luacov-${verrev_luacov}.src.rock" 230 get "$luarocks_repo/luacov-${verrev_luacov}.src.rock"
224 get "$luarocks_repo/luacov-${verrev_luacov}.rockspec" 231 get "$luarocks_repo/luacov-${verrev_luacov}.rockspec"
@@ -226,26 +233,33 @@ mkdir -p "$testing_server"
226 get "$luarocks_repo/lualogging-1.3.0-1.src.rock" 233 get "$luarocks_repo/lualogging-1.3.0-1.src.rock"
227 get "$luarocks_repo/luasocket-${verrev_luasocket}.src.rock" 234 get "$luarocks_repo/luasocket-${verrev_luasocket}.src.rock"
228 get "$luarocks_repo/luasocket-${verrev_luasocket}.rockspec" 235 get "$luarocks_repo/luasocket-${verrev_luasocket}.rockspec"
229 get "$luarocks_repo/luafilesystem-1.6.2-1.src.rock" 236 get "$luarocks_repo/luafilesystem-1.6.3-1.src.rock"
230 get "$luarocks_repo/stdlib-35-1.src.rock" 237 get "$luarocks_repo/stdlib-41.0.0-1.src.rock"
231 get "$luarocks_repo/luarepl-0.4-1.src.rock" 238 get "$luarocks_repo/luarepl-0.4-1.src.rock"
232 get "$luarocks_repo/validate-args-1.5.4-1.rockspec" 239 get "$luarocks_repo/validate-args-1.5.4-1.rockspec"
233 get "$luarocks_scm_repo/luasec-scm-1.rockspec" 240 get "$luarocks_repo/luasec-0.6-1.rockspec"
234 get "$luarocks_repo/luabitop-1.0.2-1.rockspec" 241 get "$luarocks_repo/luabitop-1.0.2-1.rockspec"
242 get "$luarocks_repo/luabitop-1.0.2-1.src.rock"
235 get "$luarocks_repo/lpty-1.0.1-1.src.rock" 243 get "$luarocks_repo/lpty-1.0.1-1.src.rock"
236 get "$luarocks_repo/cprint-${verrev_cprint}.src.rock" 244 get "$luarocks_repo/cprint-${verrev_cprint}.src.rock"
237 get "$luarocks_repo/cprint-${verrev_cprint}.rockspec" 245 get "$luarocks_repo/cprint-${verrev_cprint}.rockspec"
238 get "$luarocks_repo/wsapi-1.6-1.src.rock" 246 get "$luarocks_repo/wsapi-1.6-1.src.rock"
239 get "$luarocks_repo/lxsh-${verrev_lxsh}.src.rock" 247 get "$luarocks_repo/lxsh-${verrev_lxsh}.src.rock"
240 get "$luarocks_repo/abelhas-1.0-1.rockspec" 248 get "$luarocks_repo/lxsh-${verrev_lxsh}.rockspec"
241 get "$luarocks_repo/lzlib-0.4.work3-1.src.rock" 249 get "$luarocks_repo/abelhas-${verrev_abelhas}.rockspec"
250 get "$luarocks_repo/lzlib-0.4.1.53-1.src.rock"
242 get "$luarocks_repo/lpeg-0.12-1.src.rock" 251 get "$luarocks_repo/lpeg-0.12-1.src.rock"
243 get "$luarocks_repo/luaposix-31-1.src.rock" 252 get "$luarocks_repo/luaposix-33.2.1-1.src.rock"
244 get "$luarocks_repo/md5-1.2-1.src.rock" 253 get "$luarocks_repo/md5-1.2-1.src.rock"
245 get "$luarocks_repo/lrandom-20120430.51-1.src.rock" 254 get "$luarocks_repo/lmathx-20120430.51-1.src.rock"
246 get "$luarocks_repo/lrandom-20120430.52-1.src.rock" 255 get "$luarocks_repo/lmathx-20120430.51-1.rockspec"
247 get "$luarocks_repo/lrandom-20120430.51-1.rockspec" 256 get "$luarocks_repo/lmathx-20120430.52-1.src.rock"
248 get "$luarocks_repo/lrandom-20120430.52-1.rockspec" 257 get "$luarocks_repo/lmathx-20120430.52-1.rockspec"
258 get "$luarocks_repo/lmathx-20150505-1.src.rock"
259 get "$luarocks_repo/lmathx-20150505-1.rockspec"
260 get "$luarocks_repo/lua-path-0.2.3-1.src.rock"
261 get "$luarocks_repo/lua-cjson-2.1.0-1.src.rock"
262 get "$luarocks_repo/luacov-coveralls-0.1.1-1.src.rock"
249) 263)
250$luarocks_admin_nocov make_manifest "$testing_server" 264$luarocks_admin_nocov make_manifest "$testing_server"
251 265
@@ -270,6 +284,8 @@ build_environment() {
270 $luarocks_nocov pack --tree="$testing_sys_tree" $package; mv $package-*.rock "$testing_cache" 284 $luarocks_nocov pack --tree="$testing_sys_tree" $package; mv $package-*.rock "$testing_cache"
271 } 285 }
272 done 286 done
287 export LUA_PATH=
288 export LUA_CPATH=
273 eval `$luarocks_noecho_nocov path --bin` 289 eval `$luarocks_noecho_nocov path --bin`
274 cp -a "$testing_tree" "$testing_tree_copy" 290 cp -a "$testing_tree" "$testing_tree_copy"
275 cp -a "$testing_sys_tree" "$testing_sys_tree_copy" 291 cp -a "$testing_sys_tree" "$testing_sys_tree_copy"
@@ -313,14 +329,23 @@ need() {
313need_luasocket() { need luasocket $verrev_luasocket; } 329need_luasocket() { need luasocket $verrev_luasocket; }
314 330
315# Tests ######################################### 331# Tests #########################################
316
317test_version() { $luarocks --version; } 332test_version() { $luarocks --version; }
318 333
319fail_arg_server() { $luarocks --server; }
320fail_arg_only_server() { $luarocks --only-server; }
321fail_unknown_command() { $luarocks unknown_command; } 334fail_unknown_command() { $luarocks unknown_command; }
322 335
336fail_arg_boolean_parameter() { $luarocks --porcelain=invalid; }
337fail_arg_boolean_unknown() { $luarocks --invalid-flag; }
338fail_arg_string_no_parameter() { $luarocks --server; }
339fail_arg_string_followed_by_flag() { $luarocks --server --porcelain; }
340fail_arg_string_unknown() { $luarocks --invalid-flag=abc; }
341
342fail_invalid_assignment() { $luarocks invalid=5; }
343
323test_empty_list() { $luarocks list; } 344test_empty_list() { $luarocks list; }
345test_list_outdated() { $luarocks list --outdated; }
346
347fail_sysconfig_err() { local err=0; local scdir="$testing_lrprefix/etc/luarocks/"; mkdir -p "$scdir"; local sysconfig="$scdir/config.lua"; echo "aoeui" > "$sysconfig"; echo $sysconfig; $luarocks list; err=$?; rm "$sysconfig"; return "$err"; }
348fail_sysconfig_default_err() { local err=0; local scdir="$testing_lrprefix/etc/luarocks/"; mkdir -p "$scdir"; local sysconfig="$scdir/config-$luashortversion.lua"; echo "aoeui" > "$sysconfig"; echo $sysconfig; $luarocks list; err=$?; rm "$sysconfig"; return "$err"; }
324 349
325fail_build_noarg() { $luarocks build; } 350fail_build_noarg() { $luarocks build; }
326fail_download_noarg() { $luarocks download; } 351fail_download_noarg() { $luarocks download; }
@@ -329,6 +354,7 @@ fail_lint_noarg() { $luarocks lint; }
329fail_search_noarg() { $luarocks search; } 354fail_search_noarg() { $luarocks search; }
330fail_show_noarg() { $luarocks show; } 355fail_show_noarg() { $luarocks show; }
331fail_unpack_noarg() { $luarocks unpack; } 356fail_unpack_noarg() { $luarocks unpack; }
357fail_upload_noarg() { $luarocks upload; }
332fail_remove_noarg() { $luarocks remove; } 358fail_remove_noarg() { $luarocks remove; }
333fail_doc_noarg() { $luarocks doc; } 359fail_doc_noarg() { $luarocks doc; }
334fail_new_version_noarg() { $luarocks new_version; } 360fail_new_version_noarg() { $luarocks new_version; }
@@ -341,45 +367,80 @@ fail_lint_invalid() { $luarocks lint invalid; }
341fail_show_invalid() { $luarocks show invalid; } 367fail_show_invalid() { $luarocks show invalid; }
342fail_new_version_invalid() { $luarocks new_version invalid; } 368fail_new_version_invalid() { $luarocks new_version invalid; }
343 369
370test_list_invalidtree() { $luarocks --tree=/some/invalid/tree list; }
371
372fail_inexistent_dir() { mkdir idontexist; cd idontexist; rmdir ../idontexist; $luarocks; err=$?; cd ..; return $err; }
373
344fail_make_norockspec() { $luarocks make; } 374fail_make_norockspec() { $luarocks make; }
345 375
376fail_build_permissions() { $luarocks build --tree=/usr lpeg; }
377fail_build_permissions_parent() { $luarocks build --tree=/usr/invalid lpeg; }
378
379test_build_verbose() { $luarocks build --verbose lpeg; }
380test_build_timeout() { $luarocks --timeout=10; }
381fail_build_timeout_invalid() { $luarocks --timeout=abc; }
382test_build_branch() { $luarocks build --branch=master lpeg; }
383fail_build_invalid_entry_deps_mode() { $luarocks build --deps-mode=123 lpeg; }
384test_build_only_server() { $luarocks --only-server=testing; }
385test_build_only_sources() { $luarocks build --only-sources="http://example.com" lpeg; }
346fail_build_blank_arg() { $luarocks build --tree="" lpeg; } 386fail_build_blank_arg() { $luarocks build --tree="" lpeg; }
347test_build_withpatch() { need_luasocket; $luarocks build luadoc; } 387test_build_withpatch() { need_luasocket; $luarocks build luadoc; }
348test_build_diffversion() { $luarocks build luacov ${version_luacov}; } 388test_build_diffversion() { $luarocks build luacov ${version_luacov}; }
349test_build_command() { $luarocks build stdlib; } 389test_build_command() { $luarocks build stdlib; }
350test_build_install_bin() { $luarocks build luarepl; } 390test_build_install_bin() { $luarocks build luarepl; }
351fail_build_nohttps() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks build ./validate-args-${version_validate_args}-1.rockspec && rm ./validate-args-${version_validate_args}-1.rockspec; } 391test_build_nohttps() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks build ./validate-args-${version_validate_args}-1.rockspec && rm ./validate-args-${version_validate_args}-1.rockspec; }
352test_build_https() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks install $luasec && $luarocks build ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; } 392test_build_https() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks install $luasec && $luarocks build ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; }
353test_build_supported_platforms() { $luarocks build lpty; } 393test_build_supported_platforms() { $luarocks build lpty; }
394test_build_only_deps_rockspec() { $luarocks download --rockspec lxsh ${verrev_lxsh} && $luarocks build ./lxsh-${verrev_lxsh}.rockspec --only-deps && { $luarocks show lxsh; [ $? -ne 0 ]; }; }
395test_build_only_deps_src_rock() { $luarocks download --source lxsh ${verrev_lxsh} && $luarocks build ./lxsh-${verrev_lxsh}.src.rock --only-deps && { $luarocks show lxsh; [ $? -ne 0 ]; }; }
396test_build_only_deps() { $luarocks build luasec --only-deps && { $luarocks show luasec; [ $? -ne 0 ]; }; }
397test_install_only_deps() { $luarocks install lxsh ${verrev_lxsh} --only-deps && { $luarocks show lxsh; [ $? -ne 0 ]; }; }
398test_build_no_deps() { $luarocks build luasec --nodeps; }
399test_install_no_deps() { $luarocks install luasec --nodeps; }
354fail_build_missing_external() { $luarocks build "$testing_dir/testfiles/missing_external-0.1-1.rockspec" INEXISTENT_INCDIR="/invalid/dir"; } 400fail_build_missing_external() { $luarocks build "$testing_dir/testfiles/missing_external-0.1-1.rockspec" INEXISTENT_INCDIR="/invalid/dir"; }
401fail_build_invalidpatch() { need_luasocket; $luarocks build "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"; }
355 402
356test_build_deps_partial_match() { $luarocks build lrandom; } 403test_build_deps_partial_match() { $luarocks build lmathx; }
357test_build_show_downloads() { export LUAROCKS_CONFIG="$testing_dir/testing_config_show_downloads.lua" && $luarocks build alien; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; } 404test_build_show_downloads() { export LUAROCKS_CONFIG="$testing_dir/testing_config_show_downloads.lua" && $luarocks build alien; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; }
358 405
359test_download_all() { $luarocks download --all validate-args && rm validate-args-*; } 406test_download_all() { $luarocks download --all validate-args && rm validate-args-*; }
360test_download_rockspecversion() { $luarocks download --rockspec validate-args ${verrev_validate_args} && rm validate-args-*; } 407test_download_rockspecversion() { $luarocks download --rockspec validate-args ${verrev_validate_args} && rm validate-args-*; }
361 408
362test_help() { $luarocks help; } 409test_help() { $luarocks help; }
410fail_help_invalid() { $luarocks help invalid; }
363 411
412test_install_only_deps() { $luarocks install --only-deps "$testing_cache/luasocket-$verrev_luasocket.$platform.rock"; }
364test_install_binaryrock() { $luarocks build --pack-binary-rock cprint && $luarocks install ./cprint-${verrev_cprint}.${platform}.rock && rm ./cprint-${verrev_cprint}.${platform}.rock; } 413test_install_binaryrock() { $luarocks build --pack-binary-rock cprint && $luarocks install ./cprint-${verrev_cprint}.${platform}.rock && rm ./cprint-${verrev_cprint}.${platform}.rock; }
365test_install_with_bin() { $luarocks install wsapi; } 414test_install_with_bin() { $luarocks install wsapi; }
366fail_install_notazipfile() { $luarocks install "$testing_dir/testfiles/not_a_zipfile-1.0-1.src.rock"; } 415fail_install_notazipfile() { $luarocks install "$testing_dir/testfiles/not_a_zipfile-1.0-1.src.rock"; }
416fail_install_invalidpatch() { need_luasocket; $luarocks install "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"; }
417fail_install_invalid_filename() { $luarocks install "invalid.rock"; }
418fail_install_invalid_arch() { $luarocks install "foo-1.0-1.impossible-x86.rock"; }
419test_install_reinstall() { $luarocks install "$testing_cache/luasocket-$verrev_luasocket.$platform.rock"; $luarocks install --deps-mode=none "$testing_cache/luasocket-$verrev_luasocket.$platform.rock"; }
420
421fail_local_root() { USER=root $luarocks install --local luasocket; }
422
423test_site_config() { mv ../src/luarocks/site_config.lua ../src/luarocks/site_config.lua.tmp; $luarocks; mv ../src/luarocks/site_config.lua.tmp ../src/luarocks/site_config.lua; }
367 424
368test_lint_ok() { $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks lint ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; } 425test_lint_ok() { $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks lint ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; }
369fail_lint_type_mismatch_string() { $luarocks lint "$testing_dir/testfiles/type_mismatch_string-1.0-1.rockspec"; } 426fail_lint_type_mismatch_string() { $luarocks lint "$testing_dir/testfiles/type_mismatch_string-1.0-1.rockspec"; }
370fail_lint_type_mismatch_version() { $luarocks lint "$testing_dir/testfiles/type_mismatch_version-1.0-1.rockspec"; } 427fail_lint_type_mismatch_version() { $luarocks lint "$testing_dir/testfiles/type_mismatch_version-1.0-1.rockspec"; }
371fail_lint_type_mismatch_table() { $luarocks lint "$testing_dir/testfiles/type_mismatch_table-1.0-1.rockspec"; } 428fail_lint_type_mismatch_table() { $luarocks lint "$testing_dir/testfiles/type_mismatch_table-1.0-1.rockspec"; }
429fail_lint_no_build_table() { $luarocks lint "$testing_dir/testfiles/no_build_table-0.1-1.rockspec"; }
372 430
373test_list() { $luarocks list; } 431test_list() { $luarocks list; }
374test_list_porcelain() { $luarocks list --porcelain; } 432test_list_porcelain() { $luarocks list --porcelain; }
375 433
376test_make_with_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks download --src luasocket && $luarocks unpack ./luasocket-${verrev_luasocket}.src.rock && cd luasocket-${verrev_luasocket}/${srcdir_luasocket} && $luarocks make luasocket-${verrev_luasocket}.rockspec && cd ../.. && rm -rf ./luasocket-${verrev_luasocket}; } 434test_make_with_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks download --source luasocket && $luarocks unpack ./luasocket-${verrev_luasocket}.src.rock && cd luasocket-${verrev_luasocket}/${srcdir_luasocket} && $luarocks make luasocket-${verrev_luasocket}.rockspec && cd ../.. && rm -rf ./luasocket-${verrev_luasocket}; }
377test_make_default_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; } 435test_make_default_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks new_version lxsh-${verrev_lxsh}.rockspec && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
378test_make_pack_binary_rock() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --deps-mode=none --pack-binary-rock && [ -e ./lxsh-${verrev_lxsh}.all.rock ] && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; } 436test_make_unnamed_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && cp lxsh-${verrev_lxsh}.rockspec rockspec && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
379fail_make_which_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks download --src luasocket && $luarocks unpack ./luasocket-${verrev_luasocket}.src.rock && cd luasocket-${verrev_luasocket}/${srcdir_luasocket} && $luarocks make && cd ../.. && rm -rf ./luasocket-${verrev_luasocket}; } 437fail_make_ambiguous_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && cp lxsh-${verrev_lxsh}.rockspec lxsh2-${verrev_lxsh}.rockspec && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
438fail_make_ambiguous_unnamed_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && mv lxsh-${verrev_lxsh}.rockspec 1_rockspec && cp 1_rockspec 2_rockspec && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
439test_make_pack_binary_rock() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --deps-mode=none --pack-binary-rock && [ -e ./lxsh-${verrev_lxsh}.all.rock ] && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
380 440
381test_new_version() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2 && rm ./luacov-0.*; } 441test_new_version() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2 && rm ./luacov-0.*; }
382test_new_version_url() { $luarocks download --rockspec abelhas 1.0 && $luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz && rm ./abelhas-*; } 442test_new_version_url() { $luarocks download --rockspec abelhas 1.0 && $luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz && rm ./abelhas-*; }
443test_new_version_tag() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec --tag v0.3 && rm ./luacov-0.3-1.rockspec; }
383 444
384test_pack() { $luarocks list && $luarocks pack luacov && rm ./luacov-*.rock; } 445test_pack() { $luarocks list && $luarocks pack luacov && rm ./luacov-*.rock; }
385test_pack_src() { $luarocks install $luasec && $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-${verrev_luasocket}.rockspec && rm ./luasocket-${version_luasocket}-*.rock; } 446test_pack_src() { $luarocks install $luasec && $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-${verrev_luasocket}.rockspec && rm ./luasocket-${version_luasocket}-*.rock; }
@@ -388,39 +449,61 @@ test_path() { $luarocks path --bin; }
388test_path_lr_path() { $luarocks path --lr-path; } 449test_path_lr_path() { $luarocks path --lr-path; }
389test_path_lr_cpath() { $luarocks path --lr-cpath; } 450test_path_lr_cpath() { $luarocks path --lr-cpath; }
390test_path_lr_bin() { $luarocks path --lr-bin; } 451test_path_lr_bin() { $luarocks path --lr-bin; }
452test_path_with_tree() { $luarocks path --tree=lua_modules; }
391 453
392fail_purge_missing_tree() { $luarocks purge --tree="$testing_tree"; } 454fail_purge_missing_tree() { $luarocks purge --tree="$testing_tree"; }
455fail_purge_tree_notstring() { $luarocks purge --tree=1; }
393test_purge() { $luarocks purge --tree="$testing_sys_tree"; } 456test_purge() { $luarocks purge --tree="$testing_sys_tree"; }
457test_purge_oldversions() { $luarocks purge --old-versions --tree="$testing_sys_tree"; }
394 458
395test_remove() { $luarocks build luacov ${version_luacov} && $luarocks remove luacov ${version_luacov}; } 459test_remove() { $luarocks build abelhas ${version_abelhas} && $luarocks remove abelhas ${version_abelhas}; }
396test_remove_force() { need_luasocket; $luarocks build lualogging && $luarocks remove --force luasocket; } 460test_remove_force() { need_luasocket; $luarocks build lualogging && $luarocks remove --force luasocket; }
397fail_remove_deps() { need_luasocket; $luarocks build lualogging && $luarocks remove luasocket; } 461fail_remove_deps() { need_luasocket; $luarocks build lualogging && $luarocks remove luasocket; }
462fail_remove_missing() { $luarocks remove missing_rock; }
398fail_remove_invalid_name() { $luarocks remove invalid.rock; } 463fail_remove_invalid_name() { $luarocks remove invalid.rock; }
399 464
400test_search_found() { $luarocks search zlib; } 465test_search_found() { $luarocks search zlib; }
401test_search_missing() { $luarocks search missing_rock; } 466test_search_missing() { $luarocks search missing_rock; }
467test_search_version() { $luarocks search zlib 1.1; }
468test_search_all() { $luarocks search --all; }
469fail_search_nostring() { $var=123; $luarocks search $var; }
402 470
403test_show() { $luarocks show luacov; } 471test_show() { $luarocks show luacov; }
404test_show_modules() { $luarocks show --modules luacov; } 472test_show_modules() { $luarocks show --modules luacov; }
473test_show_home() { $luarocks show --home luacov; }
474test_show_deps() { $luarocks show --deps luacov; }
475test_show_rockspec() { $luarocks show --rockspec luacov; }
476test_show_mversion() { $luarocks show --mversion luacov; }
477test_show_rocktree() { $luarocks show --rock-tree luacov; }
478test_show_rockdir() { $luarocks show --rock-dir luacov; }
405test_show_depends() { need_luasocket; $luarocks install $luasec && $luarocks show luasec; } 479test_show_depends() { need_luasocket; $luarocks install $luasec && $luarocks show luasec; }
406test_show_oldversion() { $luarocks install luacov ${version_luacov} && $luarocks show luacov ${version_luacov}; } 480test_show_oldversion() { $luarocks install luacov ${version_luacov} && $luarocks show luacov ${version_luacov}; }
407 481
408test_unpack_download() { rm -rf ./cprint-${verrev_cprint} && $luarocks unpack cprint && rm -rf ./cprint-${verrev_cprint}; } 482test_unpack_download() { rm -rf ./cprint-${verrev_cprint} && $luarocks unpack cprint && rm -rf ./cprint-${verrev_cprint}; }
409test_unpack_src() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --src cprint && $luarocks unpack ./cprint-${verrev_cprint}.src.rock && rm -rf ./cprint-${verrev_cprint}; } 483test_unpack_src() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --source cprint && $luarocks unpack ./cprint-${verrev_cprint}.src.rock && rm -rf ./cprint-${verrev_cprint}; }
410test_unpack_rockspec() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --rockspec cprint && $luarocks unpack ./cprint-${verrev_cprint}.rockspec && rm -rf ./cprint-${verrev_cprint}; } 484test_unpack_rockspec() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --rockspec cprint && $luarocks unpack ./cprint-${verrev_cprint}.rockspec && rm -rf ./cprint-${verrev_cprint}; }
411test_unpack_binary() { rm -rf ./cprint-${verrev_cprint} && $luarocks build cprint && $luarocks pack cprint && $luarocks unpack ./cprint-${verrev_cprint}.${platform}.rock && rm -rf ./cprint-${verrev_cprint}; } 485test_unpack_binary() { rm -rf ./cprint-${verrev_cprint} && $luarocks build cprint && $luarocks pack cprint && $luarocks unpack ./cprint-${verrev_cprint}.${platform}.rock && rm -rf ./cprint-${verrev_cprint}; }
486fail_unpack_invalidpatch() { need_luasocket; $luarocks unpack "$testing_dir/testfiles/invalid_patch-0.1-1.rockspec"; }
487fail_unpack_invalidrockspec() { need_luasocket; $luarocks unpack "invalid.rockspec"; }
488
489fail_upload_invalidrockspec() { $luarocks upload "invalid.rockspec"; }
490fail_upload_invalidkey() { $luarocks upload --api-key="invalid" "invalid.rockspec"; }
491fail_upload_skippack() { $luarocks upload --api-key="invalid" --skip-pack "luacov-${verrev_luacov}.rockspec"; }
492fail_upload_force() { $luarocks install lua-cjson && $luarocks upload --api-key="invalid" --force "luacov-${verrev_luacov}.rockspec" && $luarocks remove lua-cjson; }
493
412 494
413test_admin_help() { $luarocks_admin help; } 495test_admin_help() { $luarocks_admin help; }
414 496
415test_admin_make_manifest() { $luarocks_admin make_manifest; } 497test_admin_make_manifest() { $luarocks_admin make_manifest; }
416test_admin_add_rsync() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; } 498test_admin_add_rsync() { $luarocks_admin --server=testing add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; }
417test_admin_add_sftp() { if [ "$travis" ]; then return; fi; export LUAROCKS_CONFIG="$testing_dir/testing_config_sftp.lua" && $luarocks_admin --server=testing add ./luasocket-${verrev_luasocket}.src.rock; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; } 499test_admin_add_sftp() { export LUAROCKS_CONFIG="$testing_dir/testing_config_sftp.lua" && $luarocks_admin --server=testing add ./luasocket-${verrev_luasocket}.src.rock; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; }
418fail_admin_add_missing() { $luarocks_admin --server=testing add; } 500fail_admin_add_missing() { $luarocks_admin --server=testing add; }
419fail_admin_invalidserver() { $luarocks_admin --server=invalid add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; } 501fail_admin_invalidserver() { $luarocks_admin --server=invalid add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; }
420fail_admin_invalidrock() { if [ "$travis" ]; then return 1; fi; $luarocks_admin --server=testing add invalid; } 502fail_admin_invalidrock() { $luarocks_admin --server=testing add invalid; }
421test_admin_refresh_cache() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing refresh_cache; } 503test_admin_refresh_cache() { $luarocks_admin --server=testing refresh_cache; }
422test_admin_remove() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing remove luasocket-${verrev_luasocket}.src.rock; } 504test_admin_remove() { $luarocks_admin --server=testing remove luasocket-${verrev_luasocket}.src.rock; }
423fail_admin_remove_missing() { $luarocks_admin --server=testing remove; } 505fail_admin_remove_missing() { $luarocks_admin --server=testing remove; }
506fail_admin_split_server_url() { $luarocks_admin --server="localhost@/tmp/luarocks_testing" add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; }
424 507
425fail_deps_mode_invalid_arg() { $luarocks remove luacov --deps-mode; } 508fail_deps_mode_invalid_arg() { $luarocks remove luacov --deps-mode; }
426test_deps_mode_one() { $luarocks build --tree="system" lpeg && $luarocks list && $luarocks build --deps-mode=one --tree="$testing_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ]; } 509test_deps_mode_one() { $luarocks build --tree="system" lpeg && $luarocks list && $luarocks build --deps-mode=one --tree="$testing_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ]; }
@@ -429,18 +512,50 @@ test_deps_mode_order_sys() { $luarocks build --tree="$testing_tree" lpeg && $lua
429test_deps_mode_all_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=all --tree="$testing_sys_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 0 ]; } 512test_deps_mode_all_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=all --tree="$testing_sys_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 0 ]; }
430test_deps_mode_none() { $luarocks build --tree="$testing_tree" --deps-mode=none lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; } 513test_deps_mode_none() { $luarocks build --tree="$testing_tree" --deps-mode=none lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
431test_deps_mode_nodeps_alias() { $luarocks build --tree="$testing_tree" --nodeps lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; } 514test_deps_mode_nodeps_alias() { $luarocks build --tree="$testing_tree" --nodeps lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
432test_deps_mode_make_order() { $luarocks build --tree="$testing_sys_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ] && rm -rf ./lxsh-${verrev_lxsh}; } 515test_deps_mode_make_order() { $luarocks build --tree="$testing_sys_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ] && rm -rf ./lxsh-${verrev_lxsh}; }
433test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-${verrev_lxsh}; } 516test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-${verrev_lxsh}; }
434 517
435test_write_rockspec() { $luarocks write_rockspec git://github.com/keplerproject/luarocks; } 518test_write_rockspec() { $luarocks write_rockspec git://github.com/keplerproject/luarocks; }
519test_write_rockspec_tag() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --tag=v2.3.0; }
436test_write_rockspec_lib() { $luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2; } 520test_write_rockspec_lib() { $luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2; }
521test_write_rockspec_format() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --rockspec-format=1.1 --lua-version=5.1,5.2; }
437test_write_rockspec_fullargs() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --lua-version=5.1,5.2 --license="MIT/X11" --homepage="http://www.luarocks.org" --summary="A package manager for Lua modules"; } 522test_write_rockspec_fullargs() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --lua-version=5.1,5.2 --license="MIT/X11" --homepage="http://www.luarocks.org" --summary="A package manager for Lua modules"; }
438fail_write_rockspec_args() { $luarocks write_rockspec invalid; } 523fail_write_rockspec_args() { $luarocks write_rockspec invalid; }
439fail_write_rockspec_args_url() { $luarocks write_rockspec http://example.com/invalid.zip; } 524fail_write_rockspec_args_url() { $luarocks write_rockspec http://example.com/invalid.zip; }
440test_write_rockspec_http() { $luarocks write_rockspec http://luarocks.org/releases/luarocks-2.1.0.tar.gz --lua-version=5.1; } 525test_write_rockspec_http() { $luarocks write_rockspec http://luarocks.org/releases/luarocks-2.1.0.tar.gz --lua-version=5.1; }
441test_write_rockspec_basedir() { $luarocks write_rockspec https://github.com/downloads/Olivine-Labs/luassert/luassert-1.2.tar.gz --lua-version=5.1; } 526test_write_rockspec_basedir() { $luarocks write_rockspec https://github.com/downloads/Olivine-Labs/luassert/luassert-1.2.tar.gz --lua-version=5.1; }
442 527
528fail_config_noflags() { $luarocks config; }
529test_config_lua_incdir() { $luarocks config --lua-incdir; }
530test_config_lua_libdir() { $luarocks config --lua-libdir; }
531test_config_lua_ver() { $luarocks config --lua-ver; }
532fail_config_system_config() { rm -f "$testing_lrprefix/etc/luarocks/config.lua"; $luarocks config --system-config; }
533test_config_system_config() { mkdir -p "$testing_lrprefix/etc/luarocks"; touch "$testing_lrprefix/etc/luarocks/config.lua"; $luarocks config --system-config; err=$?; rm -f "$testing_lrprefix/etc/luarocks/config.lua"; return $err; }
534fail_config_system_config_invalid() { mkdir -p "$testing_lrprefix/etc/luarocks"; echo "if if if" > "$testing_lrprefix/etc/luarocks/config.lua"; $luarocks config --system-config; err=$?; rm -f "$testing_lrprefix/etc/luarocks/config.lua"; return $err; }
535test_config_user_config() { $luarocks config --user-config; }
536fail_config_user_config() { LUAROCKS_CONFIG="/missing_file.lua" $luarocks config --user-config; }
537test_config_rock_trees() { $luarocks config --rock-trees; }
538test_config_help() { $luarocks help config; }
539
540# Tests for https://github.com/keplerproject/luarocks/issues/375
541test_fetch_base_dir() { $lua <<EOF
542 local fetch = require "luarocks.fetch"
543
544 assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3.zip"))
545 assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.zip"))
546 assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.gz"))
547 assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.bz2"))
548 assert("parser.moon" == fetch.url_to_base_dir("git://github.com/Cirru/parser.moon"))
549 assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3"))
550EOF
551}
552
443test_doc() { $luarocks install luarepl; $luarocks doc luarepl; } 553test_doc() { $luarocks install luarepl; $luarocks doc luarepl; }
554test_doc_home() { $luarocks install luacov; $luarocks doc luacov --home; }
555fail_doc_invalid() { $luarocks doc invalid; }
556test_doc_list() { $luarocks install luacov; $luarocks doc luacov --list; }
557test_doc_local() { $luarocks install luacov; $luarocks doc luacov --local; }
558test_doc_porcelain() { $luarocks install luacov; $luarocks doc luacov --porcelain; }
444 559
445# Driver ######################################### 560# Driver #########################################
446 561
@@ -452,8 +567,13 @@ run_tests() {
452 echo "-------------------------------------------" 567 echo "-------------------------------------------"
453 reset_environment 568 reset_environment
454 if $test 569 if $test
455 then echo "OK: Expected success." 570 then
456 else echo "FAIL: Unexpected failure."; exit 1 571 echo "OK: Expected success."
572 else
573 if [ $? = 99 ]
574 then echo "FAIL: Unexpected crash!"; exit 99
575 fi
576 echo "FAIL: Unexpected failure."; exit 1
457 fi 577 fi
458 done 578 done
459 grep "^fail_$1.*(" < $testing_dir/testing.sh | cut -d'(' -f1 | while read test 579 grep "^fail_$1.*(" < $testing_dir/testing.sh | cut -d'(' -f1 | while read test
@@ -464,7 +584,11 @@ run_tests() {
464 reset_environment 584 reset_environment
465 if $test 585 if $test
466 then echo "FAIL: Unexpected success."; exit 1 586 then echo "FAIL: Unexpected success."; exit 1
467 else echo "OK: Expected failure." 587 else
588 if [ $? = 99 ]
589 then echo "FAIL: Unexpected crash!"; exit 99
590 fi
591 echo "OK: Expected failure."
468 fi 592 fi
469 done 593 done
470} 594}
@@ -481,7 +605,11 @@ run_with_full_environment() {
481 echo "===========================================" 605 echo "==========================================="
482 echo "Running with full environment" 606 echo "Running with full environment"
483 echo "===========================================" 607 echo "==========================================="
484 build_environment luacov luafilesystem luasocket luabitop luaposix md5 lzlib 608
609 local bitop=
610 [ "$luaversion" = "5.1.5" ] && bitop=luabitop
611
612 build_environment luacov luafilesystem luasocket $bitop luaposix md5 lzlib
485 run_tests $1 613 run_tests $1
486} 614}
487 615
@@ -493,12 +621,18 @@ run_all_tests() {
493run_all_tests $1 621run_all_tests $1
494#run_with_minimal_environment $1 622#run_with_minimal_environment $1
495 623
496$testing_sys_tree/bin/luacov -c $testing_dir/luacov.config src/luarocks src/bin 624cd "$testing_dir/.."
497 625
498if [ "$travis" ] 626if [ "$travis" ]
499then 627then
500 grep "Summary" -B1 -A1000 $testing_dir/luacov.report.out 628 if [ "$TRAVIS" ]
629 then
630 build_environment luacov luafilesystem luacov-coveralls
631 $testing_sys_tree/bin/luacov-coveralls -c "$testing_dir/luacov.config" || echo "ok"
632 fi
633 $testing_sys_tree/bin/luacov -c "$testing_dir/luacov.config"
634 grep "Summary" -B1 -A1000 "$testing_dir/luacov.report.out"
501else 635else
636 $testing_sys_tree/bin/luacov -c "$testing_dir/luacov.config"
502 cat "$testing_dir/luacov.report.out" 637 cat "$testing_dir/luacov.report.out"
503fi 638fi
504
diff --git a/win32/pe-parser.lua b/win32/pe-parser.lua
index 30bb8390..9cd36ffc 100644
--- a/win32/pe-parser.lua
+++ b/win32/pe-parser.lua
@@ -1,7 +1,11 @@
1--------------------------------------------------------------------------------------- 1---------------------------------------------------------------------------------------
2-- Lua module to parse a Portable Executable (.exe , .dll, etc.) file and extract metadata. 2-- Lua module to parse a Portable Executable (.exe , .dll, etc.) file and extract metadata.
3-- 3--
4-- Version 0.1, [copyright (c) 2013 - Thijs Schreijer](http://www.thijsschreijer.nl) 4-- NOTE: numerical information is extracted as strings (hex) to prevent numerical overflows in
5-- case of 64 bit fields (bit/flag fields). Pointer arithmetic is still done numerically, so for
6-- very large files this could lead to undefined results. Use with care!
7--
8-- Version 0.4, [copyright (c) 2013-2015 Thijs Schreijer](http://www.thijsschreijer.nl)
5-- @name pe-parser 9-- @name pe-parser
6-- @class module 10-- @class module
7 11
@@ -238,7 +242,7 @@ local function readstring(f)
238end 242end
239 243
240--- Parses a file and extracts the information. 244--- Parses a file and extracts the information.
241-- All numbers are delivered as "string" types containing hex values, see `toHex` and `toDec` conversion functions. 245-- All numbers are delivered as "string" types containing hex values (to prevent numerical overflows in case of 64bit sizes or bit-fields), see `toHex` and `toDec` conversion functions.
242-- @return table with data, or nil + error 246-- @return table with data, or nil + error
243-- @usage local pe = require("pe-parser") 247-- @usage local pe = require("pe-parser")
244-- local obj = pe.parse("c:\lua\lua.exe") 248-- local obj = pe.parse("c:\lua\lua.exe")
@@ -524,9 +528,12 @@ function M.msvcrt(infile)
524 528
525 for i, dll in ipairs(obj.DataDirectory.ImportTable) do 529 for i, dll in ipairs(obj.DataDirectory.ImportTable) do
526 dll = dll.Name:upper() 530 dll = dll.Name:upper()
527 local result = dll:match('(MSVCR%d*)%.DLL') 531 local result = dll:match('(MSVCR%d*D?)%.DLL')
532 if not result then
533 result = dll:match('(MSVCRTD?)%.DLL')
534 end
528 if not result then 535 if not result then
529 result = dll:match('(MSVCRT)%.DLL') 536 result = dll:match('(VCRUNTIME%d*D?)%.DLL')
530 end 537 end
531 -- success, found it return name + binary where it was found 538 -- success, found it return name + binary where it was found
532 if result then return result, infile end 539 if result then return result, infile end