aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2018-09-03 19:53:18 +0200
committerHisham Muhammad <hisham@gobolinux.org>2018-09-04 18:11:12 +0200
commitc2fde487834c6d7505d7e803256e8764237d4476 (patch)
tree97253f34b90c463ca3bb2039e0aa1ab0855031fd /src
parentd09f92a84d0a9267a066af2d6978f9a51e555f5f (diff)
downloadluarocks-c2fde487834c6d7505d7e803256e8764237d4476.tar.gz
luarocks-c2fde487834c6d7505d7e803256e8764237d4476.tar.bz2
luarocks-c2fde487834c6d7505d7e803256e8764237d4476.zip
repos: fix upgrade and downgrade of files when module names clash
This reworks the logic of upgrading/downgrading multiple versions of the same package (or different packages) when they have different files that resolve to the same module name (foo.lua and foo.so). For a concrete example, this was hitting LuaSec downgrades.
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/cmd/show.lua55
-rw-r--r--src/luarocks/repos.lua394
2 files changed, 262 insertions, 187 deletions
diff --git a/src/luarocks/cmd/show.lua b/src/luarocks/cmd/show.lua
index c90a6bea..bb0fdfd7 100644
--- a/src/luarocks/cmd/show.lua
+++ b/src/luarocks/cmd/show.lua
@@ -5,6 +5,7 @@ local show = {}
5local queries = require("luarocks.queries") 5local queries = require("luarocks.queries")
6local search = require("luarocks.search") 6local search = require("luarocks.search")
7local dir = require("luarocks.core.dir") 7local dir = require("luarocks.core.dir")
8local fs = require("luarocks.fs")
8local cfg = require("luarocks.core.cfg") 9local cfg = require("luarocks.core.cfg")
9local util = require("luarocks.util") 10local util = require("luarocks.util")
10local path = require("luarocks.path") 11local path = require("luarocks.path")
@@ -145,25 +146,52 @@ local function render(template, data)
145 return table.concat(out, "\n") 146 return table.concat(out, "\n")
146end 147end
147 148
148local function files_to_list(name, version, item_set, item_type, repo) 149local function adjust_path(name, version, basedir, pathname, suffix)
149 local ret = {} 150 pathname = dir.path(basedir, pathname)
150 for item_name in util.sortedpairs(item_set) do 151 local vpathname = path.versioned_name(pathname, basedir, name, version)
151 table.insert(ret, { name = item_name, file = repos.which(name, version, item_type, item_name, repo) }) 152 return (fs.exists(vpathname)
152 end 153 and vpathname
153 return ret 154 or pathname) .. (suffix or "")
154end 155end
155 156
156local function modules_to_list(name, version, repo) 157local function modules_to_list(name, version, repo)
157 local ret = {} 158 local ret = {}
158 local rock_manifest = manif.load_rock_manifest(name, version, repo) 159 local rock_manifest = manif.load_rock_manifest(name, version, repo)
159 160
160 local lua_dir = path.lua_dir(name, version, repo) 161 local lua_dir = path.deploy_lua_dir(repo)
161 local lib_dir = path.lib_dir(name, version, repo) 162 local lib_dir = path.deploy_lib_dir(repo)
162 repos.recurse_rock_manifest_entry(rock_manifest.lua, function(pathname, modname) 163 repos.recurse_rock_manifest_entry(rock_manifest.lua, function(pathname)
163 table.insert(ret, { name = modname, file = dir.path(lua_dir, pathname) }) 164 table.insert(ret, {
165 name = path.path_to_module(pathname),
166 file = adjust_path(name, version, lua_dir, pathname),
167 })
164 end) 168 end)
165 repos.recurse_rock_manifest_entry(rock_manifest.lib, function(pathname, modname) 169 repos.recurse_rock_manifest_entry(rock_manifest.lib, function(pathname)
166 table.insert(ret, { name = modname, file = dir.path(lib_dir, pathname) }) 170 table.insert(ret, {
171 name = path.path_to_module(pathname),
172 file = adjust_path(name, version, lib_dir, pathname),
173 })
174 end)
175 table.sort(ret, function(a, b)
176 if a.name == b.name then
177 return a.file < b.file
178 end
179 return a.name < b.name
180 end)
181 return ret
182end
183
184local function commands_to_list(name, version, repo)
185 local ret = {}
186 local rock_manifest = manif.load_rock_manifest(name, version, repo)
187
188 local bin_dir = path.deploy_bin_dir(repo)
189 repos.recurse_rock_manifest_entry(rock_manifest.bin, function(pathname)
190 pathname = adjust_path(name, version, bin_dir, pathname)
191 table.insert(ret, {
192 name = pathname,
193 file = adjust_path(name, version, bin_dir, pathname, cfg.wrapper_suffix),
194 })
167 end) 195 end)
168 table.sort(ret, function(a, b) 196 table.sort(ret, function(a, b)
169 if a.name == b.name then 197 if a.name == b.name then
@@ -209,7 +237,7 @@ local function show_rock(template, namespace, name, version, rockspec, repo, min
209 issues = desc.issues_url, 237 issues = desc.issues_url,
210 labels = desc.labels and table.concat(desc.labels, ", "), 238 labels = desc.labels and table.concat(desc.labels, ", "),
211 location = path.rocks_tree_to_string(repo), 239 location = path.rocks_tree_to_string(repo),
212 commands = files_to_list(name, version, minfo.commands, "command", repo), 240 commands = commands_to_list(name, version, repo),
213 modules = modules_to_list(name, version, repo), 241 modules = modules_to_list(name, version, repo),
214 bdeps = deps_to_list(rockspec.build_dependencies, tree), 242 bdeps = deps_to_list(rockspec.build_dependencies, tree),
215 tdeps = deps_to_list(rockspec.test_dependencies, tree), 243 tdeps = deps_to_list(rockspec.test_dependencies, tree),
@@ -278,5 +306,4 @@ function show.command(flags, name, version)
278 return true 306 return true
279end 307end
280 308
281
282return show 309return show
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua
index 37a81c20..eaec87b8 100644
--- a/src/luarocks/repos.lua
+++ b/src/luarocks/repos.lua
@@ -9,6 +9,21 @@ local util = require("luarocks.util")
9local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
10local manif = require("luarocks.manif") 10local manif = require("luarocks.manif")
11local vers = require("luarocks.core.vers") 11local vers = require("luarocks.core.vers")
12local E = {}
13
14local unpack = unpack or table.unpack
15
16--- Get type and name of an item (a module or a command) provided by a file.
17-- @param deploy_type string: rock manifest subtree the file comes from ("bin", "lua", or "lib").
18-- @param file_path string: path to the file relatively to deploy_type subdirectory.
19-- @return (string, string): item type ("module" or "command") and name.
20local function get_provided_item(deploy_type, file_path)
21 assert(type(deploy_type) == "string")
22 assert(type(file_path) == "string")
23 local item_type = deploy_type == "bin" and "command" or "module"
24 local item_name = item_type == "command" and file_path or path.path_to_module(file_path)
25 return item_type, item_name
26end
12 27
13-- Tree of files installed by a package are stored 28-- Tree of files installed by a package are stored
14-- in its rock manifest. Some of these files have to 29-- in its rock manifest. Some of these files have to
@@ -52,37 +67,35 @@ function repos.is_installed(name, version)
52end 67end
53 68
54function repos.recurse_rock_manifest_entry(entry, action) 69function repos.recurse_rock_manifest_entry(entry, action)
55 assert(entry == nil or type(entry) == "table")
56 assert(type(action) == "function") 70 assert(type(action) == "function")
57 71
58 if entry == nil then 72 if entry == nil then
59 return true 73 return true
60 end 74 end
61 75
62 local function do_recurse_rock_manifest_tree(tree, parent_path, parent_mod) 76 local function do_recurse_rock_manifest_entry(tree, parent_path)
77
63 for file, sub in pairs(tree) do 78 for file, sub in pairs(tree) do
64 local sub_path = (parent_path and (parent_path .. "/") or "") .. file 79 local sub_path = (parent_path and (parent_path .. "/") or "") .. file
65 local sub_mod = (parent_mod and (parent_mod .. ".") or "") .. file
66 local ok, err 80 local ok, err
67 81
68 if type(sub) == "table" then 82 if type(sub) == "table" then
69 ok, err = do_recurse_rock_manifest_tree(sub, sub_path, sub_mod) 83 ok, err = do_recurse_rock_manifest_entry(sub, sub_path)
70 else 84 else
71 local mod_no_ext = sub_mod:gsub("%.[^.]*$", "") 85 ok, err = action(sub_path)
72 ok, err = action(sub_path, mod_no_ext)
73 end 86 end
74 87
75 if err then return nil, err end 88 if err then return nil, err end
76 end 89 end
77 return true 90 return true
78 end 91 end
79 return do_recurse_rock_manifest_tree(entry) 92 return do_recurse_rock_manifest_entry(entry)
80end 93end
81 94
82local function store_package_data(result, rock_manifest, deploy_type) 95local function store_package_data(result, rock_manifest, deploy_type)
83 if rock_manifest[deploy_type] then 96 if rock_manifest[deploy_type] then
84 repos.recurse_rock_manifest_entry(rock_manifest[deploy_type], function(file_path) 97 repos.recurse_rock_manifest_entry(rock_manifest[deploy_type], function(file_path)
85 local _, item_name = manif.get_provided_item(deploy_type, file_path) 98 local _, item_name = get_provided_item(deploy_type, file_path)
86 result[item_name] = file_path 99 result[item_name] = file_path
87 return true 100 return true
88 end) 101 end)
@@ -206,29 +219,12 @@ local function find_suffixed(file, suffix)
206 return nil, table.concat(filenames, ", ") .. " not found" 219 return nil, table.concat(filenames, ", ") .. " not found"
207end 220end
208 221
209local function move_suffixed(from_file, to_file, suffix) 222local function check_suffix(filename, suffix)
210 local suffixed_from_file, err = find_suffixed(from_file, suffix) 223 local suffixed_filename, err = find_suffixed(filename, suffix)
211 if not suffixed_from_file then 224 if not suffixed_filename then
212 return nil, "Could not move " .. from_file .. " to " .. to_file .. ": " .. err 225 return ""
213 end 226 end
214 227 return suffixed_filename:sub(#filename + 1)
215 suffix = suffixed_from_file:sub(#from_file + 1)
216 local suffixed_to_file = to_file .. suffix
217 return fs.move(suffixed_from_file, suffixed_to_file)
218end
219
220local function delete_suffixed(file, suffix)
221 local suffixed_file, err = find_suffixed(file, suffix)
222 if not suffixed_file then
223 return nil, "Could not remove " .. file .. ": " .. err, "not found"
224 end
225
226 fs.delete(suffixed_file)
227 if fs.exists(suffixed_file) then
228 return nil, "Failed deleting " .. suffixed_file .. ": file still exists", "fail"
229 end
230
231 return true
232end 228end
233 229
234-- Files can be deployed using versioned and non-versioned names. 230-- Files can be deployed using versioned and non-versioned names.
@@ -238,38 +234,92 @@ end
238-- is deployed using non-versioned name and others use versioned names. 234-- is deployed using non-versioned name and others use versioned names.
239 235
240local function get_deploy_paths(name, version, deploy_type, file_path, repo) 236local function get_deploy_paths(name, version, deploy_type, file_path, repo)
237 assert(type(name) == "string")
238 assert(type(version) == "string")
239 assert(type(deploy_type) == "string")
240 assert(type(file_path) == "string")
241
241 repo = repo or cfg.root_dir 242 repo = repo or cfg.root_dir
242 local deploy_dir = path["deploy_" .. deploy_type .. "_dir"](repo) 243 local deploy_dir = path["deploy_" .. deploy_type .. "_dir"](repo)
243 local non_versioned = dir.path(deploy_dir, file_path) 244 local non_versioned = dir.path(deploy_dir, file_path)
244 local versioned = path.versioned_name(non_versioned, deploy_dir, name, version) 245 local versioned = path.versioned_name(non_versioned, deploy_dir, name, version)
245 return non_versioned, versioned 246 return { nv = non_versioned, v = versioned }
246end 247end
247 248
248local function prepare_target(name, version, deploy_type, file_path, suffix) 249local function check_spot_if_available(name, version, deploy_type, file_path)
249 local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) 250 local item_type, item_name = get_provided_item(deploy_type, file_path)
250 local item_type, item_name = manif.get_provided_item(deploy_type, file_path)
251 local cur_name, cur_version = manif.get_current_provider(item_type, item_name) 251 local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
252 if (not cur_name)
253 or (name < cur_name)
254 or (name == cur_name and (version == cur_version
255 or vers.compare_versions(version, cur_version))) then
256 return "nv", cur_name, cur_version, item_name
257 else
258 -- Existing version has priority, deploy new version using versioned name.
259 return "v", cur_name, cur_version, item_name
260 end
261end
262
263local function backup_existing(should_backup, target)
264 if not should_backup then
265 return
266 end
267 if fs.exists(target) then
268 local backup = target
269 repeat
270 backup = backup.."~"
271 until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem.
272
273 util.warning(target.." is not tracked by this installation of LuaRocks. Moving it to "..backup)
274 local move_ok, move_err = fs.move(target, backup)
275 if not move_ok then
276 return nil, move_err
277 end
278 end
279end
280
281local function op_install(op)
282 local ok, err = fs.make_dir(dir.dir_name(op.dst))
283 if not ok then
284 return nil, err
285 end
252 286
253 if not cur_name then 287 ok, err = op.fn(op.src, op.dst, op.backup)
254 return non_versioned 288 if not ok then
255 elseif name < cur_name or (name == cur_name and vers.compare_versions(version, cur_version)) then 289 return nil, err
256 -- New version has priority. Move currently provided version back using versioned name. 290 end
257 local cur_deploy_type, cur_file_path = manif.get_providing_file(cur_name, cur_version, item_type, item_name)
258 local cur_non_versioned, cur_versioned = get_deploy_paths(cur_name, cur_version, cur_deploy_type, cur_file_path)
259 291
260 local dir_ok, dir_err = fs.make_dir(dir.dir_name(cur_versioned)) 292 fs.remove_dir_tree_if_empty(dir.dir_name(op.src))
261 if not dir_ok then return nil, dir_err end 293end
262 294
263 local move_ok, move_err = move_suffixed(cur_non_versioned, cur_versioned, suffix) 295local function op_rename(op)
264 if not move_ok then return nil, move_err end 296 if op.suffix then
297 local suffix = check_suffix(op.src, op.suffix)
298 op.src = op.src .. suffix
299 op.dst = op.dst .. suffix
300 end
265 301
266 return non_versioned 302 if fs.exists(op.src) then
303 fs.make_dir(dir.dir_name(op.dst))
304 local ok, err = fs.move(op.src, op.dst)
305 fs.remove_dir_tree_if_empty(dir.dir_name(op.src))
306 return ok, err
267 else 307 else
268 -- Current version has priority, deploy new version using versioned name. 308 return true
269 return versioned
270 end 309 end
271end 310end
272 311
312local function op_delete(op)
313 if op.suffix then
314 local suffix = check_suffix(op.name, op.suffix)
315 op.name = op.name .. suffix
316 end
317
318 local ok, err = fs.delete(op.name)
319 fs.remove_dir_tree_if_empty(dir.dir_name(op.name))
320 return ok, err
321end
322
273--- Deploy a package from the rocks subdirectory. 323--- Deploy a package from the rocks subdirectory.
274-- @param name string: name of package 324-- @param name string: name of package
275-- @param version string: exact package version in string format 325-- @param version string: exact package version in string format
@@ -284,63 +334,89 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode)
284 334
285 local rock_manifest, load_err = manif.load_rock_manifest(name, version) 335 local rock_manifest, load_err = manif.load_rock_manifest(name, version)
286 if not rock_manifest then return nil, load_err end 336 if not rock_manifest then return nil, load_err end
337
338 local repo = cfg.root_dir
339 local renames = {}
340 local installs = {}
287 341
288 local function deploy_file_tree(deploy_type, source_dir, move_fn, suffix) 342 local function install_binary(source, target, should_backup)
289 return repos.recurse_rock_manifest_entry(rock_manifest[deploy_type], function(file_path) 343 if wrap_bin_scripts and fs.is_lua(source) then
290 local source = dir.path(source_dir, file_path) 344 backup_existing(should_backup, target .. (cfg.wrapper_suffix or ""))
345 return fs.wrap_script(source, target, deps_mode, name, version)
346 else
347 backup_existing(should_backup, target)
348 return fs.copy_binary(source, target)
349 end
350 end
291 351
292 local target, prepare_err = prepare_target(name, version, deploy_type, file_path, suffix) 352 local function move_lua(source, target, should_backup)
293 if not target then return nil, prepare_err end 353 backup_existing(should_backup, target)
354 return fs.move(source, target, "read")
355 end
294 356
295 local dir_ok, dir_err = fs.make_dir(dir.dir_name(target)) 357 local function move_lib(source, target, should_backup)
296 if not dir_ok then return nil, dir_err end 358 backup_existing(should_backup, target)
359 return fs.move(source, target, "exec")
360 end
297 361
298 local suffixed_target, mover = move_fn(source, target) 362 if rock_manifest.bin then
299 if fs.exists(suffixed_target) then 363 local source_dir = path.bin_dir(name, version)
300 local backup = suffixed_target 364 repos.recurse_rock_manifest_entry(rock_manifest.bin, function(file_path)
301 repeat 365 local source = dir.path(source_dir, file_path)
302 backup = backup.."~" 366 local paths = get_deploy_paths(name, version, "bin", file_path, repo)
303 until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem. 367 local mode, cur_name, cur_version = check_spot_if_available(name, version, "bin", file_path)
304 368
305 util.warning(suffixed_target.." is not tracked by this installation of LuaRocks. Moving it to "..backup) 369 if mode == "nv" and cur_name then
306 local move_ok, move_err = fs.move(suffixed_target, backup) 370 local cur_paths = get_deploy_paths(cur_name, cur_version, "bin", file_path, repo)
307 if not move_ok then return nil, move_err end 371 table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v, suffix = cfg.wrapper_suffix })
308 end 372 end
309 373 local backup = name ~= cur_name or version ~= cur_version
310 local move_ok, move_err = mover() 374 table.insert(installs, { fn = install_binary, src = source, dst = mode == "nv" and paths.nv or paths.v, backup = backup })
311 if not move_ok then return nil, move_err end
312
313 fs.remove_dir_tree_if_empty(dir.dir_name(source))
314 return true
315 end) 375 end)
316 end 376 end
317 377
318 local function install_binary(source, target) 378 if rock_manifest.lua then
319 if wrap_bin_scripts and fs.is_lua(source) then 379 local source_dir = path.lua_dir(name, version)
320 return target .. (cfg.wrapper_suffix or ""), function() 380 repos.recurse_rock_manifest_entry(rock_manifest.lua, function(file_path)
321 return fs.wrap_script(source, target, deps_mode, name, version) 381 local source = dir.path(source_dir, file_path)
322 end 382 local paths = get_deploy_paths(name, version, "lua", file_path, repo)
323 else 383 local mode, cur_name, cur_version = check_spot_if_available(name, version, "lua", file_path)
324 return target, function() 384
325 return fs.copy_binary(source, target) 385 if mode == "nv" and cur_name then
386 local cur_paths = get_deploy_paths(cur_name, cur_version, "lua", file_path, repo)
387 table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
388 cur_paths = get_deploy_paths(cur_name, cur_version, "lib", file_path:gsub("%.lua$", "." .. cfg.lib_extension), repo)
389 table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
326 end 390 end
327 end 391 local backup = name ~= cur_name or version ~= cur_version
392 table.insert(installs, { fn = move_lua, src = source, dst = mode == "nv" and paths.nv or paths.v, backup = backup })
393 end)
328 end 394 end
329 395
330 local function make_mover(perms) 396 if rock_manifest.lib then
331 return function(source, target) 397 local source_dir = path.lib_dir(name, version)
332 return target, function() return fs.move(source, target, perms) end 398 repos.recurse_rock_manifest_entry(rock_manifest.lib, function(file_path)
333 end 399 local source = dir.path(source_dir, file_path)
400 local paths = get_deploy_paths(name, version, "lib", file_path, repo)
401 local mode, cur_name, cur_version = check_spot_if_available(name, version, "lib", file_path)
402
403 if mode == "nv" and cur_name then
404 local cur_paths = get_deploy_paths(cur_name, cur_version, "lua", file_path:gsub("%.[^.]+$", ".lua"), repo)
405 table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
406 cur_paths = get_deploy_paths(cur_name, cur_version, "lib", file_path, repo)
407 table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
408 end
409 local backup = name ~= cur_name or version ~= cur_version
410 table.insert(installs, { fn = move_lib, src = source, dst = mode == "nv" and paths.nv or paths.v, backup = backup })
411 end)
334 end 412 end
335 413
336 local ok, err = deploy_file_tree("bin", path.bin_dir(name, version), install_binary, cfg.wrapper_suffix) 414 for _, op in ipairs(renames) do
337 if not ok then return nil, err end 415 op_rename(op)
338 416 end
339 ok, err = deploy_file_tree("lua", path.lua_dir(name, version), make_mover("read")) 417 for _, op in ipairs(installs) do
340 if not ok then return nil, err end 418 op_install(op)
341 419 end
342 ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover("exec"))
343 if not ok then return nil, err end
344 420
345 local writer = require("luarocks.manif.writer") 421 local writer = require("luarocks.manif.writer")
346 return writer.add_to_manifest(name, version, nil, deps_mode) 422 return writer.add_to_manifest(name, version, nil, deps_mode)
@@ -364,60 +440,76 @@ function repos.delete_version(name, version, deps_mode, quick)
364 local rock_manifest, load_err = manif.load_rock_manifest(name, version) 440 local rock_manifest, load_err = manif.load_rock_manifest(name, version)
365 if not rock_manifest then return nil, load_err end 441 if not rock_manifest then return nil, load_err end
366 442
367 local function delete_deployed_file_tree(deploy_type, suffix) 443 local repo = cfg.root_dir
368 return repos.recurse_rock_manifest_entry(rock_manifest[deploy_type], function(file_path) 444 local renames = {}
369 local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) 445 local deletes = {}
370
371 -- Figure out if the file is deployed using versioned or non-versioned name.
372 local target
373 local item_type, item_name = manif.get_provided_item(deploy_type, file_path)
374 local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
375 446
376 if cur_name == name and cur_version == version then 447 if rock_manifest.bin then
377 -- This package has highest priority, should be in non-versioned location. 448 repos.recurse_rock_manifest_entry(rock_manifest.bin, function(file_path)
378 target = non_versioned 449 local paths = get_deploy_paths(name, version, "bin", file_path, repo)
450 local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "bin", file_path)
451 if mode == "v" then
452 table.insert(deletes, { name = paths.v, suffix = cfg.wrapper_suffix })
379 else 453 else
380 target = versioned 454 table.insert(deletes, { name = paths.nv, suffix = cfg.wrapper_suffix })
381 end
382 455
383 local ok, err, err_type = delete_suffixed(target, suffix) 456 local next_name, next_version = manif.get_next_provider("command", item_name)
384 if not ok then 457 if next_name then
385 if err_type == "not found" then 458 local next_paths = get_deploy_paths(next_name, next_version, "lua", file_path, repo)
386 util.warning(err) 459 table.insert(renames, { src = next_paths.v, dst = next_paths.nv, suffix = cfg.wrapper_suffix })
387 else
388 return nil, err
389 end 460 end
390 end 461 end
462 end)
463 end
391 464
392 if not quick and target == non_versioned then 465 if rock_manifest.lua then
393 -- If another package provides this file, move its version 466 repos.recurse_rock_manifest_entry(rock_manifest.lua, function(file_path)
394 -- into non-versioned location instead. 467 local paths = get_deploy_paths(name, version, "lua", file_path, repo)
395 local next_name, next_version = manif.get_next_provider(item_type, item_name) 468 local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "lua", file_path)
469 if mode == "v" then
470 table.insert(deletes, { name = paths.v })
471 else
472 table.insert(deletes, { name = paths.nv })
396 473
474 local next_name, next_version = manif.get_next_provider("module", item_name)
397 if next_name then 475 if next_name then
398 local next_deploy_type, next_file_path = manif.get_providing_file(next_name, next_version, item_type, item_name) 476 local next_lua_paths = get_deploy_paths(next_name, next_version, "lua", file_path, repo)
399 local next_non_versioned, next_versioned = get_deploy_paths(next_name, next_version, next_deploy_type, next_file_path) 477 table.insert(renames, { src = next_lua_paths.v, dst = next_lua_paths.nv })
400 478 local next_lib_paths = get_deploy_paths(next_name, next_version, "lib", file_path:gsub("%.[^.]+$", ".lua"), repo)
401 local move_ok, move_err = move_suffixed(next_versioned, next_non_versioned, suffix) 479 table.insert(renames, { src = next_lib_paths.v, dst = next_lib_paths.nv })
402 if not move_ok then return nil, move_err end
403
404 fs.remove_dir_tree_if_empty(dir.dir_name(next_versioned))
405 end 480 end
406 end 481 end
407
408 fs.remove_dir_tree_if_empty(dir.dir_name(target))
409 return true
410 end) 482 end)
411 end 483 end
412 484
413 local ok, err = delete_deployed_file_tree("bin", cfg.wrapper_suffix) 485 if rock_manifest.lib then
414 if not ok then return nil, err end 486 repos.recurse_rock_manifest_entry(rock_manifest.lib, function(file_path)
487 local paths = get_deploy_paths(name, version, "lib", file_path, repo)
488 local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "lib", file_path)
489 if mode == "v" then
490 table.insert(deletes, { name = paths.v })
491 else
492 table.insert(deletes, { name = paths.nv })
415 493
416 ok, err = delete_deployed_file_tree("lua") 494 local next_name, next_version = manif.get_next_provider("module", item_name)
417 if not ok then return nil, err end 495 if next_name then
496 local next_lua_paths = get_deploy_paths(next_name, next_version, "lua", file_path:gsub("%.[^.]+$", ".lua"), repo)
497 table.insert(renames, { src = next_lua_paths.v, dst = next_lua_paths.nv })
498 local next_lib_paths = get_deploy_paths(next_name, next_version, "lib", file_path, repo)
499 table.insert(renames, { src = next_lib_paths.v, dst = next_lib_paths.nv })
500 end
501 end
502 end)
503 end
418 504
419 ok, err = delete_deployed_file_tree("lib") 505 for _, op in ipairs(deletes) do
420 if not ok then return nil, err end 506 op_delete(op)
507 end
508 if not quick then
509 for _, op in ipairs(renames) do
510 op_rename(op)
511 end
512 end
421 513
422 fs.delete(path.install_dir(name, version)) 514 fs.delete(path.install_dir(name, version))
423 if not get_installed_versions(name) then 515 if not get_installed_versions(name) then
@@ -432,48 +524,4 @@ function repos.delete_version(name, version, deps_mode, quick)
432 return writer.remove_from_manifest(name, version, nil, deps_mode) 524 return writer.remove_from_manifest(name, version, nil, deps_mode)
433end 525end
434 526
435--- Find full path to a file providing a module or a command
436-- in a package.
437-- @param name string: name of package.
438-- @param version string: exact package version in string format.
439-- @param item_type string: "module" or "command".
440-- @param item_name string: module or command name.
441-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used.
442-- @return string: absolute path to the file providing given module
443-- or command.
444function repos.which(name, version, item_type, item_name, repo)
445 local deploy_type, file_path = manif.get_providing_file(name, version, item_type, item_name, repo)
446 local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path, repo)
447 local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
448 local deploy_path = (name == cur_name and version == cur_version) and non_versioned or versioned
449
450 if deploy_type == "bin" and cfg.wrapper_suffix and cfg.wrapper_suffix ~= "" then
451 deploy_path = find_suffixed(deploy_path, cfg.wrapper_suffix) or deploy_path
452 end
453
454 return deploy_path
455end
456
457--- Find full path to a file providing a module or a command
458-- in a package.
459-- @param name string: name of package.
460-- @param version string: exact package version in string format.
461-- @param item_type string: "module" or "command".
462-- @param item_name string: module or command name.
463-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used.
464-- @return string: absolute path to the file providing given module
465-- or command.
466function repos.which(name, version, item_type, item_name, repo)
467 local deploy_type, file_path = manif.get_providing_file(name, version, item_type, item_name, repo)
468 local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path, repo)
469 local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
470 local deploy_path = (name == cur_name and version == cur_version) and non_versioned or versioned
471
472 if deploy_type == "bin" and cfg.wrapper_suffix and cfg.wrapper_suffix ~= "" then
473 deploy_path = find_suffixed(deploy_path, cfg.wrapper_suffix) or deploy_path
474 end
475
476 return deploy_path
477end
478
479return repos 527return repos