diff options
author | Peter Melnichenko <mpeterval@gmail.com> | 2016-11-01 14:18:16 +0300 |
---|---|---|
committer | Peter Melnichenko <mpeterval@gmail.com> | 2016-11-01 23:00:51 +0300 |
commit | cee2d3abfc1c06f382787d7bf7d2110a52ca0e76 (patch) | |
tree | 5e68eab6d55f48687b2169a5b8a267f9682d163c | |
parent | 933386b16d944eac3f93100886b03c3ae745b802 (diff) | |
download | luarocks-cee2d3abfc1c06f382787d7bf7d2110a52ca0e76.tar.gz luarocks-cee2d3abfc1c06f382787d7bf7d2110a52ca0e76.tar.bz2 luarocks-cee2d3abfc1c06f382787d7bf7d2110a52ca0e76.zip |
Fix and refactor conflict resolution on deploy/delete
Refactor repos.deploy_files and repos.delete_version
to make relationships between properties of deployed
files clearer and to avoid converting back and forth
between related properties.
Location of each deployable file in its rock manifest is
pair deploy_type - the first subtree name ("bin", "lib", or "lua")
and file_path - remaining path from the subtree to the file. These
components determine where each file is physically located.
Conflicts are considered based on two other properties: type
and name of an item a file provides. Type can be "command" or "module".
For items deployed using non-versioned names pairs (type, name) should be
unique.
Conversion from (deploy_type, file_path) to (item_type, item_name)
is obvious, using path.path_to_module() for modules. Reversing this
conversion is necessary for moving files between versioned and
non-versioned locations on conflicts, and also for path.which
function used in luarocks.show. However,
rock tree manifest only allows to get file_path, which
is not enough for modules - deploy_type can be both "lua" and "lib".
Currently path.which infers deploy_type based on extension,
falling back to "lib" if it's unknown, causing luarocks.show
to display wrong paths (#424). This commit does not address that
but adds relevant funcionality.
Currently conflict resolution assumes that both files in conflict
have same deploy_type and errors on conflict between
a C module and a Lua module. This commit fixes that, inferring
deploy_type for files with unknown extension using rock manifest.
-rw-r--r-- | src/luarocks/manif.lua | 132 | ||||
-rw-r--r-- | src/luarocks/repos.lua | 256 |
2 files changed, 205 insertions, 183 deletions
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 |