From 984adfca55d6fb8ae06e1b894ffca87cf3b90ecf Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Fri, 3 Sep 2010 14:26:27 -0300 Subject: Add the 'show' command by Steve Donovan, plus some changes. Added an error check and some layout improvements, to make it look a bit like index.html from the repository. The only 'major' change was to present the repository path instead of the rock directory. I thought it would be confusing to present that path there since it's not where the modules are. --- src/bin/luarocks | 1 + src/luarocks/search.lua | 3 +- src/luarocks/show.lua | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ src/luarocks/util.lua | 27 ++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/luarocks/show.lua (limited to 'src') diff --git a/src/bin/luarocks b/src/bin/luarocks index fd0c1d9c..5da4bc25 100755 --- a/src/bin/luarocks +++ b/src/bin/luarocks @@ -17,5 +17,6 @@ commands.remove = require("luarocks.remove") commands.make = require("luarocks.make") commands.download = require("luarocks.download") commands.path = require("luarocks.path") +commands.show = require("luarocks.show") command_line.run_command(...) diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua index 6303eb8c..97b86a45 100644 --- a/src/luarocks/search.lua +++ b/src/luarocks/search.lua @@ -283,8 +283,9 @@ end -- @param results table: A table where keys are package names and versions -- are tables matching version strings to an array of rocks servers. -- @param show_repo boolean or nil: Whether to show repository +-- @param long boolean or nil: Whether to show module files -- information or not. Default is true. -function print_results(results, show_repo) +function print_results(results, show_repo, long) assert(type(results) == "table") assert(type(show_repo) == "boolean" or not show_repo) -- Force display of repo location for the time being diff --git a/src/luarocks/show.lua b/src/luarocks/show.lua new file mode 100644 index 00000000..fcdffb9c --- /dev/null +++ b/src/luarocks/show.lua @@ -0,0 +1,136 @@ + +--- Module implementing the LuaRocks "show" command. +-- Shows information about an installed rock. +module("luarocks.show", package.seeall) + +local search = require("luarocks.search") +local cfg = require("luarocks.cfg") +local util = require("luarocks.util") +local path = require("luarocks.path") +local dir = require("luarocks.dir") +local deps = require("luarocks.deps") +local fetch = require("luarocks.fetch") +local manif = require("luarocks.manif") +help_summary = "Shows information about an installed rock." + +help = [[ + is an existing package name. +Without any flags, show all module information. +With these flags, return only the desired information: + +--home home page of project +--modules all modules provided by this package as used by require() +--deps packages this package depends on +--rockspec the full path of the rockspec file +--mversion the package version +--tree local tree where rock is installed +--rock-dir data directory of the installed rock +]] + +local function keys_as_string(t, sep) + return table.concat(util.keys(t), sep or " ") +end + +local function word_wrap(line) + local width = tonumber(os.getenv("COLUMNS")) or 80 + if width > 80 then width = 80 end + if #line > width then + local brk = width + while brk > 0 and line:sub(brk, brk) ~= " " do + brk = brk - 1 + end + if brk > 0 then + return line:sub(1, brk-1) .. "\n" .. word_wrap(line:sub(brk+1)) + end + end + return line +end + +local function format_text(text) + text = text:gsub("^%s*",""):gsub("%s$", ""):gsub("\n[ \t]+","\n"):gsub("([^\n])\n([^\n])","%1 %2") + local paragraphs = util.split_string(text, "\n\n") + for n, line in ipairs(paragraphs) do + paragraphs[n] = word_wrap(line) + end + return (table.concat(paragraphs, "\n\n"):gsub("%s$", "")) +end + +--- Driver function for "show" command. +-- @param name or nil: an existing package name. +-- @param version string or nil: a version may also be passed. +-- @return boolean: True if succeeded, nil on errors. +function run(...) + local flags, name, version = util.parse_flags(...) + if not name then + return nil, "Argument missing, see help." + end + local results = {} + local query = search.make_query(name, version) + query.exact_name = true + local tree_map = {} + for _, tree in ipairs(cfg.rocks_trees) do + local rocks_dir = path.rocks_dir(tree) + tree_map[rocks_dir] = tree + search.manifest_search(results, rocks_dir, query) + end + + if not next(results) then -- + return nil,"cannot find package "..name.."\nUse 'list' to find installed rocks" + end + + local version,repo_url + local package, versions = util.sortedpairs(results)() + --question: what do we do about multiple versions? This should + --give us the latest version on the last repo (which is usually the global one) + for vs, repos in util.sortedpairs(versions, deps.compare_versions) do + version = vs + for _, rp in ipairs(repos) do repo_url = rp.repo end + end + + + local repo = tree_map[repo_url] + local directory = path.install_dir(name,version,repo) + local rockspec_file = path.rockspec_file(name, version, repo) + local rockspec, err = fetch.load_local_rockspec(rockspec_file) + if not rockspec then return nil,err end + + local descript = rockspec.description + local manifest, err = manif.load_manifest(repo_url) + if not manifest then return nil,err end + local minfo = manifest.repository[name][version][1] + + if flags["tree"] then print(repo) + elseif flags["rock-dir"] then print(directory) + elseif flags["home"] then print(descript.homepage) + elseif flags["modules"] then print(keys_as_string(minfo.modules)) + elseif flags["deps"] then print(keys_as_string(minfo.dependencies)) + elseif flags["rockspec"] then print(rockspec_file) + elseif flags["mversion"] then print(version) + else + print() + print(rockspec.package.." "..rockspec.version.." - "..descript.summary) + print() + print(format_text(descript.detailed)) + print() + if descript.license then + print("License: ", descript.license) + end + if descript.homepage then + print("Homepage: ", descript.homepage) + end + print("Installed in: ", repo) + if next(minfo.modules) then + print() + print("Modules:") + print("\t"..keys_as_string(minfo.modules, "\n\t")) + end + if next(minfo.dependencies) then + print() + print("Depends on:") + print("\t"..keys_as_string(minfo.dependencies, "\n\t")) + end + print() + end + return true +end + diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index 164dd260..ed70b2ba 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua @@ -243,6 +243,33 @@ function starts_with(s, prefix) return s:sub(1,#prefix) == prefix end +-- from http://lua-users.org/wiki/SplitJoin +-- by PhilippeLhoste +function split_string(str, delim, maxNb) + -- Eliminate bad cases... + if string.find(str, delim) == nil then + return { str } + end + if maxNb == nil or maxNb < 1 then + maxNb = 0 -- No limit + end + local result = {} + local pat = "(.-)" .. delim .. "()" + local nb = 0 + local lastPos + for part, pos in string.gfind(str, pat) do + nb = nb + 1 + result[nb] = part + lastPos = pos + if nb == maxNb then break end + end + -- Handle the last field + if nb ~= maxNb then + result[nb + 1] = string.sub(str, lastPos) + end + return result +end + --[[ Author: Julio Manuel Fernandez-Diaz Date: January 12, 2007 -- cgit v1.2.3-55-g6feb From 70182a664e30bd73c72cd15e82118325d12d499b Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 8 Sep 2010 17:27:43 -0300 Subject: Modify algorithm selection of rocks tree and add --local. Drop old behavior in which the tree list was scanned to find the first writable one (which meant users ended up installing rocks locally). Now it always tries the last in the list (which is by default the global one) and warns users when they have no write permissions. (It picks the _last_ one so that the old behavior when running sudo remains the same). Also add --local as a shorthand to specify the local tree, as suggested by Steve Donovan. --- src/luarocks/build.lua | 6 ++++ src/luarocks/cfg.lua | 2 +- src/luarocks/command_line.lua | 72 ++++++++++++++++++++----------------------- src/luarocks/help.lua | 1 + src/luarocks/install.lua | 5 +++ src/luarocks/make.lua | 6 ++++ src/luarocks/remove.lua | 7 +++++ src/luarocks/rep.lua | 6 ++-- 8 files changed, 64 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index 62ac3808..c6c3a002 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua @@ -11,6 +11,7 @@ local fs = require("luarocks.fs") local dir = require("luarocks.dir") local deps = require("luarocks.deps") local manif = require("luarocks.manif") +local cfg = require("luarocks.cfg") help_summary = "Build/compile a rock." help_arguments = "{|| []}" @@ -269,6 +270,11 @@ function run(...) end assert(type(version) == "string" or not version) + if not flags["local"] and not fs.is_writable(cfg.root_dir) then + return nil, "Your user does not have write permissions in " .. cfg.root_dir .. + " \n-- you may want to run as a privileged user or use your local tree with --local." + end + if name:match("%.rockspec$") then return build_rockspec(name, true) elseif name:match("%.src%.rock$") then diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua index 261411b7..67cd17b7 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/cfg.lua @@ -83,7 +83,7 @@ end -- Path configuration: -local sys_config_file, home_config_file, home_tree +local sys_config_file, home_config_file if detected.windows or detected.mingw32 then home = os.getenv("APPDATA") or "c:" sys_config_file = "c:/luarocks/config.lua" diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua index d501d121..71ded87d 100644 --- a/src/luarocks/command_line.lua +++ b/src/luarocks/command_line.lua @@ -33,6 +33,14 @@ local function is_writable(tree) end end +local function use_tree(tree) + cfg.root_dir = tree + cfg.rocks_dir = path.rocks_dir(tree) + cfg.deploy_bin_dir = path.deploy_bin_dir(tree) + cfg.deploy_lua_dir = path.deploy_lua_dir(tree) + cfg.deploy_lib_dir = path.deploy_lib_dir(tree) +end + --- Main command-line processor. -- Parses input arguments and calls the appropriate driver function -- to execute the action requested on the command-line, forwarding @@ -58,30 +66,39 @@ function run_command(...) local nonflags = { util.parse_flags(unpack(args)) } local flags = table.remove(nonflags, 1) cfg.flags = flags + + local command + + if flags["version"] then + print(program_name.." "..cfg.program_version) + print(program_description) + print() + os.exit(0) + elseif flags["help"] or #nonflags == 0 then + command = "help" + args = nonflags + else + command = nonflags[1] + for i, arg in ipairs(args) do + if arg == command then + table.remove(args, i) + break + end + end + end + command = command:gsub("-", "_") if flags["to"] then if flags["to"] == true then die("Argument error: use --to=") end local root_dir = fs.absolute_name(flags["to"]) - cfg.root_dir = root_dir - cfg.rocks_dir = path.rocks_dir(root_dir) - cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir) - cfg.deploy_lua_dir = path.deploy_lua_dir(root_dir) - cfg.deploy_lib_dir = path.deploy_lib_dir(root_dir) + use_tree(root_dir) + elseif flags["local"] then + use_tree(cfg.home_tree) else local trees = cfg.rocks_trees - for i = #trees, 1, -1 do - local tree = trees[i] - if is_writable(tree) then - cfg.root_dir = tree - cfg.rocks_dir = path.rocks_dir(tree) - cfg.deploy_bin_dir = path.deploy_bin_dir(tree) - cfg.deploy_lua_dir = path.deploy_lua_dir(tree) - cfg.deploy_lib_dir = path.deploy_lib_dir(tree) - break - end - end + use_tree(trees[#trees]) end if type(cfg.root_dir) == "string" then @@ -111,34 +128,13 @@ function run_command(...) end cfg.rocks_servers = { flags["only-from"] } end - - local command - - if flags["version"] then - print(program_name.." "..cfg.program_version) - print(program_description) - print() - os.exit(0) - elseif flags["help"] or #nonflags == 0 then - command = "help" - args = nonflags - else - command = nonflags[1] - for i, arg in ipairs(args) do - if arg == command then - table.remove(args, i) - break - end - end - end - + if command ~= "help" then for k, v in pairs(cmdline_vars) do cfg.variables[k] = v end end - command = command:gsub("-", "_") if commands[command] then local xp, ok, err = xpcall(function() return commands[command].run(unpack(args)) end, function(err) die(debug.traceback("LuaRocks "..cfg.program_version diff --git a/src/luarocks/help.lua b/src/luarocks/help.lua index 04fea7ce..5162b917 100644 --- a/src/luarocks/help.lua +++ b/src/luarocks/help.lua @@ -40,6 +40,7 @@ can be overriden with VAR=VALUE assignments. --only-from= Fetch rocks/rockspecs from this server only (overrides any entries in the config file) --to= Which tree to operate on. +--local Use the tree in the user's home directory. Supported commands: ]]) diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua index 260c7751..74602f47 100644 --- a/src/luarocks/install.lua +++ b/src/luarocks/install.lua @@ -99,6 +99,11 @@ function run(...) return nil, "Argument missing, see help." end + if not flags["local"] and not fs.is_writable(cfg.root_dir) then + return nil, "Your user does not have write permissions in " .. cfg.root_dir .. + " \n-- you may want to run as a privileged user or use your local tree with --local." + end + if name:match("%.rockspec$") or name:match("%.src%.rock$") then local build = require("luarocks.build") return build.run(name) diff --git a/src/luarocks/make.lua b/src/luarocks/make.lua index cb2ba374..ec3772ac 100644 --- a/src/luarocks/make.lua +++ b/src/luarocks/make.lua @@ -8,6 +8,7 @@ module("luarocks.make", package.seeall) local build = require("luarocks.build") local fs = require("luarocks.fs") local util = require("luarocks.util") +local cfg = require("luarocks.cfg") help_summary = "Compile package in current directory using a rockspec." help_arguments = "[]" @@ -30,6 +31,11 @@ To install rocks, you'll normally want to use the "install" and function run(...) local flags, rockspec = util.parse_flags(...) assert(type(rockspec) == "string" or not rockspec) + + if not flags["local"] and not fs.is_writable(cfg.root_dir) then + return nil, "Your user does not have write permissions in " .. cfg.root_dir .. + " \n-- you may want to run as a privileged user or use your local tree with --local." + end if not rockspec then local files = fs.list_dir(fs.current_dir()) diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua index afd299ae..d77f28fa 100644 --- a/src/luarocks/remove.lua +++ b/src/luarocks/remove.lua @@ -11,6 +11,7 @@ local path = require("luarocks.path") local util = require("luarocks.util") local cfg = require("luarocks.cfg") local manif = require("luarocks.manif") +local fs = require("luarocks.fs") help_summary = "Uninstall a rock." help_arguments = "[--force] []" @@ -81,6 +82,12 @@ function run(...) if type(name) ~= "string" then return nil, "Argument missing, see help." end + + if not flags["local"] and not fs.is_writable(cfg.rocks_dir) then + return nil, "Your user does not have write permissions in " .. cfg.rocks_dir .. + " \n-- you may want to run as a privileged user or use your local tree with --local." + end + local results = {} search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version)) diff --git a/src/luarocks/rep.lua b/src/luarocks/rep.lua index 5da5953f..322ab166 100644 --- a/src/luarocks/rep.lua +++ b/src/luarocks/rep.lua @@ -252,10 +252,11 @@ function delete_version(name, version) local target = dir.path(deploy_dir, parent_path, file) local versioned = path.versioned_name(target, deploy_dir, name, version) if fs.exists(versioned) then - fs.delete(versioned) + local ok = fs.delete(versioned) fs.remove_dir_tree_if_empty(dir.dir_name(versioned)) + if not ok then return nil, "Failed deleting "..versioned end else - fs.delete(target) + local ok = fs.delete(target) local next_name, next_version = manif.find_next_provider(target) if next_name then local versioned = path.versioned_name(target, deploy_dir, next_name, next_version) @@ -263,6 +264,7 @@ function delete_version(name, version) fs.remove_dir_tree_if_empty(dir.dir_name(versioned)) end fs.remove_dir_tree_if_empty(dir.dir_name(target)) + if not ok then return nil, "Failed deleting "..target end end return true end -- cgit v1.2.3-55-g6feb From 455818ca4ce650a31a27de7f2a57c04293c2ffe8 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 9 Sep 2010 13:46:01 -0300 Subject: Add message after build and install complete. Indicates where installation took place, and license. --- src/luarocks/build.lua | 8 ++++++++ src/luarocks/install.lua | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index c6c3a002..b7386688 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua @@ -230,6 +230,14 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode) ok, err = manif.update_manifest(name, version) if err then return nil, err end + local license = "" + if rockspec.description.license then + license = ("(license: "..rockspec.description.license..")") + end + + print() + print(name.." "..version.." is now built and installed in "..cfg.root_dir.." "..license) + util.remove_scheduled_function(rollback) return true end diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua index 74602f47..4bb073dc 100644 --- a/src/luarocks/install.lua +++ b/src/luarocks/install.lua @@ -79,6 +79,14 @@ function install_binary_rock(rock_file) ok, err = manif.update_manifest(name, version) if err then return nil, err end + local license = "" + if rockspec.description.license then + license = ("(license: "..rockspec.description.license..")") + end + + print() + print(name.." "..version.." is now installed in "..cfg.root_dir.." "..license) + util.remove_scheduled_function(rollback) return true end -- cgit v1.2.3-55-g6feb From b6cfc996eb570cdcab1ca4d4c3e80c851aef7d1e Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 9 Sep 2010 16:01:11 -0300 Subject: Remove LuaCurl now that we have download() implemented with LuaSocket --- src/luarocks/fs/lua.lua | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'src') diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index f3d75b44..cd0a31e0 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -14,7 +14,6 @@ local _, ftp = pcall(require, "socket.ftp") local zip_ok, lrzip = pcall(require, "luarocks.tools.zip") local unzip_ok, luazip = pcall(require, "zip"); _G.zip = nil local lfs_ok, lfs = pcall(require, "lfs") ---local curl_ok, curl = pcall(require, "luacurl") local md5_ok, md5 = pcall(require, "md5") local posix_ok, posix = pcall(require, "posix") @@ -449,47 +448,6 @@ end end ---------------------------------------------------------------------- --- LuaCurl functions ---------------------------------------------------------------------- - -if curl_ok then - ---- Download a remote file. --- @param url string: URL to be fetched. --- @param filename string or nil: this function attempts to detect the --- resulting local filename of the remote file as the basename of the URL; --- if that is not correct (due to a redirection, for example), the local --- filename can be given explicitly as this second argument. --- @return boolean: true on success, false on failure. -function download(url, filename) - assert(type(url) == "string") - assert(type(filename) == "string" or not filename) - - filename = dir.path(fs.current_dir(), filename or dir.base_name(url)) - - local c = curl.new() - if not c then return false end - local file = io.open(filename, "wb") - if not file then return false end - local ok = c:setopt(curl.OPT_WRITEFUNCTION, function (stream, buffer) - stream:write(buffer) - return string.len(buffer) - end) - ok = ok and c:setopt(curl.OPT_WRITEDATA, file) - ok = ok and c:setopt(curl.OPT_BUFFERSIZE, 5000) - ok = ok and c:setopt(curl.OPT_HTTPHEADER, "Connection: Keep-Alive") - ok = ok and c:setopt(curl.OPT_URL, url) - ok = ok and c:setopt(curl.OPT_CONNECTTIMEOUT, 15) - ok = ok and c:setopt(curl.OPT_USERAGENT, cfg.user_agent) - ok = ok and c:perform() - ok = ok and c:close() - file:close() - return ok -end - -end - --------------------------------------------------------------------- -- LuaSocket functions --------------------------------------------------------------------- -- cgit v1.2.3-55-g6feb From 569ab48390725c2d87f9a89cdeb47bae3fc2cd46 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Thu, 9 Sep 2010 16:03:13 -0300 Subject: Preserve permissions when copying files --- src/luarocks/cfg.lua | 2 ++ src/luarocks/fs/lua.lua | 6 ++++++ src/luarocks/fs/unix.lua | 1 - src/luarocks/fs/unix/tools.lua | 9 +++++++++ src/luarocks/fs/win32.lua | 8 ++++++++ 5 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua index 67cd17b7..45c73bf6 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/cfg.lua @@ -63,9 +63,11 @@ end if system == "FreeBSD" then detected.unix = true detected.freebsd = true + detected.bsd = true elseif system == "Darwin" then detected.unix = true detected.macosx = true + detected.bsd = true elseif system == "Linux" then detected.unix = true detected.linux = true diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index cd0a31e0..70df65be 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -230,6 +230,7 @@ function copy(src, dest) if destmode == "directory" then dest = dir.path(dest, dir.base_name(src)) end + local perms = fs.get_permissions(src) local src_h, err = io.open(src, "rb") if not src_h then return nil, err end local dest_h, err = io.open(dest, "wb+") @@ -241,6 +242,7 @@ function copy(src, dest) end src_h:close() dest_h:close() + fs.chmod(dest, perms) return true end @@ -571,6 +573,10 @@ function chmod(file, mode) return err == 0 end +function get_permissions(file) + return posix.stat(file, "mode") +end + end --------------------------------------------------------------------- diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index 94a3ad4e..f2290412 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua @@ -122,4 +122,3 @@ end function copy_binary(filename, dest) return fs.copy(filename, dest) end - diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua index 33dbc489..2bfa7c3e 100644 --- a/src/luarocks/fs/unix/tools.lua +++ b/src/luarocks/fs/unix/tools.lua @@ -343,3 +343,12 @@ function unpack_archive(archive) end return true end + +function get_permissions(filename) + local ret + local flag = cfg.is_platform("bsd") and "-f '%A'" or "-c '%a'" + local pipe = io.popen("stat "..flag.." "..fs.Q(filename)) + ret = pipe:read("*l") + pipe:close() + return ret +end diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index d87ad90d..44740850 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua @@ -95,3 +95,11 @@ function copy_binary(filename, dest) end return true end + +function chmod(filename, mode) + return true +end + +function get_permissions(filename) + return "" +end -- cgit v1.2.3-55-g6feb