local logger = require('dep.log') local git = require('dep.git') local fs = require('dep.fs') local packager = require('dep.package') local h = require('dep.helpers') local modules = require("dep.modules") local bench = require("dep.bench") local lazy = require("dep.lazy") -- all functions for convenience local M = {} -- TODO: maybe add the ability to get a lockfile? it's useful to make a config -- rebuildable, but idk if it's actually useful for a neovim config -- (look into how ofter people who use lazy.nvim us it) --- sync a tree of plugins ---@param tree package[] tree of plugins ---@param cb function? callback function M.synctree(tree, cb) local progress = 0 local has_errors = false local function done(err) progress = progress + 1 has_errors = has_errors or err if progress == #tree then 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 fs:clean(packager) for _, package in pairs(tree) do package:reload() end if cb then cb() end end end for _, package in pairs(tree) do local co = coroutine.create(function() -- if the package provided prefers a local source then use the local -- source instead of the git repository if package.path then fs:sync(package, done) else git.sync(package, done) end end) coroutine.resume(co) end end -- basically the main function of our program ---@param opts speclist return function(opts) M.config_path = debug.getinfo(2, "S").source:sub(2) logger.pipe = logger:setup() bench:setup() lazy.setup() --- make comparison for table.sort ---@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 -- consistant, thus we can just check if the unicode value of one package -- id is less than the other return a.id < b.id end local initialized, err = pcall(function() packager.set_base_dir(opts.base_dir or vim.fn.stdpath("data").."/site/pack/deps/opt/") bench.mark("load", function() -- register all packages local root = packager:new({ "squibid/dep", url = "https://git.squi.bid/squibid/dep.git", branch = "lazy", pin = true }) if not root then logger:log("error", "couldn't register root package") return end -- setup all packages and modules if opts.modules then modules:setup(opts, nil, M.config_path) end packager.register_speclist(opts) -- sort package dependencies for _, package in pairs(packager.get_packages()) do table.sort(package.requirements, comp) table.sort(package.dependents, comp) end -- make sure there arent any circular dependencies 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 for _, package in pairs(packager.get_packages()) do package:reload() end --- check if a package should be synced ---@param package table package table spec ---@return boolean sync local function shouldsync(package) if opts.sync == "new" or opts.sync == nil then return not package.exists else return opts.sync == "always" end end -- get all package that need syncing local targets = {} for _, package in pairs(packager.get_packages()) do if shouldsync(package) then table.insert(targets, package) end end -- install all targets M.synctree(targets) end) if not initialized then 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 = h.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.cmd('checktime') w:stop() watch_file(fname) end)) end watch_file(logger.path) end, {}) vim.api.nvim_create_user_command("DepSync", function() M.synctree(packager.get_packages()) end, {}) vim.api.nvim_create_user_command("DepReload", function() for _, package in pairs(packager.get_packages()) do package:reload() end end, {}) vim.api.nvim_create_user_command("DepClean", function() -- clean AND reload to make sure that all old packages are gone fs:clean(packager) end, {}) logger:cleanup() end