From 498ca1b4ee0e0b118363b3a473cf0e6b216c8e33 Mon Sep 17 00:00:00 2001 From: Marc Jakobi Date: Sun, 8 Oct 2023 20:41:09 +0200 Subject: [PATCH] fix(sync): do not attempt to remove dependencies --- lua/rocks/internal-types.lua | 4 +++ lua/rocks/operations.lua | 52 ++++++++++++++++++++++++------------ lua/rocks/setup.lua | 12 +++++---- lua/rocks/state.lua | 33 +++++++++++++++++++++++ todos.norg | 2 +- 5 files changed, 80 insertions(+), 23 deletions(-) diff --git a/lua/rocks/internal-types.lua b/lua/rocks/internal-types.lua index 3bd0b4d5..93082bb9 100644 --- a/lua/rocks/internal-types.lua +++ b/lua/rocks/internal-types.lua @@ -19,4 +19,8 @@ ---@field public name string ---@field public version string +---@class (exact) RockDependency +---@field public name string +---@field public version? string + --- internal-types.lua ends here diff --git a/lua/rocks/operations.lua b/lua/rocks/operations.lua index aeb4d069..483a9299 100644 --- a/lua/rocks/operations.lua +++ b/lua/rocks/operations.lua @@ -113,6 +113,11 @@ operations.sync = function(user_rocks) local line_nr = 1 + ---@type {[string]: RockDependency} + local dependencies = {} + ---@type string[] + local to_remove_keys = {} + for _, key in ipairs(key_list) do local linenr_copy = line_nr local expand_ui = true @@ -131,44 +136,57 @@ operations.sync = function(user_rocks) return ret end) - elseif not user_rocks[key] and installed_rocks[key] then - local text = NuiText("Removing '" .. key .. "'") + elseif user_rocks[key].version ~= installed_rocks[key].version then + local is_downgrading = vim.version.parse(user_rocks[key].version) + < vim.version.parse(installed_rocks[key].version) + + local text = NuiText((is_downgrading and "Downgrading" or "Updating") .. " '" .. key .. "'") local msg_length = text:content():len() text:render_char(split.bufnr, -1, linenr_copy, 0, linenr_copy, msg_length) table.insert(actions, function() - -- NOTE: This will fail if it breaks dependencies. - -- That is generally good, although we definitely want a handler - -- that ignores this and doesn't display the "Removing" text for. - -- To my knowledge there is no way to query all rocks that are *not* - -- dependencies. - local ret = operations.remove(installed_rocks[key].name).wait() + local ret = operations.install(user_rocks[key].name, user_rocks[key].version).wait() nio.scheduler() - text:set("Removed '" .. key .. "'") + text:set((is_downgrading and "Downgraded" or "Updated") .. " '" .. key .. "'") text:render_char(split.bufnr, -1, linenr_copy, 0, linenr_copy, msg_length) return ret end) - elseif user_rocks[key].version ~= installed_rocks[key].version then - local is_downgrading = vim.version.parse(user_rocks[key].version) - < vim.version.parse(installed_rocks[key].version) + elseif not user_rocks[key] and installed_rocks[key] then + table.insert(to_remove_keys, key) + expand_ui = false + else + expand_ui = false + end - local text = NuiText((is_downgrading and "Downgrading" or "Updating") .. " '" .. key .. "'") + vim.tbl_extend("force", dependencies, state.rock_dependencies(user_rocks[key])) + + if expand_ui and line_nr >= 1 then + vim.api.nvim_buf_set_lines(split.bufnr, line_nr, line_nr, true, { "" }) + line_nr = line_nr + 1 + end + end + + for _, key in ipairs(to_remove_keys) do + local linenr_copy = line_nr + local is_dependency = dependencies[key] ~= nil + local expand_ui = not is_dependency + + if not is_dependency then + local text = NuiText("Removing '" .. key .. "'") local msg_length = text:content():len() text:render_char(split.bufnr, -1, linenr_copy, 0, linenr_copy, msg_length) table.insert(actions, function() - local ret = operations.install(user_rocks[key].name, user_rocks[key].version).wait() + local ret = operations.remove(installed_rocks[key].name).wait() nio.scheduler() - text:set((is_downgrading and "Downgraded" or "Updated") .. " '" .. key .. "'") + text:set("Removed '" .. key .. "'") text:render_char(split.bufnr, -1, linenr_copy, 0, linenr_copy, msg_length) return ret end) - else - expand_ui = false end if expand_ui and line_nr >= 1 then diff --git a/lua/rocks/setup.lua b/lua/rocks/setup.lua index 9f203f8c..8f17e8ef 100644 --- a/lua/rocks/setup.lua +++ b/lua/rocks/setup.lua @@ -22,11 +22,13 @@ local config = require("rocks.config") local luarocks = require("rocks.luarocks") local function bootstrap_install(name, version) - luarocks.cli({ - "install", - name, - version, - }):wait() + luarocks + .cli({ + "install", + name, + version, + }) + :wait() end --- Initialize rocks.nvim diff --git a/lua/rocks/state.lua b/lua/rocks/state.lua index 76aebadf..9e79289b 100644 --- a/lua/rocks/state.lua +++ b/lua/rocks/state.lua @@ -73,4 +73,37 @@ state.outdated_rocks = nio.create(function() return rocks end) +---List the dependencies of an installed Rock +---@type fun(rock:Rock): {[string]: RockDependency} +---@async +state.rock_dependencies = nio.create(function(rock) + ---@type {[string]: RockDependency} + local dependencies = {} + + local future = nio.control.future() + + luarocks.cli({ + "show", + "--deps", + rock.name, + }, function(obj) + -- TODO: Error handling + future.set(obj.stdout) + end, { text = true }) + + local dependency_list = future.wait() + + for line in string.gmatch(dependency_list, "[^%s*][^\n]+") do + local name, version = line:match("([^%s]+)%s[^%s]+%s([^%s]+)") + if not name then + name = line:match("([^%s]+)") + end + if name and name ~= "lua" then + dependencies[name] = { name = name, version = version } + end + end + + return dependencies +end) + return state diff --git a/todos.norg b/todos.norg index 4008589e..dfe4e598 100644 --- a/todos.norg +++ b/todos.norg @@ -2,7 +2,7 @@ The most urgent ones are marked with the urgent (`(!)`) TODO tag. - - (!) When syncing, do not attempt to remove plugins that are dependencies of another project. + - (x) When syncing, do not attempt to remove plugins that are dependencies of another project. To achieve this, you must first attempt to remove the dependency, see if luarocks allows you to, and if it does mark it as removed. - (!) Improve error messages across the whole repository, they're currently pretty bad. - ( ) Running `:Rocks update` should not update core rocks in the `[rocks]` table