diff options
author | Hisham <hisham@gobolinux.org> | 2016-05-25 01:24:58 -0300 |
---|---|---|
committer | Hisham <hisham@gobolinux.org> | 2016-05-25 01:24:58 -0300 |
commit | 4c12525d1f52bccc71c2a3054d3db328a0577179 (patch) | |
tree | 899bca39ac9f2692419a0271306d2f326917e0d7 | |
parent | 6217339cd4ba6d7ee7f08aa86443032ede033752 (diff) | |
parent | a3650d51e96aef84657cb29e5f52e570fed828c9 (diff) | |
download | luarocks-4c12525d1f52bccc71c2a3054d3db328a0577179.tar.gz luarocks-4c12525d1f52bccc71c2a3054d3db328a0577179.tar.bz2 luarocks-4c12525d1f52bccc71c2a3054d3db328a0577179.zip |
Merge branch 'master' of https://github.com/keplerproject/luarocks
-rw-r--r-- | Makefile.setup.inc | 2 | ||||
-rw-r--r-- | src/luarocks/build.lua | 10 | ||||
-rw-r--r-- | src/luarocks/deps.lua | 128 | ||||
-rw-r--r-- | src/luarocks/fs.lua | 5 | ||||
-rw-r--r-- | src/luarocks/fs/tools.lua | 156 | ||||
-rw-r--r-- | src/luarocks/fs/unix.lua | 7 | ||||
-rw-r--r-- | src/luarocks/fs/unix/tools.lua | 151 | ||||
-rw-r--r-- | src/luarocks/fs/win32.lua | 7 | ||||
-rw-r--r-- | src/luarocks/fs/win32/tools.lua | 170 | ||||
-rw-r--r-- | src/luarocks/install.lua | 13 | ||||
-rw-r--r-- | src/luarocks/manif.lua | 2 | ||||
-rw-r--r-- | src/luarocks/repos.lua | 5 | ||||
-rw-r--r-- | src/luarocks/util.lua | 14 | ||||
-rw-r--r-- | src/luarocks/write_rockspec.lua | 56 | ||||
-rw-r--r-- | test/testing.lua | 21 | ||||
-rwxr-xr-x | test/testing.sh | 16 |
16 files changed, 335 insertions, 428 deletions
diff --git a/Makefile.setup.inc b/Makefile.setup.inc index 0a049bc4..092d0423 100644 --- a/Makefile.setup.inc +++ b/Makefile.setup.inc | |||
@@ -5,7 +5,7 @@ BINDIR ?= $(PREFIX)/bin | |||
5 | LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)/ | 5 | LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)/ |
6 | 6 | ||
7 | BIN_FILES = luarocks luarocks-admin | 7 | BIN_FILES = luarocks luarocks-admin |
8 | LUAROCKS_FILES = fs/unix/tools.lua fs/unix.lua fs/win32/tools.lua fs/win32.lua \ | 8 | LUAROCKS_FILES = fs/tools.lua fs/unix/tools.lua fs/unix.lua fs/win32/tools.lua fs/win32.lua \ |
9 | fs/lua.lua persist.lua list.lua require.lua repos.lua dir.lua make_manifest.lua \ | 9 | fs/lua.lua persist.lua list.lua require.lua repos.lua dir.lua make_manifest.lua \ |
10 | command_line.lua config_cmd.lua install.lua build/command.lua build/cmake.lua \ | 10 | command_line.lua config_cmd.lua install.lua build/command.lua build/cmake.lua \ |
11 | build/make.lua build/builtin.lua fetch/cvs.lua fetch/git.lua fetch/sscm.lua \ | 11 | build/make.lua build/builtin.lua fetch/cvs.lua fetch/git.lua fetch/sscm.lua \ |
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index a1aeb501..c62e4694 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua | |||
@@ -332,15 +332,7 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m | |||
332 | ok, err = manif.update_manifest(name, version, nil, deps_mode) | 332 | ok, err = manif.update_manifest(name, version, nil, deps_mode) |
333 | if err then return nil, err end | 333 | if err then return nil, err end |
334 | 334 | ||
335 | local license = "" | 335 | util.announce_install(rockspec) |
336 | if rockspec.description and rockspec.description.license then | ||
337 | license = ("(license: "..rockspec.description.license..")") | ||
338 | end | ||
339 | |||
340 | local root_dir = path.root_dir(cfg.rocks_dir) | ||
341 | util.printout(name.." "..version.." is now built and installed in "..root_dir.." "..license) | ||
342 | util.printout() | ||
343 | |||
344 | util.remove_scheduled_function(rollback) | 336 | util.remove_scheduled_function(rollback) |
345 | return name, version | 337 | return name, version |
346 | end | 338 | end |
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index 812e6d18..536b6c51 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -322,48 +322,32 @@ end | |||
322 | -- @param dep table: A dependency parsed in table format. | 322 | -- @param dep table: A dependency parsed in table format. |
323 | -- @param blacklist table: Versions that can't be accepted. Table where keys | 323 | -- @param blacklist table: Versions that can't be accepted. Table where keys |
324 | -- are program versions and values are 'true'. | 324 | -- are program versions and values are 'true'. |
325 | -- @return table or nil: A table containing fields 'name' and 'version' | 325 | -- @return string or nil: latest installed version of the rock matching the dependency |
326 | -- representing an installed rock which matches the given dependency, | ||
327 | -- or nil if it could not be matched. | 326 | -- or nil if it could not be matched. |
328 | local function match_dep(dep, blacklist, deps_mode) | 327 | local function match_dep(dep, blacklist, deps_mode) |
329 | assert(type(dep) == "table") | 328 | assert(type(dep) == "table") |
330 | 329 | ||
331 | local versions = cfg.rocks_provided[dep.name] | 330 | local versions |
332 | if cfg.rocks_provided[dep.name] then | 331 | if cfg.rocks_provided[dep.name] then |
333 | -- provided rocks have higher priority than manifest's rocks | 332 | -- provided rocks have higher priority than manifest's rocks |
334 | versions = { cfg.rocks_provided[dep.name] } | 333 | versions = { cfg.rocks_provided[dep.name] } |
335 | else | 334 | else |
336 | versions = manif_core.get_versions(dep.name, deps_mode) | 335 | versions = manif_core.get_versions(dep.name, deps_mode) |
337 | end | 336 | end |
338 | if not versions then | 337 | |
339 | return nil | 338 | local latest_version |
340 | end | ||
341 | if blacklist then | ||
342 | local i = 1 | ||
343 | while versions[i] do | ||
344 | if blacklist[versions[i]] then | ||
345 | table.remove(versions, i) | ||
346 | else | ||
347 | i = i + 1 | ||
348 | end | ||
349 | end | ||
350 | end | ||
351 | local candidates = {} | ||
352 | for _, vstring in ipairs(versions) do | 339 | for _, vstring in ipairs(versions) do |
353 | local version = deps.parse_version(vstring) | 340 | if not blacklist or not blacklist[vstring] then |
354 | if deps.match_constraints(version, dep.constraints) then | 341 | local version = deps.parse_version(vstring) |
355 | table.insert(candidates, version) | 342 | if deps.match_constraints(version, dep.constraints) then |
343 | if not latest_version or version > latest_version then | ||
344 | latest_version = version | ||
345 | end | ||
346 | end | ||
356 | end | 347 | end |
357 | end | 348 | end |
358 | if #candidates == 0 then | 349 | |
359 | return nil | 350 | return latest_version and latest_version.string |
360 | else | ||
361 | table.sort(candidates) | ||
362 | return { | ||
363 | name = dep.name, | ||
364 | version = candidates[#candidates].string | ||
365 | } | ||
366 | end | ||
367 | end | 351 | end |
368 | 352 | ||
369 | --- Attempt to match dependencies of a rockspec to installed rocks. | 353 | --- Attempt to match dependencies of a rockspec to installed rocks. |
@@ -386,7 +370,7 @@ function deps.match_deps(rockspec, blacklist, deps_mode) | |||
386 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode) | 370 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode) |
387 | if found then | 371 | if found then |
388 | if not cfg.rocks_provided[dep.name] then | 372 | if not cfg.rocks_provided[dep.name] then |
389 | matched[dep] = found | 373 | matched[dep] = {name = dep.name, version = found} |
390 | end | 374 | end |
391 | else | 375 | else |
392 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | 376 | if dep.constraints[1] and dep.constraints[1].no_upgrade then |
@@ -410,6 +394,13 @@ local function values_set(tbl) | |||
410 | return set | 394 | return set |
411 | end | 395 | end |
412 | 396 | ||
397 | local function rock_status(name, deps_mode) | ||
398 | local search = require("luarocks.search") | ||
399 | local installed = match_dep(search.make_query(name), nil, deps_mode) | ||
400 | local installation_type = cfg.rocks_provided[name] and "provided by VM" or "installed" | ||
401 | return installed and installed.." "..installation_type or "not installed" | ||
402 | end | ||
403 | |||
413 | --- Check dependencies of a rock and attempt to install any missing ones. | 404 | --- Check dependencies of a rock and attempt to install any missing ones. |
414 | -- Packages are installed using the LuaRocks "install" command. | 405 | -- Packages are installed using the LuaRocks "install" command. |
415 | -- Aborts the program if a dependency could not be fulfilled. | 406 | -- Aborts the program if a dependency could not be fulfilled. |
@@ -449,52 +440,53 @@ function deps.fulfill_dependencies(rockspec, deps_mode) | |||
449 | end | 440 | end |
450 | end | 441 | end |
451 | 442 | ||
452 | local _, missing, no_upgrade = deps.match_deps(rockspec, nil, deps_mode) | 443 | local first_missing_dep = true |
453 | 444 | ||
454 | if next(no_upgrade) then | 445 | for _, dep in ipairs(rockspec.dependencies) do |
455 | util.printerr("Missing dependencies for "..rockspec.name.." "..rockspec.version..":") | 446 | if not match_dep(dep, nil, deps_mode) then |
456 | for _, dep in pairs(no_upgrade) do | 447 | if first_missing_dep then |
457 | util.printerr(deps.show_dep(dep)) | 448 | util.printout(("Missing dependencies for %s %s:"):format(rockspec.name, rockspec.version)) |
458 | end | 449 | first_missing_dep = false |
459 | if next(missing) then | ||
460 | for _, dep in pairs(missing) do | ||
461 | util.printerr(deps.show_dep(dep)) | ||
462 | end | 450 | end |
451 | |||
452 | util.printout((" %s (%s)"):format(deps.show_dep(dep), rock_status(dep.name, deps_mode))) | ||
463 | end | 453 | end |
464 | util.printerr() | ||
465 | for _, dep in pairs(no_upgrade) do | ||
466 | util.printerr("This version of "..rockspec.name.." is designed for use with") | ||
467 | util.printerr(deps.show_dep(dep)..", but is configured to avoid upgrading it") | ||
468 | util.printerr("automatically. Please upgrade "..dep.name.." with") | ||
469 | util.printerr(" luarocks install "..dep.name) | ||
470 | util.printerr("or choose an older version of "..rockspec.name.." with") | ||
471 | util.printerr(" luarocks search "..rockspec.name) | ||
472 | end | ||
473 | return nil, "Failed matching dependencies." | ||
474 | end | 454 | end |
475 | 455 | ||
476 | if next(missing) then | 456 | first_missing_dep = true |
477 | util.printerr() | 457 | |
478 | util.printerr("Missing dependencies for "..rockspec.name..":") | 458 | for _, dep in ipairs(rockspec.dependencies) do |
479 | for _, dep in pairs(missing) do | 459 | if not match_dep(dep, nil, deps_mode) then |
480 | util.printerr(deps.show_dep(dep)) | 460 | if first_missing_dep then |
481 | end | 461 | util.printout() |
482 | util.printerr() | 462 | first_missing_dep = false |
483 | 463 | end | |
484 | for _, dep in pairs(missing) do | 464 | |
485 | -- Double-check in case dependency was filled during recursion. | 465 | util.printout(("%s %s depends on %s (%s)"):format( |
486 | if not match_dep(dep, nil, deps_mode) then | 466 | rockspec.name, rockspec.version, deps.show_dep(dep), rock_status(dep.name, deps_mode))) |
487 | local url, err = search.find_suitable_rock(dep) | 467 | |
488 | if not url then | 468 | if dep.constraints[1] and dep.constraints[1].no_upgrade then |
489 | return nil, "Could not satisfy dependency "..deps.show_dep(dep)..": "..err | 469 | util.printerr("This version of "..rockspec.name.." is designed for use with") |
490 | end | 470 | util.printerr(deps.show_dep(dep)..", but is configured to avoid upgrading it") |
491 | local ok, err, errcode = install.run(url, deps.deps_mode_to_flag(deps_mode)) | 471 | util.printerr("automatically. Please upgrade "..dep.name.." with") |
492 | if not ok then | 472 | util.printerr(" luarocks install "..dep.name) |
493 | return nil, "Failed installing dependency: "..url.." - "..err, errcode | 473 | util.printerr("or choose an older version of "..rockspec.name.." with") |
494 | end | 474 | util.printerr(" luarocks search "..rockspec.name) |
475 | return nil, "Failed matching dependencies" | ||
476 | end | ||
477 | |||
478 | local url, search_err = search.find_suitable_rock(dep) | ||
479 | if not url then | ||
480 | return nil, "Could not satisfy dependency "..deps.show_dep(dep)..": "..search_err | ||
481 | end | ||
482 | util.printout("Installing "..url) | ||
483 | local ok, install_err, errcode = install.run(url, deps.deps_mode_to_flag(deps_mode)) | ||
484 | if not ok then | ||
485 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode | ||
495 | end | 486 | end |
496 | end | 487 | end |
497 | end | 488 | end |
489 | |||
498 | return true | 490 | return true |
499 | end | 491 | end |
500 | 492 | ||
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua index 57302c7f..f3d86a13 100644 --- a/src/luarocks/fs.lua +++ b/src/luarocks/fs.lua | |||
@@ -68,7 +68,10 @@ load_fns(fs_lua) | |||
68 | 68 | ||
69 | -- Load platform-specific fallbacks for missing Lua modules | 69 | -- Load platform-specific fallbacks for missing Lua modules |
70 | local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools") | 70 | local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools") |
71 | if ok and fs_plat_tools then load_fns(fs_plat_tools) end | 71 | if ok and fs_plat_tools then |
72 | load_fns(fs_plat_tools) | ||
73 | load_fns(require("luarocks.fs.tools")) | ||
74 | end | ||
72 | 75 | ||
73 | 76 | ||
74 | return fs | 77 | return fs |
diff --git a/src/luarocks/fs/tools.lua b/src/luarocks/fs/tools.lua new file mode 100644 index 00000000..ed51b545 --- /dev/null +++ b/src/luarocks/fs/tools.lua | |||
@@ -0,0 +1,156 @@ | |||
1 | |||
2 | --- Common fs operations implemented with third-party tools. | ||
3 | local tools = {} | ||
4 | |||
5 | local fs = require("luarocks.fs") | ||
6 | local dir = require("luarocks.dir") | ||
7 | local cfg = require("luarocks.cfg") | ||
8 | |||
9 | local vars = cfg.variables | ||
10 | |||
11 | local dir_stack = {} | ||
12 | |||
13 | --- Obtain current directory. | ||
14 | -- Uses the module's internal directory stack. | ||
15 | -- @return string: the absolute pathname of the current directory. | ||
16 | function tools.current_dir() | ||
17 | local current = cfg.cache_pwd | ||
18 | if not current then | ||
19 | local pipe = io.popen(fs.quiet_stderr(fs.Q(vars.PWD))) | ||
20 | current = pipe:read("*l") | ||
21 | pipe:close() | ||
22 | cfg.cache_pwd = current | ||
23 | end | ||
24 | for _, directory in ipairs(dir_stack) do | ||
25 | current = fs.absolute_name(directory, current) | ||
26 | end | ||
27 | return current | ||
28 | end | ||
29 | |||
30 | --- Change the current directory. | ||
31 | -- Uses the module's internal directory stack. This does not have exact | ||
32 | -- semantics of chdir, as it does not handle errors the same way, | ||
33 | -- but works well for our purposes for now. | ||
34 | -- @param directory string: The directory to switch to. | ||
35 | -- @return boolean or (nil, string): true if successful, (nil, error message) if failed. | ||
36 | function tools.change_dir(directory) | ||
37 | assert(type(directory) == "string") | ||
38 | if fs.is_dir(directory) then | ||
39 | table.insert(dir_stack, directory) | ||
40 | return true | ||
41 | end | ||
42 | return nil, "directory not found: "..directory | ||
43 | end | ||
44 | |||
45 | --- Change directory to root. | ||
46 | -- Allows leaving a directory (e.g. for deleting it) in | ||
47 | -- a crossplatform way. | ||
48 | function tools.change_dir_to_root() | ||
49 | table.insert(dir_stack, "/") | ||
50 | end | ||
51 | |||
52 | --- Change working directory to the previous in the directory stack. | ||
53 | function tools.pop_dir() | ||
54 | local directory = table.remove(dir_stack) | ||
55 | return directory ~= nil | ||
56 | end | ||
57 | |||
58 | --- Run the given command. | ||
59 | -- The command is executed in the current directory in the directory stack. | ||
60 | -- @param cmd string: No quoting/escaping is applied to the command. | ||
61 | -- @return boolean: true if command succeeds (status code 0), false | ||
62 | -- otherwise. | ||
63 | function tools.execute_string(cmd) | ||
64 | local current = fs.current_dir() | ||
65 | if not current then return false end | ||
66 | cmd = fs.command_at(current, cmd) | ||
67 | local code = os.execute(cmd) | ||
68 | if code == 0 or code == true then | ||
69 | return true | ||
70 | else | ||
71 | return false | ||
72 | end | ||
73 | end | ||
74 | |||
75 | --- Internal implementation function for fs.dir. | ||
76 | -- Yields a filename on each iteration. | ||
77 | -- @param at string: directory to list | ||
78 | -- @return nil | ||
79 | function tools.dir_iterator(at) | ||
80 | local pipe = io.popen(fs.command_at(at, fs.Q(vars.LS))) | ||
81 | for file in pipe:lines() do | ||
82 | if file ~= "." and file ~= ".." then | ||
83 | coroutine.yield(file) | ||
84 | end | ||
85 | end | ||
86 | pipe:close() | ||
87 | end | ||
88 | |||
89 | --- Download a remote file. | ||
90 | -- @param url string: URL to be fetched. | ||
91 | -- @param filename string or nil: this function attempts to detect the | ||
92 | -- resulting local filename of the remote file as the basename of the URL; | ||
93 | -- if that is not correct (due to a redirection, for example), the local | ||
94 | -- filename can be given explicitly as this second argument. | ||
95 | -- @return (boolean, string): true and the filename on success, | ||
96 | -- false and the error message on failure. | ||
97 | function tools.use_downloader(url, filename, cache) | ||
98 | assert(type(url) == "string") | ||
99 | assert(type(filename) == "string" or not filename) | ||
100 | |||
101 | filename = fs.absolute_name(filename or dir.base_name(url)) | ||
102 | |||
103 | local ok | ||
104 | if cfg.downloader == "wget" then | ||
105 | local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet " | ||
106 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
107 | wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 " | ||
108 | end | ||
109 | if cache then | ||
110 | -- --timestamping is incompatible with --output-document, | ||
111 | -- but that's not a problem for our use cases. | ||
112 | fs.change_dir(dir.dir_name(filename)) | ||
113 | ok = fs.execute_quiet(wget_cmd.." --timestamping ", url) | ||
114 | fs.pop_dir() | ||
115 | elseif filename then | ||
116 | ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url) | ||
117 | else | ||
118 | ok = fs.execute_quiet(wget_cmd, url) | ||
119 | end | ||
120 | elseif cfg.downloader == "curl" then | ||
121 | local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent \""..cfg.user_agent.." via curl\" " | ||
122 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
123 | curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." " | ||
124 | end | ||
125 | ok = fs.execute_string(fs.quiet_stderr(curl_cmd..fs.Q(url).." > "..fs.Q(filename))) | ||
126 | end | ||
127 | if ok then | ||
128 | return true, filename | ||
129 | else | ||
130 | return false | ||
131 | end | ||
132 | end | ||
133 | |||
134 | local md5_cmd = { | ||
135 | md5sum = fs.Q(vars.MD5SUM), | ||
136 | openssl = fs.Q(vars.OPENSSL).." md5", | ||
137 | md5 = fs.Q(vars.MD5), | ||
138 | } | ||
139 | |||
140 | --- Get the MD5 checksum for a file. | ||
141 | -- @param file string: The file to be computed. | ||
142 | -- @return string: The MD5 checksum or nil + message | ||
143 | function tools.get_md5(file) | ||
144 | local cmd = md5_cmd[cfg.md5checker] | ||
145 | if not cmd then return nil, "no MD5 checker command configured" end | ||
146 | local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file))) | ||
147 | local computed = pipe:read("*a") | ||
148 | pipe:close() | ||
149 | if computed then | ||
150 | computed = computed:match("("..("%x"):rep(32)..")") | ||
151 | end | ||
152 | if computed then return computed end | ||
153 | return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file)) | ||
154 | end | ||
155 | |||
156 | return tools | ||
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index e2cc825b..520b3e99 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua | |||
@@ -16,6 +16,13 @@ function unix.quiet(cmd) | |||
16 | return cmd.." 1> /dev/null 2> /dev/null" | 16 | return cmd.." 1> /dev/null 2> /dev/null" |
17 | end | 17 | end |
18 | 18 | ||
19 | --- Annotate command string for execution with quiet stderr. | ||
20 | -- @param cmd string: A command-line string. | ||
21 | -- @return string: The command-line, with stderr silencing annotation. | ||
22 | function unix.quiet_stderr(cmd) | ||
23 | return cmd.." 2> /dev/null" | ||
24 | end | ||
25 | |||
19 | --- Return an absolute pathname from a potentially relative one. | 26 | --- Return an absolute pathname from a potentially relative one. |
20 | -- @param pathname string: pathname to convert. | 27 | -- @param pathname string: pathname to convert. |
21 | -- @param relative_to string or nil: path to prepend when making | 28 | -- @param relative_to string or nil: path to prepend when making |
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua index ab55897e..84bd53fd 100644 --- a/src/luarocks/fs/unix/tools.lua +++ b/src/luarocks/fs/unix/tools.lua | |||
@@ -7,74 +7,16 @@ local fs = require("luarocks.fs") | |||
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.cfg") |
9 | 9 | ||
10 | local dir_stack = {} | ||
11 | |||
12 | local vars = cfg.variables | 10 | local vars = cfg.variables |
13 | 11 | ||
14 | local function command_at(directory, cmd) | 12 | --- Adds prefix to command to make it run from a directory. |
13 | -- @param directory string: Path to a directory. | ||
14 | -- @param cmd string: A command-line string. | ||
15 | -- @return string: The command-line with prefix. | ||
16 | function tools.command_at(directory, cmd) | ||
15 | return "cd " .. fs.Q(fs.absolute_name(directory)) .. " && " .. cmd | 17 | return "cd " .. fs.Q(fs.absolute_name(directory)) .. " && " .. cmd |
16 | end | 18 | end |
17 | 19 | ||
18 | --- Obtain current directory. | ||
19 | -- Uses the module's internal directory stack. | ||
20 | -- @return string: the absolute pathname of the current directory. | ||
21 | function tools.current_dir() | ||
22 | local current = cfg.cache_pwd | ||
23 | if not current then | ||
24 | local pipe = io.popen(fs.Q(vars.PWD).." 2> /dev/null") | ||
25 | current = pipe:read("*l") | ||
26 | pipe:close() | ||
27 | cfg.cache_pwd = current | ||
28 | end | ||
29 | for _, directory in ipairs(dir_stack) do | ||
30 | current = fs.absolute_name(directory, current) | ||
31 | end | ||
32 | return current | ||
33 | end | ||
34 | |||
35 | --- Run the given command. | ||
36 | -- The command is executed in the current directory in the directory stack. | ||
37 | -- @param cmd string: No quoting/escaping is applied to the command. | ||
38 | -- @return boolean: true if command succeeds (status code 0), false | ||
39 | -- otherwise. | ||
40 | function tools.execute_string(cmd) | ||
41 | local current = fs.current_dir() | ||
42 | if not current then return false end | ||
43 | local code, err = os.execute(command_at(current, cmd)) | ||
44 | if code == 0 or code == true then | ||
45 | return true | ||
46 | else | ||
47 | return false | ||
48 | end | ||
49 | end | ||
50 | |||
51 | --- Change the current directory. | ||
52 | -- Uses the module's internal directory stack. This does not have exact | ||
53 | -- semantics of chdir, as it does not handle errors the same way, | ||
54 | -- but works well for our purposes for now. | ||
55 | -- @param directory string: The directory to switch to. | ||
56 | function tools.change_dir(directory) | ||
57 | assert(type(directory) == "string") | ||
58 | if fs.is_dir(directory) then | ||
59 | table.insert(dir_stack, directory) | ||
60 | return true | ||
61 | end | ||
62 | return nil, "directory not found: "..directory | ||
63 | end | ||
64 | |||
65 | --- Change directory to root. | ||
66 | -- Allows leaving a directory (e.g. for deleting it) in | ||
67 | -- a crossplatform way. | ||
68 | function tools.change_dir_to_root() | ||
69 | table.insert(dir_stack, "/") | ||
70 | end | ||
71 | |||
72 | --- Change working directory to the previous in the directory stack. | ||
73 | function tools.pop_dir() | ||
74 | local directory = table.remove(dir_stack) | ||
75 | return directory ~= nil | ||
76 | end | ||
77 | |||
78 | --- Create a directory if it does not already exist. | 20 | --- Create a directory if it does not already exist. |
79 | -- If any of the higher levels in the path name does not exist | 21 | -- If any of the higher levels in the path name does not exist |
80 | -- too, they are created as well. | 22 | -- too, they are created as well. |
@@ -155,20 +97,6 @@ function tools.delete(arg) | |||
155 | fs.execute_quiet(vars.RM, "-rf", arg) | 97 | fs.execute_quiet(vars.RM, "-rf", arg) |
156 | end | 98 | end |
157 | 99 | ||
158 | --- Internal implementation function for fs.dir. | ||
159 | -- Yields a filename on each iteration. | ||
160 | -- @param at string: directory to list | ||
161 | -- @return nil | ||
162 | function tools.dir_iterator(at) | ||
163 | local pipe = io.popen(command_at(at, vars.LS)) | ||
164 | for file in pipe:lines() do | ||
165 | if file ~= "." and file ~= ".." then | ||
166 | coroutine.yield(file) | ||
167 | end | ||
168 | end | ||
169 | pipe:close() | ||
170 | end | ||
171 | |||
172 | --- Recursively scan the contents of a directory. | 100 | --- Recursively scan the contents of a directory. |
173 | -- @param at string or nil: directory to scan (will be the current | 101 | -- @param at string or nil: directory to scan (will be the current |
174 | -- directory if none is given). | 102 | -- directory if none is given). |
@@ -183,7 +111,7 @@ function tools.find(at) | |||
183 | return {} | 111 | return {} |
184 | end | 112 | end |
185 | local result = {} | 113 | local result = {} |
186 | local pipe = io.popen(command_at(at, vars.FIND.." * 2>/dev/null")) | 114 | local pipe = io.popen(fs.command_at(at, fs.quiet_stderr(vars.FIND.." *"))) |
187 | for file in pipe:lines() do | 115 | for file in pipe:lines() do |
188 | table.insert(result, file) | 116 | table.insert(result, file) |
189 | end | 117 | end |
@@ -232,51 +160,6 @@ function tools.is_file(file) | |||
232 | return fs.execute(vars.TEST, "-f", file) | 160 | return fs.execute(vars.TEST, "-f", file) |
233 | end | 161 | end |
234 | 162 | ||
235 | --- Download a remote file. | ||
236 | -- @param url string: URL to be fetched. | ||
237 | -- @param filename string or nil: this function attempts to detect the | ||
238 | -- resulting local filename of the remote file as the basename of the URL; | ||
239 | -- if that is not correct (due to a redirection, for example), the local | ||
240 | -- filename can be given explicitly as this second argument. | ||
241 | -- @return (boolean, string): true and the filename on success, | ||
242 | -- false and the error message on failure. | ||
243 | function tools.use_downloader(url, filename, cache) | ||
244 | assert(type(url) == "string") | ||
245 | assert(type(filename) == "string" or not filename) | ||
246 | |||
247 | filename = fs.absolute_name(filename or dir.base_name(url)) | ||
248 | |||
249 | local ok | ||
250 | if cfg.downloader == "wget" then | ||
251 | local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet " | ||
252 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
253 | wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 " | ||
254 | end | ||
255 | if cache then | ||
256 | -- --timestamping is incompatible with --output-document, | ||
257 | -- but that's not a problem for our use cases. | ||
258 | fs.change_dir(dir.dir_name(filename)) | ||
259 | ok = fs.execute_quiet(wget_cmd.." --timestamping ", url) | ||
260 | fs.pop_dir() | ||
261 | elseif filename then | ||
262 | ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url) | ||
263 | else | ||
264 | ok = fs.execute_quiet(wget_cmd, url) | ||
265 | end | ||
266 | elseif cfg.downloader == "curl" then | ||
267 | local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent '"..cfg.user_agent.." via curl' " | ||
268 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
269 | curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." " | ||
270 | end | ||
271 | ok = fs.execute_string(curl_cmd..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename)) | ||
272 | end | ||
273 | if ok then | ||
274 | return true, filename | ||
275 | else | ||
276 | return false | ||
277 | end | ||
278 | end | ||
279 | |||
280 | function tools.chmod(pathname, mode) | 163 | function tools.chmod(pathname, mode) |
281 | if mode then | 164 | if mode then |
282 | return fs.execute(vars.CHMOD, mode, pathname) | 165 | return fs.execute(vars.CHMOD, mode, pathname) |
@@ -319,28 +202,6 @@ function tools.unpack_archive(archive) | |||
319 | return true | 202 | return true |
320 | end | 203 | end |
321 | 204 | ||
322 | local md5_cmd = { | ||
323 | md5sum = vars.MD5SUM, | ||
324 | openssl = vars.OPENSSL.." md5", | ||
325 | md5 = vars.MD5, | ||
326 | } | ||
327 | |||
328 | --- Get the MD5 checksum for a file. | ||
329 | -- @param file string: The file to be computed. | ||
330 | -- @return string: The MD5 checksum | ||
331 | function tools.get_md5(file) | ||
332 | local cmd = md5_cmd[cfg.md5checker] | ||
333 | if not cmd then return nil, "no MD5 checker command configured" end | ||
334 | local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file))) | ||
335 | local computed = pipe:read("*a") | ||
336 | pipe:close() | ||
337 | if computed then | ||
338 | computed = computed:match("("..("%x"):rep(32)..")") | ||
339 | end | ||
340 | if computed then return computed end | ||
341 | return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file)) | ||
342 | end | ||
343 | |||
344 | function tools.get_permissions(filename) | 205 | function tools.get_permissions(filename) |
345 | local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename)) | 206 | local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename)) |
346 | local ret = pipe:read("*l") | 207 | local ret = pipe:read("*l") |
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index c14c421b..74f3ed69 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua | |||
@@ -27,6 +27,13 @@ function win32.quiet(cmd) | |||
27 | return cmd.." 2> NUL 1> NUL" | 27 | return cmd.." 2> NUL 1> NUL" |
28 | end | 28 | end |
29 | 29 | ||
30 | --- Annotate command string for execution with quiet stderr. | ||
31 | -- @param cmd string: A command-line string. | ||
32 | -- @return string: The command-line, with stderr silencing annotation. | ||
33 | function win32.quiet_stderr(cmd) | ||
34 | return cmd.." 2> NUL" | ||
35 | end | ||
36 | |||
30 | local drive_letter = "[%.a-zA-Z]?:?[\\/]" | 37 | local drive_letter = "[%.a-zA-Z]?:?[\\/]" |
31 | 38 | ||
32 | local win_escape_chars = { | 39 | local win_escape_chars = { |
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua index b9dce85c..9cb6d47a 100644 --- a/src/luarocks/fs/win32/tools.lua +++ b/src/luarocks/fs/win32/tools.lua | |||
@@ -9,22 +9,13 @@ local fs = require("luarocks.fs") | |||
9 | local dir = require("luarocks.dir") | 9 | local dir = require("luarocks.dir") |
10 | local cfg = require("luarocks.cfg") | 10 | local cfg = require("luarocks.cfg") |
11 | 11 | ||
12 | local dir_stack = {} | ||
13 | |||
14 | local vars = cfg.variables | 12 | local vars = cfg.variables |
15 | 13 | ||
16 | --- Strip the last extension of a filename. | 14 | --- Adds prefix to command to make it run from a directory. |
17 | -- Example: "foo.tar.gz" becomes "foo.tar". | 15 | -- @param directory string: Path to a directory. |
18 | -- If filename has no dots, returns it unchanged. | 16 | -- @param cmd string: A command-line string. |
19 | -- @param filename string: The file name to strip. | 17 | -- @return string: The command-line with prefix. |
20 | -- @return string: The stripped name. | 18 | function tools.command_at(directory, cmd) |
21 | local function strip_extension(filename) | ||
22 | assert(type(filename) == "string") | ||
23 | |||
24 | return (filename:gsub("%.[^.]+$", "")) or filename | ||
25 | end | ||
26 | |||
27 | local function command_at(directory, cmd) | ||
28 | local drive = directory:match("^([A-Za-z]:)") | 19 | local drive = directory:match("^([A-Za-z]:)") |
29 | cmd = "cd " .. fs.Q(directory) .. " & " .. cmd | 20 | cmd = "cd " .. fs.Q(directory) .. " & " .. cmd |
30 | if drive then | 21 | if drive then |
@@ -33,68 +24,6 @@ local function command_at(directory, cmd) | |||
33 | return cmd | 24 | return cmd |
34 | end | 25 | end |
35 | 26 | ||
36 | --- Obtain current directory. | ||
37 | -- Uses the module's internal directory stack. | ||
38 | -- @return string: the absolute pathname of the current directory. | ||
39 | function tools.current_dir() | ||
40 | local current = cfg.cache_pwd | ||
41 | if not current then | ||
42 | local pipe = io.popen(fs.Q(vars.PWD).. " 2> NUL") | ||
43 | current = pipe:read("*l") | ||
44 | pipe:close() | ||
45 | cfg.cache_pwd = current | ||
46 | end | ||
47 | for _, directory in ipairs(dir_stack) do | ||
48 | current = fs.absolute_name(directory, current) | ||
49 | end | ||
50 | return current | ||
51 | end | ||
52 | |||
53 | --- Run the given command. | ||
54 | -- The command is executed in the current directory in the directory stack. | ||
55 | -- @param cmd string: No quoting/escaping is applied to the command. | ||
56 | -- @return boolean: true if command succeeds (status code 0), false | ||
57 | -- otherwise. | ||
58 | function tools.execute_string(cmd) | ||
59 | local current = fs.current_dir() | ||
60 | if not current then return false end | ||
61 | cmd = command_at(current, cmd) | ||
62 | local code = os.execute(cmd) | ||
63 | if code == 0 or code == true then | ||
64 | return true | ||
65 | else | ||
66 | return false | ||
67 | end | ||
68 | end | ||
69 | |||
70 | --- Change the current directory. | ||
71 | -- Uses the module's internal directory stack. This does not have exact | ||
72 | -- semantics of chdir, as it does not handle errors the same way, | ||
73 | -- but works well for our purposes for now. | ||
74 | -- @param directory string: The directory to switch to. | ||
75 | -- @return boolean or (nil, string): true if successful, (nil, error message) if failed. | ||
76 | function tools.change_dir(directory) | ||
77 | assert(type(directory) == "string") | ||
78 | if fs.is_dir(directory) then | ||
79 | table.insert(dir_stack, directory) | ||
80 | return true | ||
81 | end | ||
82 | return nil, "directory not found: "..directory | ||
83 | end | ||
84 | |||
85 | --- Change directory to root. | ||
86 | -- Allows leaving a directory (e.g. for deleting it) in | ||
87 | -- a crossplatform way. | ||
88 | function tools.change_dir_to_root() | ||
89 | table.insert(dir_stack, "/") | ||
90 | end | ||
91 | |||
92 | --- Change working directory to the previous in the directory stack. | ||
93 | function tools.pop_dir() | ||
94 | local directory = table.remove(dir_stack) | ||
95 | return directory ~= nil | ||
96 | end | ||
97 | |||
98 | --- Create a directory if it does not already exist. | 27 | --- Create a directory if it does not already exist. |
99 | -- If any of the higher levels in the path name does not exist | 28 | -- If any of the higher levels in the path name does not exist |
100 | -- too, they are created as well. | 29 | -- too, they are created as well. |
@@ -168,20 +97,6 @@ function tools.delete(arg) | |||
168 | fs.execute_quiet("if exist "..fs.Q(arg.."\\").." ( RMDIR /S /Q "..fs.Q(arg).." ) else ( DEL /Q /F "..fs.Q(arg).." )") | 97 | fs.execute_quiet("if exist "..fs.Q(arg.."\\").." ( RMDIR /S /Q "..fs.Q(arg).." ) else ( DEL /Q /F "..fs.Q(arg).." )") |
169 | end | 98 | end |
170 | 99 | ||
171 | --- Internal implementation function for fs.dir. | ||
172 | -- Yields a filename on each iteration. | ||
173 | -- @param at string: directory to list | ||
174 | -- @return nil | ||
175 | function tools.dir_iterator(at) | ||
176 | local pipe = io.popen(command_at(at, fs.Q(vars.LS))) | ||
177 | for file in pipe:lines() do | ||
178 | if file ~= "." and file ~= ".." then | ||
179 | coroutine.yield(file) | ||
180 | end | ||
181 | end | ||
182 | pipe:close() | ||
183 | end | ||
184 | |||
185 | --- Recursively scan the contents of a directory. | 100 | --- Recursively scan the contents of a directory. |
186 | -- @param at string or nil: directory to scan (will be the current | 101 | -- @param at string or nil: directory to scan (will be the current |
187 | -- directory if none is given). | 102 | -- directory if none is given). |
@@ -196,7 +111,7 @@ function tools.find(at) | |||
196 | return {} | 111 | return {} |
197 | end | 112 | end |
198 | local result = {} | 113 | local result = {} |
199 | local pipe = io.popen(command_at(at, fs.Q(vars.FIND).." 2> NUL")) | 114 | local pipe = io.popen(fs.command_at(at, fs.quiet_stderr(fs.Q(vars.FIND)))) |
200 | for file in pipe:lines() do | 115 | for file in pipe:lines() do |
201 | -- Windows find is a bit different | 116 | -- Windows find is a bit different |
202 | local first_two = file:sub(1,2) | 117 | local first_two = file:sub(1,2) |
@@ -242,49 +157,14 @@ function tools.is_file(file) | |||
242 | return fs.execute(fs.Q(vars.TEST).." -f", file) | 157 | return fs.execute(fs.Q(vars.TEST).." -f", file) |
243 | end | 158 | end |
244 | 159 | ||
245 | --- Download a remote file. | 160 | --- Strip the last extension of a filename. |
246 | -- @param url string: URL to be fetched. | 161 | -- Example: "foo.tar.gz" becomes "foo.tar". |
247 | -- @param filename string or nil: this function attempts to detect the | 162 | -- If filename has no dots, returns it unchanged. |
248 | -- resulting local filename of the remote file as the basename of the URL; | 163 | -- @param filename string: The file name to strip. |
249 | -- if that is not correct (due to a redirection, for example), the local | 164 | -- @return string: The stripped name. |
250 | -- filename can be given explicitly as this second argument. | 165 | local function strip_extension(filename) |
251 | -- @return (boolean, string): true and the filename on success, | 166 | assert(type(filename) == "string") |
252 | -- false and the error message on failure. | 167 | return (filename:gsub("%.[^.]+$", "")) or filename |
253 | function tools.use_downloader(url, filename, cache) | ||
254 | assert(type(url) == "string") | ||
255 | assert(type(filename) == "string" or not filename) | ||
256 | |||
257 | filename = fs.absolute_name(filename or dir.base_name(url)) | ||
258 | |||
259 | local ok | ||
260 | if cfg.downloader == "wget" then | ||
261 | local wget_cmd = fs.Q(vars.WGET).." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet " | ||
262 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
263 | wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 " | ||
264 | end | ||
265 | if cache then | ||
266 | -- --timestamping is incompatible with --output-document, | ||
267 | -- but that's not a problem for our use cases. | ||
268 | fs.change_dir(dir.dir_name(filename)) | ||
269 | ok = fs.execute_quiet(wget_cmd.." --timestamping ", url) | ||
270 | fs.pop_dir() | ||
271 | elseif filename then | ||
272 | ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url) | ||
273 | else | ||
274 | ok = fs.execute_quiet(wget_cmd, url) | ||
275 | end | ||
276 | elseif cfg.downloader == "curl" then | ||
277 | local curl_cmd = fs.Q(vars.CURL).." "..vars.CURLNOCERTFLAG.." -f -L --user-agent \""..cfg.user_agent.." via curl\" " | ||
278 | if cfg.connection_timeout and cfg.connection_timeout > 0 then | ||
279 | curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." " | ||
280 | end | ||
281 | ok = fs.execute_string(curl_cmd..fs.Q(url).." 2> NUL 1> "..fs.Q(filename)) | ||
282 | end | ||
283 | if ok then | ||
284 | return true, filename | ||
285 | else | ||
286 | return false | ||
287 | end | ||
288 | end | 168 | end |
289 | 169 | ||
290 | --- Uncompress gzip file. | 170 | --- Uncompress gzip file. |
@@ -334,28 +214,6 @@ function tools.unpack_archive(archive) | |||
334 | return true | 214 | return true |
335 | end | 215 | end |
336 | 216 | ||
337 | local md5_cmd = { | ||
338 | md5sum = fs.Q(vars.MD5SUM), | ||
339 | openssl = fs.Q(vars.OPENSSL).." md5", | ||
340 | md5 = fs.Q(vars.MD5), | ||
341 | } | ||
342 | |||
343 | --- Get the MD5 checksum for a file. | ||
344 | -- @param file string: The file to be computed. | ||
345 | -- @return string: The MD5 checksum or nil + message | ||
346 | function tools.get_md5(file) | ||
347 | local cmd = md5_cmd[cfg.md5checker] | ||
348 | if not cmd then return nil, "no MD5 checker command configured" end | ||
349 | local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file))) | ||
350 | local computed = pipe:read("*a") | ||
351 | pipe:close() | ||
352 | if computed then | ||
353 | computed = computed:match("("..("%x"):rep(32)..")") | ||
354 | end | ||
355 | if computed then return computed end | ||
356 | return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file)) | ||
357 | end | ||
358 | |||
359 | --- Test for existance of a file. | 217 | --- Test for existance of a file. |
360 | -- @param file string: filename to test | 218 | -- @param file string: filename to test |
361 | -- @return boolean: true if file exists, false otherwise. | 219 | -- @return boolean: true if file exists, false otherwise. |
diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua index b6af43cc..e3ab6fac 100644 --- a/src/luarocks/install.lua +++ b/src/luarocks/install.lua | |||
@@ -98,15 +98,7 @@ function install.install_binary_rock(rock_file, deps_mode) | |||
98 | ok, err = manif.update_manifest(name, version, nil, deps_mode) | 98 | ok, err = manif.update_manifest(name, version, nil, deps_mode) |
99 | if err then return nil, err end | 99 | if err then return nil, err end |
100 | 100 | ||
101 | local license = "" | 101 | util.announce_install(rockspec) |
102 | if rockspec.description.license then | ||
103 | license = ("(license: "..rockspec.description.license..")") | ||
104 | end | ||
105 | |||
106 | local root_dir = path.root_dir(cfg.rocks_dir) | ||
107 | util.printout() | ||
108 | util.printout(name.." "..version.." is now installed in "..root_dir.." "..license) | ||
109 | |||
110 | util.remove_scheduled_function(rollback) | 102 | util.remove_scheduled_function(rollback) |
111 | return name, version | 103 | return name, version |
112 | end | 104 | end |
@@ -168,7 +160,6 @@ function install.run(...) | |||
168 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | 160 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end |
169 | 161 | ||
170 | if name:match("%.rockspec$") or name:match("%.src%.rock$") then | 162 | if name:match("%.rockspec$") or name:match("%.src%.rock$") then |
171 | util.printout("Using "..name.."... switching to 'build' mode") | ||
172 | local build = require("luarocks.build") | 163 | local build = require("luarocks.build") |
173 | return build.run(name, util.forward_flags(flags, "local", "keep", "deps-mode", "only-deps", "force", "force-fast")) | 164 | return build.run(name, util.forward_flags(flags, "local", "keep", "deps-mode", "only-deps", "force", "force-fast")) |
174 | elseif name:match("%.rock$") then | 165 | elseif name:match("%.rock$") then |
@@ -190,7 +181,7 @@ function install.run(...) | |||
190 | if not url then | 181 | if not url then |
191 | return nil, err | 182 | return nil, err |
192 | end | 183 | end |
193 | util.printout("Installing "..url.."...") | 184 | util.printout("Installing "..url) |
194 | return install.run(url, util.forward_flags(flags)) | 185 | return install.run(url, util.forward_flags(flags)) |
195 | end | 186 | end |
196 | end | 187 | end |
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index 05621315..bc202be3 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua | |||
@@ -432,8 +432,6 @@ function manif.update_manifest(name, version, repo, deps_mode) | |||
432 | 432 | ||
433 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | 433 | if deps_mode == "none" then deps_mode = cfg.deps_mode end |
434 | 434 | ||
435 | util.printout("Updating manifest for "..repo) | ||
436 | |||
437 | local manifest, err = manif.load_manifest(repo) | 435 | local manifest, err = manif.load_manifest(repo) |
438 | if not manifest then | 436 | if not manifest then |
439 | util.printerr("No existing manifest. Attempting to rebuild...") | 437 | util.printerr("No existing manifest. Attempting to rebuild...") |
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua index 66b1377f..b6d5825a 100644 --- a/src/luarocks/repos.lua +++ b/src/luarocks/repos.lua | |||
@@ -157,11 +157,10 @@ local function install_binary(source, target, name, version) | |||
157 | assert(type(target) == "string") | 157 | assert(type(target) == "string") |
158 | 158 | ||
159 | if fs.is_lua(source) then | 159 | if fs.is_lua(source) then |
160 | repos.ok, repos.err = fs.wrap_script(source, target, name, version) | 160 | return fs.wrap_script(source, target, name, version) |
161 | else | 161 | else |
162 | repos.ok, repos.err = fs.copy_binary(source, target) | 162 | return fs.copy_binary(source, target) |
163 | end | 163 | end |
164 | return repos.ok, repos.err | ||
165 | end | 164 | end |
166 | 165 | ||
167 | local function resolve_conflict(target, deploy_dir, name, version) | 166 | local function resolve_conflict(target, deploy_dir, name, version) |
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index 80f1684a..520625c0 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua | |||
@@ -506,6 +506,20 @@ function util.see_help(command, program) | |||
506 | return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'." | 506 | return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'." |
507 | end | 507 | end |
508 | 508 | ||
509 | function util.announce_install(rockspec) | ||
510 | local cfg = require("luarocks.cfg") | ||
511 | local path = require("luarocks.path") | ||
512 | |||
513 | local suffix = "" | ||
514 | if rockspec.description and rockspec.description.license then | ||
515 | suffix = " (license: "..rockspec.description.license..")" | ||
516 | end | ||
517 | |||
518 | local root_dir = path.root_dir(cfg.rocks_dir) | ||
519 | util.printout(rockspec.name.." "..rockspec.version.." is now installed in "..root_dir..suffix) | ||
520 | util.printout() | ||
521 | end | ||
522 | |||
509 | -- from http://lua-users.org/wiki/SplitJoin | 523 | -- from http://lua-users.org/wiki/SplitJoin |
510 | -- by PhilippeLhoste | 524 | -- by PhilippeLhoste |
511 | function util.split_string(str, delim, maxNb) | 525 | function util.split_string(str, delim, maxNb) |
diff --git a/src/luarocks/write_rockspec.lua b/src/luarocks/write_rockspec.lua index 972562c3..abfca322 100644 --- a/src/luarocks/write_rockspec.lua +++ b/src/luarocks/write_rockspec.lua | |||
@@ -12,14 +12,16 @@ local type_check = require("luarocks.type_check") | |||
12 | local util = require("luarocks.util") | 12 | local util = require("luarocks.util") |
13 | 13 | ||
14 | write_rockspec.help_summary = "Write a template for a rockspec file." | 14 | write_rockspec.help_summary = "Write a template for a rockspec file." |
15 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] {<url>|<path>}" | 15 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" |
16 | write_rockspec.help = [[ | 16 | write_rockspec.help = [[ |
17 | This command writes an initial version of a rockspec file, | 17 | This command writes an initial version of a rockspec file, |
18 | based on an URL or a local path. You may use a relative path such as '.'. | 18 | based on a name, a version, and a location (an URL or a local path). |
19 | If a local path is given, name and version arguments are mandatory. | 19 | If only two arguments are given, the first one is considered the name and the |
20 | For URLs, LuaRocks will attempt to infer name and version if not given. | 20 | second one is the location. |
21 | 21 | If only one argument is given, it must be the location. | |
22 | If a repository URL is given with no version, it creates an 'scm' rock. | 22 | If no arguments are given, current directory is used as location. |
23 | LuaRocks will attempt to infer name and version if not given, | ||
24 | using 'scm' as default version. | ||
23 | 25 | ||
24 | Note that the generated file is a _starting point_ for writing a | 26 | Note that the generated file is a _starting point_ for writing a |
25 | rockspec, and is not guaranteed to be complete or correct. | 27 | rockspec, and is not guaranteed to be complete or correct. |
@@ -198,18 +200,17 @@ end | |||
198 | 200 | ||
199 | function write_rockspec.run(...) | 201 | function write_rockspec.run(...) |
200 | local flags, name, version, url_or_dir = util.parse_flags(...) | 202 | local flags, name, version, url_or_dir = util.parse_flags(...) |
201 | |||
202 | if not name then | ||
203 | return nil, "Missing arguments. "..util.see_help("write_rockspec") | ||
204 | end | ||
205 | 203 | ||
206 | if name and not version then | 204 | if not name then |
205 | url_or_dir = "." | ||
206 | elseif not version then | ||
207 | url_or_dir = name | 207 | url_or_dir = name |
208 | name = nil | 208 | name = nil |
209 | elseif not url_or_dir then | 209 | elseif not url_or_dir then |
210 | url_or_dir = version | 210 | url_or_dir = version |
211 | version = nil | ||
211 | end | 212 | end |
212 | 213 | ||
213 | if flags["tag"] then | 214 | if flags["tag"] then |
214 | if not version then | 215 | if not version then |
215 | version = flags["tag"]:gsub("^v", "") | 216 | version = flags["tag"]:gsub("^v", "") |
@@ -217,28 +218,25 @@ function write_rockspec.run(...) | |||
217 | end | 218 | end |
218 | 219 | ||
219 | local protocol, pathname = dir.split_url(url_or_dir) | 220 | local protocol, pathname = dir.split_url(url_or_dir) |
220 | if not fetch.is_basic_protocol(protocol) then | 221 | if protocol == "file" then |
221 | if not name then | 222 | if pathname == "." then |
222 | name = dir.base_name(url_or_dir):gsub("%.[^.]+$", "") | 223 | name = name or dir.base_name(fs.current_dir()) |
223 | end | 224 | end |
224 | if not version then | 225 | elseif fetch.is_basic_protocol(protocol) then |
225 | version = "scm" | ||
226 | end | ||
227 | elseif protocol ~= "file" then | ||
228 | local filename = dir.base_name(url_or_dir) | 226 | local filename = dir.base_name(url_or_dir) |
229 | local newname, newversion = filename:match("(.*)-([^-]+)") | 227 | local newname, newversion = filename:match("(.*)-([^-]+)") |
230 | if (not name) and newname then | 228 | if newname then |
231 | name = newname | 229 | name = name or newname |
232 | end | 230 | version = version or newversion:gsub("%.[a-z]+$", ""):gsub("%.tar$", "") |
233 | if (not version) and newversion then | ||
234 | version = newversion:gsub(".[a-z]+$", ""):gsub(".tar$", "") | ||
235 | end | 231 | end |
236 | if not (name and version) then | 232 | else |
237 | return nil, "Missing name and version arguments. "..util.see_help("write_rockspec") | 233 | name = name or dir.base_name(url_or_dir):gsub("%.[^.]+$", "") |
238 | end | 234 | end |
239 | elseif not version then | 235 | |
240 | return nil, "Missing name and version arguments. "..util.see_help("write_rockspec") | 236 | if not name then |
237 | return nil, "Could not infer rock name. "..util.see_help("write_rockspec") | ||
241 | end | 238 | end |
239 | version = version or "scm" | ||
242 | 240 | ||
243 | local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec") | 241 | local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec") |
244 | 242 | ||
diff --git a/test/testing.lua b/test/testing.lua index c37293ee..1a837484 100644 --- a/test/testing.lua +++ b/test/testing.lua | |||
@@ -459,6 +459,25 @@ local tests = { | |||
459 | and assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.bz2")) | 459 | and assert("lua-compat-5.2" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2.tar.bz2")) |
460 | and assert("parser.moon" == fetch.url_to_base_dir("git://github.com/Cirru/parser.moon")) | 460 | and assert("parser.moon" == fetch.url_to_base_dir("git://github.com/Cirru/parser.moon")) |
461 | and assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3")) | 461 | and assert("v0.3" == fetch.url_to_base_dir("https://github.com/hishamhm/lua-compat-5.2/archive/v0.3")) |
462 | end, | ||
463 | |||
464 | -- Tests for https://github.com/keplerproject/luarocks/issues/552 | ||
465 | test_install_break_dependencies_warning = function() | ||
466 | need_luasocket() | ||
467 | return run "$luarocks install say ${new_version_say}" | ||
468 | and run "$luarocks install luassert" | ||
469 | and run "$luarocks install say ${old_version_say}" | ||
470 | end, | ||
471 | test_install_break_dependencies_force = function() | ||
472 | need_luasocket() | ||
473 | return run "$luarocks install say ${new_version_say}" | ||
474 | and run "$luarocks install luassert" | ||
475 | and run "$luarocks install --force say ${old_version_say}" | ||
476 | end, | ||
477 | test_install_break_dependencies_force = function() | ||
478 | need_luasocket() | ||
479 | return run "$luarocks install say ${new_version_say}" | ||
480 | and run "$luarocks install luassert" | ||
481 | and run "$luarocks install --force-fast say ${old_version_say}" | ||
462 | end | 482 | end |
463 | |||
464 | } | 483 | } |
diff --git a/test/testing.sh b/test/testing.sh index 5269e42a..f56f2aa9 100755 --- a/test/testing.sh +++ b/test/testing.sh | |||
@@ -179,6 +179,9 @@ srcdir_luasocket=luasocket-3.0-rc1 | |||
179 | version_cprint=0.1 | 179 | version_cprint=0.1 |
180 | verrev_cprint=0.1-2 | 180 | verrev_cprint=0.1-2 |
181 | 181 | ||
182 | new_version_say=1.2-1 | ||
183 | old_version_say=1.0-1 | ||
184 | |||
182 | version_luacov=0.11.0 | 185 | version_luacov=0.11.0 |
183 | verrev_luacov=${version_luacov}-1 | 186 | verrev_luacov=${version_luacov}-1 |
184 | version_lxsh=0.8.6 | 187 | version_lxsh=0.8.6 |
@@ -260,6 +263,9 @@ mkdir -p "$testing_server" | |||
260 | get "$luarocks_repo/lua-path-0.2.3-1.src.rock" | 263 | get "$luarocks_repo/lua-path-0.2.3-1.src.rock" |
261 | get "$luarocks_repo/lua-cjson-2.1.0-1.src.rock" | 264 | get "$luarocks_repo/lua-cjson-2.1.0-1.src.rock" |
262 | get "$luarocks_repo/luacov-coveralls-0.1.1-1.src.rock" | 265 | get "$luarocks_repo/luacov-coveralls-0.1.1-1.src.rock" |
266 | get "$luarocks_repo/say-1.2-1.src.rock" | ||
267 | get "$luarocks_repo/say-1.0-1.src.rock" | ||
268 | get "$luarocks_repo/luassert-1.7.0-1.src.rock" | ||
263 | ) | 269 | ) |
264 | $luarocks_admin_nocov make_manifest "$testing_server" | 270 | $luarocks_admin_nocov make_manifest "$testing_server" |
265 | 271 | ||
@@ -358,7 +364,6 @@ fail_upload_noarg() { $luarocks upload; } | |||
358 | fail_remove_noarg() { $luarocks remove; } | 364 | fail_remove_noarg() { $luarocks remove; } |
359 | fail_doc_noarg() { $luarocks doc; } | 365 | fail_doc_noarg() { $luarocks doc; } |
360 | fail_new_version_noarg() { $luarocks new_version; } | 366 | fail_new_version_noarg() { $luarocks new_version; } |
361 | fail_write_rockspec_noarg() { $luarocks write_rockspec; } | ||
362 | 367 | ||
363 | fail_build_invalid() { $luarocks build invalid; } | 368 | fail_build_invalid() { $luarocks build invalid; } |
364 | fail_download_invalid() { $luarocks download invalid; } | 369 | fail_download_invalid() { $luarocks download invalid; } |
@@ -517,6 +522,9 @@ test_deps_mode_make_order() { $luarocks build --tree="$testing_sys_tree" lpeg && | |||
517 | test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-${verrev_lxsh}; } | 522 | test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --source lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-${verrev_lxsh}; } |
518 | 523 | ||
519 | test_write_rockspec() { $luarocks write_rockspec git://github.com/keplerproject/luarocks; } | 524 | test_write_rockspec() { $luarocks write_rockspec git://github.com/keplerproject/luarocks; } |
525 | test_write_rockspec_name() { $luarocks write_rockspec luarocks git://github.com/keplerproject/luarocks; } | ||
526 | test_write_rockspec_name_version() { $luarocks write_rockspec luarocks 7.8.9 git://github.com/keplerproject/luarocks; } | ||
527 | test_write_rockspec_current_dir() { $luarocks write_rockspec; } | ||
520 | test_write_rockspec_tag() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --tag=v2.3.0; } | 528 | test_write_rockspec_tag() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --tag=v2.3.0; } |
521 | test_write_rockspec_lib() { $luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2; } | 529 | test_write_rockspec_lib() { $luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2; } |
522 | test_write_rockspec_format() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --rockspec-format=1.1 --lua-version=5.1,5.2; } | 530 | test_write_rockspec_format() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --rockspec-format=1.1 --lua-version=5.1,5.2; } |
@@ -558,8 +566,12 @@ test_doc_list() { $luarocks install luacov; $luarocks doc luacov --list; } | |||
558 | test_doc_local() { $luarocks install luacov; $luarocks doc luacov --local; } | 566 | test_doc_local() { $luarocks install luacov; $luarocks doc luacov --local; } |
559 | test_doc_porcelain() { $luarocks install luacov; $luarocks doc luacov --porcelain; } | 567 | test_doc_porcelain() { $luarocks install luacov; $luarocks doc luacov --porcelain; } |
560 | 568 | ||
561 | # Driver ######################################### | 569 | # Tests for https://github.com/keplerproject/luarocks/pull/552 |
570 | test_install_break_dependencies_warning() { need_luasocket; $luarocks install say ${new_version_say} && $luarocks install luassert && $luarocks install say ${old_version_say}; } | ||
571 | test_install_break_dependencies_force() { need_luasocket; $luarocks install say ${new_version_say} && $luarocks install luassert && $luarocks install --force say ${old_version_say}; } | ||
572 | test_install_break_dependencies_forcefast() { need_luasocket; $luarocks install say ${new_version_say} && $luarocks install luassert && $luarocks install --force-fast say ${old_version_say}; } | ||
562 | 573 | ||
574 | # Driver ######################################### | ||
563 | run_tests() { | 575 | run_tests() { |
564 | grep "^test_$1.*(" < $testing_dir/testing.sh | cut -d'(' -f1 | while read test | 576 | grep "^test_$1.*(" < $testing_dir/testing.sh | cut -d'(' -f1 | while read test |
565 | do | 577 | do |