more fixes

This commit is contained in:
2025-04-23 00:15:13 -05:00
parent 254436c24d
commit c29395004d
6 changed files with 282 additions and 183 deletions

View File

@ -2,15 +2,10 @@ local logger = require('dep.log')
local git = require('dep.git')
local packager = require('dep.package')
---all functions for convenience
---@type table
-- all functions for convenience
local M = {}
---@type boolean
local initialized
---performance logging
---@type table
-- performance logging
local perf = {}
--- get execution time of a function
@ -30,13 +25,13 @@ function M.registertree(speclist, overrides)
overrides = overrides or {}
-- recurse the packages
local over = overrides
for _, spec in pairs(speclist) do
-- make sure the overrides override and take into account the packages spec
---@diagnostic disable-next-line: missing-fields
overrides = {
pin = overrides.pin or spec.pin,
disable = overrides.disable or spec.disable
over = {
pin = over.pin or spec.pin,
disable = over.disable or spec.disable
}
local ok = packager:new(spec, overrides)
@ -48,8 +43,48 @@ function M.registertree(speclist, overrides)
end
end
--- clean out old packages
function M.clean()
vim.loop.fs_scandir(
packager.get_base_dir(),
vim.schedule_wrap(function(err, handle)
if err then
logger:log("error", string.format("failed to clean; reason: %s", err))
else
local queue = {}
while handle do
local name = vim.loop.fs_scandir_next(handle)
if name then
queue[name] = packager.get_base_dir()..name
else
break
end
end
-- keep packages that still exist
for _, package in pairs(packager.get_packages()) do
queue[package.name] = nil
end
for name, dir in pairs(queue) do
local co = coroutine.create(function()
local ok = vim.fn.delete(dir, "rf")
if ok then
logger:log("clean", string.format("deleted %s", name))
else
logger:log("error", string.format("failed to delete %s", name))
end
end)
coroutine.resume(co)
end
end
end)
)
end
--- reload all packages in package table spec
---@param force boolean|nil force all packages to load
---@param force boolean? force all packages to load
function M.reload(force)
local reloaded = packager.get_root():loadtree(force)
@ -72,63 +107,6 @@ function M.reload(force)
end
end
--- check if there's a circular dependency in the package tree
function M.findcycle()
local index = 0
local indexes = {}
local lowlink = {}
local stack = {}
-- use tarjan algorithm to find circular dependencies (strongly connected
-- components)
local function connect(package)
indexes[package.id], lowlink[package.id] = index, index
stack[#stack + 1], stack[package.id] = package, true
index = index + 1
for i = 1, #package.dependents do
local dependent = package.dependents[i]
if not indexes[dependent.id] then
local cycle = connect(dependent)
if cycle then
return cycle
else
lowlink[package.id] = math.min(lowlink[package.id], lowlink[dependent.id])
end
elseif stack[dependent.id] then
lowlink[package.id] = math.min(lowlink[package.id], indexes[dependent.id])
end
end
if lowlink[package.id] == indexes[package.id] then
local cycle = { package }
local node
repeat
node = stack[#stack]
stack[#stack], stack[node.id] = nil, nil
cycle[#cycle + 1] = node
until node == package
-- a node is by definition strongly connected to itself ignore single-node
-- components unless it explicitly specified itself as a dependency
if #cycle > 2 or package.dependents[package.id] then
return cycle
end
end
end
for _, package in pairs(packager.get_packages()) do
if not indexes[package.id] then
local cycle = connect(package)
if cycle then
return cycle
end
end
end
end
--- sync a tree of plugins
---@param tree package[] tree of plugins
---@param cb function? callback
@ -141,16 +119,15 @@ function M.synctree(tree, cb)
has_errors = has_errors or err
if progress == #tree then
-- TODO: implement clean
-- clean()
M.reload()
if has_errors then
logger:log("error", "there were errors during sync; see :messages or :DepLog for more information")
else
logger:log("update", "synchronized %s %s", #tree, #tree == 1 and "package" or "packages")
end
M.clean()
M.reload()
if cb then
cb()
end
@ -158,7 +135,10 @@ function M.synctree(tree, cb)
end
for _, package in pairs(tree) do
git.sync(package, done)
local co = coroutine.create(function()
git.sync(package, done)
end)
coroutine.resume(co)
end
end
@ -167,8 +147,8 @@ return function(opts)
logger.pipe = logger:setup()
--- make comparison for table.sort
---@param a table package spec a
---@param b table package spec b
---@param a package package spec a
---@param b package package spec b
---@return boolean
local function comp(a, b)
-- NOTE: this doesn't have to be in any real order, it just has to be
@ -177,7 +157,7 @@ return function(opts)
return a.id < b.id
end
initialized, err = pcall(function()
local initialized, err = pcall(function()
packager.set_base_dir(opts.base_dir or vim.fn.stdpath("data").."/site/pack/deps/opt/")
M.benchmark("load", function()
-- register all packages
@ -199,7 +179,10 @@ return function(opts)
end
-- make sure there arent any circular dependencies
M.findcycle()
local ok = packager.findcycle(packager.get_packages())
if type(ok) == "table" then
logger:log("error", "found a cycle in the package spec here: %s", vim.inspect(ok))
end
end)
-- load packages
@ -218,12 +201,13 @@ return function(opts)
-- get all package that need syncing
local targets = {}
for i, package in pairs(packager.get_packages()) do
for _, package in pairs(packager.get_packages()) do
if shouldsync(package) then
targets[i] = package
table.insert(targets, package)
end
end
-- install all targets
M.synctree(targets)
end)
@ -231,17 +215,18 @@ return function(opts)
logger:log("error", err)
end
-- add some user commands
vim.api.nvim_create_user_command("DepLog", function()
vim.cmd('vsp '..logger.path)
vim.opt_local.readonly = true
-- make the log auto update while it's open
local w = vim.uv.new_fs_event()
local function watch_file(fname)
local fullpath = vim.api.nvim_call_function(
'fnamemodify', { fname, ':p' })
w:start(fullpath, {}, vim.schedule_wrap(function(...)
vim.api.nvim_command('checktime')
-- Debounce: stop/start.
w:stop()
watch_file(fname)
end))
@ -258,5 +243,11 @@ return function(opts)
M.reload()
end, {})
vim.api.nvim_create_user_command("DepClean", function()
-- clean AND reload to make sure that all old packages are gone
M.clean()
M.reload()
end, {})
logger:cleanup()
end