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 /src | |
| 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
Diffstat (limited to 'src')
| -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 |
13 files changed, 300 insertions, 424 deletions
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 | ||
