From 230da1deaefff2404e0ea4aa380c2e7cda306733 Mon Sep 17 00:00:00 2001 From: hisham Date: Sun, 4 Oct 2009 19:47:11 +0000 Subject: Implement deployment and removal of files git-svn-id: http://luarocks.org/svn/luarocks/trunk@63 9ca3f7c1-7366-0410-b1a3-b5c78f85698c --- src/luarocks/fs/lua.lua | 2 +- src/luarocks/manif.lua | 36 ++++++++++- src/luarocks/path.lua | 17 ++++++ src/luarocks/rep.lua | 154 +++++++++++++++++++++++++++++++----------------- 4 files changed, 152 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index dd9857a0..c7d7fb2a 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -511,7 +511,7 @@ end -- plus an error message. function move(src, dest) assert(src and dest) - if fs.exists(dest) then + if fs.exists(dest) and not fs.is_dir(dest) then return false, "File already exists: "..dest end local ok, err = fs.copy(src, dest) diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index de885ca5..e3e2728b 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua @@ -293,9 +293,41 @@ function update_manifest(name, version, repo) local results = {[name] = {[version] = {{arch = "installed", repo = repo}}}} - print("TODO LR2 update manifest") - store_results(results, manifest) return save_table(repo, "manifest", manifest) end + +--- Given a path of a deployed file, figure out which rock name and version +-- correspond to it in the tree manifest. +-- @param file string: The full path of a deployed file. +-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used. +-- @return string, string: name and version of the provider rock. +function find_current_provider(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)) + local deploy_bin = path.deploy_bin_dir(root) + local deploy_lua = path.deploy_lua_dir(root) + local deploy_lib = path.deploy_lib_dir(root) + local key, manifest_tbl + + if file:match("^"..deploy_bin) then + manifest_tbl = manifest.commands + key = file:sub(#deploy_bin+1) + elseif file:match("^"..deploy_lua) then + manifest_tbl = manifest.modules + key = path.path_to_module(file:sub(#deploy_lua+1)) + elseif file:match("^"..deploy_lib) then + manifest_tbl = manifest.modules + key = path.path_to_module(file:sub(#deploy_lib+1)) + end + + local providers = manifest_tbl[key] + if not providers then + return nil, "File "..file.." is not tracked by LuaRocks." + end + return providers[1]:match("([^/]*)/([^/]*)") +end diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua index f62ff230..b63eaa43 100644 --- a/src/luarocks/path.lua +++ b/src/luarocks/path.lua @@ -216,6 +216,7 @@ function path_to_module(file) name = name:gsub(dir.separator, ".") end end + name = name:gsub("^%.+", ""):gsub("%.+$", "") return name end @@ -247,3 +248,19 @@ function configure_paths(rockspec) vars.DOCDIR = doc_dir(name, version) rockspec.variables = vars end + +function versioned_name(file, name, version) + assert(type(file) == "string") + assert(type(name) == "string") + assert(type(version) == "string") + + name = name:gsub("%-", "_") + version = version:gsub("%-", "_") + return dir.path(dir.dir_name(file), name.."_"..version.."-"..dir.base_name(file)) +end + +function unversioned_name(file) + assert(type(file) == "string") + + return dir.path(dir.dir_name(file), dir.base_name(file):match("^[^-]+-(.*)")) +end diff --git a/src/luarocks/rep.lua b/src/luarocks/rep.lua index 0a2e9cbb..8d3ecfb2 100644 --- a/src/luarocks/rep.lua +++ b/src/luarocks/rep.lua @@ -8,6 +8,7 @@ local cfg = require("luarocks.cfg") local util = require("luarocks.util") local dir = require("luarocks.dir") local manif = require("luarocks.manif") +local deps = require("luarocks.deps") --- Get all installed versions of a package. -- @param name string: a package name. @@ -32,21 +33,6 @@ function is_installed(name, version) return fs.is_dir(path.install_dir(name, version)) end - ---- Delete a package from the local repository. --- Version numbers are compared as exact string comparison. --- @param name string: name of package --- @param version string: package version in string format -function delete_version(name, version) - assert(type(name) == "string") - assert(type(version) == "string") - - fs.delete(path.install_dir(name, version)) - print("TODO LR2 remove deployed files based on rock_manifest") - if not get_versions(name) then - fs.delete(dir.path(cfg.rocks_dir, name)) - end -end --[[ --- Install bin entries in the repository bin dir. @@ -121,8 +107,6 @@ function package_modules(package, version) local result = {} local rock_manifest = manif.load_rock_manifest(package, version) - print(pkg, version, util.show_table(rock_manifest)) - if rock_manifest.lib then for name,sub in pairs(rock_manifest.lib) do store_package_data(result, name, sub, "", "") @@ -202,35 +186,6 @@ function run_hook(rockspec, hook_name) return true end -local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn) - assert(type(file_tree) == "table") - assert(type(source_dir) == "string") - assert(type(deploy_dir) == "string") - assert(type(move_fn) == "function" or not move_fn) - - print("TODO LR2 actually fs.move") - if not move_fn then move_fn = fs.copy end - - local ok, err = fs.make_dir(deploy_dir) - if not ok then - return nil, "Could not create "..deploy_dir - end - for file, sub in pairs(file_tree) do - if type(sub) == "table" then - ok, err = deploy_file_tree(sub, dir.path(source_dir, file), dir.path(deploy_dir, file)) - if not ok then return nil, err end - else - local target = dir.path(deploy_dir, file) - if fs.exists(target) then - print("TODO LR2 make_way_for_new_version(target)") - end - local source = dir.path(source_dir, file) - ok, err = move_fn(source, deploy_dir) - if not ok then return nil, err end - end - end -end - local function install_binary(source, target) assert(type(source) == "string") assert(type(target) == "string") @@ -249,22 +204,113 @@ local function install_binary(source, target) return ok, err end +local function resolve_conflict(name, version, target) + local cname, cversion = manif.find_current_provider(target) + if not cname then + return nil, cversion + end + if name ~= cname or deps.compare_versions(version, cversion) then +print("MOVE EXISTING, MAKE WAY FOR NEW") + fs.move(target, path.versioned_name(target, cname, cversion)) + return target + else +print("INSTALL NEW WITH DIFFERENT NAME") + return path.versioned_name(target, name, version) + end +end + function deploy_files(name, version) assert(type(name) == "string") assert(type(version) == "string") + + local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn) + assert(type(file_tree) == "table") + assert(type(source_dir) == "string") + assert(type(deploy_dir) == "string") + assert(type(move_fn) == "function" or not move_fn) + + if not move_fn then move_fn = fs.move end + + local ok, err = fs.make_dir(deploy_dir) + if not ok then + return nil, "Could not create "..deploy_dir + end + for file, sub in pairs(file_tree) do + local target = dir.path(deploy_dir, file) + if type(sub) == "table" then + ok, err = deploy_file_tree(sub, dir.path(source_dir, file), dir.path(deploy_dir, file)) + if not ok then return nil, err end + fs.remove_dir_if_empty(target) + else + if fs.exists(target) then + target, err = resolve_conflict(name, version, target) + if err then return nil, err.." Cannot install new version." end + end + local source = dir.path(source_dir, file) + ok, err = move_fn(source, target) + if not ok then return nil, err end + end + end + return true + end local rock_manifest = manif.load_rock_manifest(name, version) + local ok, err = true if rock_manifest.bin then - local ok, err = deploy_file_tree(rock_manifest.bin, path_bin_dir(name, version), cfg.deploy_bin_dir, install_binary) - if err then return nil, err end + ok, err = deploy_file_tree(rock_manifest.bin, path_bin_dir(name, version), cfg.deploy_bin_dir, install_binary) end - if rock_manifest.lua then - local ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir) - if err then return nil, err end + if ok and rock_manifest.lua then + ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir) end - if rock_manifest.lib then - local ok, err = deploy_file_tree(rock_manifest.lib, path.lib_dir(name, version), cfg.deploy_lib_dir) - if err then return nil, err end + if ok and rock_manifest.lib then + ok, err = deploy_file_tree(rock_manifest.lib, path.lib_dir(name, version), cfg.deploy_lib_dir) end + return ok, err +end + +--- Delete a package from the local repository. +-- Version numbers are compared as exact string comparison. +-- @param name string: name of package +-- @param version string: package version in string format +function delete_version(name, version) + assert(type(name) == "string") + assert(type(version) == "string") + + local function delete_deployed_file_tree(file_tree, deploy_dir) + for file, sub in pairs(file_tree) do + local target = dir.path(deploy_dir, file) + if type(sub) == "table" then + local ok, err = delete_deployed_file_tree(sub, dir.path(deploy_dir, file)) + fs.remove_dir_if_empty(target) + else + local versioned = path.versioned_name(target, name, version) + if fs.exists(versioned) then + fs.delete(versioned) + else + fs.delete(target) + end + end + end + return true + end + + local rock_manifest = manif.load_rock_manifest(name, version) + local ok, err = true + if rock_manifest.bin then + ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir) + end + if ok and rock_manifest.lua then + ok, err = delete_deployed_file_tree(rock_manifest.lua, cfg.deploy_lua_dir) + end + if ok and rock_manifest.lib then + ok, err = delete_deployed_file_tree(rock_manifest.lib, cfg.deploy_lib_dir) + end + if err then return nil, err end + + fs.delete(path.install_dir(name, version)) + if not get_versions(name) then + fs.delete(dir.path(cfg.rocks_dir, name)) + end + return true end -- cgit v1.2.3-55-g6feb