From 69a6a162a0def6a52252bbcae3fc747dfd4268aa Mon Sep 17 00:00:00 2001 From: Fabio Mascarenhas Date: Fri, 15 Jan 2010 17:56:26 -0200 Subject: --force option for install/build/make to overwrite non-tracked files, parameterized paths for working with Lua for Windows --- src/luarocks/cfg.lua | 23 +++++---- src/luarocks/command_line.lua | 29 ++++++++--- src/luarocks/fs/lua.lua | 52 ++++++++++++++------ src/luarocks/fs/win32/tools.lua | 10 ++-- src/luarocks/manif.lua | 28 +++++------ src/luarocks/path.lua | 103 ++++++++++++++++++++++------------------ src/luarocks/rep.lua | 13 +++-- src/luarocks/validate.lua | 5 +- 8 files changed, 160 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua index c39056b4..220e7b29 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/cfg.lua @@ -1,6 +1,6 @@ -local rawset, next, table, pairs, print, require, io, os, setmetatable, pcall, ipairs, package = - rawset, next, table, pairs, print, require, io, os, setmetatable, pcall, ipairs, package +local rawset, next, table, pairs, print, require, io, os, setmetatable, pcall, ipairs, package, type = + rawset, next, table, pairs, print, require, io, os, setmetatable, pcall, ipairs, package, type --- Configuration for LuaRocks. -- Tries to load the user's configuration file and @@ -22,6 +22,8 @@ if not ok then config = {} end +_M.config = config + program_version = "2.0.2" user_agent = "LuaRocks/"..program_version @@ -117,15 +119,10 @@ end -- Configure defaults: -local root = config.LUAROCKS_ROCKS_TREE or home_tree +local root = rocks_trees[#rocks_trees] local defaults = { - root_dir = root, - rocks_dir = root.."/lib/luarocks/rocks", lua_modules_path = "/share/lua/5.1/", lib_modules_path = "/lib/lua/5.1/", - deploy_bin_dir = root.."/bin/", - deploy_lua_dir = root.."/share/lua/5.1/", - deploy_lib_dir = root.."/lib/lua/5.1/", arch = "unknown", lib_extension = "unknown", @@ -289,7 +286,13 @@ setmetatable(_M, cfg_mt) for _,tree in ipairs(rocks_trees) do - package.path = tree..lua_modules_path.."/?.lua;"..tree..lua_modules_path.."/?/init.lua;"..package.path - package.cpath = tree..lib_modules_path.."/?."..lib_extension..";"..package.cpath + if type(tree) == "string" then + package.path = tree..lua_modules_path.."/?.lua;"..tree..lua_modules_path.."/?/init.lua;"..package.path + package.cpath = tree..lib_modules_path.."/?."..lib_extension..";"..package.cpath + else + package.path = (tree.lua_dir or tree.root..lua_modules_path).."/?.lua;".. + (tree.lua_dir or tree.root..lua_modules_path).."/?/init.lua;"..package.path + package.cpath = (tree.lib_dir or tree.root..lib_modules_path).."/?."..lib_extension..";"..package.cpath + end end diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua index f2afc16a..d501d121 100644 --- a/src/luarocks/command_line.lua +++ b/src/luarocks/command_line.lua @@ -21,6 +21,18 @@ local function die(message) os.exit(1) end +local function is_writable(tree) + if type(tree) == "string" then + return fs.make_dir(tree) and fs.is_writable(tree) + else + writable = true + for k, v in pairs(tree) do + writable = writable and fs.make_dir(v) and fs.is_writable(v) + end + return writable + end +end + --- Main command-line processor. -- Parses input arguments and calls the appropriate driver function -- to execute the action requested on the command-line, forwarding @@ -45,6 +57,7 @@ function run_command(...) end local nonflags = { util.parse_flags(unpack(args)) } local flags = table.remove(nonflags, 1) + cfg.flags = flags if flags["to"] then if flags["to"] == true then @@ -60,24 +73,28 @@ function run_command(...) local trees = cfg.rocks_trees for i = #trees, 1, -1 do local tree = trees[i] - if fs.make_dir(tree) and fs.is_writable(tree) then + if is_writable(tree) then cfg.root_dir = tree cfg.rocks_dir = path.rocks_dir(tree) - cfg.deploy_bin_dir = rawget(cfg, "deploy_bin_dir") or path.deploy_bin_dir(tree) - cfg.deploy_lua_dir = rawget(cfg, "deploy_lua_dir") or path.deploy_lua_dir(tree) - cfg.deploy_lib_dir = rawget(cfg, "deploy_lib_dir") or path.deploy_lib_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 end - cfg.root_dir = cfg.root_dir:gsub("/+$", "") + if type(cfg.root_dir) == "string" then + cfg.root_dir = cfg.root_dir:gsub("/+$", "") + else + cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "") + end cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "") cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "") cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "") cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "") - cfg.variables.ROCKS_TREE = cfg.root_dir + cfg.variables.ROCKS_TREE = cfg.rocks_dir cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir if flags["from"] then diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index 3314d394..220c046d 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -8,7 +8,8 @@ local fs = require("luarocks.fs") local cfg = require("luarocks.cfg") local dir = require("luarocks.dir") -local zip_ok, zip = pcall(require, "luarocks.tools.zip") +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") @@ -18,7 +19,7 @@ local tar = require("luarocks.tools.tar") local patch = require("luarocks.tools.patch") local dir_stack = {} - + math.randomseed(os.time()) dir_separator = "/" @@ -29,7 +30,7 @@ dir_separator = "/" -- @return string: Quoted argument. function Q(arg) assert(type(arg) == "string") - + -- FIXME Unix-specific return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'" end @@ -82,7 +83,7 @@ end -- otherwise. function execute(command, ...) assert(type(command) == "string") - + for _, arg in ipairs({...}) do assert(type(arg) == "string") command = command .. " " .. fs.Q(arg) @@ -243,7 +244,7 @@ end -- @return boolean or (boolean, string): true on success, false on failure local function recursive_copy(src, dest) local srcmode = lfs.attributes(src, "mode") - + if srcmode == "file" then local ok = fs.copy(src, dest) if not ok then return false end @@ -268,7 +269,7 @@ end function copy_contents(src, dest) assert(src and dest) assert(lfs.attributes(src, "mode") == "directory") - + for file in lfs.dir(src) do if file ~= "." and file ~= ".." then local ok = recursive_copy(dir.path(src, file), dest) @@ -287,7 +288,7 @@ end -- or nil and an error message on failure. local function recursive_delete(src) local srcmode = lfs.attributes(src, "mode") - + if srcmode == "file" then return os.remove(src) elseif srcmode == "directory" then @@ -312,7 +313,7 @@ function delete(arg) return recursive_delete(arg) or false end ---- List the contents of a directory. +--- List the contents of a directory. -- @param at string or nil: directory to list (will be the current -- directory if none is given). -- @return table: an array of strings with the filenames representing @@ -351,7 +352,7 @@ local function recursive_find(cwd, prefix, result) end end ---- Recursively scan the contents of a directory. +--- Recursively scan the contents of a directory. -- @param at string or nil: directory to scan (will be the current -- directory if none is given). -- @return table: an array of strings with the filenames representing @@ -405,17 +406,38 @@ end if zip_ok then -local function zip(zipfile, ...) - return zip.zip(zipfile, ...) +function zip(zipfile, ...) + return lrzip.zip(zipfile, ...) +end + end +if unzip_ok then --- Uncompress files from a .zip archive. -- @param zipfile string: pathname of .zip archive to be extracted. -- @return boolean: true on success, false on failure. function unzip(zipfile) - assert(zipfile) - -- FIXME!!!! - return fs.execute("unzip", zipfile) + local zipfile, err = luazip.open(zipfile) + if not zipfile then return nil, err end + local files = zipfile:files() + local file = files() + repeat + if file.filename:sub(#file.filename) == "/" then + fs.make_dir(dir.path(fs.current_dir(), file.filename)) + else + local rf, err = zipfile:open(file.filename) + if not rf then zipfile:close(); return nil, err end + local contents = rf:read("*a") + rf:close() + local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb") + if not wf then zipfile:close(); return nil, err end + wf:write(contents) + wf:close() + end + file = files() + until not file + zipfile:close() + return true end end @@ -437,7 +459,7 @@ function download(url, filename) assert(type(url) == "string") assert(type(filename) == "string" or not filename) - filename = filename or dir.base_name(url) + filename = dir.path(fs.current_dir(), filename or dir.base_name(url)) local c = curl.new() if not c then return false end diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua index 2bd2b8c5..0555a3b1 100644 --- a/src/luarocks/fs/win32/tools.lua +++ b/src/luarocks/fs/win32/tools.lua @@ -206,7 +206,7 @@ function delete(arg) return fs.execute_string("rm -rf " .. fs.Q(arg) .. " 1> NUL 2> NUL") end ---- List the contents of a directory. +--- List the contents of a directory. -- @param at string or nil: directory to list (will be the current -- directory if none is given). -- @return table: an array of strings with the filenames representing @@ -229,7 +229,7 @@ function list_dir(at) return result end ---- Recursively scan the contents of a directory. +--- Recursively scan the contents of a directory. -- @param at string or nil: directory to scan (will be the current -- directory if none is given). -- @return table: an array of strings with the filenames representing @@ -243,7 +243,7 @@ function find(at) return {} end local result = {} - local pipe = io.popen(command_at(at, "find 2> NUL")) + local pipe = io.popen(command_at(at, "find 2> NUL")) for file in pipe:lines() do -- Windows find is a bit different if file:sub(1,2)==".\\" then file=file:sub(3) end @@ -266,7 +266,7 @@ function download(url, filename) assert(type(filename) == "string" or not filename) local wget_cmd = "wget --cache=off --user-agent="..cfg.user_agent.." --quiet --continue " - if filename then + if filename then return fs.execute(wget_cmd.." --output-document ", filename, url) else return fs.execute(wget_cmd, url) @@ -307,7 +307,7 @@ end -- @return boolean or (boolean, string): true on success, false and an error message on failure. function unpack_archive(archive) assert(type(archive) == "string") - + local ok if archive:match("%.tar%.gz$") then ok = gunzip(archive) diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index 9f6f6fa2..7f0a4ea0 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua @@ -56,7 +56,7 @@ function make_rock_manifest(name, version) local last_name for name in file:gmatch("[^/]+") do local next = walk[name] - if not next then + if not next then next = {} walk[name] = next end @@ -81,7 +81,7 @@ end -- or nil followed by an error message and an optional error code. function load_manifest(repo_url) assert(type(repo_url) == "string") - + if manif_core.manifest_cache[repo_url] then return manif_core.manifest_cache[repo_url] end @@ -141,7 +141,7 @@ local function sort_pkgs(a, b) local na, va = a:match("(.*)/(.*)$") local nb, vb = b:match("(.*)/(.*)$") - + return (na == nb) and deps.compare_versions(va, vb) or na < nb end @@ -150,7 +150,7 @@ end -- and values arrays of strings with packages names in "name/version" format. local function sort_package_matching_table(tbl) assert(type(tbl) == "table") - + if next(tbl) then for item, pkgs in pairs(tbl) do if #pkgs > 1 then @@ -275,8 +275,7 @@ end function update_manifest(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(type(repo) == "string" or not repo) - repo = repo or cfg.rocks_dir + repo = path.rocks_dir(repo or cfg.root_dir) print("Updating manifest for "..repo) @@ -297,7 +296,7 @@ function update_manifest(name, version, repo) local ok, err = store_results(results, manifest) if not ok then return nil, err end - + return save_table(repo, "manifest", manifest) end @@ -307,7 +306,6 @@ end local function find_providers(file, root) assert(type(file) == "string") - assert(type(root) == "string" or not root) root = root or cfg.root_dir local manifest = manif_core.load_local_manifest(path.rocks_dir(root)) @@ -319,22 +317,22 @@ local function find_providers(file, root) local deploy_lib = path.deploy_lib_dir(root) local key, manifest_tbl - if starts_with(file, deploy_bin) then - manifest_tbl = manifest.commands - key = file:sub(#deploy_bin+1):gsub("^/*", "") - elseif starts_with(file, deploy_lua) then + if starts_with(file, deploy_lua) then manifest_tbl = manifest.modules - key = path.path_to_module(file:sub(#deploy_lua+1)) + key = path.path_to_module(file:sub(#deploy_lua+1):gsub("\\", "/")) elseif starts_with(file, deploy_lib) then manifest_tbl = manifest.modules - key = path.path_to_module(file:sub(#deploy_lib+1)) + key = path.path_to_module(file:sub(#deploy_lib+1):gsub("\\", "/")) + elseif starts_with(file, deploy_bin) then + manifest_tbl = manifest.commands + key = file:sub(#deploy_bin+1):gsub("^[\\/]*", "") else assert(false, "Assertion failed: '"..file.."' is not a deployed file.") end local providers = manifest_tbl[key] if not providers then - return nil, "File "..file.." is not tracked by LuaRocks." + return nil, "untracked" end return providers end diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua index 596b73b8..05e04b43 100644 --- a/src/luarocks/path.lua +++ b/src/luarocks/path.lua @@ -17,28 +17,48 @@ function rockspec_name_from_rock(rock_name) end function rocks_dir(repo) - assert(type(repo) == "string") - return dir.path(repo, "lib", "luarocks", "rocks") + if type(repo) == "string" then + return dir.path(repo, "lib", "luarocks", "rocks") + else + assert(type(repo) == "table") + return repo.rocks_dir or dir.path(repo.root, "lib", "luarocks", "rocks") + end end function deploy_bin_dir(repo) - assert(type(repo) == "string") - return dir.path(repo, "bin") + if type(repo) == "string" then + return dir.path(repo, "bin") + else + assert(type(repo) == "table") + return repo.bin_dir or dir.path(repo.root, "bin") + end end function deploy_lua_dir(repo) - assert(type(repo) == "string") - return dir.path(repo, "share", "lua", "5.1") + if type(repo) == "string" then + return dir.path(repo, "share", "lua", "5.1") + else + assert(type(repo) == "table") + return repo.lua_dir or dir.path(repo.root, "share", "lua", "5.1") + end end function deploy_lib_dir(repo) - assert(type(repo) == "string") - return dir.path(repo, "lib", "lua", "5.1") + if type(repo) == "string" then + return dir.path(repo, "lib", "lua", "5.1") + else + assert(type(repo) == "table") + return repo.lib_dir or dir.path(repo.root, "lib", "lua", "5.1") + end end function manifest_file(repo) - assert(type(repo) == "string") - return dir.path(repo, "lib", "luarocks", "rocks", "manifest") + if type(repo) == "string" then + return dir.path(repo, "lib", "luarocks", "rocks", "manifest") + else + assert(type(repo) == "table") + return (repo.rocks_dir and dir.path(repo.rocks_dir, "manifest")) or dir.path(repo.root, "lib", "luarocks", "rocks", "manifest") + end end --- Get the repository directory for all versions of a package. @@ -46,11 +66,10 @@ end -- @return string: The resulting path -- does not guarantee that -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- the package (and by extension, the path) exists. -function versions_dir(name, rocks_dir) +function versions_dir(name, repo) assert(type(name) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name) + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name) end --- Get the local installation directory (prefix) for a package. @@ -59,12 +78,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function install_dir(name, version, rocks_dir) +function install_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version) + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version) end --- Get the local filename of the rockspec of an installed rock. @@ -73,12 +91,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the file) exists. -function rockspec_file(name, version, rocks_dir) +function rockspec_file(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, name.."-"..version..".rockspec") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, name.."-"..version..".rockspec") end --- Get the local filename of the rock_manifest file of an installed rock. @@ -87,12 +104,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the file) exists. -function rock_manifest_file(name, version, rocks_dir) +function rock_manifest_file(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "rock_manifest") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "rock_manifest") end --- Get the local installation directory for C libraries of a package. @@ -101,12 +117,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function lib_dir(name, version, rocks_dir) +function lib_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "lib") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "lib") end --- Get the local installation directory for Lua modules of a package. @@ -115,12 +130,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function lua_dir(name, version, rocks_dir) +function lua_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "lua") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "lua") end --- Get the local installation directory for documentation of a package. @@ -129,12 +143,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function doc_dir(name, version, rocks_dir) +function doc_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "doc") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "doc") end --- Get the local installation directory for configuration files of a package. @@ -143,12 +156,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function conf_dir(name, version, rocks_dir) +function conf_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "conf") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "conf") end --- Get the local installation directory for command-line scripts @@ -158,12 +170,11 @@ end -- @param rocks_dir string or nil: If given, specifies the local repository to use. -- @return string: The resulting path -- does not guarantee that -- the package (and by extension, the path) exists. -function bin_dir(name, version, rocks_dir) +function bin_dir(name, version, repo) assert(type(name) == "string") assert(type(version) == "string") - assert(not rocks_dir or type(rocks_dir) == "string") - - return dir.path(rocks_dir or cfg.rocks_dir, name, version, "bin") + repo = repo or cfg.root_dir + return dir.path(rocks_dir(repo), name, version, "bin") end --- Extract name, version and arch of a rock filename. diff --git a/src/luarocks/rep.lua b/src/luarocks/rep.lua index de6b01bb..8b42caa2 100644 --- a/src/luarocks/rep.lua +++ b/src/luarocks/rep.lua @@ -208,9 +208,16 @@ function deploy_files(name, version) local target = dir.path(deploy_dir, parent_path, file) local ok, err if fs.exists(target) then - target, err = resolve_conflict(target, deploy_dir, name, version) - if err then return nil, err.." Cannot install new version." end - end + local new_target, err = resolve_conflict(target, deploy_dir, name, version) + if err == "untracked" then + if cfg.flags["force"] then + fs.delete(target) + else + return nil, "File "..file.." is not tracked by LuaRocks. Cannot install new version. Install with --force if you want to install anyway." + end + elseif err then return nil, err.." Cannot install new version." + else target = new_target end + end fs.make_dir(dir.dir_name(target)) ok, err = move_fn(source, target) fs.remove_dir_tree_if_empty(dir.dir_name(source)) diff --git a/src/luarocks/validate.lua b/src/luarocks/validate.lua index b8b4edfd..ef402988 100644 --- a/src/luarocks/validate.lua +++ b/src/luarocks/validate.lua @@ -33,7 +33,7 @@ local function restore_settings(settings) cfg.deploy_bin_dir = settings.deploy_bin_dir cfg.deploy_lua_dir = settings.deploy_lua_dir cfg.deploy_lib_dir = settings.deploy_lib_dir - cfg.variables.ROCKS_TREE = settings.root_dir + cfg.variables.ROCKS_TREE = settings.rocks_dir cfg.variables.SCRIPTS_DIR = settings.deploy_bin_dir table.remove(cfg.rocks_servers, 1) end @@ -43,7 +43,7 @@ local function prepare_sandbox(file) cfg.root_dir = root_dir cfg.rocks_dir = path.rocks_dir(root_dir) cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir) - cfg.variables.ROCKS_TREE = cfg.root_dir + cfg.variables.ROCKS_TREE = cfg.rocks_dir cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir return root_dir end @@ -154,7 +154,6 @@ end function run(...) local flags, repo = util.parse_flags(...) - assert(type(repo) == "string" or not repo) repo = repo or cfg.rocks_dir print("Verifying contents of "..repo) -- cgit v1.2.3-55-g6feb