diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2016-11-03 18:16:02 -0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-03 18:16:02 -0200 |
| commit | bfab09559cdbbc7e163490129ac7d3c4060b905d (patch) | |
| tree | b2cb4e9eda30c0ccabad972393dd4435e6ed9573 | |
| parent | 9822682e68b252b049e2fa6ef9d052d7ac739378 (diff) | |
| parent | cee2d3abfc1c06f382787d7bf7d2110a52ca0e76 (diff) | |
| download | luarocks-bfab09559cdbbc7e163490129ac7d3c4060b905d.tar.gz luarocks-bfab09559cdbbc7e163490129ac7d3c4060b905d.tar.bz2 luarocks-bfab09559cdbbc7e163490129ac7d3c4060b905d.zip | |
Merge pull request #644 from mpeterv/fix-conflict-resolve
Fix conflict resolution on deploy/remove w.r.t. C/Lua modules with same name
| -rw-r--r-- | spec/make_spec.lua | 69 | ||||
| -rw-r--r-- | src/luarocks/manif.lua | 132 | ||||
| -rw-r--r-- | src/luarocks/repos.lua | 256 | ||||
| -rw-r--r-- | test/test_environment.lua | 10 | ||||
| -rw-r--r-- | test/testfiles/mixed_deploy_type/mdt.c | 6 | ||||
| -rw-r--r-- | test/testfiles/mixed_deploy_type/mdt.lua | 1 | ||||
| -rw-r--r-- | test/testfiles/mixed_deploy_type/mdt_file | 1 | ||||
| -rw-r--r-- | test/testfiles/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec | 21 | ||||
| -rw-r--r-- | test/testfiles/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec | 21 |
9 files changed, 328 insertions, 189 deletions
diff --git a/spec/make_spec.lua b/spec/make_spec.lua index ae79a29c..89036d26 100644 --- a/spec/make_spec.lua +++ b/spec/make_spec.lua | |||
| @@ -2,11 +2,11 @@ local test_env = require("test/test_environment") | |||
| 2 | local lfs = require("lfs") | 2 | local lfs = require("lfs") |
| 3 | local run = test_env.run | 3 | local run = test_env.run |
| 4 | local testing_paths = test_env.testing_paths | 4 | local testing_paths = test_env.testing_paths |
| 5 | local env_variables = test_env.env_variables | ||
| 5 | 6 | ||
| 6 | test_env.unload_luarocks() | 7 | test_env.unload_luarocks() |
| 7 | 8 | ||
| 8 | local extra_rocks = { | 9 | local extra_rocks = { |
| 9 | "lpeg-1.0.0-1.rockspec", | ||
| 10 | "/luasocket-3.0rc1-2.src.rock", | 10 | "/luasocket-3.0rc1-2.src.rock", |
| 11 | "/luasocket-3.0rc1-2.rockspec", | 11 | "/luasocket-3.0rc1-2.rockspec", |
| 12 | "/lxsh-0.8.6-2.src.rock", | 12 | "/lxsh-0.8.6-2.src.rock", |
| @@ -98,4 +98,71 @@ describe("LuaRocks make tests #blackbox #b_make", function() | |||
| 98 | assert.is.truthy(lfs.attributes("lxsh-0.8.6-2.all.rock")) | 98 | assert.is.truthy(lfs.attributes("lxsh-0.8.6-2.all.rock")) |
| 99 | end) | 99 | end) |
| 100 | end) | 100 | end) |
| 101 | |||
| 102 | describe("LuaRocks make upgrading rockspecs with mixed deploy types", function() | ||
| 103 | setup(function() | ||
| 104 | test_env.copy_dir(testing_paths.testing_dir .. "/testfiles/mixed_deploy_type", "mdt") | ||
| 105 | end) | ||
| 106 | |||
| 107 | teardown(function() | ||
| 108 | test_env.remove_dir("mdt") | ||
| 109 | os.remove("mdt."..test_env.lib_extension) | ||
| 110 | end) | ||
| 111 | |||
| 112 | it("modules with same name from lua/ and lib/ when upgrading", function() | ||
| 113 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) | ||
| 114 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 115 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 116 | |||
| 117 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) | ||
| 118 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 119 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 120 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 121 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 122 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) | ||
| 123 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) | ||
| 124 | end) | ||
| 125 | |||
| 126 | it("modules with same name from lua/ and lib/ when upgrading with --keep", function() | ||
| 127 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) | ||
| 128 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 129 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 130 | |||
| 131 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec --keep")) | ||
| 132 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 133 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 134 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 135 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 136 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) | ||
| 137 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) | ||
| 138 | end) | ||
| 139 | |||
| 140 | it("modules with same name from lua/ and lib/ when downgrading", function() | ||
| 141 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) | ||
| 142 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 143 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 144 | |||
| 145 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) | ||
| 146 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 147 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 148 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt."..test_env.lib_extension)) | ||
| 149 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) | ||
| 150 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 151 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 152 | end) | ||
| 153 | |||
| 154 | it("modules with same name from lua/ and lib/ when downgrading with --keep", function() | ||
| 155 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) | ||
| 156 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 157 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 158 | |||
| 159 | assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec --keep")) | ||
| 160 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) | ||
| 161 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 162 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) | ||
| 163 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) | ||
| 164 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) | ||
| 165 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) | ||
| 166 | end) | ||
| 167 | end) | ||
| 101 | end) | 168 | end) |
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index 86209d06..88a13f10 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua | |||
| @@ -540,85 +540,89 @@ function manif.zip_manifests() | |||
| 540 | end | 540 | end |
| 541 | end | 541 | end |
| 542 | 542 | ||
| 543 | local function relative_path(from_dir, to_file) | 543 | --- Get type and name of an item (a module or a command) provided by a file. |
| 544 | -- It is assumed that `from_dir` is prefix of `to_file`. | 544 | -- @param deploy_type string: rock manifest subtree the file comes from ("bin", "lua", or "lib"). |
| 545 | return (to_file:sub(#from_dir + 1):gsub("^[\\/]*", "")) | 545 | -- @param file_path string: path to the file relatively to deploy_type subdirectory. |
| 546 | -- @return (string, string): item type ("module" or "command") and name. | ||
| 547 | function manif.get_provided_item(deploy_type, file_path) | ||
| 548 | assert(type(deploy_type) == "string") | ||
| 549 | assert(type(file_path) == "string") | ||
| 550 | local item_type = deploy_type == "bin" and "command" or "module" | ||
| 551 | local item_name = item_type == "command" and file_path or path.path_to_module(file_path) | ||
| 552 | return item_type, item_name | ||
| 546 | end | 553 | end |
| 547 | 554 | ||
| 548 | local function file_manifest_coordinates(manifest, file, root) | 555 | local function get_providers(item_type, item_name, repo) |
| 549 | local deploy_bin = path.deploy_bin_dir(root) | 556 | assert(type(item_type) == "string") |
| 550 | local deploy_lua = path.deploy_lua_dir(root) | 557 | assert(type(item_name) == "string") |
| 551 | local deploy_lib = path.deploy_lib_dir(root) | 558 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) |
| 552 | 559 | local manifest = manif_core.load_local_manifest(rocks_dir) | |
| 553 | if util.starts_with(file, deploy_lua) then | 560 | return manifest and manifest[item_type .. "s"][item_name] |
| 554 | return "modules", path.path_to_module(relative_path(deploy_lua, file):gsub("\\", "/")), deploy_lua | ||
| 555 | elseif util.starts_with(file, deploy_lib) then | ||
| 556 | return "modules", path.path_to_module(relative_path(deploy_lib, file):gsub("\\", "/")), deploy_lib | ||
| 557 | elseif util.starts_with(file, deploy_bin) then | ||
| 558 | return "commands", relative_path(deploy_bin, file), deploy_bin | ||
| 559 | else | ||
| 560 | assert(false, "Assertion failed: '"..file.."' is not a deployed file.") | ||
| 561 | end | ||
| 562 | end | 561 | end |
| 563 | 562 | ||
| 564 | local function find_providers(file, root) | 563 | --- Given a name of a module or a command, figure out which rock name and version |
| 565 | assert(type(file) == "string") | 564 | -- correspond to it in the rock tree manifest. |
| 566 | root = root or cfg.root_dir | 565 | -- @param item_type string: "module" or "command". |
| 567 | 566 | -- @param item_name string: module or command name. | |
| 568 | local manifest, err = manif_core.load_local_manifest(path.rocks_dir(root)) | 567 | -- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used. |
| 569 | if not manifest then | 568 | -- @return (string, string) or nil: name and version of the provider rock or nil if there |
| 570 | return nil, "untracked" | 569 | -- is no provider. |
| 570 | function manif.get_current_provider(item_type, item_name, repo) | ||
| 571 | local providers = get_providers(item_type, item_name, repo) | ||
| 572 | if providers then | ||
| 573 | return providers[1]:match("([^/]*)/([^/]*)") | ||
| 571 | end | 574 | end |
| 575 | end | ||
| 572 | 576 | ||
| 573 | local type_key, key = file_manifest_coordinates(manifest, file, root) | 577 | function manif.get_next_provider(item_type, item_name, repo) |
| 574 | 578 | local providers = get_providers(item_type, item_name, repo) | |
| 575 | local providers = manifest[type_key][key] | 579 | if providers and providers[2] then |
| 576 | if not providers then | 580 | return providers[2]:match("([^/]*)/([^/]*)") |
| 577 | return nil, "untracked" | ||
| 578 | end | 581 | end |
| 579 | return providers | ||
| 580 | end | 582 | end |
| 581 | 583 | ||
| 582 | --- Given a path of a deployed file, figure out which rock name and version | 584 | --- Given a name of a module or a command provided by a package, figure out |
| 583 | -- correspond to it in the tree manifest. | 585 | -- which file provides it. |
| 584 | -- @param file string: The full path of a deployed file. | 586 | -- @param name string: package name. |
| 587 | -- @param version string: package version. | ||
| 588 | -- @param item_type string: "module" or "command". | ||
| 589 | -- @param item_name string: module or command name. | ||
| 585 | -- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used. | 590 | -- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used. |
| 586 | -- @return string, string: name and version of the provider rock. | 591 | -- @return (string, string): rock manifest subtree the file comes from ("bin", "lua", or "lib") |
| 587 | function manif.find_current_provider(file, root) | 592 | -- and path to the providing file relatively to that subtree. |
| 588 | local providers, err = find_providers(file, root) | 593 | function manif.get_providing_file(name, version, item_type, item_name, repo) |
| 589 | if not providers then return nil, err end | 594 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) |
| 590 | return providers[1]:match("([^/]*)/([^/]*)") | 595 | local manifest = manif_core.load_local_manifest(rocks_dir) |
| 591 | end | ||
| 592 | 596 | ||
| 593 | function manif.find_next_provider(file, root) | 597 | local entry_table = manifest.repository[name][version][1] |
| 594 | local providers, err = find_providers(file, root) | 598 | local file_path = entry_table[item_type .. "s"][item_name] |
| 595 | if not providers then return nil, err end | 599 | |
| 596 | if providers[2] then | 600 | if item_type == "command" then |
| 597 | return providers[2]:match("([^/]*)/([^/]*)") | 601 | return "bin", file_path |
| 598 | else | ||
| 599 | return nil | ||
| 600 | end | 602 | end |
| 601 | end | ||
| 602 | 603 | ||
| 603 | --- Given a file conflicting with a module or command | 604 | -- A module can be in "lua" or "lib". Decide based on extension first: |
| 604 | -- provided by a version of a package, return which file | 605 | -- most likely Lua modules are in "lua/" and C modules are in "lib/". |
| 605 | -- in that version corresponds to the conflicting item. | 606 | if file_path:match("%." .. cfg.lua_extension .. "$") then |
| 606 | -- @param name string: name of the package with conflicting module or command. | 607 | return "lua", file_path |
| 607 | -- @param version string: version of the package with conflicting module or command. | 608 | elseif file_path:match("%." .. cfg.lib_extension .. "$") then |
| 608 | -- @param file string: full, unversioned path to a deployed file. | 609 | return "lib", file_path |
| 609 | -- @return string: full, unversioned path to a deployed file in | ||
| 610 | -- given package that conflicts with given file. | ||
| 611 | function manif.find_conflicting_file(name, version, file, root) | ||
| 612 | root = root or cfg.root_dir | ||
| 613 | |||
| 614 | local manifest = manif_core.load_local_manifest(path.rocks_dir(root)) | ||
| 615 | if not manifest then | ||
| 616 | return | ||
| 617 | end | 610 | end |
| 618 | 611 | ||
| 619 | local entry_table = manifest.repository[name][version][1] | 612 | -- Fallback to rock manifest scanning. |
| 620 | local type_key, key, deploy_dir = file_manifest_coordinates(manifest, file, root) | 613 | local rock_manifest = manif.load_rock_manifest(name, version) |
| 621 | return dir.path(deploy_dir, entry_table[type_key][key]) | 614 | local subtree = rock_manifest.lib |
| 615 | |||
| 616 | for path_part in file_path:gmatch("[^/]+") do | ||
| 617 | if type(subtree) == "table" then | ||
| 618 | subtree = subtree[path_part] | ||
| 619 | else | ||
| 620 | -- Assume it's in "lua/" if it's not in "lib/". | ||
| 621 | return "lua", file_path | ||
| 622 | end | ||
| 623 | end | ||
| 624 | |||
| 625 | return type(subtree) == "string" and "lib" or "lua", file_path | ||
| 622 | end | 626 | end |
| 623 | 627 | ||
| 624 | return manif | 628 | return manif |
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua index d4d9694e..5d5eac70 100644 --- a/src/luarocks/repos.lua +++ b/src/luarocks/repos.lua | |||
| @@ -11,6 +11,23 @@ local dir = require("luarocks.dir") | |||
| 11 | local manif = require("luarocks.manif") | 11 | local manif = require("luarocks.manif") |
| 12 | local deps = require("luarocks.deps") | 12 | local deps = require("luarocks.deps") |
| 13 | 13 | ||
| 14 | -- Tree of files installed by a package are stored | ||
| 15 | -- in its rock manifest. Some of these files have to | ||
| 16 | -- be deployed to locations where Lua can load them as | ||
| 17 | -- modules or where they can be used as commands. | ||
| 18 | -- These files are characterised by pair | ||
| 19 | -- (deploy_type, file_path), where deploy_type is the first | ||
| 20 | -- component of the file path and file_path is the rest of the | ||
| 21 | -- path. Only files with deploy_type in {"lua", "lib", "bin"} | ||
| 22 | -- are deployed somewhere. | ||
| 23 | -- Each deployed file provides an "item". An item is | ||
| 24 | -- characterised by pair (item_type, item_name). | ||
| 25 | -- item_type is "command" for files with deploy_type | ||
| 26 | -- "bin" and "module" for deploy_type in {"lua", "lib"}. | ||
| 27 | -- item_name is same as file_path for commands | ||
| 28 | -- and is produced using path.path_to_module(file_path) | ||
| 29 | -- for modules. | ||
| 30 | |||
| 14 | --- Get all installed versions of a package. | 31 | --- Get all installed versions of a package. |
| 15 | -- @param name string: a package name. | 32 | -- @param name string: a package name. |
| 16 | -- @return table or nil: An array of strings listing installed | 33 | -- @return table or nil: An array of strings listing installed |
| @@ -192,44 +209,56 @@ end | |||
| 192 | local function delete_suffixed(file, suffix) | 209 | local function delete_suffixed(file, suffix) |
| 193 | local suffixed_file, err = find_suffixed(file, suffix) | 210 | local suffixed_file, err = find_suffixed(file, suffix) |
| 194 | if not suffixed_file then | 211 | if not suffixed_file then |
| 195 | return nil, "Could not remove " .. file .. ": " .. err, "not found" | 212 | return nil, "Could not remove " .. file .. ": " .. err |
| 196 | end | 213 | end |
| 197 | 214 | ||
| 198 | fs.delete(suffixed_file) | 215 | fs.delete(suffixed_file) |
| 199 | if fs.exists(suffixed_file) then | 216 | if fs.exists(suffixed_file) then |
| 200 | return nil, "Failed deleting " .. suffixed_file .. ": file still exists", "fail" | 217 | return nil, "Failed deleting " .. suffixed_file .. ": file still exists" |
| 201 | end | 218 | end |
| 202 | 219 | ||
| 203 | return true | 220 | return true |
| 204 | end | 221 | end |
| 205 | 222 | ||
| 206 | local function resolve_conflict(target, deploy_dir, name, version, cur_name, cur_version, suffix) | 223 | -- Files can be deployed using versioned and non-versioned names. |
| 207 | if name < cur_name or (name == cur_name and deps.compare_versions(version, cur_version)) then | 224 | -- Several items with same type and name can exist if they are |
| 225 | -- provided by different packages or versions. In any case | ||
| 226 | -- item from the newest version of lexicographically smallest package | ||
| 227 | -- is deployed using non-versioned name and others use versioned names. | ||
| 228 | |||
| 229 | local function get_deploy_paths(name, version, deploy_type, file_path) | ||
| 230 | local deploy_dir = cfg["deploy_" .. deploy_type .. "_dir"] | ||
| 231 | local non_versioned = dir.path(deploy_dir, file_path) | ||
| 232 | local versioned = path.versioned_name(non_versioned, deploy_dir, name, version) | ||
| 233 | return non_versioned, versioned | ||
| 234 | end | ||
| 235 | |||
| 236 | local function prepare_target(name, version, deploy_type, file_path, suffix) | ||
| 237 | local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) | ||
| 238 | local item_type, item_name = manif.get_provided_item(deploy_type, file_path) | ||
| 239 | local cur_name, cur_version = manif.get_current_provider(item_type, item_name) | ||
| 240 | |||
| 241 | if not cur_name then | ||
| 242 | return non_versioned | ||
| 243 | elseif name < cur_name or (name == cur_name and deps.compare_versions(version, cur_version)) then | ||
| 208 | -- New version has priority. Move currently provided version back using versioned name. | 244 | -- New version has priority. Move currently provided version back using versioned name. |
| 209 | local cur_target = manif.find_conflicting_file(cur_name, cur_version, target) | 245 | local cur_deploy_type, cur_file_path = manif.get_providing_file(cur_name, cur_version, item_type, item_name) |
| 210 | local versioned = path.versioned_name(cur_target, deploy_dir, cur_name, cur_version) | 246 | local cur_non_versioned, cur_versioned = get_deploy_paths(cur_name, cur_version, cur_deploy_type, cur_file_path) |
| 211 | 247 | ||
| 212 | local ok, err = fs.make_dir(dir.dir_name(versioned)) | 248 | local dir_ok, dir_err = fs.make_dir(dir.dir_name(cur_versioned)) |
| 213 | if not ok then | 249 | if not dir_ok then return nil, dir_err end |
| 214 | return nil, err | ||
| 215 | end | ||
| 216 | 250 | ||
| 217 | ok, err = move_suffixed(cur_target, versioned, suffix) | 251 | local move_ok, move_err = move_suffixed(cur_non_versioned, cur_versioned, suffix) |
| 218 | if not ok then | 252 | if not move_ok then return nil, move_err end |
| 219 | return nil, err | ||
| 220 | end | ||
| 221 | 253 | ||
| 222 | return target | 254 | return non_versioned |
| 223 | else | 255 | else |
| 224 | -- Current version has priority, deploy new version using versioned name. | 256 | -- Current version has priority, deploy new version using versioned name. |
| 225 | return path.versioned_name(target, deploy_dir, name, version) | 257 | return versioned |
| 226 | end | 258 | end |
| 227 | end | 259 | end |
| 228 | 260 | ||
| 229 | --- Deploy a package from the rocks subdirectory. | 261 | --- Deploy a package from the rocks subdirectory. |
| 230 | -- It is maintained that for each module and command the one that is provided | ||
| 231 | -- by the newest version of the lexicographically smallest package | ||
| 232 | -- is installed using unversioned name, and other versions use versioned names. | ||
| 233 | -- @param name string: name of package | 262 | -- @param name string: name of package |
| 234 | -- @param version string: exact package version in string format | 263 | -- @param version string: exact package version in string format |
| 235 | -- @param wrap_bin_scripts bool: whether commands written in Lua should be wrapped. | 264 | -- @param wrap_bin_scripts bool: whether commands written in Lua should be wrapped. |
| @@ -241,49 +270,44 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode) | |||
| 241 | assert(type(version) == "string") | 270 | assert(type(version) == "string") |
| 242 | assert(type(wrap_bin_scripts) == "boolean") | 271 | assert(type(wrap_bin_scripts) == "boolean") |
| 243 | 272 | ||
| 244 | local function deploy_file_tree(file_tree, path_fn, deploy_dir, move_fn, suffix) | 273 | local rock_manifest = manif.load_rock_manifest(name, version) |
| 245 | local source_dir = path_fn(name, version) | ||
| 246 | return recurse_rock_manifest_tree(file_tree, | ||
| 247 | function(parent_path, parent_module, file) | ||
| 248 | local source = dir.path(source_dir, parent_path, file) | ||
| 249 | local target = dir.path(deploy_dir, parent_path, file) | ||
| 250 | |||
| 251 | local cur_name, cur_version = manif.find_current_provider(target) | ||
| 252 | if cur_name then | ||
| 253 | local resolve_err | ||
| 254 | target, resolve_err = resolve_conflict(target, deploy_dir, name, version, cur_name, cur_version, suffix) | ||
| 255 | if not target then | ||
| 256 | return nil, resolve_err | ||
| 257 | end | ||
| 258 | end | ||
| 259 | 274 | ||
| 260 | local ok, err = fs.make_dir(dir.dir_name(target)) | 275 | local function deploy_file_tree(deploy_type, source_dir, move_fn, suffix) |
| 261 | if not ok then return nil, err end | 276 | if not rock_manifest[deploy_type] then |
| 277 | return true | ||
| 278 | end | ||
| 262 | 279 | ||
| 263 | local suffixed_target, mover = move_fn(source, target, name, version) | 280 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file) |
| 264 | if fs.exists(suffixed_target) then | 281 | local file_path = parent_path .. file |
| 265 | local backup = suffixed_target | 282 | local source = dir.path(source_dir, file_path) |
| 266 | repeat | ||
| 267 | backup = backup.."~" | ||
| 268 | until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem. | ||
| 269 | |||
| 270 | util.printerr("Warning: "..suffixed_target.." is not tracked by this installation of LuaRocks. Moving it to "..backup) | ||
| 271 | local ok, err = fs.move(suffixed_target, backup) | ||
| 272 | if not ok then | ||
| 273 | return nil, err | ||
| 274 | end | ||
| 275 | end | ||
| 276 | 283 | ||
| 277 | ok, err = mover() | 284 | local target, prepare_err = prepare_target(name, version, deploy_type, file_path, suffix) |
| 278 | fs.remove_dir_tree_if_empty(dir.dir_name(source)) | 285 | if not target then return nil, prepare_err end |
| 279 | return ok, err | 286 | |
| 287 | local dir_ok, dir_err = fs.make_dir(dir.dir_name(target)) | ||
| 288 | if not dir_ok then return nil, dir_err end | ||
| 289 | |||
| 290 | local suffixed_target, mover = move_fn(source, target) | ||
| 291 | if fs.exists(suffixed_target) then | ||
| 292 | local backup = suffixed_target | ||
| 293 | repeat | ||
| 294 | backup = backup.."~" | ||
| 295 | until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem. | ||
| 296 | |||
| 297 | util.printerr("Warning: "..suffixed_target.." is not tracked by this installation of LuaRocks. Moving it to "..backup) | ||
| 298 | local move_ok, move_err = fs.move(suffixed_target, backup) | ||
| 299 | if not move_ok then return nil, move_err end | ||
| 280 | end | 300 | end |
| 281 | ) | ||
| 282 | end | ||
| 283 | 301 | ||
| 284 | local rock_manifest = manif.load_rock_manifest(name, version) | 302 | local move_ok, move_err = mover() |
| 303 | if not move_ok then return nil, move_err end | ||
| 304 | |||
| 305 | fs.remove_dir_tree_if_empty(dir.dir_name(source)) | ||
| 306 | return true | ||
| 307 | end) | ||
| 308 | end | ||
| 285 | 309 | ||
| 286 | local function install_binary(source, target, name, version) | 310 | local function install_binary(source, target) |
| 287 | if wrap_bin_scripts and fs.is_lua(source) then | 311 | if wrap_bin_scripts and fs.is_lua(source) then |
| 288 | return target .. (cfg.wrapper_suffix or ""), function() return fs.wrap_script(source, target, name, version) end | 312 | return target .. (cfg.wrapper_suffix or ""), function() return fs.wrap_script(source, target, name, version) end |
| 289 | else | 313 | else |
| @@ -297,28 +321,19 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode) | |||
| 297 | end | 321 | end |
| 298 | end | 322 | end |
| 299 | 323 | ||
| 300 | local ok, err = true | 324 | local ok, err = deploy_file_tree("bin", path.bin_dir(name, version), install_binary, cfg.wrapper_suffix) |
| 301 | if rock_manifest.bin then | 325 | if not ok then return nil, err end |
| 302 | ok, err = deploy_file_tree(rock_manifest.bin, path.bin_dir, cfg.deploy_bin_dir, install_binary, cfg.wrapper_suffix) | ||
| 303 | end | ||
| 304 | if ok and rock_manifest.lua then | ||
| 305 | ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir, cfg.deploy_lua_dir, make_mover(cfg.perm_read)) | ||
| 306 | end | ||
| 307 | if ok and rock_manifest.lib then | ||
| 308 | ok, err = deploy_file_tree(rock_manifest.lib, path.lib_dir, cfg.deploy_lib_dir, make_mover(cfg.perm_exec)) | ||
| 309 | end | ||
| 310 | 326 | ||
| 311 | if not ok then | 327 | ok, err = deploy_file_tree("lua", path.lua_dir(name, version), make_mover(cfg.perm_read)) |
| 312 | return nil, err | 328 | if not ok then return nil, err end |
| 313 | end | 329 | |
| 330 | ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover(cfg.perm_exec)) | ||
| 331 | if not ok then return nil, err end | ||
| 314 | 332 | ||
| 315 | return manif.add_to_manifest(name, version, nil, deps_mode) | 333 | return manif.add_to_manifest(name, version, nil, deps_mode) |
| 316 | end | 334 | end |
| 317 | 335 | ||
| 318 | --- Delete a package from the local repository. | 336 | --- Delete a package from the local repository. |
| 319 | -- It is maintained that for each module and command the one that is provided | ||
| 320 | -- by the newest version of the lexicographically smallest package | ||
| 321 | -- is installed using unversioned name, and other versions use versioned names. | ||
| 322 | -- @param name string: name of package | 337 | -- @param name string: name of package |
| 323 | -- @param version string: exact package version in string format | 338 | -- @param version string: exact package version in string format |
| 324 | -- @param deps_mode: string: Which trees to check dependencies for: | 339 | -- @param deps_mode: string: Which trees to check dependencies for: |
| @@ -333,67 +348,70 @@ function repos.delete_version(name, version, deps_mode, quick) | |||
| 333 | assert(type(version) == "string") | 348 | assert(type(version) == "string") |
| 334 | assert(type(deps_mode) == "string") | 349 | assert(type(deps_mode) == "string") |
| 335 | 350 | ||
| 336 | local function delete_deployed_file_tree(file_tree, deploy_dir, suffix) | 351 | local rock_manifest = manif.load_rock_manifest(name, version) |
| 337 | return recurse_rock_manifest_tree(file_tree, | 352 | if not rock_manifest then |
| 338 | function(parent_path, parent_module, file) | 353 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?" |
| 339 | local target = dir.path(deploy_dir, parent_path, file) | 354 | end |
| 340 | local versioned = path.versioned_name(target, deploy_dir, name, version) | ||
| 341 | |||
| 342 | local ok, err, err_type = delete_suffixed(versioned, suffix) | ||
| 343 | if ok then | ||
| 344 | fs.remove_dir_tree_if_empty(dir.dir_name(versioned)) | ||
| 345 | return true | ||
| 346 | elseif err_type == "fail" then | ||
| 347 | return nil, err | ||
| 348 | end | ||
| 349 | 355 | ||
| 350 | ok, err = delete_suffixed(target, suffix) | 356 | local function delete_deployed_file_tree(deploy_type, suffix) |
| 351 | if not ok then | 357 | if not rock_manifest[deploy_type] then |
| 352 | return nil, err | 358 | return true |
| 353 | end | 359 | end |
| 360 | |||
| 361 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file) | ||
| 362 | local file_path = parent_path .. file | ||
| 363 | local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) | ||
| 364 | |||
| 365 | -- Figure out if the file is deployed using versioned or non-versioned name. | ||
| 366 | local target | ||
| 367 | local item_type, item_name = manif.get_provided_item(deploy_type, file_path) | ||
| 368 | local cur_name, cur_version = manif.get_current_provider(item_type, item_name) | ||
| 354 | 369 | ||
| 355 | if not quick then | 370 | if cur_name == name and cur_version == version then |
| 356 | local next_name, next_version = manif.find_next_provider(target) | 371 | -- This package has highest priority, should be in non-versioned location. |
| 357 | if next_name then | 372 | target = non_versioned |
| 358 | local next_target = manif.find_conflicting_file(next_name, next_version, target) | 373 | else |
| 359 | local next_versioned = path.versioned_name(next_target, deploy_dir, next_name, next_version) | 374 | target = versioned |
| 375 | end | ||
| 376 | |||
| 377 | local ok, err = delete_suffixed(target, suffix) | ||
| 378 | if not ok then return nil, err end | ||
| 379 | |||
| 380 | if not quick and target == non_versioned then | ||
| 381 | -- If another package provides this file, move its version | ||
| 382 | -- into non-versioned location instead. | ||
| 383 | local next_name, next_version = manif.get_next_provider(item_type, item_name) | ||
| 360 | 384 | ||
| 361 | ok, err = move_suffixed(next_versioned, next_target, suffix) | 385 | if next_name then |
| 362 | if not ok then | 386 | local next_deploy_type, next_file_path = manif.get_providing_file(next_name, next_version, item_type, item_name) |
| 363 | return nil, err | 387 | local next_non_versioned, next_versioned = get_deploy_paths(next_name, next_version, next_deploy_type, next_file_path) |
| 364 | end | ||
| 365 | 388 | ||
| 366 | fs.remove_dir_tree_if_empty(dir.dir_name(versioned)) | 389 | local move_ok, move_err = move_suffixed(next_versioned, next_non_versioned, suffix) |
| 367 | end | 390 | if not move_ok then return nil, move_err end |
| 391 | |||
| 392 | fs.remove_dir_tree_if_empty(dir.dir_name(next_versioned)) | ||
| 368 | end | 393 | end |
| 369 | fs.remove_dir_tree_if_empty(dir.dir_name(target)) | ||
| 370 | return true | ||
| 371 | end | 394 | end |
| 372 | ) | ||
| 373 | end | ||
| 374 | 395 | ||
| 375 | local rock_manifest = manif.load_rock_manifest(name, version) | 396 | fs.remove_dir_tree_if_empty(dir.dir_name(target)) |
| 376 | if not rock_manifest then | 397 | return true |
| 377 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?" | 398 | end) |
| 378 | end | ||
| 379 | |||
| 380 | local ok, err = true | ||
| 381 | if rock_manifest.bin then | ||
| 382 | ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir, cfg.wrapper_suffix) | ||
| 383 | end | ||
| 384 | if ok and rock_manifest.lua then | ||
| 385 | ok, err = delete_deployed_file_tree(rock_manifest.lua, cfg.deploy_lua_dir) | ||
| 386 | end | ||
| 387 | if ok and rock_manifest.lib then | ||
| 388 | ok, err = delete_deployed_file_tree(rock_manifest.lib, cfg.deploy_lib_dir) | ||
| 389 | end | 399 | end |
| 400 | |||
| 401 | local ok, err = delete_deployed_file_tree("bin", cfg.wrapper_suffix) | ||
| 402 | if not ok then return nil, err end | ||
| 403 | |||
| 404 | ok, err = delete_deployed_file_tree("lua") | ||
| 405 | if not ok then return nil, err end | ||
| 406 | |||
| 407 | ok, err = delete_deployed_file_tree("lib") | ||
| 390 | if not ok then return nil, err end | 408 | if not ok then return nil, err end |
| 391 | 409 | ||
| 392 | fs.delete(path.install_dir(name, version)) | 410 | fs.delete(path.install_dir(name, version)) |
| 393 | if not get_installed_versions(name) then | 411 | if not get_installed_versions(name) then |
| 394 | fs.delete(dir.path(cfg.rocks_dir, name)) | 412 | fs.delete(dir.path(cfg.rocks_dir, name)) |
| 395 | end | 413 | end |
| 396 | 414 | ||
| 397 | if quick then | 415 | if quick then |
| 398 | return true | 416 | return true |
| 399 | end | 417 | end |
diff --git a/test/test_environment.lua b/test/test_environment.lua index 196202df..6f6f1cfe 100644 --- a/test/test_environment.lua +++ b/test/test_environment.lua | |||
| @@ -214,7 +214,7 @@ function test_env.set_args() | |||
| 214 | return true | 214 | return true |
| 215 | end | 215 | end |
| 216 | 216 | ||
| 217 | local function copy_dir(source_path, target_path) | 217 | function test_env.copy_dir(source_path, target_path) |
| 218 | local testing_paths = test_env.testing_paths | 218 | local testing_paths = test_env.testing_paths |
| 219 | if test_env.TEST_TARGET_OS == "windows" then | 219 | if test_env.TEST_TARGET_OS == "windows" then |
| 220 | execute_bool(testing_paths.win_tools .. "/cp -R ".. source_path .. "/. " .. target_path) | 220 | execute_bool(testing_paths.win_tools .. "/cp -R ".. source_path .. "/. " .. target_path) |
| @@ -430,8 +430,8 @@ local function build_environment(rocks, env_variables) | |||
| 430 | end | 430 | end |
| 431 | end | 431 | end |
| 432 | 432 | ||
| 433 | copy_dir(testing_paths.testing_tree, testing_paths.testing_tree_copy) | 433 | test_env.copy_dir(testing_paths.testing_tree, testing_paths.testing_tree_copy) |
| 434 | copy_dir(testing_paths.testing_sys_tree, testing_paths.testing_sys_tree_copy) | 434 | test_env.copy_dir(testing_paths.testing_sys_tree, testing_paths.testing_sys_tree_copy) |
| 435 | end | 435 | end |
| 436 | 436 | ||
| 437 | --- Reset testing environment | 437 | --- Reset testing environment |
| @@ -441,12 +441,12 @@ local function reset_environment(testing_paths, md5sums) | |||
| 441 | 441 | ||
| 442 | if testing_tree_md5 ~= md5sums.testing_tree_copy_md5 then | 442 | if testing_tree_md5 ~= md5sums.testing_tree_copy_md5 then |
| 443 | test_env.remove_dir(testing_paths.testing_tree) | 443 | test_env.remove_dir(testing_paths.testing_tree) |
| 444 | copy_dir(testing_paths.testing_tree_copy, testing_paths.testing_tree) | 444 | test_env.copy_dir(testing_paths.testing_tree_copy, testing_paths.testing_tree) |
| 445 | end | 445 | end |
| 446 | 446 | ||
| 447 | if testing_sys_tree_md5 ~= md5sums.testing_sys_tree_copy_md5 then | 447 | if testing_sys_tree_md5 ~= md5sums.testing_sys_tree_copy_md5 then |
| 448 | test_env.remove_dir(testing_paths.testing_sys_tree) | 448 | test_env.remove_dir(testing_paths.testing_sys_tree) |
| 449 | copy_dir(testing_paths.testing_sys_tree_copy, testing_paths.testing_sys_tree) | 449 | test_env.copy_dir(testing_paths.testing_sys_tree_copy, testing_paths.testing_sys_tree) |
| 450 | end | 450 | end |
| 451 | print("\n[ENVIRONMENT RESET]") | 451 | print("\n[ENVIRONMENT RESET]") |
| 452 | end | 452 | end |
diff --git a/test/testfiles/mixed_deploy_type/mdt.c b/test/testfiles/mixed_deploy_type/mdt.c new file mode 100644 index 00000000..a162ce23 --- /dev/null +++ b/test/testfiles/mixed_deploy_type/mdt.c | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #include "lua.h" | ||
| 2 | |||
| 3 | int luaopen_mdt(lua_State *L) { | ||
| 4 | lua_pushstring(L, "mdt.c"); | ||
| 5 | return 1; | ||
| 6 | } | ||
diff --git a/test/testfiles/mixed_deploy_type/mdt.lua b/test/testfiles/mixed_deploy_type/mdt.lua new file mode 100644 index 00000000..c9ca9c68 --- /dev/null +++ b/test/testfiles/mixed_deploy_type/mdt.lua | |||
| @@ -0,0 +1 @@ | |||
| return "mdt.lua" | |||
diff --git a/test/testfiles/mixed_deploy_type/mdt_file b/test/testfiles/mixed_deploy_type/mdt_file new file mode 100644 index 00000000..1a15f7d7 --- /dev/null +++ b/test/testfiles/mixed_deploy_type/mdt_file | |||
| @@ -0,0 +1 @@ | |||
| return "mdt_file" | |||
diff --git a/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec b/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec new file mode 100644 index 00000000..91b725da --- /dev/null +++ b/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | package = "mixed_deploy_type" | ||
| 2 | version = "0.1.0-1" | ||
| 3 | source = { | ||
| 4 | url = "http://example.com" | ||
| 5 | } | ||
| 6 | description = { | ||
| 7 | homepage = "http://example.com", | ||
| 8 | license = "*** please specify a license ***" | ||
| 9 | } | ||
| 10 | dependencies = {} | ||
| 11 | build = { | ||
| 12 | type = "builtin", | ||
| 13 | modules = { | ||
| 14 | mdt = "mdt/mdt.lua" | ||
| 15 | }, | ||
| 16 | install = { | ||
| 17 | lua = { | ||
| 18 | mdt_file = "mdt/mdt_file" | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec b/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec new file mode 100644 index 00000000..9ca03180 --- /dev/null +++ b/test/testfiles/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | package = "mixed_deploy_type" | ||
| 2 | version = "0.2.0-1" | ||
| 3 | source = { | ||
| 4 | url = "http://example.com" | ||
| 5 | } | ||
| 6 | description = { | ||
| 7 | homepage = "http://example.com", | ||
| 8 | license = "*** please specify a license ***" | ||
| 9 | } | ||
| 10 | dependencies = {} | ||
| 11 | build = { | ||
| 12 | type = "builtin", | ||
| 13 | modules = { | ||
| 14 | mdt = "mdt/mdt.c" | ||
| 15 | }, | ||
| 16 | install = { | ||
| 17 | lib = { | ||
| 18 | mdt_file = "mdt/mdt_file" | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
