From 01a0723c9dd08b86ac96b09c08b9ce16cafa2438 Mon Sep 17 00:00:00 2001 From: hisham Date: Sun, 11 Oct 2009 04:47:08 +0000 Subject: Fix conflict resolution scheme using proper Lua 5.1 mechanism git-svn-id: http://luarocks.org/svn/luarocks/trunk@76 9ca3f7c1-7366-0410-b1a3-b5c78f85698c --- src/luarocks/loader.lua | 30 +++++------- src/luarocks/manif.lua | 35 +++++++++++--- src/luarocks/path.lua | 14 ++---- src/luarocks/rep.lua | 122 +++++++++++++++++------------------------------ src/luarocks/require.lua | 6 ++- 5 files changed, 92 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua index 02e46085..f8880a58 100644 --- a/src/luarocks/loader.lua +++ b/src/luarocks/loader.lua @@ -89,12 +89,11 @@ local function sort_versions(a,b) return a.version > b.version end -local function call_other_loaders(module, name, version, file) +local function call_other_loaders(module, name, version, module_name) - local actual_module = file:match(".*/(.*)%.[^.]+$") for i, loader in pairs(package.loaders) do if loader ~= luarocks_loader then - local results = { loader(actual_module) } + local results = { loader(module_name) } if type(results[1]) == "function" then return unpack(results) end @@ -116,23 +115,16 @@ local function pick_module(module) if entries then for i, entry in ipairs(entries) do local name, version = entry:match("^([^/]*)/(.*)$") - local file = tree.manifest.repository[name][version][1].modules[module] - local deploy_dir - if file:match(cfg.lua_extension.."$") then - deploy_dir = cfg.deploy_lua_dir - else - deploy_dir = cfg.deploy_bin_dir - end - if i == 1 then - file = deploy_dir.."/"..file - else - file = path.versioned_name(deploy_dir.."/"..file, name, version) + local module_name = tree.manifest.repository[name][version][1].modules[module] + if i > 1 then + module_name = path.versioned_name(module_name, "", name, version) end + module_name = path.path_to_module(module_name) if context[name] == version then - return name, version, file + return name, version, module_name end version = deps.parse_version(version) - table.insert(providers, {name = name, version = version, file = file}) + table.insert(providers, {name = name, version = version, module_name = module_name}) end end end @@ -140,7 +132,7 @@ local function pick_module(module) if next(providers) then table.sort(providers, sort_versions) local first = providers[1] - return first.name, first.version.string, first.file + return first.name, first.version.string, first.module_name end end @@ -155,12 +147,12 @@ end -- in the Lua reference manual for details. function luarocks_loader(module) - local name, version, file = pick_module(module) + local name, version, module_name = pick_module(module) if not name then return nil, "No LuaRocks module found for "..module else add_context(name, version) - return call_other_loaders(module, name, version, file) + return call_other_loaders(module, name, version, module_name) end end diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index bdb691ab..6a0d637a 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua @@ -38,7 +38,7 @@ function load_rock_manifest(name, version) if rock_manifest_cache[name_version] then return rock_manifest_cache[name_version].rock_manifest end - local pathname = dir.rock_manifest_file(name, version) + local pathname = path.rock_manifest_file(name, version) local rock_manifest = persist.load_into_table(pathname) if not rock_manifest then return nil end rock_manifest_cache[name_version] = rock_manifest @@ -301,17 +301,15 @@ function update_manifest(name, version, repo) 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) +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)) + if not manifest then + return nil, "manifest file is missing. Corrupted local rocks tree?" + end local deploy_bin = path.deploy_bin_dir(root) local deploy_lua = path.deploy_lua_dir(root) local deploy_lib = path.deploy_lib_dir(root) @@ -326,11 +324,34 @@ function find_current_provider(file, root) elseif file:match("^"..deploy_lib) then manifest_tbl = manifest.modules key = path.path_to_module(file:sub(#deploy_lib+1)) + else + assert(false, "Assertion failed: find_current_provider must operate on a deployed file.") end local providers = manifest_tbl[key] if not providers then return nil, "File "..file.." is not tracked by LuaRocks." end + return providers +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) + local providers, err = find_providers(file, root) + if not providers then return nil, err end return providers[1]:match("([^/]*)/([^/]*)") end + +function find_next_provider(file, root) + local providers, err = find_providers(file, root) + if not providers then return nil, err end + if providers[2] then + return providers[2]:match("([^/]*)/([^/]*)") + else + return nil + end +end diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua index f2d02ded..8c5aa0da 100644 --- a/src/luarocks/path.lua +++ b/src/luarocks/path.lua @@ -263,18 +263,12 @@ function configure_paths(rockspec) rockspec.variables = vars end -function versioned_name(file, name, version) +function versioned_name(file, prefix, 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("^[^-]+-(.*)")) + local rest = file:gsub("^"..prefix.."/*", "") + name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_") + return dir.path(prefix, name_version.."-"..rest) end diff --git a/src/luarocks/rep.lua b/src/luarocks/rep.lua index cabb83ef..8134a678 100644 --- a/src/luarocks/rep.lua +++ b/src/luarocks/rep.lua @@ -41,7 +41,7 @@ local function recurse_rock_manifest_tree(file_tree, action) for file, sub in pairs(tree) do if type(sub) == "table" then - local ok, err = recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".", action) + local ok, err = do_recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".") if not ok then return nil, err end else local ok, err = action(parent_path, parent_module, file) @@ -50,7 +50,7 @@ local function recurse_rock_manifest_tree(file_tree, action) end return true end - return do_recurse_rock_manifest_tree(file_tree, "", "", action) + return do_recurse_rock_manifest_tree(file_tree, "", "") end local function store_package_data(result, name, sub, prefix) @@ -69,6 +69,17 @@ local function store_package_data(result, name, sub, prefix) end end +local function store_package_data(result, name, file_tree) + if not file_tree then return end + return recurse_rock_manifest_tree(file_tree, + function(parent_path, parent_module, file) + local pathname = parent_path..file + result[path.path_to_module(pathname)] = pathname + return true + end + ) +end + --- Obtain a list of modules within an installed package. -- @param package string: The package name; for example "luasocket" -- @param version string: The exact version number including revision; @@ -84,16 +95,8 @@ function package_modules(package, version) local result = {} local rock_manifest = manif.load_rock_manifest(package, version) - if rock_manifest.lib then - for name,sub in pairs(rock_manifest.lib) do - store_package_data(result, name, sub, "", "") - end - end - if rock_manifest.lua then - for name,sub in pairs(rock_manifest.lua) do - store_package_data(result, name, sub, "", "") - end - end + store_package_data(result, name, rock_manifest.lib) + store_package_data(result, name, rock_manifest.lua) return result end @@ -181,16 +184,18 @@ local function install_binary(source, target) return ok, err end -local function resolve_conflict(name, version, target) +local function resolve_conflict(target, deploy_dir, name, version) 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 - fs.move(target, path.versioned_name(target, cname, cversion)) + local versioned = path.versioned_name(target, deploy_dir, cname, cversion) + fs.make_dir(dir.dir_name(versioned)) + fs.move(target, versioned) return target else - return path.versioned_name(target, name, version) + return path.versioned_name(target, deploy_dir, name, version) end end @@ -198,68 +203,26 @@ function deploy_files(name, version) assert(type(name) == "string") assert(type(version) == "string") - local function deploy_file_tree(file_tree, deploy_dir, source_dir, move_fn) - return recurse_rock_manifest_tree(file_tree, - function(name, version, deploy_dir, parent_path, parent_module, file) - - local versioned = path.versioned_name(dir.path(deploy_dir, file), name, version) - if fs.exists(versioned) then - fs.delete(versioned) - else - fs.delete(target) - end - return true - - local source = dir.path(source_dir, file) - local target = dir.path(deploy_dir, file) - if type(sub) == "table" then - ok, err = deploy_file_tree(sub, source, target) - if not ok then return nil, err end - fs.remove_dir_if_empty(source) - 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 - ok, err = move_fn(source, target) - if not ok then return nil, err end - end - - end - ) - 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) - - 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 + if not move_fn then + move_fn = fs.move end - for file, sub in pairs(file_tree) do - local source = dir.path(source_dir, file) - local target = dir.path(deploy_dir, file) - if type(sub) == "table" then - ok, err = deploy_file_tree(sub, source, target) - if not ok then return nil, err end - fs.remove_dir_if_empty(source) - else + return recurse_rock_manifest_tree(file_tree, + function(parent_path, parent_module, file) + local source = dir.path(source_dir, parent_path, file) + local target = dir.path(deploy_dir, parent_path, file) if fs.exists(target) then - target, err = resolve_conflict(name, version, target) + target, err = resolve_conflict(target, deploy_dir, name, version) if err then return nil, err.." Cannot install new version." end end + fs.make_dir(dir.dir_name(target)) ok, err = move_fn(source, target) if not ok then return nil, err end + return true end - end - return true + ) end - + local rock_manifest = manif.load_rock_manifest(name, version) local ok, err = true @@ -283,18 +246,23 @@ function delete_version(name, version) assert(type(name) == "string") assert(type(version) == "string") - local function delete_deployed_file_tree(name, version, file_tree, deploy_dir) - return recurse_rock_manifest_tree(name, version, file_tree, deploy_dir, "", "", - function(name, version, deploy_dir, parent_path, parent_module, file) - - local versioned = path.versioned_name(dir.path(deploy_dir, file), name, version) + local function delete_deployed_file_tree(file_tree, deploy_dir) + return recurse_rock_manifest_tree(file_tree, + function(parent_path, parent_module, file) + 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) else 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) + fs.move(versioned, target) + fs.remove_dir_tree_if_empty(dir.dir_name(versioned)) + end end return true - end ) end @@ -306,13 +274,13 @@ function delete_version(name, version) local ok, err = true if rock_manifest.bin then - ok, err = delete_deployed_file_tree(name, version, rock_manifest.bin, cfg.deploy_bin_dir) + 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(name, version, rock_manifest.lua, cfg.deploy_lua_dir) + 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(name, version, rock_manifest.lib, cfg.deploy_lib_dir) + ok, err = delete_deployed_file_tree(rock_manifest.lib, cfg.deploy_lib_dir) end if err then return nil, err end diff --git a/src/luarocks/require.lua b/src/luarocks/require.lua index 653597f9..99177700 100644 --- a/src/luarocks/require.lua +++ b/src/luarocks/require.lua @@ -1,4 +1,6 @@ --- Retained for compatibility reasons only. Use luarocks.loader instead. -local require = require +local require, pairs = require, pairs module("luarocks.require") -require("luarocks.loader") +for k,v in pairs(require("luarocks.loader")) do + _M[k] = v +end -- cgit v1.2.3-55-g6feb