Skip to content

Commit

Permalink
refactor(sync): extract state.out_of_sync_rocks (nvim-neorocks#418)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb authored Jun 26, 2024
1 parent 9b9fddb commit 704940f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 40 deletions.
48 changes: 8 additions & 40 deletions lua/rocks/operations/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -134,38 +134,7 @@ operations.sync = function(user_rocks, on_complete)

local installed_rocks = state.installed_rocks()

-- The following code uses `nio.fn.keys` instead of `vim.tbl_keys`
-- which invokes the scheduler and works in async contexts.
---@type string[]
---@diagnostic disable-next-line: invisible
local key_list = nio.fn.keys(vim.tbl_deep_extend("force", installed_rocks, user_rocks))

local external_actions = vim.empty_dict()
---@cast external_actions rock_handler_callback[]
local to_install = vim.empty_dict()
---@cast to_install string[]
local to_updowngrade = vim.empty_dict()
---@cast to_updowngrade string[]
local to_prune = vim.empty_dict()
---@cast to_prune string[]
for _, key in ipairs(key_list) do
local user_rock = user_rocks[key]
local callback = user_rock and handlers.get_sync_handler_callback(user_rock)
if callback then
table.insert(external_actions, callback)
elseif user_rocks and not installed_rocks[key] then
table.insert(to_install, key)
elseif
user_rock
and user_rock.version
and installed_rocks[key]
and user_rock.version ~= installed_rocks[key].version
then
table.insert(to_updowngrade, key)
elseif not user_rock and installed_rocks[key] then
table.insert(to_prune, key)
end
end
local sync_status = state.out_of_sync_rocks(user_rocks)

local ct = 1

Expand All @@ -176,7 +145,7 @@ operations.sync = function(user_rocks, on_complete)
---@type SyncSkippedRock[]
local skipped_rocks = {}

for _, key in ipairs(to_install) do
for _, key in ipairs(sync_status.to_install) do
-- Save skipped rocks for later, when an external handler may have been bootstrapped
if not user_rocks[key].version then
table.insert(skipped_rocks, {
Expand Down Expand Up @@ -215,7 +184,7 @@ operations.sync = function(user_rocks, on_complete)
end

-- Sync actions handled by external modules that have registered handlers
for _, callback in ipairs(external_actions) do
for _, callback in ipairs(sync_status.external_actions) do
ct = ct + 1
callback(report_progress, report_error)
end
Expand All @@ -233,7 +202,7 @@ operations.sync = function(user_rocks, on_complete)
end
end

for _, key in ipairs(to_updowngrade) do
for _, key in ipairs(sync_status.to_updowngrade) do
local is_installed_version_semver, installed_version =
pcall(vim.version.parse, installed_rocks[key].version)
local is_user_version_semver, user_version = pcall(vim.version.parse, user_rocks[key].version or "dev")
Expand Down Expand Up @@ -268,13 +237,12 @@ operations.sync = function(user_rocks, on_complete)
-- NOTE(mrcjkb): This has to be done after installation,
-- so that we don't prune dependencies of newly installed rocks.
local function refresh_rocks_state()
to_prune = vim.empty_dict()
sync_status.to_prune = vim.empty_dict()
installed_rocks = state.installed_rocks()
key_list = nio.fn.keys(vim.tbl_deep_extend("force", installed_rocks, user_rocks))
---@cast to_prune string[]
local key_list = nio.fn.keys(vim.tbl_deep_extend("force", installed_rocks, user_rocks))
for _, key in ipairs(key_list) do
if not user_rocks[key] and installed_rocks[key] then
table.insert(to_prune, key)
table.insert(sync_status.to_prune, key)
end
end
local dependencies = vim.empty_dict()
Expand All @@ -285,7 +253,7 @@ operations.sync = function(user_rocks, on_complete)
end
end

prunable_rocks = vim.iter(to_prune)
prunable_rocks = vim.iter(sync_status.to_prune)
:filter(function(key)
return dependencies[key] == nil
end)
Expand Down
46 changes: 46 additions & 0 deletions lua/rocks/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ local state = {}

local luarocks = require("rocks.luarocks")
local constants = require("rocks.constants")
local config = require("rocks.config.internal")
local log = require("rocks.log")
local nio = require("nio")

Expand Down Expand Up @@ -150,4 +151,49 @@ state.query_removable_rocks = nio.create(function()
:totable()
end)

---@class rocks.state.SyncStatus
---@field external_actions table<rock_name, rock_handler_callback>
---@field to_install rock_name[]
---@field to_updowngrade rock_name[]
---@field to_prune rock_name[]

---@type async fun(user_rocks?: table<rock_name, RockSpec>): rocks.state.SyncStatus
state.out_of_sync_rocks = nio.create(function(user_rocks)
local handlers = require("rocks.operations.handlers")
user_rocks = user_rocks or config.get_user_rocks()
local installed_rocks = state.installed_rocks()
-- The following code uses `nio.fn.keys` instead of `vim.tbl_keys`
-- which invokes the scheduler and works in async contexts.
---@type string[]
---@diagnostic disable-next-line: invisible
local key_list = nio.fn.keys(vim.tbl_deep_extend("force", installed_rocks, user_rocks))
---@type rocks.state.SyncStatus
local mempty = {
external_actions = vim.empty_dict(),
to_install = vim.empty_dict(),
to_updowngrade = vim.empty_dict(),
to_prune = vim.empty_dict(),
}
---@param acc rocks.state.SyncStatus
return vim.iter(key_list):fold(mempty, function(acc, key)
local user_rock = user_rocks[key]
local callback = user_rock and handlers.get_sync_handler_callback(user_rock)
if callback then
acc.external_actions[key] = callback
elseif user_rocks and not installed_rocks[key] then
table.insert(acc.to_install, key)
elseif
user_rock
and user_rock.version
and installed_rocks[key]
and user_rock.version ~= installed_rocks[key].version
then
table.insert(acc.to_updowngrade, key)
elseif not user_rock and installed_rocks[key] then
table.insert(acc.to_prune, key)
end
return acc
end)
end, 1)

return state

0 comments on commit 704940f

Please sign in to comment.