more fixes
This commit is contained in:
153
lua/dep.lua
153
lua/dep.lua
@ -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
|
||||
|
Reference in New Issue
Block a user