aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bin/luarocks1
-rw-r--r--src/luarocks/add.lua6
-rw-r--r--src/luarocks/admin_remove.lua2
-rw-r--r--src/luarocks/build.lua75
-rw-r--r--src/luarocks/build/builtin.lua12
-rw-r--r--src/luarocks/build/cmake.lua6
-rw-r--r--src/luarocks/build/make.lua3
-rw-r--r--src/luarocks/cfg.lua126
-rw-r--r--src/luarocks/command_line.lua40
-rw-r--r--src/luarocks/deps.lua13
-rw-r--r--src/luarocks/dir.lua3
-rw-r--r--src/luarocks/download.lua77
-rw-r--r--src/luarocks/fetch.lua24
-rw-r--r--src/luarocks/fetch/git.lua2
-rw-r--r--src/luarocks/fetch/git_file.lua17
-rw-r--r--src/luarocks/fs.lua5
-rw-r--r--src/luarocks/fs/lua.lua57
-rw-r--r--src/luarocks/fs/unix.lua62
-rw-r--r--src/luarocks/fs/unix/tools.lua66
-rw-r--r--src/luarocks/fs/win32.lua6
-rw-r--r--src/luarocks/fs/win32/tools.lua51
-rw-r--r--src/luarocks/help.lua80
-rw-r--r--src/luarocks/index.lua13
-rw-r--r--src/luarocks/install.lua27
-rw-r--r--src/luarocks/loader.lua46
-rw-r--r--src/luarocks/make.lua23
-rw-r--r--src/luarocks/manif.lua23
-rw-r--r--src/luarocks/manif_core.lua1
-rw-r--r--src/luarocks/new_version.lua141
-rw-r--r--src/luarocks/pack.lua37
-rw-r--r--src/luarocks/path.lua128
-rw-r--r--src/luarocks/persist.lua96
-rw-r--r--src/luarocks/refresh_cache.lua3
-rw-r--r--src/luarocks/remove.lua8
-rw-r--r--src/luarocks/rep.lua29
-rw-r--r--src/luarocks/search.lua8
-rw-r--r--src/luarocks/show.lua4
-rw-r--r--src/luarocks/tools/patch.lua2
-rw-r--r--src/luarocks/tools/tar.lua1
-rw-r--r--src/luarocks/tools/zip.lua6
-rw-r--r--src/luarocks/type_check.lua38
-rw-r--r--src/luarocks/unpack.lua2
-rw-r--r--src/luarocks/util.lua52
-rw-r--r--src/luarocks/validate.lua1
44 files changed, 973 insertions, 450 deletions
diff --git a/src/bin/luarocks b/src/bin/luarocks
index 5da4bc25..1397bbd0 100755
--- a/src/bin/luarocks
+++ b/src/bin/luarocks
@@ -18,5 +18,6 @@ commands.make = require("luarocks.make")
18commands.download = require("luarocks.download") 18commands.download = require("luarocks.download")
19commands.path = require("luarocks.path") 19commands.path = require("luarocks.path")
20commands.show = require("luarocks.show") 20commands.show = require("luarocks.show")
21commands.new_version = require("luarocks.new_version")
21 22
22command_line.run_command(...) 23command_line.run_command(...)
diff --git a/src/luarocks/add.lua b/src/luarocks/add.lua
index 6edfea35..bf3f8979 100644
--- a/src/luarocks/add.lua
+++ b/src/luarocks/add.lua
@@ -13,10 +13,10 @@ local fs = require("luarocks.fs")
13local cache = require("luarocks.cache") 13local cache = require("luarocks.cache")
14 14
15help_summary = "Add a rock or rockspec to a rocks server." 15help_summary = "Add a rock or rockspec to a rocks server."
16help_arguments = "[--to=<server>] [--no-refresh] {<rockspec>|<rock>...}" 16help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
17help = [[ 17help = [[
18Arguments are local files, which may be rockspecs or rocks. 18Arguments are local files, which may be rockspecs or rocks.
19The flag --to indicates which server to use. 19The flag --server indicates which server to use.
20If not given, the default server set in the upload_server variable 20If not given, the default server set in the upload_server variable
21from the configuration file is used instead. 21from the configuration file is used instead.
22The flag --no-refresh indicates the local cache should not be refreshed 22The flag --no-refresh indicates the local cache should not be refreshed
@@ -101,7 +101,7 @@ function run(...)
101 if #files < 1 then 101 if #files < 1 then
102 return nil, "Argument missing, see help." 102 return nil, "Argument missing, see help."
103 end 103 end
104 local server, server_table = cache.get_upload_server(flags["to"]) 104 local server, server_table = cache.get_upload_server(flags["server"])
105 if not server then return nil, server_table end 105 if not server then return nil, server_table end
106 return add_files_to_server(not flags["no-refresh"], files, server, server_table) 106 return add_files_to_server(not flags["no-refresh"], files, server, server_table)
107end 107end
diff --git a/src/luarocks/admin_remove.lua b/src/luarocks/admin_remove.lua
index 1b897e7d..f1268576 100644
--- a/src/luarocks/admin_remove.lua
+++ b/src/luarocks/admin_remove.lua
@@ -80,7 +80,7 @@ function run(...)
80 if #files < 1 then 80 if #files < 1 then
81 return nil, "Argument missing, see help." 81 return nil, "Argument missing, see help."
82 end 82 end
83 local server, server_table = cache.get_upload_server(flags["from"]) 83 local server, server_table = cache.get_upload_server(flags["server"])
84 if not server then return nil, server_table end 84 if not server then return nil, server_table end
85 return remove_files_from_server(not flags["no-refresh"], files, server, server_table) 85 return remove_files_from_server(not flags["no-refresh"], files, server, server_table)
86end 86end
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index 77dd1dad..42ae3fd7 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -3,6 +3,7 @@
3-- Builds a rock, compiling its C parts if any. 3-- Builds a rock, compiling its C parts if any.
4module("luarocks.build", package.seeall) 4module("luarocks.build", package.seeall)
5 5
6local pack = require("luarocks.pack")
6local path = require("luarocks.path") 7local path = require("luarocks.path")
7local util = require("luarocks.util") 8local util = require("luarocks.util")
8local rep = require("luarocks.rep") 9local rep = require("luarocks.rep")
@@ -46,9 +47,17 @@ local function install_files(files, location, is_module_path)
46 for k, file in pairs(files) do 47 for k, file in pairs(files) do
47 local dest = location 48 local dest = location
48 if type(k) == "string" then 49 if type(k) == "string" then
49 dest = is_module_path and dir.path(location, path.module_to_path(k)) or k 50 if is_module_path then
51 dest = dir.path(location, path.module_to_path(k))
52 fs.make_dir(dest)
53 else
54 dest = dir.path(location, dir.dir_name(k))
55 fs.make_dir(dest)
56 dest = dir.path(dest, dir.base_name(k))
57 end
58 else
59 fs.make_dir(dest)
50 end 60 end
51 fs.make_dir(dest)
52 local ok = fs.copy(dir.path(file), dest) 61 local ok = fs.copy(dir.path(file), dest)
53 if not ok then 62 if not ok then
54 return nil, "Failed copying "..file 63 return nil, "Failed copying "..file
@@ -102,9 +111,10 @@ end
102-- @param minimal_mode boolean: true if there's no need to fetch, 111-- @param minimal_mode boolean: true if there's no need to fetch,
103-- unpack or change dir (this is used by "luarocks make"). Implies 112-- unpack or change dir (this is used by "luarocks make"). Implies
104-- need_to_fetch = false. 113-- need_to_fetch = false.
114-- @param no_deps boolean: true if dependency check needs to be skipped
105-- @return boolean or (nil, string, [string]): True if succeeded or 115-- @return boolean or (nil, string, [string]): True if succeeded or
106-- nil and an error message followed by an error code. 116-- nil and an error message followed by an error code.
107function build_rockspec(rockspec_file, need_to_fetch, minimal_mode) 117function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, no_deps)
108 assert(type(rockspec_file) == "string") 118 assert(type(rockspec_file) == "string")
109 assert(type(need_to_fetch) == "boolean") 119 assert(type(need_to_fetch) == "boolean")
110 120
@@ -117,10 +127,15 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode)
117 return nil, "Rockspec error: build type not specified" 127 return nil, "Rockspec error: build type not specified"
118 end 128 end
119 129
120 local ok, err, errcode = deps.fulfill_dependencies(rockspec) 130 if no_deps then
121 if err then 131 util.printerr("Warning: skipping dependency checks.")
122 return nil, err, errcode 132 else
133 local ok, err, errcode = deps.fulfill_dependencies(rockspec)
134 if err then
135 return nil, err, errcode
136 end
123 end 137 end
138
124 ok, err, errcode = deps.check_external_deps(rockspec, "build") 139 ok, err, errcode = deps.check_external_deps(rockspec, "build")
125 if err then 140 if err then
126 return nil, err, errcode 141 return nil, err, errcode
@@ -225,7 +240,7 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode)
225 ok, err = manif.make_rock_manifest(name, version) 240 ok, err = manif.make_rock_manifest(name, version)
226 if err then return nil, err end 241 if err then return nil, err end
227 242
228 ok, err = rep.deploy_files(name, version) 243 ok, err = rep.deploy_files(name, version, rep.should_wrap_bin_scripts(rockspec))
229 if err then return nil, err end 244 if err then return nil, err end
230 245
231 util.remove_scheduled_function(rollback) 246 util.remove_scheduled_function(rollback)
@@ -240,7 +255,7 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode)
240 if err then return nil, err end 255 if err then return nil, err end
241 256
242 local license = "" 257 local license = ""
243 if rockspec.description.license then 258 if rockspec.description and rockspec.description.license then
244 license = ("(license: "..rockspec.description.license..")") 259 license = ("(license: "..rockspec.description.license..")")
245 end 260 end
246 261
@@ -258,7 +273,7 @@ end
258-- false if the rockspec was obtained from inside a source rock. 273-- false if the rockspec was obtained from inside a source rock.
259-- @return boolean or (nil, string, [string]): True if build was successful, 274-- @return boolean or (nil, string, [string]): True if build was successful,
260-- or false and an error message and an optional error code. 275-- or false and an error message and an optional error code.
261function build_rock(rock_file, need_to_fetch) 276function build_rock(rock_file, need_to_fetch, no_deps)
262 assert(type(rock_file) == "string") 277 assert(type(rock_file) == "string")
263 assert(type(need_to_fetch) == "boolean") 278 assert(type(need_to_fetch) == "boolean")
264 279
@@ -268,47 +283,28 @@ function build_rock(rock_file, need_to_fetch)
268 end 283 end
269 local rockspec_file = path.rockspec_name_from_rock(rock_file) 284 local rockspec_file = path.rockspec_name_from_rock(rock_file)
270 fs.change_dir(unpack_dir) 285 fs.change_dir(unpack_dir)
271 local ok, err, errcode = build_rockspec(rockspec_file, need_to_fetch) 286 local ok, err, errcode = build_rockspec(rockspec_file, need_to_fetch, false, no_deps)
272 fs.pop_dir() 287 fs.pop_dir()
273 return ok, err, errcode 288 return ok, err, errcode
274end 289end
275 290
276local function do_build(name, version) 291local function do_build(name, version, no_deps)
277 if name:match("%.rockspec$") then 292 if name:match("%.rockspec$") then
278 return build_rockspec(name, true) 293 return build_rockspec(name, true, false, no_deps)
279 elseif name:match("%.src%.rock$") then 294 elseif name:match("%.src%.rock$") then
280 return build_rock(name, false) 295 return build_rock(name, false, no_deps)
281 elseif name:match("%.all%.rock$") then 296 elseif name:match("%.all%.rock$") then
282 local install = require("luarocks.install") 297 local install = require("luarocks.install")
283 return install.install_binary_rock(name) 298 return install.install_binary_rock(name, no_deps)
284 elseif name:match("%.rock$") then 299 elseif name:match("%.rock$") then
285 return build_rock(name, true) 300 return build_rock(name, true, no_deps)
286 elseif not name:match(dir.separator) then 301 elseif not name:match(dir.separator) then
287 local search = require("luarocks.search") 302 local search = require("luarocks.search")
288 return search.act_on_src_or_rockspec(run, name:lower(), version) 303 return search.act_on_src_or_rockspec(run, name:lower(), version, no_deps and "--nodeps")
289 end 304 end
290 return nil, "Don't know what to do with "..name 305 return nil, "Don't know what to do with "..name
291end 306end
292 307
293local function pack_binary_rock(name, version)
294 local temp_dir = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
295 if not temp_dir then
296 return nil, "Failed creating temporary directory."
297 end
298 util.schedule_function(fs.delete, temp_dir)
299
300 path.use_tree(temp_dir)
301 local ok, err = do_build(name, version)
302 if not ok then
303 return nil, err
304 end
305 local rname, rversion = path.parse_name(name)
306 if not rname then
307 rname, rversion = name, version
308 end
309 return pack.pack_binary_rock(rname, rversion)
310end
311
312--- Driver function for "build" command. 308--- Driver function for "build" command.
313-- @param name string: A local or remote rockspec or rock file. 309-- @param name string: A local or remote rockspec or rock file.
314-- If a package name is given, forwards the request to "search" and, 310-- If a package name is given, forwards the request to "search" and,
@@ -324,12 +320,11 @@ function run(...)
324 end 320 end
325 assert(type(version) == "string" or not version) 321 assert(type(version) == "string" or not version)
326 322
327 local ok, err = fs.check_command_permissions(flags)
328 if not ok then return nil, err end
329
330 if flags["pack-binary-rock"] then 323 if flags["pack-binary-rock"] then
331 return pack_binary_rock(name, version) 324 return pack.pack_binary_rock(name, version, do_build, name, version, flags["nodeps"])
332 else 325 else
333 return do_build(name, version) 326 local ok, err = fs.check_command_permissions(flags)
327 if not ok then return nil, err end
328 return do_build(name, version, flags["nodeps"])
334 end 329 end
335end 330end
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua
index 7b550bff..aea8b853 100644
--- a/src/luarocks/build/builtin.lua
+++ b/src/luarocks/build/builtin.lua
@@ -46,7 +46,7 @@ end
46-- nil and an error message otherwise. 46-- nil and an error message otherwise.
47function run(rockspec) 47function run(rockspec)
48 assert(type(rockspec) == "table") 48 assert(type(rockspec) == "table")
49 local compile_object, compile_library 49 local compile_object, compile_library, compile_wrapper_binary
50 50
51 local build = rockspec.build 51 local build = rockspec.build
52 local variables = rockspec.variables 52 local variables = rockspec.variables
@@ -74,7 +74,7 @@ function run(rockspec)
74 local extras = { unpack(objects) } 74 local extras = { unpack(objects) }
75 add_flags(extras, "-L%s", libdirs) 75 add_flags(extras, "-L%s", libdirs)
76 add_flags(extras, "%s.lib", libraries) 76 add_flags(extras, "%s.lib", libraries)
77 extras[#extras+1] = dir.path(variables.LUA_LIBDIR, "lua5.1.lib") 77 extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB)
78 extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80") 78 extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80")
79 local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras)) 79 local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
80 return ok 80 return ok
@@ -89,7 +89,7 @@ function run(rockspec)
89 local ok = execute(variables.RC, "-o", resname, rcname) 89 local ok = execute(variables.RC, "-o", resname, rcname)
90 if not ok then return ok end 90 if not ok then return ok end
91 ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER, 91 ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER,
92 dir.path(variables.LUA_LIBDIR, "lua5.1.lib"), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32") 92 dir.path(variables.LUA_LIBDIR, variables.LUALIB), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32")
93 return ok, wrapname 93 return ok, wrapname
94 end 94 end
95 elseif cfg.is_platform("win32") then 95 elseif cfg.is_platform("win32") then
@@ -109,7 +109,7 @@ function run(rockspec)
109 def:write("EXPORTS\n") 109 def:write("EXPORTS\n")
110 def:write("luaopen_"..name:gsub("%.", "_").."\n") 110 def:write("luaopen_"..name:gsub("%.", "_").."\n")
111 def:close() 111 def:close()
112 local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, "lua5.1.lib"), unpack(extras)) 112 local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras))
113 local manifestfile = basename..".dll.manifest" 113 local manifestfile = basename..".dll.manifest"
114 if ok and fs.exists(manifestfile) then 114 if ok and fs.exists(manifestfile) then
115 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2") 115 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2")
@@ -126,7 +126,7 @@ function run(rockspec)
126 local ok = execute(variables.RC, "-r", "-fo"..resname, rcname) 126 local ok = execute(variables.RC, "-r", "-fo"..resname, rcname)
127 if not ok then return ok end 127 if not ok then return ok end
128 ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER, 128 ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER,
129 dir.path(variables.LUA_LIBDIR, "lua5.1.lib"), "user32.lib") 129 dir.path(variables.LUA_LIBDIR, variables.LUALIB), "user32.lib")
130 local manifestfile = wrapname..".manifest" 130 local manifestfile = wrapname..".manifest"
131 if ok and fs.exists(manifestfile) then 131 if ok and fs.exists(manifestfile) then
132 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1") 132 ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1")
@@ -187,7 +187,7 @@ function run(rockspec)
187 if type(info) == "string" then 187 if type(info) == "string" then
188 local ext = info:match(".([^.]+)$") 188 local ext = info:match(".([^.]+)$")
189 if ext == "lua" then 189 if ext == "lua" then
190 if info:match("init.lua$") then 190 if info:match("init%.lua$") and not name:match("%.init$") then
191 moddir = path.module_to_path(name..".init") 191 moddir = path.module_to_path(name..".init")
192 end 192 end
193 local dest = dir.path(luadir, moddir) 193 local dest = dir.path(luadir, moddir)
diff --git a/src/luarocks/build/cmake.lua b/src/luarocks/build/cmake.lua
index 295f5df6..2d9abf9e 100644
--- a/src/luarocks/build/cmake.lua
+++ b/src/luarocks/build/cmake.lua
@@ -16,9 +16,9 @@ function run(rockspec)
16 local variables = build.variables or {} 16 local variables = build.variables or {}
17 17
18 -- Pass Env variables 18 -- Pass Env variables
19 build.variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH") 19 variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH")
20 build.variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH") 20 variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH")
21 build.variables.CMAKE_INCLUDE_PATH=os.getenv("CMAKE_INCLUDE_PATH") 21 variables.CMAKE_INCLUDE_PATH=os.getenv("CMAKE_INCLUDE_PATH")
22 22
23 util.variable_substitutions(variables, rockspec.variables) 23 util.variable_substitutions(variables, rockspec.variables)
24 24
diff --git a/src/luarocks/build/make.lua b/src/luarocks/build/make.lua
index 80c0d4f4..c4b21578 100644
--- a/src/luarocks/build/make.lua
+++ b/src/luarocks/build/make.lua
@@ -7,6 +7,9 @@ local util = require("luarocks.util")
7local cfg = require("luarocks.cfg") 7local cfg = require("luarocks.cfg")
8 8
9--- Call "make" with given target and variables 9--- Call "make" with given target and variables
10-- @param make_cmd string: the make command to be used (typically
11-- configured through variables.MAKE in the config files, or
12-- the appropriate platform-specific default).
10-- @param pass boolean: If true, run make; if false, do nothing. 13-- @param pass boolean: If true, run make; if false, do nothing.
11-- @param target string: The make target; an empty string indicates 14-- @param target string: The make target; an empty string indicates
12-- the default target. 15-- the default target.
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua
index 2b48d576..56a9a965 100644
--- a/src/luarocks/cfg.lua
+++ b/src/luarocks/cfg.lua
@@ -1,7 +1,4 @@
1 1
2local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert =
3 rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert
4
5--- Configuration for LuaRocks. 2--- Configuration for LuaRocks.
6-- Tries to load the user's configuration file and 3-- Tries to load the user's configuration file and
7-- defines defaults for unset values. See the 4-- defines defaults for unset values. See the
@@ -10,21 +7,26 @@ local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs,
10-- 7--
11-- End-users shouldn't edit this file. They can override any defaults 8-- End-users shouldn't edit this file. They can override any defaults
12-- set in this file using their system-wide $LUAROCKS_SYSCONFIG file 9-- set in this file using their system-wide $LUAROCKS_SYSCONFIG file
13-- (see luarocks.config) or their user-specific configuration file 10-- (see luarocks.site_config) or their user-specific configuration file
14-- (~/.luarocks/config.lua on Unix or %APPDATA%/luarocks/config.lua on 11-- (~/.luarocks/config.lua on Unix or %APPDATA%/luarocks/config.lua on
15-- Windows). 12-- Windows).
13
14local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert, _VERSION =
15 rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert, _VERSION
16
16module("luarocks.cfg") 17module("luarocks.cfg")
17 18
18-- Load site-local global configurations 19-- Load site-local global configurations
19local ok, config = pcall(require, "luarocks.config") 20local ok, site_config = pcall(require, "luarocks.site_config")
20if not ok then 21if not ok then
21 io.stderr:write("Site-local luarocks/config.lua file not found. Incomplete installation?\n") 22 io.stderr:write("Site-local luarocks/site_config.lua file not found. Incomplete installation?\n")
22 config = {} 23 site_config = {}
23end 24end
24 25
25_M.config = config 26_M.site_config = site_config
26 27
27program_version = "2.0.5" 28lua_version = _VERSION:sub(5)
29program_version = "2.0.8"
28user_agent = "LuaRocks/"..program_version 30user_agent = "LuaRocks/"..program_version
29 31
30local persist = require("luarocks.persist") 32local persist = require("luarocks.persist")
@@ -46,12 +48,12 @@ local detected = {}
46local system,proc 48local system,proc
47 49
48-- A proper installation of LuaRocks will hardcode the system 50-- A proper installation of LuaRocks will hardcode the system
49-- and proc values with config.LUAROCKS_UNAME_S and config.LUAROCKS_UNAME_M, 51-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M,
50-- so that this detection does not run every time. When it is 52-- so that this detection does not run every time. When it is
51-- performed, we use the Unix way to identify the system, 53-- performed, we use the Unix way to identify the system,
52-- even on Windows (assuming UnxUtils or Cygwin). 54-- even on Windows (assuming UnxUtils or Cygwin).
53system = config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l") 55system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
54proc = config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l") 56proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l")
55if proc:match("i[%d]86") then 57if proc:match("i[%d]86") then
56 proc = "x86" 58 proc = "x86"
57elseif proc:match("amd64") or proc:match("x86_64") then 59elseif proc:match("amd64") or proc:match("x86_64") then
@@ -75,6 +77,9 @@ elseif system == "Darwin" then
75elseif system == "Linux" then 77elseif system == "Linux" then
76 detected.unix = true 78 detected.unix = true
77 detected.linux = true 79 detected.linux = true
80elseif system == "SunOS" then
81 detected.unix = true
82 detected.solaris = true
78elseif system and system:match("^CYGWIN") then 83elseif system and system:match("^CYGWIN") then
79 detected.unix = true 84 detected.unix = true
80 detected.cygwin = true 85 detected.cygwin = true
@@ -90,14 +95,15 @@ end
90-- Path configuration: 95-- Path configuration:
91 96
92local sys_config_file, home_config_file 97local sys_config_file, home_config_file
98local sys_config_ok, home_config_ok = false, false
93if detected.windows or detected.mingw32 then 99if detected.windows or detected.mingw32 then
94 home = os.getenv("APPDATA") or "c:" 100 home = os.getenv("APPDATA") or "c:"
95 sys_config_file = "c:/luarocks/config.lua" 101 sys_config_file = site_config.LUAROCKS_SYSCONFIG or "c:/luarocks/config.lua"
96 home_config_file = home.."/luarocks/config.lua" 102 home_config_file = home.."/luarocks/config.lua"
97 home_tree = home.."/luarocks/" 103 home_tree = home.."/luarocks/"
98else 104else
99 home = os.getenv("HOME") or "" 105 home = os.getenv("HOME") or ""
100 sys_config_file = "/etc/luarocks/config.lua" 106 sys_config_file = site_config.LUAROCKS_SYSCONFIG or "/etc/luarocks/config.lua"
101 home_config_file = home.."/.luarocks/config.lua" 107 home_config_file = home.."/.luarocks/config.lua"
102 home_tree = home.."/.luarocks/" 108 home_tree = home.."/.luarocks/"
103end 109end
@@ -105,14 +111,34 @@ end
105variables = {} 111variables = {}
106rocks_trees = {} 112rocks_trees = {}
107 113
108persist.load_into_table(config.LUAROCKS_SYSCONFIG or sys_config_file, _M) 114local ok, err = persist.load_into_table(sys_config_file, _M)
115if ok then
116 sys_config_ok = true
117else -- nil or false
118 sys_config_ok = ok
119 if err and ok == nil then
120 io.stderr:write(err.."\n")
121 end
122end
109 123
110if not config.LUAROCKS_FORCE_CONFIG then 124if not site_config.LUAROCKS_FORCE_CONFIG then
111 home_config_file = os.getenv("LUAROCKS_CONFIG") or home_config_file 125 home_config_file = os.getenv("LUAROCKS_CONFIG") or home_config_file
112 local home_overrides = persist.load_into_table(home_config_file, { home = home }) 126 local home_overrides, err = persist.load_into_table(home_config_file, { home = home })
113 if home_overrides then 127 if home_overrides then
128 home_config_ok = true
114 local util = require("luarocks.util") 129 local util = require("luarocks.util")
130 if home_overrides.rocks_trees then
131 _M.rocks_trees = nil
132 end
133 if home_overrides.rocks_servers then
134 _M.rocks_servers = nil
135 end
115 util.deep_merge(_M, home_overrides) 136 util.deep_merge(_M, home_overrides)
137 else -- nil or false
138 home_config_ok = home_overrides
139 if err and home_config_ok == nil then
140 io.stderr:write(err.."\n")
141 end
116 end 142 end
117end 143end
118 144
@@ -120,8 +146,8 @@ if not next(rocks_trees) then
120 if home_tree then 146 if home_tree then
121 table.insert(rocks_trees, home_tree) 147 table.insert(rocks_trees, home_tree)
122 end 148 end
123 if config.LUAROCKS_ROCKS_TREE then 149 if site_config.LUAROCKS_ROCKS_TREE then
124 table.insert(rocks_trees, config.LUAROCKS_ROCKS_TREE) 150 table.insert(rocks_trees, site_config.LUAROCKS_ROCKS_TREE)
125 end 151 end
126end 152end
127 153
@@ -129,8 +155,13 @@ end
129 155
130local root = rocks_trees[#rocks_trees] 156local root = rocks_trees[#rocks_trees]
131local defaults = { 157local defaults = {
132 lua_modules_path = "/share/lua/5.1/", 158
133 lib_modules_path = "/lib/lua/5.1/", 159 local_by_default = false,
160 use_extensions = false,
161 accept_unknown_fields = false,
162
163 lua_modules_path = "/share/lua/"..lua_version,
164 lib_modules_path = "/lib/lua/"..lua_version,
134 165
135 arch = "unknown", 166 arch = "unknown",
136 lib_extension = "unknown", 167 lib_extension = "unknown",
@@ -141,9 +172,9 @@ local defaults = {
141 }, 172 },
142 173
143 lua_extension = "lua", 174 lua_extension = "lua",
144 lua_interpreter = config.LUA_INTERPRETER or "lua", 175 lua_interpreter = site_config.LUA_INTERPRETER or "lua",
145 downloader = config.LUAROCKS_DOWNLOADER or "wget", 176 downloader = site_config.LUAROCKS_DOWNLOADER or "wget",
146 md5checker = config.LUAROCKS_MD5CHECKER or "md5sum", 177 md5checker = site_config.LUAROCKS_MD5CHECKER or "md5sum",
147 178
148 variables = { 179 variables = {
149 MAKE = "make", 180 MAKE = "make",
@@ -183,6 +214,7 @@ local defaults = {
183 MD5 = "md5", 214 MD5 = "md5",
184 STAT = "stat", 215 STAT = "stat",
185 216
217 CMAKE = "cmake",
186 SEVENZ = "7z", 218 SEVENZ = "7z",
187 219
188 STATFLAG = "-c '%a'", 220 STATFLAG = "-c '%a'",
@@ -208,19 +240,21 @@ if detected.windows then
208 defaults.external_lib_extension = "dll" 240 defaults.external_lib_extension = "dll"
209 defaults.obj_extension = "obj" 241 defaults.obj_extension = "obj"
210 defaults.external_deps_dirs = { "c:/external/" } 242 defaults.external_deps_dirs = { "c:/external/" }
211 defaults.variables.LUA_BINDIR = config.LUA_BINDIR and config.LUA_BINDIR:gsub("\\", "/") or "c:/lua5.1/bin" 243 defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/bin"
212 defaults.variables.LUA_INCDIR = config.LUA_INCDIR and config.LUA_INCDIR:gsub("\\", "/") or "c:/lua5.1/include" 244 defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/include"
213 defaults.variables.LUA_LIBDIR = config.LUA_LIBDIR and config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua5.1/lib" 245 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/lib"
214 defaults.cmake_generator = "MinGW Makefiles" 246 defaults.cmake_generator = "MinGW Makefiles"
215 defaults.makefile = "Makefile.win" 247 defaults.makefile = "Makefile.win"
216 defaults.variables.MAKE = "nmake" -- TODO: Split Windows flavors between mingw and msvc 248 defaults.variables.MAKE = "nmake" -- TODO: Split Windows flavors between mingw and msvc
217 defaults.variables.CC = "cl" 249 defaults.variables.CC = "cl"
218 defaults.variables.RC = "rc" 250 defaults.variables.RC = "rc"
219 defaults.variables.WRAPPER = config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.obj" 251 defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.obj"
220 defaults.variables.LD = "link" 252 defaults.variables.LD = "link"
221 defaults.variables.MT = "mt" 253 defaults.variables.MT = "mt"
254 defaults.variables.LUALIB = "lua"..lua_version..".lib"
222 defaults.variables.CFLAGS = "/MD /O2" 255 defaults.variables.CFLAGS = "/MD /O2"
223 defaults.variables.LIBFLAG = "/dll" 256 defaults.variables.LIBFLAG = "/dll"
257 defaults.variables.LUALIB = "lua"..lua_version..".lib"
224 defaults.external_deps_patterns = { 258 defaults.external_deps_patterns = {
225 bin = { "?.exe", "?.bat" }, 259 bin = { "?.exe", "?.bat" },
226 lib = { "?.lib", "?.dll", "lib?.dll" }, 260 lib = { "?.lib", "?.dll", "lib?.dll" },
@@ -244,15 +278,15 @@ if detected.mingw32 then
244 defaults.external_lib_extension = "dll" 278 defaults.external_lib_extension = "dll"
245 defaults.obj_extension = "o" 279 defaults.obj_extension = "o"
246 defaults.external_deps_dirs = { "c:/external/" } 280 defaults.external_deps_dirs = { "c:/external/" }
247 defaults.variables.LUA_BINDIR = config.LUA_BINDIR and config.LUA_BINDIR:gsub("\\", "/") or "c:/lua5.1/bin" 281 defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/bin"
248 defaults.variables.LUA_INCDIR = config.LUA_INCDIR and config.LUA_INCDIR:gsub("\\", "/") or "c:/lua5.1/include" 282 defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/include"
249 defaults.variables.LUA_LIBDIR = config.LUA_LIBDIR and config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua5.1/lib" 283 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/lib"
250 defaults.cmake_generator = "MinGW Makefiles" 284 defaults.cmake_generator = "MinGW Makefiles"
251 defaults.make = "mingw32-make" -- TODO: Split Windows flavors between mingw and msvc 285 defaults.make = "mingw32-make" -- TODO: Split Windows flavors between mingw and msvc
252 defaults.makefile = "Makefile.win" 286 defaults.makefile = "Makefile.win"
253 defaults.variables.CC = "mingw32-gcc" 287 defaults.variables.CC = "mingw32-gcc"
254 defaults.variables.RC = "windres" 288 defaults.variables.RC = "windres"
255 defaults.variables.WRAPPER = config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.o" 289 defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.o"
256 defaults.variables.LD = "mingw32-gcc" 290 defaults.variables.LD = "mingw32-gcc"
257 defaults.variables.CFLAGS = "-O2" 291 defaults.variables.CFLAGS = "-O2"
258 defaults.variables.LIBFLAG = "-shared" 292 defaults.variables.LIBFLAG = "-shared"
@@ -276,9 +310,9 @@ if detected.unix then
276 defaults.external_lib_extension = "so" 310 defaults.external_lib_extension = "so"
277 defaults.obj_extension = "o" 311 defaults.obj_extension = "o"
278 defaults.external_deps_dirs = { "/usr/local", "/usr" } 312 defaults.external_deps_dirs = { "/usr/local", "/usr" }
279 defaults.variables.LUA_BINDIR = config.LUA_BINDIR or "/usr/local/bin" 313 defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR or "/usr/local/bin"
280 defaults.variables.LUA_INCDIR = config.LUA_INCDIR or "/usr/local/include" 314 defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR or "/usr/local/include"
281 defaults.variables.LUA_LIBDIR = config.LUA_LIBDIR or "/usr/local/lib" 315 defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib"
282 defaults.variables.CFLAGS = "-O2" 316 defaults.variables.CFLAGS = "-O2"
283 defaults.cmake_generator = "Unix Makefiles" 317 defaults.cmake_generator = "Unix Makefiles"
284 defaults.platforms = { "unix" } 318 defaults.platforms = { "unix" }
@@ -311,6 +345,10 @@ if detected.cygwin then
311 defaults.variables.LIBFLAG = "-shared" 345 defaults.variables.LIBFLAG = "-shared"
312end 346end
313 347
348if detected.bsd then
349 defaults.variables.STATFLAG = "-f '%Op'"
350end
351
314if detected.macosx then 352if detected.macosx then
315 defaults.external_lib_extension = "dylib" 353 defaults.external_lib_extension = "dylib"
316 defaults.arch = "macosx-"..proc 354 defaults.arch = "macosx-"..proc
@@ -318,9 +356,6 @@ if detected.macosx then
318 defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc" 356 defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc"
319 defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc" 357 defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc"
320 defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load" 358 defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
321end
322
323if detected.bsd then
324 defaults.variables.STATFLAG = "-f '%A'" 359 defaults.variables.STATFLAG = "-f '%A'"
325end 360end
326 361
@@ -344,14 +379,21 @@ end
344if detected.openbsd then 379if detected.openbsd then
345 defaults.arch = "openbsd-"..proc 380 defaults.arch = "openbsd-"..proc
346 defaults.platforms = {"unix", "bsd", "openbsd"} 381 defaults.platforms = {"unix", "bsd", "openbsd"}
347 defaults.variables.STATFLAG = "-f '%Op'" 382end
383
384if detected.solaris then
385 defaults.arch = "solaris-"..proc
386 defaults.platforms = {"unix", "solaris"}
387 defaults.variables.MAKE = "gmake"
388 defaults.variables.CC = "gcc"
389 defaults.variables.LD = "gcc"
348end 390end
349 391
350-- Expose some more values detected by LuaRocks for use by rockspec authors. 392-- Expose some more values detected by LuaRocks for use by rockspec authors.
351defaults.variables.LUA = defaults.lua_interpreter 393defaults.variables.LUA = defaults.lua_interpreter
352defaults.variables.LIB_EXTENSION = defaults.lib_extension 394defaults.variables.LIB_EXTENSION = defaults.lib_extension
353defaults.variables.OBJ_EXTENSION = defaults.obj_extension 395defaults.variables.OBJ_EXTENSION = defaults.obj_extension
354defaults.variables.LUAROCKS_PREFIX = config.LUAROCKS_PREFIX 396defaults.variables.LUAROCKS_PREFIX = site_config.LUAROCKS_PREFIX
355 397
356-- Use defaults: 398-- Use defaults:
357 399
@@ -389,6 +431,10 @@ for _,tree in ipairs(rocks_trees) do
389 end 431 end
390end 432end
391 433
434function which_config()
435 return sys_config_file, sys_config_ok, home_config_file, home_config_ok
436end
437
392--- Check if platform was detected 438--- Check if platform was detected
393-- @param query string: The platform name to check. 439-- @param query string: The platform name to check.
394-- @return boolean: true if LuaRocks is currently running on queried platform. 440-- @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 02793c5a..8fa9073c 100644
--- a/src/luarocks/command_line.lua
+++ b/src/luarocks/command_line.lua
@@ -57,6 +57,12 @@ function run_command(...)
57 end 57 end
58 local nonflags = { util.parse_flags(unpack(args)) } 58 local nonflags = { util.parse_flags(unpack(args)) }
59 local flags = table.remove(nonflags, 1) 59 local flags = table.remove(nonflags, 1)
60
61 if flags["from"] then flags["server"] = flags["from"] end
62 if flags["only-from"] then flags["only-server"] = flags["only-from"] end
63 if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end
64 if flags["to"] then flags["tree"] = flags["to"] end
65
60 cfg.flags = flags 66 cfg.flags = flags
61 67
62 local command 68 local command
@@ -79,16 +85,22 @@ function run_command(...)
79 end 85 end
80 end 86 end
81 command = command:gsub("-", "_") 87 command = command:gsub("-", "_")
88
89 if flags["extensions"] then
90 cfg.use_extensions = true
91 local type_check = require("luarocks.type_check")
92 type_check.load_extensions()
93 end
82 94
83 if cfg.local_by_default then 95 if cfg.local_by_default then
84 flags["local"] = true 96 flags["local"] = true
85 end 97 end
86 98
87 if flags["to"] then 99 if flags["tree"] then
88 if flags["to"] == true then 100 if flags["tree"] == true then
89 die("Argument error: use --to=<path>") 101 die("Argument error: use --tree=<path>")
90 end 102 end
91 local root_dir = fs.absolute_name(flags["to"]) 103 local root_dir = fs.absolute_name(flags["tree"])
92 path.use_tree(root_dir) 104 path.use_tree(root_dir)
93 elseif flags["local"] then 105 elseif flags["local"] then
94 path.use_tree(cfg.home_tree) 106 path.use_tree(cfg.home_tree)
@@ -110,19 +122,23 @@ function run_command(...)
110 cfg.variables.ROCKS_TREE = cfg.rocks_dir 122 cfg.variables.ROCKS_TREE = cfg.rocks_dir
111 cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir 123 cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
112 124
113 if flags["from"] then 125 if flags["server"] then
114 if flags["from"] == true then 126 if flags["server"] == true then
115 die("Argument error: use --from=<url>") 127 die("Argument error: use --server=<url>")
116 end 128 end
117 local protocol, path = dir.split_url(flags["from"]) 129 local protocol, path = dir.split_url(flags["server"])
118 table.insert(cfg.rocks_servers, 1, protocol.."://"..path) 130 table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
119 end 131 end
120 132
121 if flags["only-from"] then 133 if flags["only-server"] then
122 if flags["only-from"] == true then 134 if flags["only-server"] == true then
123 die("Argument error: use --only-from=<url>") 135 die("Argument error: use --only-server=<url>")
124 end 136 end
125 cfg.rocks_servers = { flags["only-from"] } 137 cfg.rocks_servers = { flags["only-server"] }
138 end
139
140 if flags["only-sources"] then
141 cfg.only_sources_from = flags["only-sources"]
126 end 142 end
127 143
128 if command ~= "help" then 144 if command ~= "help" then
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index 27062cbb..a669ad66 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -317,7 +317,7 @@ local function match_dep(dep, blacklist)
317 317
318 local versions 318 local versions
319 if dep.name == "lua" then 319 if dep.name == "lua" then
320 versions = { "5.1" } 320 versions = { cfg.lua_version }
321 else 321 else
322 versions = manif_core.get_versions(dep.name) 322 versions = manif_core.get_versions(dep.name)
323 end 323 end
@@ -470,7 +470,7 @@ function fulfill_dependencies(rockspec)
470 if not match_dep(dep) then 470 if not match_dep(dep) then
471 local rock = search.find_suitable_rock(dep) 471 local rock = search.find_suitable_rock(dep)
472 if not rock then 472 if not rock then
473 return nil, "Could not find a rock to satisfy dependency: "..show_dep(dep) 473 return nil, "Could not satisfy dependency: "..show_dep(dep)
474 end 474 end
475 local ok, err, errcode = install.run(rock) 475 local ok, err, errcode = install.run(rock)
476 if not ok then 476 if not ok then
@@ -568,7 +568,7 @@ function check_external_deps(rockspec, mode)
568 end 568 end
569 end 569 end
570 else 570 else
571 found = fs.exists(dir.path(dirdata.dir, f)) 571 found = fs.is_file(dir.path(dirdata.dir, f))
572 end 572 end
573 if found then 573 if found then
574 break 574 break
@@ -606,12 +606,15 @@ end
606--- Recursively scan dependencies, to build a transitive closure of all 606--- Recursively scan dependencies, to build a transitive closure of all
607-- dependent packages. 607-- dependent packages.
608-- @param results table: The results table being built. 608-- @param results table: The results table being built.
609-- @param missing table: The table of missing dependencies being recursively built.
610-- @param manifest table: The manifest table containing dependencies.
609-- @param name string: Package name. 611-- @param name string: Package name.
610-- @param version string: Package version. 612-- @param version string: Package version.
611-- @return (table, table): The results and a table of missing dependencies. 613-- @return (table, table): The results and a table of missing dependencies.
612function scan_deps(results, missing, manifest, name, version) 614function scan_deps(results, missing, manifest, name, version)
613 assert(type(results) == "table") 615 assert(type(results) == "table")
614 assert(type(missing) == "table") 616 assert(type(missing) == "table")
617 assert(type(manifest) == "table")
615 assert(type(name) == "string") 618 assert(type(name) == "string")
616 assert(type(version) == "string") 619 assert(type(version) == "string")
617 620
@@ -630,7 +633,7 @@ function scan_deps(results, missing, manifest, name, version)
630 if not deplist then 633 if not deplist then
631 rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version)) 634 rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version))
632 if err then 635 if err then
633 missing[name.." "..version] = true 636 missing[name.." "..version] = err
634 return results, missing 637 return results, missing
635 end 638 end
636 dependencies_name[version] = rockspec.dependencies 639 dependencies_name[version] = rockspec.dependencies
@@ -643,7 +646,7 @@ function scan_deps(results, missing, manifest, name, version)
643 end 646 end
644 if next(failures) then 647 if next(failures) then
645 for _, failure in pairs(failures) do 648 for _, failure in pairs(failures) do
646 missing[show_dep(failure)] = true 649 missing[show_dep(failure)] = "failed"
647 end 650 end
648 end 651 end
649 results[name] = version 652 results[name] = version
diff --git a/src/luarocks/dir.lua b/src/luarocks/dir.lua
index 5a8058dc..69968917 100644
--- a/src/luarocks/dir.lua
+++ b/src/luarocks/dir.lua
@@ -1,4 +1,5 @@
1 1
2--- Generic utilities for handling pathnames.
2module("luarocks.dir", package.seeall) 3module("luarocks.dir", package.seeall)
3 4
4separator = "/" 5separator = "/"
@@ -10,7 +11,7 @@ separator = "/"
10function base_name(pathname) 11function base_name(pathname)
11 assert(type(pathname) == "string") 12 assert(type(pathname) == "string")
12 13
13 local base = pathname:match(".*[/\\]([^/\\]*)") 14 local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)")
14 return base or pathname 15 return base or pathname
15end 16end
16 17
diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua
index 6ae5f7af..474e4d39 100644
--- a/src/luarocks/download.lua
+++ b/src/luarocks/download.lua
@@ -9,60 +9,37 @@ local fetch = require("luarocks.fetch")
9local search = require("luarocks.search") 9local search = require("luarocks.search")
10 10
11help_summary = "Download a specific rock file from a rocks server." 11help_summary = "Download a specific rock file from a rocks server."
12help_arguments = "[--all] [--source] [--arch=<arch>] [<name> [<version>]]" 12help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]"
13 13
14help = [[ 14help = [[
15--all Download multiple rock files if there is more than one match. 15--all Download all files if there are multiple matches.
16--source Download .src.rock if available. 16--source Download .src.rock if available.
17--rockspec Download .rockspec if available.
17--arch=<arch> Download rock for a specific architecture. 18--arch=<arch> Download rock for a specific architecture.
18]] 19]]
19 20
20local function download(rock_file) 21function download(arch, name, version, all)
21 local rock = fetch.fetch_url(rock_file)
22 return rock ~= nil
23end
24
25--- Driver function for the "download" command.
26-- @param name string: a rock name.
27-- @param version string or nil: if the name of a package is given, a
28-- version may also be passed.
29-- @return boolean or (nil, string): true if successful or nil followed
30-- by an error message.
31function run(...)
32 local flags, name, version = util.parse_flags(...)
33
34 assert(type(version) == "string" or not version)
35 if type(name) ~= "string" and not flags["all"] then
36 return nil, "Argument missing, see help."
37 end
38 if not name then name, version = "", "" end
39
40 local query = search.make_query(name, version)
41 if flags["source"] then
42 query.arch = "src"
43 elseif flags["rockspec"] then
44 query.arch = "rockspec"
45 elseif flags["arch"] then
46 query.arch = flags["arch"]
47 end
48 local results, err 22 local results, err
49 if flags["all"] then 23 local query = search.make_query(name, version)
24 if arch then query.arch = arch end
25 if all then
50 if name == "" then query.exact_name = false end 26 if name == "" then query.exact_name = false end
51 results, err = search.search_repos(query) 27 results, err = search.search_repos(query)
52 else 28 else
53 results, err = search.find_suitable_rock(query) 29 results, err = search.find_suitable_rock(query)
54 end 30 end
55 if type(results) == "string" then 31 if type(results) == "string" then
56 return download(results) 32 local file = fetch.fetch_url(results)
33 return file
57 elseif type(results) == "table" and next(results) then 34 elseif type(results) == "table" and next(results) then
58 if flags["all"] then 35 if all then
59 local all_ok = true 36 local all_ok = true
60 local any_err = "" 37 local any_err = ""
61 for name, result in pairs(results) do 38 for name, result in pairs(results) do
62 for version, versions in pairs(result) do 39 for version, versions in pairs(result) do
63 for _,items in pairs(versions) do 40 for _,items in pairs(versions) do
64 local filename = path.make_url(items.repo, name, version, items.arch) 41 local filename = path.make_url(items.repo, name, version, items.arch)
65 local ok, err = download(filename) 42 local ok, err = fetch.fetch_url(filename)
66 if not ok then 43 if not ok then
67 all_ok = false 44 all_ok = false
68 any_err = any_err .. "\n" .. err 45 any_err = any_err .. "\n" .. err
@@ -79,7 +56,35 @@ function run(...)
79 search.print_results(results) 56 search.print_results(results)
80 return nil, "Please narrow your query or use --all." 57 return nil, "Please narrow your query or use --all."
81 end 58 end
82 else
83 return nil, "Could not find a result named "..name..(version and " "..version or "").."."
84 end 59 end
60 return nil, "Could not find a result named "..name..(version and " "..version or "").."."
61end
62
63--- Driver function for the "download" command.
64-- @param name string: a rock name.
65-- @param version string or nil: if the name of a package is given, a
66-- version may also be passed.
67-- @return boolean or (nil, string): true if successful or nil followed
68-- by an error message.
69function run(...)
70 local flags, name, version = util.parse_flags(...)
71
72 assert(type(version) == "string" or not version)
73 if type(name) ~= "string" and not flags["all"] then
74 return nil, "Argument missing, see help."
75 end
76 if not name then name, version = "", "" end
77
78 local arch
79
80 if flags["source"] then
81 arch = "src"
82 elseif flags["rockspec"] then
83 arch = "rockspec"
84 elseif flags["arch"] then
85 arch = flags["arch"]
86 end
87
88 local dl, err = download(arch, name, version, flags["all"])
89 return dl and true, err
85end 90end
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua
index 2ea2c906..b835b20e 100644
--- a/src/luarocks/fetch.lua
+++ b/src/luarocks/fetch.lua
@@ -9,6 +9,7 @@ local path = require("luarocks.path")
9local deps = require("luarocks.deps") 9local deps = require("luarocks.deps")
10local persist = require("luarocks.persist") 10local persist = require("luarocks.persist")
11local util = require("luarocks.util") 11local util = require("luarocks.util")
12local cfg = require("luarocks.cfg")
12 13
13--- Fetch a local or remote file. 14--- Fetch a local or remote file.
14-- Make a remote or local URL/pathname local, fetching the file if necessary. 15-- Make a remote or local URL/pathname local, fetching the file if necessary.
@@ -59,7 +60,11 @@ function fetch_url_at_temp_dir(url, tmpname, filename)
59 60
60 local protocol, pathname = dir.split_url(url) 61 local protocol, pathname = dir.split_url(url)
61 if protocol == "file" then 62 if protocol == "file" then
62 return pathname, dir.dir_name(fs.absolute_name(pathname)) 63 if fs.exists(pathname) then
64 return pathname, dir.dir_name(fs.absolute_name(pathname))
65 else
66 return nil, "File not found: "..pathname
67 end
63 else 68 else
64 local temp_dir = fs.make_temp_dir(tmpname) 69 local temp_dir = fs.make_temp_dir(tmpname)
65 if not temp_dir then 70 if not temp_dir then
@@ -117,7 +122,7 @@ end
117 122
118--- Back-end function that actually loads the local rockspec. 123--- Back-end function that actually loads the local rockspec.
119-- Performs some validation and postprocessing of the rockspec contents. 124-- Performs some validation and postprocessing of the rockspec contents.
120-- @param file string: The local filename of the rockspec file. 125-- @param filename string: The local filename of the rockspec file.
121-- @return table or (nil, string): A table representing the rockspec 126-- @return table or (nil, string): A table representing the rockspec
122-- or nil followed by an error message. 127-- or nil followed by an error message.
123function load_local_rockspec(filename) 128function load_local_rockspec(filename)
@@ -162,8 +167,8 @@ function load_local_rockspec(filename)
162 rockspec.source.protocol, rockspec.source.pathname = protocol, pathname 167 rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
163 168
164 -- Temporary compatibility 169 -- Temporary compatibility
165 if not rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end 170 if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
166 if not rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end 171 if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end
167 172
168 local name_version = rockspec.package:lower() .. "-" .. rockspec.version 173 local name_version = rockspec.package:lower() .. "-" .. rockspec.version
169 if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then 174 if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then
@@ -297,11 +302,20 @@ function fetch_sources(rockspec, extract, dest_dir)
297 if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then 302 if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
298 proto = require("luarocks.fetch") 303 proto = require("luarocks.fetch")
299 else 304 else
300 ok, proto = pcall(require, "luarocks.fetch."..protocol) 305 ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_"))
301 if not ok then 306 if not ok then
302 return nil, "Unknown protocol "..protocol 307 return nil, "Unknown protocol "..protocol
303 end 308 end
304 end 309 end
305 310
311 if cfg.only_sources_from
312 and rockspec.source.pathname
313 and #rockspec.source.pathname > 0 then
314 if #cfg.only_sources_from == 0 then
315 return nil, "Can't download "..rockspec.source.url.." -- download from remote servers disabled"
316 elseif rockspec.source.pathname:find(cfg.only_sources_from, 1, true) ~= 1 then
317 return nil, "Can't download "..rockspec.source.url.." -- only downloading from "..cfg.only_sources_from
318 end
319 end
306 return proto.get_sources(rockspec, extract, dest_dir) 320 return proto.get_sources(rockspec, extract, dest_dir)
307end 321end
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua
index 42129b22..e5f1ad4d 100644
--- a/src/luarocks/fetch/git.lua
+++ b/src/luarocks/fetch/git.lua
@@ -25,7 +25,6 @@ function get_sources(rockspec, extract, dest_dir)
25 local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module} 25 local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module}
26 local tag_or_branch = rockspec.source.tag or rockspec.source.branch 26 local tag_or_branch = rockspec.source.tag or rockspec.source.branch
27 if tag_or_branch then 27 if tag_or_branch then
28 -- ensure the branch (or tag) is available
29 table.insert(command, 4, "--branch=" .. tag_or_branch) 28 table.insert(command, 4, "--branch=" .. tag_or_branch)
30 end 29 end
31 local store_dir 30 local store_dir
@@ -38,6 +37,7 @@ function get_sources(rockspec, extract, dest_dir)
38 else 37 else
39 store_dir = dest_dir 38 store_dir = dest_dir
40 end 39 end
40 store_dir = fs.absolute_name(store_dir)
41 fs.change_dir(store_dir) 41 fs.change_dir(store_dir)
42 if not fs.execute(unpack(command)) then 42 if not fs.execute(unpack(command)) then
43 return nil, "Failed cloning git repository." 43 return nil, "Failed cloning git repository."
diff --git a/src/luarocks/fetch/git_file.lua b/src/luarocks/fetch/git_file.lua
new file mode 100644
index 00000000..1b18d0fa
--- /dev/null
+++ b/src/luarocks/fetch/git_file.lua
@@ -0,0 +1,17 @@
1
2--- Fetch back-end for retrieving sources from local Git repositories.
3module("luarocks.fetch.git_file", package.seeall)
4
5local git = require("luarocks.fetch.git")
6
7--- Fetch sources for building a rock from a local Git repository.
8-- @param rockspec table: The rockspec table
9-- @param extract boolean: Unused in this module (required for API purposes.)
10-- @param dest_dir string or nil: If set, will extract to the given directory.
11-- @return (string, string) or (nil, string): The absolute pathname of
12-- the fetched source tarball and the temporary directory created to
13-- store it; or nil and an error message.
14function get_sources(rockspec, extract, dest_dir)
15 rockspec.source.url = rockspec.source.url:gsub("^git.file://", "")
16 return git.get_sources(rockspec, extract, dest_dir)
17end
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua
index d2cb3ddb..467b1943 100644
--- a/src/luarocks/fs.lua
+++ b/src/luarocks/fs.lua
@@ -1,11 +1,12 @@
1 1
2local pairs = pairs
3
4--- Proxy module for filesystem and platform abstractions. 2--- Proxy module for filesystem and platform abstractions.
5-- All code using "fs" code should require "luarocks.fs", 3-- All code using "fs" code should require "luarocks.fs",
6-- and not the various platform-specific implementations. 4-- and not the various platform-specific implementations.
7-- However, see the documentation of the implementation 5-- However, see the documentation of the implementation
8-- for the API reference. 6-- for the API reference.
7
8local pairs = pairs
9
9module("luarocks.fs", package.seeall) 10module("luarocks.fs", package.seeall)
10 11
11local cfg = require("luarocks.cfg") 12local cfg = require("luarocks.cfg")
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index 1a7e4eff..67c3ce0f 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -59,7 +59,7 @@ function is_writable(file)
59 if fh then fh:close() end 59 if fh then fh:close() end
60 os.remove(file2) 60 os.remove(file2)
61 else 61 else
62 local fh = io.open(file, 'rb+') 62 local fh = io.open(file, 'r+b')
63 result = fh ~= nil 63 result = fh ~= nil
64 if fh then fh:close() end 64 if fh then fh:close() end
65 end 65 end
@@ -129,7 +129,8 @@ if lfs_ok then
129-- @return boolean: true if command succeeds (status code 0), false 129-- @return boolean: true if command succeeds (status code 0), false
130-- otherwise. 130-- otherwise.
131function execute_string(cmd) 131function execute_string(cmd)
132 if os.execute(cmd) == 0 then 132 local code = os.execute(cmd)
133 if code == 0 or code == true then
133 return true 134 return true
134 else 135 else
135 return false 136 return false
@@ -159,7 +160,7 @@ end
159-- a crossplatform way. 160-- a crossplatform way.
160function change_dir_to_root() 161function change_dir_to_root()
161 table.insert(dir_stack, lfs.currentdir()) 162 table.insert(dir_stack, lfs.currentdir())
162 lfs.chdir("/") -- works on Windows too 163 lfs.chdir("/") -- works on Windows too
163end 164end
164 165
165--- Change working directory to the previous in the dir stack. 166--- Change working directory to the previous in the dir stack.
@@ -231,9 +232,11 @@ end
231--- Copy a file. 232--- Copy a file.
232-- @param src string: Pathname of source 233-- @param src string: Pathname of source
233-- @param dest string: Pathname of destination 234-- @param dest string: Pathname of destination
235-- @param perms string or nil: Permissions for destination file,
236-- or nil to use the source filename permissions
234-- @return boolean or (boolean, string): true on success, false on failure, 237-- @return boolean or (boolean, string): true on success, false on failure,
235-- plus an error message. 238-- plus an error message.
236function copy(src, dest) 239function copy(src, dest, perms)
237 assert(src and dest) 240 assert(src and dest)
238 src = normalize(src) 241 src = normalize(src)
239 dest = normalize(dest) 242 dest = normalize(dest)
@@ -241,7 +244,7 @@ function copy(src, dest)
241 if destmode == "directory" then 244 if destmode == "directory" then
242 dest = dir.path(dest, dir.base_name(src)) 245 dest = dir.path(dest, dir.base_name(src))
243 end 246 end
244 local perms = fs.get_permissions(src) 247 if not perms then perms = fs.get_permissions(src) end
245 local src_h, err = io.open(src, "rb") 248 local src_h, err = io.open(src, "rb")
246 if not src_h then return nil, err end 249 if not src_h then return nil, err end
247 local dest_h, err = io.open(dest, "wb+") 250 local dest_h, err = io.open(dest, "wb+")
@@ -540,7 +543,7 @@ function download(url, filename)
540 err = "Unsupported protocol" 543 err = "Unsupported protocol"
541 end 544 end
542 if not content then 545 if not content then
543 return false, err 546 return false, tostring(err)
544 end 547 end
545 local file = io.open(filename, "wb") 548 local file = io.open(filename, "wb")
546 if not file then return false end 549 if not file then return false end
@@ -576,7 +579,26 @@ end
576 579
577if posix_ok then 580if posix_ok then
578 581
582local octal_to_rwx = {
583 ["0"] = "---",
584 ["1"] = "--x",
585 ["2"] = "-w-",
586 ["3"] = "-wx",
587 ["4"] = "r--",
588 ["5"] = "r-x",
589 ["6"] = "rw-",
590 ["7"] = "rwx",
591}
592
579function chmod(file, mode) 593function chmod(file, mode)
594 -- LuaPosix (as of 5.1.15) does not support octal notation...
595 if mode:sub(1,1) == "0" then
596 local new_mode = {}
597 for c in mode:sub(2):gmatch(".") do
598 table.insert(new_mode, octal_to_rwx[c])
599 end
600 mode = table.concat(new_mode)
601 end
580 local err = posix.chmod(file, mode) 602 local err = posix.chmod(file, mode)
581 return err == 0 603 return err == 0
582end 604end
@@ -593,6 +615,7 @@ end
593 615
594--- Apply a patch. 616--- Apply a patch.
595-- @param patchname string: The filename of the patch. 617-- @param patchname string: The filename of the patch.
618-- @param patchdata string or nil: The actual patch as a string.
596function apply_patch(patchname, patchdata) 619function apply_patch(patchname, patchdata)
597 local p, all_ok = patch.read_patch(patchname, patchdata) 620 local p, all_ok = patch.read_patch(patchname, patchdata)
598 if not all_ok then 621 if not all_ok then
@@ -631,9 +654,23 @@ end
631-- plus an error message. 654-- plus an error message.
632function check_command_permissions(flags) 655function check_command_permissions(flags)
633 local root_dir = path.root_dir(cfg.rocks_dir) 656 local root_dir = path.root_dir(cfg.rocks_dir)
634 if not flags["local"] and not fs.is_writable(root_dir) then 657 local ok = true
635 return nil, "Your user does not have write permissions in " .. root_dir .. 658 local err = ""
636 " \n-- you may want to run as a privileged user or use your local tree with --local." 659 for _, dir in ipairs { cfg.rocks_dir, root_dir, dir.dir_name(root_dir) } do
660 if fs.exists(dir) and not fs.is_writable(dir) then
661 ok = false
662 err = "Your user does not have write permissions in " .. dir
663 break
664 end
665 end
666 if ok then
667 return true
668 else
669 if flags["local"] then
670 err = err .. " \n-- please check your permissions."
671 else
672 err = err .. " \n-- you may want to run as a privileged user or use your local tree with --local."
673 end
674 return nil, err
637 end 675 end
638 return true
639end 676end
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua
index 0930cadb..88bafaf6 100644
--- a/src/luarocks/fs/unix.lua
+++ b/src/luarocks/fs/unix.lua
@@ -1,8 +1,9 @@
1 1
2--- Unix implementation of filesystem and platform abstractions.
3
2local assert, type, table, io, package, math, os, ipairs = 4local assert, type, table, io, package, math, os, ipairs =
3 assert, type, table, io, package, math, os, ipairs 5 assert, type, table, io, package, math, os, ipairs
4 6
5--- Unix implementation of filesystem and platform abstractions.
6module("luarocks.fs.unix", package.seeall) 7module("luarocks.fs.unix", package.seeall)
7 8
8local fs = require("luarocks.fs") 9local fs = require("luarocks.fs")
@@ -53,7 +54,7 @@ function wrap_script(file, dest)
53 wrapper:write('export LUA_PATH LUA_CPATH\n') 54 wrapper:write('export LUA_PATH LUA_CPATH\n')
54 wrapper:write('exec "'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader "'..file..'" "$@"\n') 55 wrapper:write('exec "'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader "'..file..'" "$@"\n')
55 wrapper:close() 56 wrapper:close()
56 if fs.execute("chmod +x",wrapname) then 57 if fs.chmod(wrapname, "0755") then
57 return true 58 return true
58 else 59 else
59 return nil, "Could not make "..wrapname.." executable." 60 return nil, "Could not make "..wrapname.." executable."
@@ -70,61 +71,18 @@ function is_actual_binary(filename)
70 return false 71 return false
71 end 72 end
72 local file = io.open(filename) 73 local file = io.open(filename)
73 if file then 74 if not file then
74 local found = false
75 local first = file:read()
76 if first:match("#!.*lua") then
77 found = true
78 elseif first:match("#!/bin/sh") then
79 local line = file:read()
80 line = file:read()
81 if not(line and line:match("LUA_PATH")) then
82 found = true
83 end
84 end
85 file:close()
86 if found then
87 return false
88 else
89 return true
90 end
91 else
92 return true 75 return true
93 end 76 end
94 return false 77 local first = file:read(2)
95end 78 file:close()
96 79 if not first then
97function is_actual_binary(filename) 80 util.printerr("Warning: could not read "..filename)
98 if filename:match("%.lua$") then
99 return false
100 end
101 local file = io.open(filename)
102 if file then
103 local found = false
104 local first = file:read()
105 if not first then
106 file:close()
107 util.printerr("Warning: could not read "..filename)
108 return false
109 end
110 if first:match("#!.*lua") then
111 file:close()
112 return true
113 elseif first:match("#!/bin/sh") then
114 local line = file:read()
115 line = file:read()
116 if not(line and line:match("LUA_PATH")) then
117 file:close()
118 return true
119 end
120 end
121 file:close()
122 else
123 return true 81 return true
124 end 82 end
125 return false 83 return first ~= "#!"
126end 84end
127 85
128function copy_binary(filename, dest) 86function copy_binary(filename, dest)
129 return fs.copy(filename, dest) 87 return fs.copy(filename, dest, "0755")
130end 88end
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
index d1722f4b..37efcf66 100644
--- a/src/luarocks/fs/unix/tools.lua
+++ b/src/luarocks/fs/unix/tools.lua
@@ -11,13 +11,14 @@ local dir_stack = {}
11local vars = cfg.variables 11local vars = cfg.variables
12 12
13--- Run the given command. 13--- Run the given command.
14-- The command is executed in the current directory in the dir stack. 14-- The command is executed in the current directory in the directory stack.
15-- @param cmd string: No quoting/escaping is applied to the command. 15-- @param cmd string: No quoting/escaping is applied to the command.
16-- @return boolean: true if command succeeds (status code 0), false 16-- @return boolean: true if command succeeds (status code 0), false
17-- otherwise. 17-- otherwise.
18function execute_string(cmd) 18function execute_string(cmd)
19 local actual_cmd = "cd " .. fs.Q(fs.current_dir()) .. " && " .. cmd 19 local actual_cmd = "cd " .. fs.Q(fs.current_dir()) .. " && " .. cmd
20 if os.execute(actual_cmd) == 0 then 20 local code = os.execute(actual_cmd)
21 if code == 0 or code == true then
21 return true 22 return true
22 else 23 else
23 return false 24 return false
@@ -25,26 +26,26 @@ function execute_string(cmd)
25end 26end
26 27
27--- Obtain current directory. 28--- Obtain current directory.
28-- Uses the module's internal dir stack. 29-- Uses the module's internal directory stack.
29-- @return string: the absolute pathname of the current directory. 30-- @return string: the absolute pathname of the current directory.
30function current_dir() 31function current_dir()
31 local pipe = io.popen(vars.PWD) 32 local pipe = io.popen(vars.PWD)
32 local current = pipe:read("*l") 33 local current = pipe:read("*l")
33 pipe:close() 34 pipe:close()
34 for _, d in ipairs(dir_stack) do 35 for _, directory in ipairs(dir_stack) do
35 current = fs.absolute_name(d, current) 36 current = fs.absolute_name(directory, current)
36 end 37 end
37 return current 38 return current
38end 39end
39 40
40--- Change the current directory. 41--- Change the current directory.
41-- Uses the module's internal dir stack. This does not have exact 42-- Uses the module's internal directory stack. This does not have exact
42-- semantics of chdir, as it does not handle errors the same way, 43-- semantics of chdir, as it does not handle errors the same way,
43-- but works well for our purposes for now. 44-- but works well for our purposes for now.
44-- @param d string: The directory to switch to. 45-- @param directory string: The directory to switch to.
45function change_dir(d) 46function change_dir(directory)
46 assert(type(d) == "string") 47 assert(type(directory) == "string")
47 table.insert(dir_stack, d) 48 table.insert(dir_stack, directory)
48end 49end
49 50
50--- Change directory to root. 51--- Change directory to root.
@@ -54,48 +55,59 @@ function change_dir_to_root()
54 table.insert(dir_stack, "/") 55 table.insert(dir_stack, "/")
55end 56end
56 57
57--- Change working directory to the previous in the dir stack. 58--- Change working directory to the previous in the directory stack.
58function pop_dir() 59function pop_dir()
59 local d = table.remove(dir_stack) 60 local directory = table.remove(dir_stack)
60 return d ~= nil 61 return directory ~= nil
61end 62end
62 63
63--- Create a directory if it does not already exist. 64--- Create a directory if it does not already exist.
64-- If any of the higher levels in the path name does not exist 65-- If any of the higher levels in the path name does not exist
65-- too, they are created as well. 66-- too, they are created as well.
66-- @param d string: pathname of directory to create. 67-- @param directory string: pathname of directory to create.
67-- @return boolean: true on success, false on failure. 68-- @return boolean: true on success, false on failure.
68function make_dir(d) 69function make_dir(directory)
69 assert(d) 70 assert(directory)
70 return fs.execute(vars.MKDIR.." -p", d) 71 return fs.execute(vars.MKDIR.." -p", directory)
71end 72end
72 73
73--- Remove a directory if it is empty. 74--- Remove a directory if it is empty.
74-- Does not return errors (for example, if directory is not empty or 75-- Does not return errors (for example, if directory is not empty or
75-- if already does not exist) 76-- if already does not exist)
76-- @param dir string: pathname of directory to remove. 77-- @param directory string: pathname of directory to remove.
77function remove_dir_if_empty(d) 78function remove_dir_if_empty(directory)
78 assert(d) 79 assert(directory)
79 fs.execute_string(vars.RMDIR.." "..fs.Q(d).." 1> /dev/null 2> /dev/null") 80 fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> /dev/null 2> /dev/null")
80end 81end
81 82
82--- Remove a directory if it is empty. 83--- Remove a directory if it is empty.
83-- Does not return errors (for example, if directory is not empty or 84-- Does not return errors (for example, if directory is not empty or
84-- if already does not exist) 85-- if already does not exist)
85-- @param dir string: pathname of directory to remove. 86-- @param directory string: pathname of directory to remove.
86function remove_dir_tree_if_empty(d) 87function remove_dir_tree_if_empty(directory)
87 assert(d) 88 assert(directory)
88 fs.execute_string(vars.RMDIR.." -p "..fs.Q(d).." 1> /dev/null 2> /dev/null") 89 fs.execute_string(vars.RMDIR.." -p "..fs.Q(directory).." 1> /dev/null 2> /dev/null")
89end 90end
90 91
91--- Copy a file. 92--- Copy a file.
92-- @param src string: Pathname of source 93-- @param src string: Pathname of source
93-- @param dest string: Pathname of destination 94-- @param dest string: Pathname of destination
95-- @param perm string or nil: Permissions for destination file,
94-- @return boolean or (boolean, string): true on success, false on failure, 96-- @return boolean or (boolean, string): true on success, false on failure,
95-- plus an error message. 97-- plus an error message.
96function copy(src, dest) 98function copy(src, dest, perm)
97 assert(src and dest) 99 assert(src and dest)
98 if fs.execute(vars.CP, src, dest) then 100 if fs.execute(vars.CP, src, dest) then
101 if perm then
102 if fs.is_dir(dest) then
103 dest = dir.path(dest, dir.base_name(src))
104 end
105 if fs.chmod(dest, perm) then
106 return true
107 else
108 return false, "Failed setting permissions of "..dest
109 end
110 end
99 return true 111 return true
100 else 112 else
101 return false, "Failed copying "..src.." to "..dest 113 return false, "Failed copying "..src.." to "..dest
@@ -194,7 +206,7 @@ function exists(file)
194 return fs.execute(vars.TEST, "-r", file) 206 return fs.execute(vars.TEST, "-r", file)
195end 207end
196 208
197--- Test is file/dir is writable. 209--- Test is file/directory is writable.
198-- @param file string: filename to test 210-- @param file string: filename to test
199-- @return boolean: true if file exists, false otherwise. 211-- @return boolean: true if file exists, false otherwise.
200function is_writable(file) 212function is_writable(file)
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua
index 44740850..98daf13f 100644
--- a/src/luarocks/fs/win32.lua
+++ b/src/luarocks/fs/win32.lua
@@ -15,7 +15,7 @@ local dir = require("luarocks.dir")
15function Q(arg) 15function Q(arg)
16 assert(type(arg) == "string") 16 assert(type(arg) == "string")
17 -- Quote DIR for Windows 17 -- Quote DIR for Windows
18 if arg:match("^[\.a-zA-Z]?:?[\\/]") then 18 if arg:match("^[%.a-zA-Z]?:?[\\/]") then
19 return '"' .. arg:gsub("/", "\\"):gsub('"', '\\"') .. '"' 19 return '"' .. arg:gsub("/", "\\"):gsub('"', '\\"') .. '"'
20 end 20 end
21 -- URLs and anything else 21 -- URLs and anything else
@@ -33,7 +33,9 @@ function absolute_name(pathname, relative_to)
33 assert(type(relative_to) == "string" or not relative_to) 33 assert(type(relative_to) == "string" or not relative_to)
34 34
35 relative_to = relative_to or fs.current_dir() 35 relative_to = relative_to or fs.current_dir()
36 if pathname:match("^[\.a-zA-Z]?:?[\\/]") then 36 -- FIXME I'm not sure this first \\ should be there at all.
37 -- What are the Windows rules for drive letters?
38 if pathname:match("^[\\.a-zA-Z]?:?[\\/]") then
37 return pathname 39 return pathname
38 else 40 else
39 return relative_to .. "/" .. pathname 41 return relative_to .. "/" .. pathname
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
index 5b7634cf..6115f382 100644
--- a/src/luarocks/fs/win32/tools.lua
+++ b/src/luarocks/fs/win32/tools.lua
@@ -42,14 +42,14 @@ function exists(file)
42end 42end
43 43
44--- Obtain current directory. 44--- Obtain current directory.
45-- Uses the module's internal dir stack. 45-- Uses the module's internal directory stack.
46-- @return string: the absolute pathname of the current directory. 46-- @return string: the absolute pathname of the current directory.
47function current_dir() 47function current_dir()
48 local pipe = io.popen(vars.PWD) 48 local pipe = io.popen(vars.PWD)
49 local current = pipe:read("*l") 49 local current = pipe:read("*l")
50 pipe:close() 50 pipe:close()
51 for _, d in ipairs(dir_stack) do 51 for _, directory in ipairs(dir_stack) do
52 current = fs.absolute_name(d, current) 52 current = fs.absolute_name(directory, current)
53 end 53 end
54 return current 54 return current
55end 55end
@@ -82,13 +82,13 @@ function get_md5(file)
82end 82end
83 83
84--- Change the current directory. 84--- Change the current directory.
85-- Uses the module's internal dir stack. This does not have exact 85-- Uses the module's internal directory stack. This does not have exact
86-- semantics of chdir, as it does not handle errors the same way, 86-- semantics of chdir, as it does not handle errors the same way,
87-- but works well for our purposes for now. 87-- but works well for our purposes for now.
88-- @param d string: The directory to switch to. 88-- @param directory string: The directory to switch to.
89function change_dir(d) 89function change_dir(directory)
90 assert(type(d) == "string") 90 assert(type(directory) == "string")
91 table.insert(dir_stack, d) 91 table.insert(dir_stack, directory)
92end 92end
93 93
94--- Change directory to root. 94--- Change directory to root.
@@ -98,19 +98,20 @@ function change_dir_to_root()
98 table.insert(dir_stack, "/") 98 table.insert(dir_stack, "/")
99end 99end
100 100
101--- Change working directory to the previous in the dir stack. 101--- Change working directory to the previous in the directory stack.
102function pop_dir() 102function pop_dir()
103 local d = table.remove(dir_stack) 103 local directory = table.remove(dir_stack)
104 return d ~= nil 104 return directory ~= nil
105end 105end
106 106
107--- Run the given command. 107--- Run the given command.
108-- The command is executed in the current directory in the dir stack. 108-- The command is executed in the current directory in the directory stack.
109-- @param cmd string: No quoting/escaping is applied to the command. 109-- @param cmd string: No quoting/escaping is applied to the command.
110-- @return boolean: true if command succeeds (status code 0), false 110-- @return boolean: true if command succeeds (status code 0), false
111-- otherwise. 111-- otherwise.
112function execute_string(cmd) 112function execute_string(cmd)
113 if os.execute(command_at(fs.current_dir(), cmd)) == 0 then 113 local code = os.execute(command_at(fs.current_dir(), cmd))
114 if code == 0 or code == true then
114 return true 115 return true
115 else 116 else
116 return false 117 return false
@@ -128,30 +129,30 @@ end
128--- Create a directory if it does not already exist. 129--- Create a directory if it does not already exist.
129-- If any of the higher levels in the path name does not exist 130-- If any of the higher levels in the path name does not exist
130-- too, they are created as well. 131-- too, they are created as well.
131-- @param d string: pathname of directory to create. 132-- @param directory string: pathname of directory to create.
132-- @return boolean: true on success, false on failure. 133-- @return boolean: true on success, false on failure.
133function make_dir(d) 134function make_dir(directory)
134 assert(d) 135 assert(directory)
135 fs.execute(vars.MKDIR.." "..fs.Q(d).." 1> NUL 2> NUL") 136 fs.execute(vars.MKDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
136 return 1 137 return 1
137end 138end
138 139
139--- Remove a directory if it is empty. 140--- Remove a directory if it is empty.
140-- Does not return errors (for example, if directory is not empty or 141-- Does not return errors (for example, if directory is not empty or
141-- if already does not exist) 142-- if already does not exist)
142-- @param d string: pathname of directory to remove. 143-- @param directory string: pathname of directory to remove.
143function remove_dir_if_empty(d) 144function remove_dir_if_empty(directory)
144 assert(d) 145 assert(directory)
145 fs.execute_string(vars.RMDIR.." "..fs.Q(d).." 1> NUL 2> NUL") 146 fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
146end 147end
147 148
148--- Remove a directory if it is empty. 149--- Remove a directory if it is empty.
149-- Does not return errors (for example, if directory is not empty or 150-- Does not return errors (for example, if directory is not empty or
150-- if already does not exist) 151-- if already does not exist)
151-- @param dir string: pathname of directory to remove. 152-- @param directory string: pathname of directory to remove.
152function remove_dir_tree_if_empty(d) 153function remove_dir_tree_if_empty(directory)
153 assert(d) 154 assert(directory)
154 fs.execute_string(vars.RMDIR.." "..fs.Q(d).." 1> NUL 2> NUL") 155 fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
155end 156end
156 157
157--- Copy a file. 158--- Copy a file.
diff --git a/src/luarocks/help.lua b/src/luarocks/help.lua
index a2e64b5d..19cd7914 100644
--- a/src/luarocks/help.lua
+++ b/src/luarocks/help.lua
@@ -9,13 +9,31 @@ module("luarocks.help", package.seeall)
9local util = require("luarocks.util") 9local util = require("luarocks.util")
10local cfg = require("luarocks.cfg") 10local cfg = require("luarocks.cfg")
11 11
12help_summary = "Help on commands." 12help_summary = "Help on commands. Type '"..program_name.." help <command>' for more."
13 13
14help_arguments = "[<command>]" 14help_arguments = "[<command>]"
15help = [[ 15help = [[
16<command> is the command to show help for. 16<command> is the command to show help for.
17]] 17]]
18 18
19local function print_banner()
20 util.printout("\nLuaRocks "..cfg.program_version..", a module deployment system for Lua")
21end
22
23local function print_section(section)
24 util.printout("\n"..section)
25end
26
27local function get_status(status)
28 if status then
29 return "ok"
30 elseif status == false then
31 return "not found"
32 else
33 return "failed"
34 end
35end
36
19--- Driver function for the "help" command. 37--- Driver function for the "help" command.
20-- @param command string or nil: command to show help for; if not 38-- @param command string or nil: command to show help for; if not
21-- given, help summaries for all commands are shown. 39-- given, help summaries for all commands are shown.
@@ -25,25 +43,29 @@ function run(...)
25 local flags, command = util.parse_flags(...) 43 local flags, command = util.parse_flags(...)
26 44
27 if not command then 45 if not command then
46 local sys_file, sys_ok, home_file, home_ok = cfg.which_config()
47 print_banner()
48 print_section("NAME")
49 util.printout("\t"..program_name..[[ - ]]..program_description)
50 print_section("SYNOPSIS")
51 util.printout("\t"..program_name..[[ [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>] ]])
52 print_section("GENERAL OPTIONS")
28 util.printout([[ 53 util.printout([[
29LuaRocks ]]..cfg.program_version..[[, a module deployment system for Lua 54 These apply to all commands, as appropriate:
30
31]]..program_name..[[ - ]]..program_description..[[
32
33usage: ]]..program_name..[[ [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>]
34
35Variables from the "variables" table of the configuration file
36can be overriden with VAR=VALUE assignments.
37 55
38--from=<server> Fetch rocks/rockspecs from this server 56 --server=<server> Fetch rocks/rockspecs from this server
39 (takes priority over config file) 57 (takes priority over config file)
40--only-from=<server> Fetch rocks/rockspecs from this server only 58 --only-server=<server> Fetch rocks/rockspecs from this server only
41 (overrides any entries in the config file) 59 (overrides any entries in the config file)
42--to=<tree> Which tree to operate on. 60 --only-sources=<url> Restrict downloads to paths matching the
43--local Use the tree in the user's home directory. 61 given URL.
44 62 --tree=<tree> Which tree to operate on.
45Supported commands: 63 --local Use the tree in the user's home directory.]])
46]]) 64 print_section("VARIABLES")
65 util.printout([[
66 Variables from the "variables" table of the configuration file
67 can be overriden with VAR=VALUE assignments.]])
68 print_section("COMMANDS")
47 local names = {} 69 local names = {}
48 for name, command in pairs(commands) do 70 for name, command in pairs(commands) do
49 table.insert(names, name) 71 table.insert(names, name)
@@ -51,18 +73,26 @@ Supported commands:
51 table.sort(names) 73 table.sort(names)
52 for _, name in ipairs(names) do 74 for _, name in ipairs(names) do
53 local command = commands[name] 75 local command = commands[name]
54 util.printout(name, command.help_summary) 76 util.printout("", name)
77 util.printout("\t", command.help_summary)
55 end 78 end
79 print_section("CONFIGURATION")
80 util.printout([[
81 System configuration file: ]]..sys_file .. " (" .. get_status(sys_ok) ..[[)
82 User configuration file: ]]..home_file .. " (" .. get_status(home_ok) ..")\n")
56 else 83 else
57 command = command:gsub("-", "_") 84 command = command:gsub("-", "_")
58 if commands[command] then 85 if commands[command] then
59 local arguments = commands[command].help_arguments or "<argument>" 86 local arguments = commands[command].help_arguments or "<argument>"
60 util.printout() 87 print_banner()
61 util.printout(program_name.." "..command.." "..arguments) 88 print_section("NAME")
62 util.printout() 89 util.printout("\t"..program_name.." "..command.." - "..commands[command].help_summary)
63 util.printout(command.." - "..commands[command].help_summary) 90 print_section("SYNOPSIS")
64 util.printout() 91 util.printout("\t"..program_name.." "..command.." "..arguments)
65 util.printout(commands[command].help) 92 print_section("DESCRIPTION")
93 util.printout("",(commands[command].help:gsub("\n","\n\t"):gsub("\n\t$","")))
94 print_section("SEE ALSO")
95 util.printout("","'luarocks help' for general options and configuration.\n")
66 else 96 else
67 return nil, "Unknown command '"..command.."'" 97 return nil, "Unknown command '"..command.."'"
68 end 98 end
diff --git a/src/luarocks/index.lua b/src/luarocks/index.lua
index 570db431..ba55f3b1 100644
--- a/src/luarocks/index.lua
+++ b/src/luarocks/index.lua
@@ -1,4 +1,5 @@
1 1
2--- Module which builds the index.html page to be used in rocks servers.
2module("luarocks.index", package.seeall) 3module("luarocks.index", package.seeall)
3 4
4local util = require("luarocks.util") 5local util = require("luarocks.util")
@@ -8,6 +9,8 @@ local persist = require("luarocks.persist")
8local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
9local manif = require("luarocks.manif") 10local manif = require("luarocks.manif")
10 11
12local ext_url_target = ' target="_blank"'
13
11local index_header = [[ 14local index_header = [[
12<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 15<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
13<html> 16<html>
@@ -143,17 +146,19 @@ function make_index(repo)
143 output = output .. index_package_end 146 output = output .. index_package_end
144 if latest_rockspec then 147 if latest_rockspec then
145 local rockspec = persist.load_into_table(dir.path(repo, latest_rockspec)) 148 local rockspec = persist.load_into_table(dir.path(repo, latest_rockspec))
149 local descript = rockspec.description or {}
146 local vars = { 150 local vars = {
147 anchor = package, 151 anchor = package,
148 package = rockspec.package, 152 package = rockspec.package,
149 original = rockspec.source.url, 153 original = rockspec.source.url,
150 summary = rockspec.description.summary or "", 154 summary = descript.summary or "",
151 detailed = rockspec.description.detailed or "", 155 detailed = descript.detailed or "",
152 license = rockspec.description.license or "N/A", 156 license = descript.license or "N/A",
153 homepage = rockspec.description.homepage and ("| <a href="..rockspec.description.homepage..">project homepage</a>") or "", 157 homepage = descript.homepage and ('| <a href="'..descript.homepage..'"'..ext_url_target..'>project homepage</a>') or "",
154 externaldependencies = format_external_dependencies(rockspec) 158 externaldependencies = format_external_dependencies(rockspec)
155 } 159 }
156 vars.detailed = vars.detailed:gsub("\n\n", "</p><p>"):gsub("%s+", " ") 160 vars.detailed = vars.detailed:gsub("\n\n", "</p><p>"):gsub("%s+", " ")
161 vars.detailed = vars.detailed:gsub("(https?://[a-zA-Z0-9%.%%-_%+%[%]=%?&/$@;:]+)", '<a href="%1"'..ext_url_target..'>%1</a>')
157 output = output:gsub("$(%w+)", vars) 162 output = output:gsub("$(%w+)", vars)
158 else 163 else
159 output = output:gsub("$anchor", package) 164 output = output:gsub("$anchor", package)
diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua
index e99b4ce0..0a779b86 100644
--- a/src/luarocks/install.lua
+++ b/src/luarocks/install.lua
@@ -23,9 +23,10 @@ or a filename of a locally available rock.
23 23
24--- Install a binary rock. 24--- Install a binary rock.
25-- @param rock_file string: local or remote filename of a rock. 25-- @param rock_file string: local or remote filename of a rock.
26-- @param no_deps boolean: true if dependency check needs to be skipped
26-- @return boolean or (nil, string, [string]): True if succeeded or 27-- @return boolean or (nil, string, [string]): True if succeeded or
27-- nil and an error message and an optional error code. 28-- nil and an error message and an optional error code.
28function install_binary_rock(rock_file) 29function install_binary_rock(rock_file, no_deps)
29 assert(type(rock_file) == "string") 30 assert(type(rock_file) == "string")
30 31
31 local name, version, arch = path.parse_name(rock_file) 32 local name, version, arch = path.parse_name(rock_file)
@@ -53,8 +54,12 @@ function install_binary_rock(rock_file)
53 return nil, "Failed loading rockspec for installed package: "..err, errcode 54 return nil, "Failed loading rockspec for installed package: "..err, errcode
54 end 55 end
55 56
56 ok, err, errcode = deps.check_external_deps(rockspec, "install") 57 if no_deps then
57 if err then return nil, err, errcode end 58 util.printerr("Warning: skipping dependency checks.")
59 else
60 ok, err, errcode = deps.check_external_deps(rockspec, "install")
61 if err then return nil, err, errcode end
62 end
58 63
59 -- For compatibility with .rock files built with LuaRocks 1 64 -- For compatibility with .rock files built with LuaRocks 1
60 if not fs.exists(path.rock_manifest_file(name, version)) then 65 if not fs.exists(path.rock_manifest_file(name, version)) then
@@ -62,10 +67,17 @@ function install_binary_rock(rock_file)
62 if err then return nil, err end 67 if err then return nil, err end
63 end 68 end
64 69
65 ok, err, errcode = deps.fulfill_dependencies(rockspec) 70 if not no_deps then
66 if err then return nil, err, errcode end 71 ok, err, errcode = deps.fulfill_dependencies(rockspec)
72 if err then return nil, err, errcode end
73 end
74
75 local wrap_bin_scripts = true
76 if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
77 wrap_bin_scripts = false
78 end
67 79
68 ok, err = rep.deploy_files(name, version) 80 ok, err = rep.deploy_files(name, version, rep.should_wrap_bin_scripts(rockspec))
69 if err then return nil, err end 81 if err then return nil, err end
70 82
71 util.remove_scheduled_function(rollback) 83 util.remove_scheduled_function(rollback)
@@ -112,10 +124,11 @@ function run(...)
112 if not ok then return nil, err end 124 if not ok then return nil, err end
113 125
114 if name:match("%.rockspec$") or name:match("%.src%.rock$") then 126 if name:match("%.rockspec$") or name:match("%.src%.rock$") then
127 util.printout("Using "..name.."... switching to 'build' mode")
115 local build = require("luarocks.build") 128 local build = require("luarocks.build")
116 return build.run(name, flags["local"] and "--local") 129 return build.run(name, flags["local"] and "--local")
117 elseif name:match("%.rock$") then 130 elseif name:match("%.rock$") then
118 return install_binary_rock(name) 131 return install_binary_rock(name, flags["nodeps"])
119 else 132 else
120 local search = require("luarocks.search") 133 local search = require("luarocks.search")
121 local results, err = search.find_suitable_rock(search.make_query(name:lower(), version)) 134 local results, err = search.find_suitable_rock(search.make_query(name:lower(), version))
diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua
index c3cba55a..ac694124 100644
--- a/src/luarocks/loader.lua
+++ b/src/luarocks/loader.lua
@@ -1,4 +1,10 @@
1 1
2--- A module which installs a Lua package loader that is LuaRocks-aware.
3-- This loader uses dependency information from the LuaRocks tree to load
4-- correct versions of modules. It does this by constructing a "context"
5-- table in the environment, which records which versions of packages were
6-- used to load previous modules, so that the loader chooses versions
7-- that are declared to be compatible with the ones loaded earlier.
2local global_env = _G 8local global_env = _G
3local package, require, ipairs, pairs, table, type, next, unpack = 9local package, require, ipairs, pairs, table, type, next, unpack =
4 package, require, ipairs, pairs, table, type, next, unpack 10 package, require, ipairs, pairs, table, type, next, unpack
@@ -88,8 +94,20 @@ local function sort_versions(a,b)
88 return a.version > b.version 94 return a.version > b.version
89end 95end
90 96
97--- Request module to be loaded through other loaders,
98-- once the proper name of the module has been determined.
99-- For example, in case the module "socket.core" has been requested
100-- to the LuaRocks loader and it determined based on context that
101-- the version 2.0.2 needs to be loaded and it is not the current
102-- version, the module requested for the other loaders will be
103-- "socket.core_2_0_2".
104-- @param module The module name requested by the user, such as "socket.core"
105-- @param name The rock name, such as "luasocket"
106-- @param version The rock version, such as "2.0.2-1"
107-- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2".
108-- @return table or (nil, string): The module table as returned by some other loader,
109-- or nil followed by an error message if no other loader managed to load the module.
91local function call_other_loaders(module, name, version, module_name) 110local function call_other_loaders(module, name, version, module_name)
92
93 for i, loader in pairs(package.loaders) do 111 for i, loader in pairs(package.loaders) do
94 if loader ~= luarocks_loader then 112 if loader ~= luarocks_loader then
95 local results = { loader(module_name) } 113 local results = { loader(module_name) }
@@ -101,6 +119,17 @@ local function call_other_loaders(module, name, version, module_name)
101 return nil, "Failed loading module "..module.." in LuaRocks rock "..name.." "..version 119 return nil, "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
102end 120end
103 121
122--- Search for a module in the rocks trees
123-- @param module string: module name (eg. "socket.core")
124-- @param filter_module_name function(string, string, string, string, number):
125-- a function that takes the module name (eg "socket.core"), the rock name
126-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree
127-- (eg "/usr/local"), and the numeric index of the matching entry, so the
128-- filter function can know if the matching module was the first entry or not.
129-- @return string, string, string: name of the rock containing the module
130-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
131-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
132-- stored versioned).
104local function select_module(module, filter_module_name) 133local function select_module(module, filter_module_name)
105 --assert(type(module) == "string") 134 --assert(type(module) == "string")
106 --assert(type(filter_module_name) == "function") 135 --assert(type(filter_module_name) == "function")
@@ -116,6 +145,9 @@ local function select_module(module, filter_module_name)
116 for i, entry in ipairs(entries) do 145 for i, entry in ipairs(entries) do
117 local name, version = entry:match("^([^/]*)/(.*)$") 146 local name, version = entry:match("^([^/]*)/(.*)$")
118 local module_name = tree.manifest.repository[name][version][1].modules[module] 147 local module_name = tree.manifest.repository[name][version][1].modules[module]
148 if type(module_name) ~= "string" then
149 error("Invalid format in manifest file (invalid data for "..tostring(name).." "..tostring(version)..")")
150 end
119 module_name = filter_module_name(module_name, name, version, tree.tree, i) 151 module_name = filter_module_name(module_name, name, version, tree.tree, i)
120 if context[name] == version then 152 if context[name] == version then
121 return name, version, module_name 153 return name, version, module_name
@@ -133,6 +165,12 @@ local function select_module(module, filter_module_name)
133 end 165 end
134end 166end
135 167
168--- Search for a module
169-- @param module string: module name (eg. "socket.core")
170-- @return string, string, string: name of the rock containing the module
171-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
172-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
173-- stored versioned).
136local function pick_module(module) 174local function pick_module(module)
137 return 175 return
138 select_module(module, function(module_name, name, version, tree, i) 176 select_module(module, function(module_name, name, version, tree, i)
@@ -144,6 +182,11 @@ local function pick_module(module)
144 end) 182 end)
145end 183end
146 184
185--- Return the pathname of the file that would be loaded for a module.
186-- @param module string: module name (eg. "socket.core")
187-- @return string, string, string: name of the rock containing the module
188-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
189-- filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
147function which(module) 190function which(module)
148 local name, version, module_name = 191 local name, version, module_name =
149 select_module(module, function(module_name, name, version, tree, i) 192 select_module(module, function(module_name, name, version, tree, i)
@@ -172,7 +215,6 @@ end
172-- @return table: The module table (typically), like in plain 215-- @return table: The module table (typically), like in plain
173-- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a> 216-- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a>
174-- in the Lua reference manual for details. 217-- in the Lua reference manual for details.
175
176function luarocks_loader(module) 218function luarocks_loader(module)
177 local name, version, module_name = pick_module(module) 219 local name, version, module_name = pick_module(module)
178 if not name then 220 if not name then
diff --git a/src/luarocks/make.lua b/src/luarocks/make.lua
index 4af5a16c..769db2f7 100644
--- a/src/luarocks/make.lua
+++ b/src/luarocks/make.lua
@@ -9,9 +9,11 @@ local build = require("luarocks.build")
9local fs = require("luarocks.fs") 9local fs = require("luarocks.fs")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11local cfg = require("luarocks.cfg") 11local cfg = require("luarocks.cfg")
12local fetch = require("luarocks.fetch")
13local pack = require("luarocks.pack")
12 14
13help_summary = "Compile package in current directory using a rockspec." 15help_summary = "Compile package in current directory using a rockspec."
14help_arguments = "[<rockspec>]" 16help_arguments = "[--pack-binary-rock] [<rockspec>]"
15help = [[ 17help = [[
16Builds sources in the current directory, but unlike "build", 18Builds sources in the current directory, but unlike "build",
17it does not fetch sources, etc., assuming everything is 19it does not fetch sources, etc., assuming everything is
@@ -22,6 +24,10 @@ is found, you must specify which to use, through the command-line.
22This command is useful as a tool for debugging rockspecs. 24This command is useful as a tool for debugging rockspecs.
23To install rocks, you'll normally want to use the "install" and 25To install rocks, you'll normally want to use the "install" and
24"build" commands. See the help on those for details. 26"build" commands. See the help on those for details.
27
28If --pack-binary-rock is passed, the rock is not installed;
29instead, a .rock file with the contents of compilation is produced
30in the current directory.
25]] 31]]
26 32
27--- Driver function for "make" command. 33--- Driver function for "make" command.
@@ -31,9 +37,6 @@ To install rocks, you'll normally want to use the "install" and
31function run(...) 37function run(...)
32 local flags, rockspec = util.parse_flags(...) 38 local flags, rockspec = util.parse_flags(...)
33 assert(type(rockspec) == "string" or not rockspec) 39 assert(type(rockspec) == "string" or not rockspec)
34
35 local ok, err = fs.check_command_permissions(flags)
36 if not ok then return nil, err end
37 40
38 if not rockspec then 41 if not rockspec then
39 local files = fs.list_dir(fs.current_dir()) 42 local files = fs.list_dir(fs.current_dir())
@@ -54,5 +57,15 @@ function run(...)
54 return nil, "Invalid argument: 'make' takes a rockspec as a parameter. See help." 57 return nil, "Invalid argument: 'make' takes a rockspec as a parameter. See help."
55 end 58 end
56 59
57 return build.build_rockspec(rockspec, false, true) 60 if flags["pack-binary-rock"] then
61 local rspec, err, errcode = fetch.load_rockspec(rockspec)
62 if not rspec then
63 return nil, err
64 end
65 return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, flags["nodeps"])
66 else
67 local ok, err = fs.check_command_permissions(flags)
68 if not ok then return nil, err end
69 return build.build_rockspec(rockspec, false, true)
70 end
58end 71end
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua
index 8ce555d8..60b0c1df 100644
--- a/src/luarocks/manif.lua
+++ b/src/luarocks/manif.lua
@@ -1,4 +1,8 @@
1 1
2--- Module for handling manifest files and tables.
3-- Manifest files describe the contents of a LuaRocks tree or server.
4-- They are loaded into manifest tables, which are then used for
5-- performing searches, matching dependencies, etc.
2module("luarocks.manif", package.seeall) 6module("luarocks.manif", package.seeall)
3 7
4local manif_core = require("luarocks.manif_core") 8local manif_core = require("luarocks.manif_core")
@@ -94,7 +98,7 @@ function load_manifest(repo_url)
94 local name = repo_url:gsub("[/:]","_") 98 local name = repo_url:gsub("[/:]","_")
95 local file, err, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-manifest-"..name) 99 local file, err, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-manifest-"..name)
96 if not file then 100 if not file then
97 return nil, "Failed fetching manifest for "..repo_url, errcode 101 return nil, "Failed fetching manifest for "..repo_url..(err and " - "..err or ""), errcode
98 end 102 end
99 pathname = file 103 pathname = file
100 end 104 end
@@ -172,12 +176,11 @@ local function sort_package_matching_table(tbl)
172 end 176 end
173end 177end
174 178
175--- Process the dependencies of a package to determine its dependency 179--- Process the dependencies of a manifest table to determine its dependency
176-- chain for loading modules. 180-- chains for loading modules. The manifest dependencies information is filled
177-- @param name string: Package name. 181-- and any dependency inconsistencies or missing dependencies are reported to
178-- @param version string: Package version. 182-- standard error.
179-- @return (table, table): A table listing dependencies as string-string pairs 183-- @param manifest table: a manifest table.
180-- of names and versions, and a similar table of missing dependencies.
181local function update_dependencies(manifest) 184local function update_dependencies(manifest)
182 for pkg, versions in pairs(manifest.repository) do 185 for pkg, versions in pairs(manifest.repository) do
183 for version, repos in pairs(versions) do 186 for version, repos in pairs(versions) do
@@ -188,9 +191,9 @@ local function update_dependencies(manifest)
188 repo.dependencies, missing = deps.scan_deps({}, {}, manifest, pkg, version) 191 repo.dependencies, missing = deps.scan_deps({}, {}, manifest, pkg, version)
189 repo.dependencies[pkg] = nil 192 repo.dependencies[pkg] = nil
190 if missing then 193 if missing then
191 for miss, _ in pairs(missing) do 194 for miss, err in pairs(missing) do
192 if miss == current then 195 if miss == current then
193 util.printerr("Tree inconsistency detected: "..current.." has no rockspec.") 196 util.printerr("Tree inconsistency detected: "..current.." has no rockspec. "..err)
194 else 197 else
195 util.printerr("Missing dependency for "..pkg.." "..version..": "..miss) 198 util.printerr("Missing dependency for "..pkg.." "..version..": "..miss)
196 end 199 end
@@ -205,6 +208,8 @@ end
205--- Store search results in a manifest table. 208--- Store search results in a manifest table.
206-- @param results table: The search results as returned by search.disk_search. 209-- @param results table: The search results as returned by search.disk_search.
207-- @param manifest table: A manifest table (must contain repository, modules, commands tables). 210-- @param manifest table: A manifest table (must contain repository, modules, commands tables).
211-- It will be altered to include the search results.
212-- @return boolean or (nil, string): true in case of success, or nil followed by an error message.
208local function store_results(results, manifest) 213local function store_results(results, manifest)
209 assert(type(results) == "table") 214 assert(type(results) == "table")
210 assert(type(manifest) == "table") 215 assert(type(manifest) == "table")
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua
index 2e1a9518..40f16898 100644
--- a/src/luarocks/manif_core.lua
+++ b/src/luarocks/manif_core.lua
@@ -15,6 +15,7 @@ manifest_cache = {}
15-- and stores it in the manifest cache. 15-- and stores it in the manifest cache.
16-- @param file string: The local filename of the manifest file. 16-- @param file string: The local filename of the manifest file.
17-- @param repo_url string: The repository identifier. 17-- @param repo_url string: The repository identifier.
18-- @param quick boolean: If given, skips type checking.
18function manifest_loader(file, repo_url, quick) 19function manifest_loader(file, repo_url, quick)
19 local manifest, err = persist.load_into_table(file) 20 local manifest, err = persist.load_into_table(file)
20 if not manifest then 21 if not manifest then
diff --git a/src/luarocks/new_version.lua b/src/luarocks/new_version.lua
new file mode 100644
index 00000000..b453704f
--- /dev/null
+++ b/src/luarocks/new_version.lua
@@ -0,0 +1,141 @@
1
2--- Module implementing the LuaRocks "new_version" command.
3-- Utility function that writes a new rockspec, updating data from a previous one.
4module("luarocks.new_version", package.seeall)
5
6local util = require("luarocks.util")
7local cfg = require("luarocks.cfg")
8local download = require("luarocks.download")
9local fetch = require("luarocks.fetch")
10local persist = require("luarocks.persist")
11local dir = require("luarocks.dir")
12local fs = require("luarocks.fs")
13
14help_summary = "Auto-write a rockspec for a new version of a rock."
15help_arguments = "{<program>|<rockspec>} [<new_version>] [<new_url>]"
16help = [[
17This is a utility function that writes a new rockspec, updating data
18from a previous one.
19
20If a package name is given, it downloads the latest rockspec from the
21default server. If a rockspec is given, it uses it instead.
22
23If the version number is not given, it only increments the revision
24number of the given (or downloaded) rockspec.
25
26If a URL is given, it replaces the one from the old rockspec with the
27given URL. If a URL is not given and a new version is given, it tries
28to guess the new URL by replacing occurrences of the version number
29in the URL or tag. It also tries to download the new URL to determine
30the new MD5 checksum.
31
32WARNING: it writes the new rockspec to the current directory,
33overwriting the file if it already exists.
34]]
35
36local order = {"rockspec_format", "package", "version",
37 { "source", { "url", "tag", "branch", "md5" } },
38 { "description", {"summary", "detailed", "homepage", "license" } },
39 "supported_platforms", "dependencies", "external_dependencies",
40 { "build", {"type", "modules", "copy_directories", "platforms"} },
41 "hooks"}
42
43local function try_replace(tbl, field, old, new)
44 if not tbl[field] then
45 return false
46 end
47 local old_field = tbl[field]
48 local new_field = tbl[field]:gsub(old, new)
49 if new_field ~= old_field then
50 util.printout("Guessing new '"..field.."' field as "..new_field)
51 tbl[field] = new_field
52 return true
53 end
54 return false
55end
56
57local function check_url_and_update_md5(out_rs, out_name)
58 out_rs.source.md5 = nil
59 local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_name)
60 if file then
61 util.printout("File successfully downloaded. Updating MD5 checksum...")
62 out_rs.source.md5 = fs.get_md5(file)
63 else
64 util.printerr("Warning: invalid URL - "..temp_dir)
65 end
66end
67
68function run(...)
69 local flags, input, version, url = util.parse_flags(...)
70 if not input then
71 return nil, "Missing arguments: expected program or rockspec. See help."
72 end
73 assert(type(input) == "string")
74
75 local filename = input
76 if not input:match(".rockspec$") then
77 local err
78 filename, err = download.download("rockspec", input)
79 if not input then
80 return nil, err
81 end
82 end
83
84 local valid_rs, err = fetch.load_rockspec(filename)
85 if not valid_rs then
86 return nil, err
87 end
88
89 local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$")
90 local new_ver, new_rev
91
92 if version then
93 new_ver, new_rev = version:match("(.*)%-(%d+)$")
94 new_rev = tonumber(new_rev)
95 if not new_rev then
96 new_ver = version
97 new_rev = 1
98 end
99 else
100 new_ver = old_ver
101 new_rev = tonumber(old_rev) + 1
102 end
103
104
105 local out_rs = persist.load_into_table(filename)
106 local out_name = out_rs.package:lower()
107 out_rs.version = new_ver.."-"..new_rev
108 if url then
109 out_rs.source.url = url
110 check_url_and_update_md5(out_rs, out_name)
111 else
112 if new_ver ~= old_ver then
113 local ok = try_replace(out_rs.source, "url", old_ver, new_ver)
114 if ok then
115 check_url_and_update_md5(out_rs, out_name)
116 else
117 ok = try_replace(out_rs.source, "tag", old_ver, new_ver)
118 if not ok then
119 return nil, "Failed to determine the location of the new version."
120 end
121 end
122 end
123 end
124
125 if out_rs.build and out_rs.build.type == "module" then
126 out_rs.build.type = "builtin"
127 end
128
129 local out_filename = out_name.."-"..new_ver.."-"..new_rev..".rockspec"
130
131 persist.save_from_table(out_filename, out_rs, order)
132
133 util.printout("Wrote "..out_filename)
134
135 local valid_out_rs, err = fetch.load_local_rockspec(out_filename)
136 if not valid_out_rs then
137 return nil, "Failed loading generated rockspec: "..err
138 end
139
140 return true
141end
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua
index b85b7460..f7a7ad12 100644
--- a/src/luarocks/pack.lua
+++ b/src/luarocks/pack.lua
@@ -80,16 +80,16 @@ end
80-- @param version string or nil: A version number may also be passed. 80-- @param version string or nil: A version number may also be passed.
81-- @return string or (nil, string): The filename of the resulting 81-- @return string or (nil, string): The filename of the resulting
82-- .src.rock file; or nil and an error message. 82-- .src.rock file; or nil and an error message.
83function pack_binary_rock(name, version) 83local function do_pack_binary_rock(name, version)
84 assert(type(name) == "string") 84 assert(type(name) == "string")
85 assert(type(version) == "string" or not version) 85 assert(type(version) == "string" or not version)
86 86
87 local query = search.make_query(name, version) 87 local query = search.make_query(name, version)
88 query.exact_name = true 88 query.exact_name = true
89 local results = {} 89 local results = {}
90 for _, tree in ipairs(cfg.rocks_trees) do 90
91 search.manifest_search(results, path.rocks_dir(tree), query) 91 search.manifest_search(results, cfg.rocks_dir, query)
92 end 92
93 if not next(results) then 93 if not next(results) then
94 return nil, "'"..name.."' does not seem to be an installed rock." 94 return nil, "'"..name.."' does not seem to be an installed rock."
95 end 95 end
@@ -149,6 +149,33 @@ function pack_binary_rock(name, version)
149 return rock_file 149 return rock_file
150end 150end
151 151
152function pack_binary_rock(name, version, cmd, ...)
153
154 -- The --pack-binary-rock option for "luarocks build" basically performs
155 -- "luarocks build" on a temporary tree and then "luarocks pack". The
156 -- alternative would require refactoring parts of luarocks.build and
157 -- luarocks.pack, which would save a few file operations: the idea would be
158 -- to shave off the final deploy steps from the build phase and the initial
159 -- collect steps from the pack phase.
160
161 local temp_dir = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
162 if not temp_dir then
163 return nil, "Failed creating temporary directory."
164 end
165 util.schedule_function(fs.delete, temp_dir)
166
167 path.use_tree(temp_dir)
168 local ok, err = cmd(...)
169 if not ok then
170 return nil, err
171 end
172 local rname, rversion = path.parse_name(name)
173 if not rname then
174 rname, rversion = name, version
175 end
176 return do_pack_binary_rock(rname, rversion)
177end
178
152--- Driver function for the "pack" command. 179--- Driver function for the "pack" command.
153-- @param arg string: may be a rockspec file, for creating a source rock, 180-- @param arg string: may be a rockspec file, for creating a source rock,
154-- or the name of an installed package, for creating a binary rock. 181-- or the name of an installed package, for creating a binary rock.
@@ -167,7 +194,7 @@ function run(...)
167 if arg:match(".*%.rockspec") then 194 if arg:match(".*%.rockspec") then
168 file, err = pack_source_rock(arg) 195 file, err = pack_source_rock(arg)
169 else 196 else
170 file, err = pack_binary_rock(arg, version) 197 file, err = do_pack_binary_rock(arg, version)
171 end 198 end
172 if err then 199 if err then
173 return nil, err 200 return nil, err
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua
index 8c795e8b..03ed1b90 100644
--- a/src/luarocks/path.lua
+++ b/src/luarocks/path.lua
@@ -1,5 +1,5 @@
1 1
2--- Path and filename handling functions. 2--- LuaRocks-specific path handling functions.
3-- All paths are configured in this module, making it a single 3-- All paths are configured in this module, making it a single
4-- point where the layout of the local installation is defined in LuaRocks. 4-- point where the layout of the local installation is defined in LuaRocks.
5module("luarocks.path", package.seeall) 5module("luarocks.path", package.seeall)
@@ -25,12 +25,12 @@ function rockspec_name_from_rock(rock_name)
25 return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec" 25 return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec"
26end 26end
27 27
28function rocks_dir(repo) 28function rocks_dir(tree)
29 if type(repo) == "string" then 29 if type(tree) == "string" then
30 return dir.path(repo, "lib", "luarocks", "rocks") 30 return dir.path(tree, "lib", "luarocks", "rocks")
31 else 31 else
32 assert(type(repo) == "table") 32 assert(type(tree) == "table")
33 return repo.rocks_dir or dir.path(repo.root, "lib", "luarocks", "rocks") 33 return tree.rocks_dir or dir.path(tree.root, "lib", "luarocks", "rocks")
34 end 34 end
35end 35end
36 36
@@ -41,156 +41,156 @@ function root_dir(rocks_dir)
41 return rocks_dir:match("(.*)" .. suffix .. "$") 41 return rocks_dir:match("(.*)" .. suffix .. "$")
42end 42end
43 43
44function deploy_bin_dir(repo) 44function deploy_bin_dir(tree)
45 if type(repo) == "string" then 45 if type(tree) == "string" then
46 return dir.path(repo, "bin") 46 return dir.path(tree, "bin")
47 else 47 else
48 assert(type(repo) == "table") 48 assert(type(tree) == "table")
49 return repo.bin_dir or dir.path(repo.root, "bin") 49 return tree.bin_dir or dir.path(tree.root, "bin")
50 end 50 end
51end 51end
52 52
53function deploy_lua_dir(repo) 53function deploy_lua_dir(tree)
54 if type(repo) == "string" then 54 if type(tree) == "string" then
55 return dir.path(repo, "share", "lua", "5.1") 55 return dir.path(tree, cfg.lua_modules_path)
56 else 56 else
57 assert(type(repo) == "table") 57 assert(type(tree) == "table")
58 return repo.lua_dir or dir.path(repo.root, "share", "lua", "5.1") 58 return tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path)
59 end 59 end
60end 60end
61 61
62function deploy_lib_dir(repo) 62function deploy_lib_dir(tree)
63 if type(repo) == "string" then 63 if type(tree) == "string" then
64 return dir.path(repo, "lib", "lua", "5.1") 64 return dir.path(tree, cfg.lib_modules_path)
65 else 65 else
66 assert(type(repo) == "table") 66 assert(type(tree) == "table")
67 return repo.lib_dir or dir.path(repo.root, "lib", "lua", "5.1") 67 return tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path)
68 end 68 end
69end 69end
70 70
71function manifest_file(repo) 71function manifest_file(tree)
72 if type(repo) == "string" then 72 if type(tree) == "string" then
73 return dir.path(repo, "lib", "luarocks", "rocks", "manifest") 73 return dir.path(tree, "lib", "luarocks", "rocks", "manifest")
74 else 74 else
75 assert(type(repo) == "table") 75 assert(type(tree) == "table")
76 return (repo.rocks_dir and dir.path(repo.rocks_dir, "manifest")) or dir.path(repo.root, "lib", "luarocks", "rocks", "manifest") 76 return (tree.rocks_dir and dir.path(tree.rocks_dir, "manifest")) or dir.path(tree.root, "lib", "luarocks", "rocks", "manifest")
77 end 77 end
78end 78end
79 79
80--- Get the repository directory for all versions of a package. 80--- Get the directory for all versions of a package in a tree.
81-- @param name string: The package name. 81-- @param name string: The package name.
82-- @return string: The resulting path -- does not guarantee that 82-- @return string: The resulting path -- does not guarantee that
83-- @param rocks_dir string or nil: If given, specifies the local repository to use. 83-- @param tree string or nil: If given, specifies the local tree to use.
84-- the package (and by extension, the path) exists. 84-- the package (and by extension, the path) exists.
85function versions_dir(name, repo) 85function versions_dir(name, tree)
86 assert(type(name) == "string") 86 assert(type(name) == "string")
87 repo = repo or cfg.root_dir 87 tree = tree or cfg.root_dir
88 return dir.path(rocks_dir(repo), name) 88 return dir.path(rocks_dir(tree), name)
89end 89end
90 90
91--- Get the local installation directory (prefix) for a package. 91--- Get the local installation directory (prefix) for a package.
92-- @param name string: The package name. 92-- @param name string: The package name.
93-- @param version string: The package version. 93-- @param version string: The package version.
94-- @param rocks_dir string or nil: If given, specifies the local repository to use. 94-- @param tree string or nil: If given, specifies the local tree to use.
95-- @return string: The resulting path -- does not guarantee that 95-- @return string: The resulting path -- does not guarantee that
96-- the package (and by extension, the path) exists. 96-- the package (and by extension, the path) exists.
97function install_dir(name, version, repo) 97function install_dir(name, version, tree)
98 assert(type(name) == "string") 98 assert(type(name) == "string")
99 assert(type(version) == "string") 99 assert(type(version) == "string")
100 repo = repo or cfg.root_dir 100 tree = tree or cfg.root_dir
101 return dir.path(rocks_dir(repo), name, version) 101 return dir.path(rocks_dir(tree), name, version)
102end 102end
103 103
104--- Get the local filename of the rockspec of an installed rock. 104--- Get the local filename of the rockspec of an installed rock.
105-- @param name string: The package name. 105-- @param name string: The package name.
106-- @param version string: The package version. 106-- @param version string: The package version.
107-- @param rocks_dir string or nil: If given, specifies the local repository to use. 107-- @param tree string or nil: If given, specifies the local tree to use.
108-- @return string: The resulting path -- does not guarantee that 108-- @return string: The resulting path -- does not guarantee that
109-- the package (and by extension, the file) exists. 109-- the package (and by extension, the file) exists.
110function rockspec_file(name, version, repo) 110function rockspec_file(name, version, tree)
111 assert(type(name) == "string") 111 assert(type(name) == "string")
112 assert(type(version) == "string") 112 assert(type(version) == "string")
113 repo = repo or cfg.root_dir 113 tree = tree or cfg.root_dir
114 return dir.path(rocks_dir(repo), name, version, name.."-"..version..".rockspec") 114 return dir.path(rocks_dir(tree), name, version, name.."-"..version..".rockspec")
115end 115end
116 116
117--- Get the local filename of the rock_manifest file of an installed rock. 117--- Get the local filename of the rock_manifest file of an installed rock.
118-- @param name string: The package name. 118-- @param name string: The package name.
119-- @param version string: The package version. 119-- @param version string: The package version.
120-- @param rocks_dir string or nil: If given, specifies the local repository to use. 120-- @param tree string or nil: If given, specifies the local tree to use.
121-- @return string: The resulting path -- does not guarantee that 121-- @return string: The resulting path -- does not guarantee that
122-- the package (and by extension, the file) exists. 122-- the package (and by extension, the file) exists.
123function rock_manifest_file(name, version, repo) 123function rock_manifest_file(name, version, tree)
124 assert(type(name) == "string") 124 assert(type(name) == "string")
125 assert(type(version) == "string") 125 assert(type(version) == "string")
126 repo = repo or cfg.root_dir 126 tree = tree or cfg.root_dir
127 return dir.path(rocks_dir(repo), name, version, "rock_manifest") 127 return dir.path(rocks_dir(tree), name, version, "rock_manifest")
128end 128end
129 129
130--- Get the local installation directory for C libraries of a package. 130--- Get the local installation directory for C libraries of a package.
131-- @param name string: The package name. 131-- @param name string: The package name.
132-- @param version string: The package version. 132-- @param version string: The package version.
133-- @param rocks_dir string or nil: If given, specifies the local repository to use. 133-- @param tree string or nil: If given, specifies the local tree to use.
134-- @return string: The resulting path -- does not guarantee that 134-- @return string: The resulting path -- does not guarantee that
135-- the package (and by extension, the path) exists. 135-- the package (and by extension, the path) exists.
136function lib_dir(name, version, repo) 136function lib_dir(name, version, tree)
137 assert(type(name) == "string") 137 assert(type(name) == "string")
138 assert(type(version) == "string") 138 assert(type(version) == "string")
139 repo = repo or cfg.root_dir 139 tree = tree or cfg.root_dir
140 return dir.path(rocks_dir(repo), name, version, "lib") 140 return dir.path(rocks_dir(tree), name, version, "lib")
141end 141end
142 142
143--- Get the local installation directory for Lua modules of a package. 143--- Get the local installation directory for Lua modules of a package.
144-- @param name string: The package name. 144-- @param name string: The package name.
145-- @param version string: The package version. 145-- @param version string: The package version.
146-- @param rocks_dir string or nil: If given, specifies the local repository to use. 146-- @param tree string or nil: If given, specifies the local tree to use.
147-- @return string: The resulting path -- does not guarantee that 147-- @return string: The resulting path -- does not guarantee that
148-- the package (and by extension, the path) exists. 148-- the package (and by extension, the path) exists.
149function lua_dir(name, version, repo) 149function lua_dir(name, version, tree)
150 assert(type(name) == "string") 150 assert(type(name) == "string")
151 assert(type(version) == "string") 151 assert(type(version) == "string")
152 repo = repo or cfg.root_dir 152 tree = tree or cfg.root_dir
153 return dir.path(rocks_dir(repo), name, version, "lua") 153 return dir.path(rocks_dir(tree), name, version, "lua")
154end 154end
155 155
156--- Get the local installation directory for documentation of a package. 156--- Get the local installation directory for documentation of a package.
157-- @param name string: The package name. 157-- @param name string: The package name.
158-- @param version string: The package version. 158-- @param version string: The package version.
159-- @param rocks_dir string or nil: If given, specifies the local repository to use. 159-- @param tree string or nil: If given, specifies the local tree to use.
160-- @return string: The resulting path -- does not guarantee that 160-- @return string: The resulting path -- does not guarantee that
161-- the package (and by extension, the path) exists. 161-- the package (and by extension, the path) exists.
162function doc_dir(name, version, repo) 162function doc_dir(name, version, tree)
163 assert(type(name) == "string") 163 assert(type(name) == "string")
164 assert(type(version) == "string") 164 assert(type(version) == "string")
165 repo = repo or cfg.root_dir 165 tree = tree or cfg.root_dir
166 return dir.path(rocks_dir(repo), name, version, "doc") 166 return dir.path(rocks_dir(tree), name, version, "doc")
167end 167end
168 168
169--- Get the local installation directory for configuration files of a package. 169--- Get the local installation directory for configuration files of a package.
170-- @param name string: The package name. 170-- @param name string: The package name.
171-- @param version string: The package version. 171-- @param version string: The package version.
172-- @param rocks_dir string or nil: If given, specifies the local repository to use. 172-- @param tree string or nil: If given, specifies the local tree to use.
173-- @return string: The resulting path -- does not guarantee that 173-- @return string: The resulting path -- does not guarantee that
174-- the package (and by extension, the path) exists. 174-- the package (and by extension, the path) exists.
175function conf_dir(name, version, repo) 175function conf_dir(name, version, tree)
176 assert(type(name) == "string") 176 assert(type(name) == "string")
177 assert(type(version) == "string") 177 assert(type(version) == "string")
178 repo = repo or cfg.root_dir 178 tree = tree or cfg.root_dir
179 return dir.path(rocks_dir(repo), name, version, "conf") 179 return dir.path(rocks_dir(tree), name, version, "conf")
180end 180end
181 181
182--- Get the local installation directory for command-line scripts 182--- Get the local installation directory for command-line scripts
183-- of a package. 183-- of a package.
184-- @param name string: The package name. 184-- @param name string: The package name.
185-- @param version string: The package version. 185-- @param version string: The package version.
186-- @param rocks_dir string or nil: If given, specifies the local repository to use. 186-- @param tree string or nil: If given, specifies the local tree to use.
187-- @return string: The resulting path -- does not guarantee that 187-- @return string: The resulting path -- does not guarantee that
188-- the package (and by extension, the path) exists. 188-- the package (and by extension, the path) exists.
189function bin_dir(name, version, repo) 189function bin_dir(name, version, tree)
190 assert(type(name) == "string") 190 assert(type(name) == "string")
191 assert(type(version) == "string") 191 assert(type(version) == "string")
192 repo = repo or cfg.root_dir 192 tree = tree or cfg.root_dir
193 return dir.path(rocks_dir(repo), name, version, "bin") 193 return dir.path(rocks_dir(tree), name, version, "bin")
194end 194end
195 195
196--- Extract name, version and arch of a rock filename, 196--- Extract name, version and arch of a rock filename,
@@ -309,7 +309,7 @@ end
309-- @return boolean This function always succeeds. 309-- @return boolean This function always succeeds.
310function run(...) 310function run(...)
311 util.printout(cfg.export_lua_path:format(package.path)) 311 util.printout(cfg.export_lua_path:format(package.path))
312 util.printout(cfg.export_lua_cpath:format(package.path)) 312 util.printout(cfg.export_lua_cpath:format(package.cpath))
313 return true 313 return true
314end 314end
315 315
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua
index c809b51c..0d37b04a 100644
--- a/src/luarocks/persist.lua
+++ b/src/luarocks/persist.lua
@@ -18,37 +18,88 @@ function load_into_table(filename, tbl)
18 assert(type(filename) == "string") 18 assert(type(filename) == "string")
19 assert(type(tbl) == "table" or not tbl) 19 assert(type(tbl) == "table" or not tbl)
20 20
21 local chunk, err = loadfile(filename) 21 local result, chunk, ran, err
22 local result = tbl or {}
23 if setfenv then -- Lua 5.1
24 chunk, err = loadfile(filename)
25 if chunk then
26 setfenv(chunk, result)
27 ran, err = pcall(chunk)
28 end
29 else -- Lua 5.2
30 chunk, err = loadfile(filename, "t", result)
31 if chunk then
32 ran, err = pcall(chunk)
33 end
34 end
35
22 if not chunk then 36 if not chunk then
23 return nil, err 37 if err:sub(1,5) ~= filename:sub(1,5) then
38 return false, err
39 end
40 return nil, "Error loading file: "..err
41 end
42 if not ran then
43 return nil, "Error running file: "..err
24 end 44 end
25 local result = tbl or {}
26 setfenv(chunk, result)
27 chunk()
28 return result 45 return result
29end 46end
30 47
48local write_table
49
50--- Write a value as Lua code, invoking write_table.
51-- This function handles only numbers, strings and tables
52-- are keys (tables are handled recursively).
53-- @param out userdata: a file object, open for writing.
54-- @param v: the value to be written.
55-- @param level number: the indentation level
56-- @param sub_order table: optional prioritization table
57-- @see write_table
58local function write_value(out, v, level, sub_order)
59 if type(v) == "table" then
60 write_table(out, v, level + 1, sub_order)
61 elseif type(v) == "string" then
62 if v:match("\n") then
63 local open, close = "[[", "]]"
64 local equals = 0
65 while v:find(open,1,true) or v:find(close,1,true) do
66 equals = equals + 1
67 local eqs = ("="):rep(equals)
68 open, close = "["..eqs.."[", "]"..eqs.."]"
69 end
70 out:write(open.."\n"..v..close)
71 else
72 out:write("\""..v:gsub("\"", "\\\"").."\"")
73 end
74 else
75 out:write(tostring(v))
76 end
77end
78
31--- Write a table as Lua code representing a table to disk 79--- Write a table as Lua code representing a table to disk
32-- (that is, in curly brackets notation). 80-- (that is, in curly brackets notation).
33-- This function handles only numbers, strings and tables 81-- This function handles only numbers, strings and tables
34-- are keys (tables are handled recursively). 82-- are keys (tables are handled recursively).
35-- @param out userdata: a file object, open for writing. 83-- @param out userdata: a file object, open for writing.
36-- @param tbl table: the table to be written. 84-- @param tbl table: the table to be written.
37local function write_table(out, tbl, level) 85-- @param level number: the indentation level
86-- @param field_order table: optional prioritization table
87write_table = function(out, tbl, level, field_order)
38 out:write("{") 88 out:write("{")
39 local sep = "\n" 89 local sep = "\n"
90 local indentation = " "
40 local indent = true 91 local indent = true
41 local i = 1 92 local i = 1
42 for k, v in util.sortedpairs(tbl) do 93 for k, v, sub_order in util.sortedpairs(tbl, field_order) do
43 out:write(sep) 94 out:write(sep)
44 if indent then 95 if indent then
45 for n = 1,level do out:write(" ") end 96 for n = 1,level do out:write(indentation) end
46 end 97 end
47 sep = ",\n" 98 sep = ",\n"
48 indent = true 99 indent = true
49 if type(k) == "number" then 100 if type(k) == "number" then
50 if k ~= i then 101 if k ~= i then
51 out:write('['..tostring(k).."]=") 102 out:write("["..tostring(k).."]=")
52 else 103 else
53 i = i + 1 104 i = i + 1
54 end 105 end
@@ -57,25 +108,19 @@ local function write_table(out, tbl, level)
57 elseif type(k) == "table" then 108 elseif type(k) == "table" then
58 out:write("[") 109 out:write("[")
59 write_table(out, k, level + 1) 110 write_table(out, k, level + 1)
60 out:write("]=") 111 out:write("] = ")
61 else 112 else
62 if k:match("^[a-z_]+$") then 113 if k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
63 out:write(k.."=") 114 out:write(k.." = ")
64 else 115 else
65 out:write("['"..k:gsub("'", "\\'").."']=") 116 out:write("['"..k:gsub("'", "\\'").."'] = ")
66 end 117 end
67 end 118 end
68 if type(v) == "table" then 119 write_value(out, v, level, sub_order)
69 write_table(out, v, level + 1)
70 elseif type(v) == "string" then
71 out:write("'"..v:gsub("'", "\\'").."'")
72 else
73 out:write(tostring(v))
74 end
75 end 120 end
76 if sep ~= "\n" then 121 if sep ~= "\n" then
77 out:write("\n") 122 out:write("\n")
78 for n = 1,level-1 do out:write(" ") end 123 for n = 1,level-1 do out:write(indentation) end
79 end 124 end
80 out:write("}") 125 out:write("}")
81end 126end
@@ -84,16 +129,19 @@ end
84-- Each element of the table is saved as a global assignment. 129-- Each element of the table is saved as a global assignment.
85-- Only numbers, strings and tables (containing numbers, strings 130-- Only numbers, strings and tables (containing numbers, strings
86-- or other recursively processed tables) are supported. 131-- or other recursively processed tables) are supported.
132-- @param filename string: the output filename
133-- @param tbl table: the table containing the data to be written
134-- @param field_order table: an optional array indicating the order of top-level fields.
87-- @return boolean or (nil, string): true if successful, or nil and a 135-- @return boolean or (nil, string): true if successful, or nil and a
88-- message in case of errors. 136-- message in case of errors.
89function save_from_table(filename, tbl) 137function save_from_table(filename, tbl, field_order)
90 local out = io.open(filename, "w") 138 local out = io.open(filename, "w")
91 if not out then 139 if not out then
92 return nil, "Cannot create file at "..filename 140 return nil, "Cannot create file at "..filename
93 end 141 end
94 for k, v in util.sortedpairs(tbl) do 142 for k, v, sub_order in util.sortedpairs(tbl, field_order) do
95 out:write(k.." = ") 143 out:write(k.." = ")
96 write_table(out, v, 1) 144 write_value(out, v, 0, sub_order)
97 out:write("\n") 145 out:write("\n")
98 end 146 end
99 out:close() 147 out:close()
diff --git a/src/luarocks/refresh_cache.lua b/src/luarocks/refresh_cache.lua
index 23f86a13..80730375 100644
--- a/src/luarocks/refresh_cache.lua
+++ b/src/luarocks/refresh_cache.lua
@@ -1,4 +1,5 @@
1 1
2--- Module implementing the luarocks-admin "refresh_cache" command.
2module("luarocks.refresh_cache", package.seeall) 3module("luarocks.refresh_cache", package.seeall)
3 4
4local util = require("luarocks.util") 5local util = require("luarocks.util")
@@ -15,7 +16,7 @@ from the configuration file is used instead.
15 16
16function run(...) 17function run(...)
17 local flags = util.parse_flags(...) 18 local flags = util.parse_flags(...)
18 local server, upload_server = cache.get_upload_server(flags["from"]) 19 local server, upload_server = cache.get_upload_server(flags["server"])
19 if not server then return nil, upload_server end 20 if not server then return nil, upload_server end
20 local download_url = cache.get_server_urls(server, upload_server) 21 local download_url = cache.get_server_urls(server, upload_server)
21 22
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua
index caa683ee..b22d1ab6 100644
--- a/src/luarocks/remove.lua
+++ b/src/luarocks/remove.lua
@@ -82,11 +82,9 @@ function run(...)
82 if type(name) ~= "string" then 82 if type(name) ~= "string" then
83 return nil, "Argument missing, see help." 83 return nil, "Argument missing, see help."
84 end 84 end
85 85
86 if not flags["local"] and not fs.is_writable(cfg.rocks_dir) then 86 local ok, err = fs.check_command_permissions(flags)
87 return nil, "Your user does not have write permissions in " .. cfg.rocks_dir .. 87 if not ok then return nil, err end
88 " \n-- you may want to run as a privileged user or use your local tree with --local."
89 end
90 88
91 local results = {} 89 local results = {}
92 search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version)) 90 search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
diff --git a/src/luarocks/rep.lua b/src/luarocks/rep.lua
index 8bbc1b52..5bb5fed5 100644
--- a/src/luarocks/rep.lua
+++ b/src/luarocks/rep.lua
@@ -194,9 +194,22 @@ local function resolve_conflict(target, deploy_dir, name, version)
194 end 194 end
195end 195end
196 196
197function deploy_files(name, version) 197function should_wrap_bin_scripts(rockspec)
198 assert(type(rockspec) == "table")
199
200 if cfg.wrap_bin_scripts ~= nil then
201 return cfg.wrap_bin_scripts
202 end
203 if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
204 return false
205 end
206 return true
207end
208
209function deploy_files(name, version, wrap_bin_scripts)
198 assert(type(name) == "string") 210 assert(type(name) == "string")
199 assert(type(version) == "string") 211 assert(type(version) == "string")
212 assert(type(wrap_bin_scripts) == "boolean")
200 213
201 local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn) 214 local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn)
202 if not move_fn then 215 if not move_fn then
@@ -209,10 +222,13 @@ function deploy_files(name, version)
209 local ok, err 222 local ok, err
210 if fs.exists(target) then 223 if fs.exists(target) then
211 local new_target, err = resolve_conflict(target, deploy_dir, name, version) 224 local new_target, err = resolve_conflict(target, deploy_dir, name, version)
212 if err == "untracked" then 225 if err == "untracked" then
213 fs.delete(target) 226 fs.delete(target)
214 elseif err then return nil, err.." Cannot install new version." 227 elseif err then
215 else target = new_target end 228 return nil, err.." Cannot install new version."
229 else
230 target = new_target
231 end
216 end 232 end
217 fs.make_dir(dir.dir_name(target)) 233 fs.make_dir(dir.dir_name(target))
218 ok, err = move_fn(source, target) 234 ok, err = move_fn(source, target)
@@ -227,7 +243,8 @@ function deploy_files(name, version)
227 243
228 local ok, err = true 244 local ok, err = true
229 if rock_manifest.bin then 245 if rock_manifest.bin then
230 ok, err = deploy_file_tree(rock_manifest.bin, path.bin_dir(name, version), cfg.deploy_bin_dir, install_binary) 246 local move_bin_fn = wrap_bin_scripts and install_binary or fs.copy_binary
247 ok, err = deploy_file_tree(rock_manifest.bin, path.bin_dir(name, version), cfg.deploy_bin_dir, move_bin_fn)
231 end 248 end
232 if ok and rock_manifest.lua then 249 if ok and rock_manifest.lua then
233 ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir) 250 ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir)
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 127bba19..5df2bd38 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -331,10 +331,10 @@ end
331-- user possibilities if it couldn't narrow down a single match. 331-- user possibilities if it couldn't narrow down a single match.
332-- @param action function: A function that takes a .src.rock or 332-- @param action function: A function that takes a .src.rock or
333-- .rockspec URL as a parameter. 333-- .rockspec URL as a parameter.
334-- @string name string: A rock name 334-- @param name string: A rock name
335-- @string version string or nil: A version number may also be given. 335-- @param version string or nil: A version number may also be given.
336-- @return The result of the action function, or nil and an error message. 336-- @return The result of the action function, or nil and an error message.
337function act_on_src_or_rockspec(action, name, version) 337function act_on_src_or_rockspec(action, name, version, ...)
338 assert(type(action) == "function") 338 assert(type(action) == "function")
339 assert(type(name) == "string") 339 assert(type(name) == "string")
340 assert(type(version) == "string" or not version) 340 assert(type(version) == "string" or not version)
@@ -343,7 +343,7 @@ function act_on_src_or_rockspec(action, name, version)
343 query.arch = "src|rockspec" 343 query.arch = "src|rockspec"
344 local results, err = find_suitable_rock(query) 344 local results, err = find_suitable_rock(query)
345 if type(results) == "string" then 345 if type(results) == "string" then
346 return action(results) 346 return action(results, ...)
347 elseif type(results) == "table" and next(results) then 347 elseif type(results) == "table" and next(results) then
348 util.printout("Multiple search results were returned.") 348 util.printout("Multiple search results were returned.")
349 util.printout() 349 util.printout()
diff --git a/src/luarocks/show.lua b/src/luarocks/show.lua
index f968bec8..7255ea63 100644
--- a/src/luarocks/show.lua
+++ b/src/luarocks/show.lua
@@ -94,7 +94,7 @@ function run(...)
94 local rockspec, err = fetch.load_local_rockspec(rockspec_file) 94 local rockspec, err = fetch.load_local_rockspec(rockspec_file)
95 if not rockspec then return nil,err end 95 if not rockspec then return nil,err end
96 96
97 local descript = rockspec.description 97 local descript = rockspec.description or {}
98 local manifest, err = manif.load_manifest(repo_url) 98 local manifest, err = manif.load_manifest(repo_url)
99 if not manifest then return nil,err end 99 if not manifest then return nil,err end
100 local minfo = manifest.repository[name][version][1] 100 local minfo = manifest.repository[name][version][1]
@@ -108,7 +108,7 @@ function run(...)
108 elseif flags["mversion"] then util.printout(version) 108 elseif flags["mversion"] then util.printout(version)
109 else 109 else
110 util.printout() 110 util.printout()
111 util.printout(rockspec.package.." "..rockspec.version.." - "..descript.summary) 111 util.printout(rockspec.package.." "..rockspec.version.." - "..(descript.summary or ""))
112 util.printout() 112 util.printout()
113 if descript.detailed then 113 if descript.detailed then
114 util.printout(format_text(descript.detailed)) 114 util.printout(format_text(descript.detailed))
diff --git a/src/luarocks/tools/patch.lua b/src/luarocks/tools/patch.lua
index a2b76954..9a89aa48 100644
--- a/src/luarocks/tools/patch.lua
+++ b/src/luarocks/tools/patch.lua
@@ -1,4 +1,4 @@
1--- Patch utility to apply unified diffs 1--- Patch utility to apply unified diffs.
2-- 2--
3-- http://lua-users.org/wiki/LuaPatch 3-- http://lua-users.org/wiki/LuaPatch
4-- 4--
diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.lua
index e47172fa..ba01a413 100644
--- a/src/luarocks/tools/tar.lua
+++ b/src/luarocks/tools/tar.lua
@@ -1,4 +1,5 @@
1 1
2--- A pure-Lua implementation of untar (unpacking .tar archives)
2module("luarocks.tools.tar", package.seeall) 3module("luarocks.tools.tar", package.seeall)
3 4
4local fs = require("luarocks.fs") 5local fs = require("luarocks.fs")
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua
index 19f6af85..35428d91 100644
--- a/src/luarocks/tools/zip.lua
+++ b/src/luarocks/tools/zip.lua
@@ -1,4 +1,6 @@
1 1
2--- A Lua implementation of .zip file archiving (used for creating .rock files),
3-- using only lua-zlib.
2module("luarocks.tools.zip", package.seeall) 4module("luarocks.tools.zip", package.seeall)
3 5
4local zlib = require("zlib") 6local zlib = require("zlib")
@@ -107,7 +109,7 @@ local function zipwriter_add(self, file)
107 if not ok then 109 if not ok then
108 err = "error in opening "..file.." in zipfile" 110 err = "error in opening "..file.." in zipfile"
109 else 111 else
110 fin = io.open(file, "rb") 112 fin = io.open(fs.absolute_name(file), "rb")
111 if not fin then 113 if not fin then
112 ok = false 114 ok = false
113 err = "error opening "..file.." for reading" 115 err = "error opening "..file.." for reading"
@@ -190,7 +192,7 @@ function new_zipwriter(name)
190 192
191 local zw = {} 193 local zw = {}
192 194
193 zw.ziphandle = io.open(name, "wb") 195 zw.ziphandle = io.open(fs.absolute_name(name), "wb")
194 if not zw.ziphandle then 196 if not zw.ziphandle then
195 return nil 197 return nil
196 end 198 end
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua
index 0e4a73af..282198f6 100644
--- a/src/luarocks/type_check.lua
+++ b/src/luarocks/type_check.lua
@@ -4,12 +4,14 @@
4-- loaded by LuaRocks. 4-- loaded by LuaRocks.
5module("luarocks.type_check", package.seeall) 5module("luarocks.type_check", package.seeall)
6 6
7local cfg = require("luarocks.cfg")
8
7rockspec_format = "1.0" 9rockspec_format = "1.0"
8 10
9rockspec_types = { 11rockspec_types = {
10 rockspec_format = "string", 12 rockspec_format = "string",
11 MUST_package = "string", 13 MUST_package = "string",
12 MUST_version = "string", 14 MUST_version = "[%w.]+-[%d]+",
13 description = { 15 description = {
14 summary = "string", 16 summary = "string",
15 detailed = "string", 17 detailed = "string",
@@ -72,6 +74,17 @@ rockspec_types = {
72 } 74 }
73} 75}
74 76
77function load_extensions()
78 rockspec_format = "1.1"
79 rockspec_types.deploy = {
80 wrap_bin_scripts = true,
81 }
82end
83
84if cfg.use_extensions then
85 load_extensions()
86end
87
75rockspec_types.build.platforms.ANY = rockspec_types.build 88rockspec_types.build.platforms.ANY = rockspec_types.build
76rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies 89rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies
77rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies 90rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies
@@ -143,6 +156,9 @@ local type_check_table
143-- @param item any: The object being checked. 156-- @param item any: The object being checked.
144-- @param expected any: The reference object. In case of a table, 157-- @param expected any: The reference object. In case of a table,
145-- its is structured as a type reference table. 158-- its is structured as a type reference table.
159-- @param context string: A string indicating the "context" where the
160-- error occurred (such as the name of the table the item is a part of),
161-- to be used by error messages.
146-- @return boolean or (nil, string): true if type checking 162-- @return boolean or (nil, string): true if type checking
147-- succeeded, or nil and an error message if it failed. 163-- succeeded, or nil and an error message if it failed.
148-- @see type_check_table 164-- @see type_check_table
@@ -155,6 +171,15 @@ local function type_check_item(name, item, expected, context)
155 if not tonumber(item) then 171 if not tonumber(item) then
156 return nil, "Type mismatch on field "..context..name..": expected a number" 172 return nil, "Type mismatch on field "..context..name..": expected a number"
157 end 173 end
174 elseif expected_type == "string" then
175 if not tostring(item) then
176 return nil, "Type mismatch on field "..context..name..": expected a value convertible to string"
177 end
178 if expected ~= "string" then
179 if not item:match("^"..expected.."$") then
180 return nil, "Type mismatch on field "..context..name..": invalid value "..item
181 end
182 end
158 elseif expected_type == "table" then 183 elseif expected_type == "table" then
159 if item_type ~= expected_type then 184 if item_type ~= expected_type then
160 return nil, "Type mismatch on field "..context..name..": expected a table" 185 return nil, "Type mismatch on field "..context..name..": expected a table"
@@ -183,6 +208,9 @@ end
183-- @param tbl table: The table to be type checked. 208-- @param tbl table: The table to be type checked.
184-- @param types table: The reference table, containing 209-- @param types table: The reference table, containing
185-- values for recognized fields in the checked table. 210-- values for recognized fields in the checked table.
211-- @param context string: A string indicating the "context" where the
212-- error occurred (such as the name of the table the item is a part of),
213-- to be used by error messages.
186-- @return boolean or (nil, string): true if type checking 214-- @return boolean or (nil, string): true if type checking
187-- succeeded, or nil and an error message if it failed. 215-- succeeded, or nil and an error message if it failed.
188type_check_table = function(tbl, types, context) 216type_check_table = function(tbl, types, context)
@@ -196,7 +224,9 @@ type_check_table = function(tbl, types, context)
196 elseif types.MORE then 224 elseif types.MORE then
197 -- Accept unknown field 225 -- Accept unknown field
198 else 226 else
199 return nil, "Unknown field "..k 227 if not cfg.accept_unknown_fields then
228 return nil, "Unknown field "..k
229 end
200 end 230 end
201 end 231 end
202 for k, v in pairs(types) do 232 for k, v in pairs(types) do
@@ -218,6 +248,10 @@ end
218-- succeeded, or nil and an error message if it failed. 248-- succeeded, or nil and an error message if it failed.
219function type_check_rockspec(rockspec) 249function type_check_rockspec(rockspec)
220 assert(type(rockspec) == "table") 250 assert(type(rockspec) == "table")
251 if rockspec.rockspec_format then
252 -- relies on global state
253 load_extensions()
254 end
221 return type_check_table(rockspec, rockspec_types, "") 255 return type_check_table(rockspec, rockspec_types, "")
222end 256end
223 257
diff --git a/src/luarocks/unpack.lua b/src/luarocks/unpack.lua
index dacafa31..6ea7353d 100644
--- a/src/luarocks/unpack.lua
+++ b/src/luarocks/unpack.lua
@@ -45,6 +45,8 @@ end
45--- Load a .rock file to the given directory and unpack it inside it. 45--- Load a .rock file to the given directory and unpack it inside it.
46-- @param rock_file string: The URL for a .rock file. 46-- @param rock_file string: The URL for a .rock file.
47-- @param dir_name string: The directory where to unpack. 47-- @param dir_name string: The directory where to unpack.
48-- @param kind string: the kind of rock file, as in the second-level
49-- extension in the rock filename (eg. "src", "all", "linux-x86")
48-- @return table or (nil, string): the loaded rockspec table or 50-- @return table or (nil, string): the loaded rockspec table or
49-- nil and an error message. 51-- nil and an error message.
50local function unpack_rock(rock_file, dir_name, kind) 52local function unpack_rock(rock_file, dir_name, kind)
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index 562953d9..2955be50 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -1,10 +1,11 @@
1 1
2local global_env = _G 2--- Assorted utilities for managing tables, plus a scheduler for rollback functions.
3
4--- Utility functions shared by other modules.
5-- Does not requires modules directly (only as locals 3-- Does not requires modules directly (only as locals
6-- inside specific functions) to avoid interdependencies, 4-- inside specific functions) to avoid interdependencies,
7-- as this is used in the bootstrapping stage of luarocks.cfg. 5-- as this is used in the bootstrapping stage of luarocks.cfg.
6
7local global_env = _G
8
8module("luarocks.util", package.seeall) 9module("luarocks.util", package.seeall)
9 10
10local scheduled_functions = {} 11local scheduled_functions = {}
@@ -26,7 +27,7 @@ end
26 27
27--- Unschedule a function. 28--- Unschedule a function.
28-- This is useful for cancelling a rollback of a completed operation. 29-- This is useful for cancelling a rollback of a completed operation.
29-- @param table: The token representing the scheduled function that was 30-- @param item table: The token representing the scheduled function that was
30-- returned from the schedule_function call. 31-- returned from the schedule_function call.
31function remove_scheduled_function(item) 32function remove_scheduled_function(item)
32 for k, v in pairs(scheduled_functions) do 33 for k, v in pairs(scheduled_functions) do
@@ -84,7 +85,11 @@ function deep_merge(dst, src)
84 if not dst[k] then 85 if not dst[k] then
85 dst[k] = {} 86 dst[k] = {}
86 end 87 end
87 deep_merge(dst[k], v) 88 if type(dst[k]) == "table" then
89 deep_merge(dst[k], v)
90 else
91 dst[k] = v
92 end
88 else 93 else
89 dst[k] = v 94 dst[k] = v
90 end 95 end
@@ -231,17 +236,42 @@ end
231-- @see sortedpairs 236-- @see sortedpairs
232local function sortedpairs_iterator(tbl, sort_function) 237local function sortedpairs_iterator(tbl, sort_function)
233 local ks = keys(tbl) 238 local ks = keys(tbl)
234 table.sort(ks, sort_function or default_sort) 239 if not sort_function or type(sort_function) == "function" then
235 for _, k in ipairs(ks) do 240 table.sort(ks, sort_function or default_sort)
236 coroutine.yield(k, tbl[k]) 241 for _, k in ipairs(ks) do
242 coroutine.yield(k, tbl[k])
243 end
244 else
245 local order = sort_function
246 local done = {}
247 for _, k in ipairs(order) do
248 local sub_order
249 if type(k) == "table" then
250 sub_order = k[2]
251 k = k[1]
252 end
253 if tbl[k] then
254 done[k] = true
255 coroutine.yield(k, tbl[k], sub_order)
256 end
257 end
258 table.sort(ks, default_sort)
259 for _, k in ipairs(ks) do
260 if not done[k] then
261 coroutine.yield(k, tbl[k])
262 end
263 end
237 end 264 end
238end 265end
239 266
240--- A table iterator generator that returns elements sorted by key, 267--- A table iterator generator that returns elements sorted by key,
241-- to be used in "for" loops. 268-- to be used in "for" loops.
242-- @param tbl table: The table to be iterated. 269-- @param tbl table: The table to be iterated.
243-- @param sort_function function or nil: An optional comparison function 270-- @param sort_function function or table or nil: An optional comparison function
244-- to be used by table.sort when sorting keys. 271-- to be used by table.sort when sorting keys, or an array listing an explicit order
272-- for keys. If a value itself is an array, it is taken so that the first element
273-- is a string representing the field name, and the second element is a priority table
274-- for that key.
245-- @return function: the iterator function. 275-- @return function: the iterator function.
246function sortedpairs(tbl, sort_function) 276function sortedpairs(tbl, sort_function)
247 return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end) 277 return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end)
@@ -283,7 +313,7 @@ function split_string(str, delim, maxNb)
283 local pat = "(.-)" .. delim .. "()" 313 local pat = "(.-)" .. delim .. "()"
284 local nb = 0 314 local nb = 0
285 local lastPos 315 local lastPos
286 for part, pos in string.gfind(str, pat) do 316 for part, pos in string.gmatch(str, pat) do
287 nb = nb + 1 317 nb = nb + 1
288 result[nb] = part 318 result[nb] = part
289 lastPos = pos 319 lastPos = pos
diff --git a/src/luarocks/validate.lua b/src/luarocks/validate.lua
index fbffadc7..03e90ecf 100644
--- a/src/luarocks/validate.lua
+++ b/src/luarocks/validate.lua
@@ -1,4 +1,5 @@
1 1
2--- Sandboxed test of build/install of all packages in a repository (unfinished and disabled).
2module("luarocks.validate", package.seeall) 3module("luarocks.validate", package.seeall)
3 4
4local fs = require("luarocks.fs") 5local fs = require("luarocks.fs")