864 lines
20 KiB
Lua
Executable File
864 lines
20 KiB
Lua
Executable File
local logger = require("dep/log")
|
|
local proc = require("dep/proc")
|
|
|
|
logger:open()
|
|
|
|
local initialized, perf, config_path, base_dir
|
|
local packages, root
|
|
|
|
local function bench(name, code, ...)
|
|
local start = os.clock()
|
|
code(...)
|
|
perf[name] = os.clock() - start
|
|
end
|
|
|
|
local function get_name(id)
|
|
local name = id:match("^[%w-_.]+/([%w-_.]+)$")
|
|
if name then
|
|
return name
|
|
else
|
|
error(string.format('invalid name "%s"; must be in the format "user/package"', id))
|
|
end
|
|
end
|
|
|
|
local function link_dependency(parent, child)
|
|
if not parent.dependents[child.id] then
|
|
parent.dependents[child.id] = child
|
|
parent.dependents[#parent.dependents + 1] = child
|
|
end
|
|
|
|
if not child.dependencies[parent.id] then
|
|
child.dependencies[parent.id] = parent
|
|
child.dependencies[#child.dependencies + 1] = parent
|
|
end
|
|
end
|
|
|
|
local function register(spec, overrides)
|
|
overrides = overrides or {}
|
|
|
|
if type(spec) ~= "table" then
|
|
spec = { spec }
|
|
end
|
|
|
|
local id = spec[1]
|
|
local package = packages[id]
|
|
|
|
if not package then
|
|
package = {
|
|
id = id,
|
|
enabled = true,
|
|
exists = false,
|
|
added = false,
|
|
configured = false,
|
|
loaded = false,
|
|
subtree_configured = false,
|
|
subtree_loaded = false,
|
|
on_setup = {},
|
|
on_config = {},
|
|
on_load = {},
|
|
dependencies = {}, -- inward edges
|
|
dependents = {}, -- outward edges
|
|
perf = {},
|
|
}
|
|
|
|
packages[id] = package
|
|
packages[#packages + 1] = package
|
|
end
|
|
|
|
local prev_dir = package.dir -- optimization
|
|
|
|
package.name = spec.as or package.name or get_name(id)
|
|
package.url = spec.url or package.url or ("https://github.com/" .. id .. ".git")
|
|
package.branch = spec.branch or package.branch
|
|
package.dir = base_dir .. package.name
|
|
package.pin = overrides.pin or spec.pin or package.pin
|
|
package.enabled = not overrides.disable and not spec.disable and package.enabled
|
|
|
|
if prev_dir ~= package.dir then
|
|
package.exists = vim.fn.isdirectory(package.dir) ~= 0
|
|
package.configured = package.exists
|
|
end
|
|
|
|
package.on_setup[#package.on_setup + 1] = spec.setup
|
|
package.on_config[#package.on_config + 1] = spec.config
|
|
package.on_load[#package.on_load + 1] = spec[2]
|
|
|
|
-- every package is implicitly dependent on us, the package manager
|
|
if root and package ~= root then
|
|
link_dependency(root, package)
|
|
end
|
|
|
|
if type(spec.requires) == "table" then
|
|
for i = 1, #spec.requires do
|
|
link_dependency(register(spec.requires[i]), package)
|
|
end
|
|
elseif spec.requires then
|
|
link_dependency(register(spec.requires), package)
|
|
end
|
|
|
|
if type(spec.deps) == "table" then
|
|
for i = 1, #spec.deps do
|
|
link_dependency(package, register(spec.deps[i]))
|
|
end
|
|
elseif spec.deps then
|
|
link_dependency(package, register(spec.deps))
|
|
end
|
|
|
|
return package
|
|
end
|
|
|
|
local function register_recursive(list, overrides)
|
|
overrides = overrides or {}
|
|
overrides = {
|
|
pin = overrides.pin or list.pin,
|
|
disable = overrides.disable or list.disable,
|
|
}
|
|
|
|
for i = 1, #list do
|
|
local ok, err = pcall(register, list[i], overrides)
|
|
if not ok then
|
|
error(string.format("%s (spec=%s)", err, vim.inspect(list[i])))
|
|
end
|
|
end
|
|
|
|
if list.modules then
|
|
for i = 1, #list.modules do
|
|
local name, module = "<unnamed module>", list.modules[i]
|
|
|
|
if type(module) == "string" then
|
|
if list.modules.prefix then
|
|
module = list.modules.prefix .. module
|
|
end
|
|
|
|
name, module = module, require(module)
|
|
end
|
|
|
|
name = module.name or name
|
|
|
|
local ok, err = pcall(register_recursive, module, overrides)
|
|
if not ok then
|
|
error(string.format("%s <- %s", err, name))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function sort_dependencies()
|
|
-- we don't do topological sort, packages are loaded by traversing the graph recursively
|
|
-- any sorting is fine as long as the order is consistent and predictable
|
|
local function compare(a, b)
|
|
local a_deps, b_deps = #a.dependencies, #b.dependencies
|
|
if a_deps == b_deps then
|
|
return a.id < b.id
|
|
else
|
|
return a_deps < b_deps
|
|
end
|
|
end
|
|
|
|
table.sort(packages, compare)
|
|
|
|
for i = 1, #packages do
|
|
table.sort(packages[i].dependencies, compare)
|
|
table.sort(packages[i].dependents, compare)
|
|
end
|
|
end
|
|
|
|
local function find_cycle()
|
|
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 i = 1, #packages do
|
|
local package = packages[i]
|
|
|
|
if not indexes[package.id] then
|
|
local cycle = connect(package)
|
|
if cycle then
|
|
return cycle
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ensure_acyclic()
|
|
local cycle = find_cycle()
|
|
|
|
if cycle then
|
|
local names = {}
|
|
for i = 1, #cycle do
|
|
names[i] = cycle[i].id
|
|
end
|
|
error("circular dependency detected in package dependency graph: " .. table.concat(names, " -> "))
|
|
end
|
|
end
|
|
|
|
local function run_hooks(package, type)
|
|
local hooks = package[type]
|
|
if #hooks == 0 then
|
|
return true
|
|
end
|
|
|
|
local start = os.clock()
|
|
|
|
for i = 1, #hooks do
|
|
local ok, err = pcall(hooks[i])
|
|
if not ok then
|
|
package.error = true
|
|
return false, err
|
|
end
|
|
end
|
|
|
|
package.perf[type] = os.clock() - start
|
|
|
|
logger:log(
|
|
"hook",
|
|
string.format("triggered %d %s %s for %s", #hooks, type, #hooks == 1 and "hook" or "hooks", package.id)
|
|
)
|
|
|
|
return true
|
|
end
|
|
|
|
local function ensure_added(package)
|
|
if not package.added then
|
|
local ok, err = run_hooks(package, "on_setup")
|
|
if not ok then
|
|
package.error = true
|
|
return false, err
|
|
end
|
|
|
|
local start = os.clock()
|
|
|
|
ok, err = pcall(vim.cmd, "packadd " .. package.name)
|
|
if not ok then
|
|
package.error = true
|
|
return false, err
|
|
end
|
|
|
|
package.added = true
|
|
package.perf.pack = os.clock() - start
|
|
|
|
logger:log("vim", string.format("packadd completed for %s", package.id))
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local function configure_recursive(package)
|
|
if not package.exists or not package.enabled or package.error then
|
|
return
|
|
end
|
|
|
|
if package.subtree_configured then
|
|
return true
|
|
end
|
|
|
|
for i = 1, #package.dependencies do
|
|
if not package.dependencies[i].configured then
|
|
return
|
|
end
|
|
end
|
|
|
|
if not package.configured then
|
|
local ok, err = ensure_added(package)
|
|
if not ok then
|
|
logger:log("error", string.format("failed to configure %s; reason: %s", package.id, err))
|
|
return
|
|
end
|
|
|
|
ok, err = run_hooks(package, "on_config")
|
|
if not ok then
|
|
logger:log("error", string.format("failed to configure %s; reason: %s", package.id, err))
|
|
return
|
|
end
|
|
|
|
package.configured = true
|
|
logger:log("config", string.format("configured %s", package.id))
|
|
end
|
|
|
|
package.subtree_configured = true
|
|
|
|
for i = 1, #package.dependents do
|
|
package.subtree_configured = configure_recursive(package.dependents[i]) and package.subtree_configured
|
|
end
|
|
|
|
return package.subtree_configured
|
|
end
|
|
|
|
local function load_recursive(package)
|
|
if not package.exists or not package.enabled or package.error then
|
|
return
|
|
end
|
|
|
|
if package.subtree_loaded then
|
|
return true
|
|
end
|
|
|
|
for i = 1, #package.dependencies do
|
|
if not package.dependencies[i].loaded then
|
|
return
|
|
end
|
|
end
|
|
|
|
if not package.loaded then
|
|
local ok, err = ensure_added(package)
|
|
if not ok then
|
|
logger:log("error", string.format("failed to configure %s; reason: %s", package.id, err))
|
|
return
|
|
end
|
|
|
|
ok, err = run_hooks(package, "on_load")
|
|
if not ok then
|
|
logger:log("error", string.format("failed to load %s; reason: %s", package.id, err))
|
|
return
|
|
end
|
|
|
|
package.loaded = true
|
|
logger:log("load", string.format("loaded %s", package.id))
|
|
end
|
|
|
|
package.subtree_loaded = true
|
|
|
|
for i = 1, #package.dependents do
|
|
package.subtree_loaded = load_recursive(package.dependents[i]) and package.subtree_loaded
|
|
end
|
|
|
|
return package.subtree_loaded
|
|
end
|
|
|
|
local function reload_meta()
|
|
local ok, err
|
|
bench("meta", function()
|
|
ok, err = pcall(
|
|
vim.cmd,
|
|
[[
|
|
silent! helptags ALL
|
|
silent! UpdateRemotePlugins
|
|
]]
|
|
)
|
|
end)
|
|
|
|
if ok then
|
|
logger:log("vim", "reloaded helptags and remote plugins")
|
|
else
|
|
logger:log("error", string.format("failed to reload helptags and remote plugins; reason: %s", err))
|
|
end
|
|
end
|
|
|
|
local function reload()
|
|
-- clear errors to retry
|
|
for i = 1, #packages do
|
|
packages[i].error = false
|
|
end
|
|
|
|
local reloaded
|
|
reloaded = configure_recursive(root) or reloaded
|
|
reloaded = load_recursive(root) or reloaded
|
|
|
|
if reloaded then
|
|
reload_meta()
|
|
end
|
|
|
|
return reloaded
|
|
end
|
|
|
|
local function reload_all()
|
|
for i = 1, #packages do
|
|
local package = packages[i]
|
|
package.loaded, package.subtree_loaded = false, false
|
|
end
|
|
|
|
reload()
|
|
end
|
|
|
|
local function clean()
|
|
vim.loop.fs_scandir(
|
|
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] = base_dir .. name
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
for i = 1, #packages do
|
|
queue[packages[i].name] = nil
|
|
end
|
|
|
|
for name, dir in pairs(queue) do
|
|
-- todo: make this async
|
|
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
|
|
end
|
|
end)
|
|
)
|
|
end
|
|
|
|
local function mark_reconfigure(package)
|
|
local function mark_dependencies(node)
|
|
node.subtree_configured, node.subtree_loaded = false, false
|
|
|
|
for i = 1, #node.dependencies do
|
|
mark_dependencies(node.dependencies[i])
|
|
end
|
|
end
|
|
|
|
local function mark_dependents(node)
|
|
node.configured, node.loaded, node.added = false, false, false
|
|
node.subtree_configured, node.subtree_loaded = false, false
|
|
|
|
for i = 1, #node.dependents do
|
|
mark_dependents(node.dependents[i])
|
|
end
|
|
end
|
|
|
|
mark_dependencies(package)
|
|
mark_dependents(package)
|
|
end
|
|
|
|
local function sync(package, cb)
|
|
if not package.enabled then
|
|
return
|
|
end
|
|
|
|
if package.exists then
|
|
if package.pin then
|
|
return
|
|
end
|
|
|
|
local function log_err(err)
|
|
logger:log("error", string.format("failed to update %s; reason: %s", package.id, err))
|
|
end
|
|
|
|
proc.git_rev_parse(package.dir, "HEAD", function(err, before)
|
|
if err then
|
|
log_err(before)
|
|
cb(err)
|
|
else
|
|
proc.git_fetch(package.dir, "origin", package.branch or "HEAD", function(err, message)
|
|
if err then
|
|
log_err(message)
|
|
cb(err)
|
|
else
|
|
proc.git_rev_parse(package.dir, "FETCH_HEAD", function(err, after)
|
|
if err then
|
|
log_err(after)
|
|
cb(err)
|
|
elseif before == after then
|
|
logger:log("skip", string.format("skipped %s", package.id))
|
|
cb(err)
|
|
else
|
|
proc.git_reset(package.dir, after, function(err, message)
|
|
if err then
|
|
log_err(message)
|
|
else
|
|
mark_reconfigure(package)
|
|
logger:log("update", string.format("updated %s; %s -> %s", package.id, before, after))
|
|
end
|
|
|
|
cb(err)
|
|
end)
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
else
|
|
proc.git_clone(package.dir, package.url, package.branch, function(err, message)
|
|
if err then
|
|
logger:log("error", string.format("failed to install %s; reason: %s", package.id, message))
|
|
else
|
|
package.exists = true
|
|
mark_reconfigure(package)
|
|
logger:log("install", string.format("installed %s", package.id))
|
|
end
|
|
|
|
cb(err)
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function sync_list(list)
|
|
local progress = 0
|
|
local has_errors = false
|
|
|
|
local function done(err)
|
|
progress = progress + 1
|
|
has_errors = has_errors or err
|
|
|
|
if progress == #list then
|
|
clean()
|
|
reload()
|
|
|
|
if has_errors then
|
|
logger:log("error", "there were errors during sync; see :messages or :DepLog for more information")
|
|
else
|
|
logger:log("update", string.format("synchronized %s %s", #list, #list == 1 and "package" or "packages"))
|
|
end
|
|
end
|
|
end
|
|
|
|
for i = 1, #list do
|
|
sync(list[i], done)
|
|
end
|
|
end
|
|
|
|
local function get_commits(cb)
|
|
local results = {}
|
|
local done = 0
|
|
for i = 1, #packages do
|
|
local package = packages[i]
|
|
|
|
if package.exists then
|
|
proc.git_rev_parse(package.dir, "HEAD", function(err, commit)
|
|
if not err then
|
|
results[package.id] = commit
|
|
end
|
|
|
|
done = done + 1
|
|
if done == #packages then
|
|
cb(results)
|
|
end
|
|
end)
|
|
else
|
|
done = done + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local function print_list(cb)
|
|
get_commits(function(commits)
|
|
local buffer = vim.api.nvim_create_buf(true, true)
|
|
local line, indent = 0, 0
|
|
|
|
local function print(chunks)
|
|
local concat = {}
|
|
local column = 0
|
|
|
|
for _ = 1, indent do
|
|
concat[#concat + 1] = " "
|
|
column = column + 2
|
|
end
|
|
|
|
if not chunks then
|
|
chunks = {}
|
|
elseif type(chunks) == "string" then
|
|
chunks = { { chunks } }
|
|
end
|
|
|
|
for i = 1, #chunks do
|
|
local chunk = chunks[i]
|
|
concat[#concat + 1] = chunk[1]
|
|
chunk.offset, column = column, column + #chunk[1]
|
|
end
|
|
|
|
vim.api.nvim_buf_set_lines(buffer, line, -1, false, { table.concat(concat) })
|
|
|
|
for i = 1, #chunks do
|
|
local chunk = chunks[i]
|
|
if chunk[2] then
|
|
vim.api.nvim_buf_add_highlight(buffer, -1, chunk[2], line, chunk.offset, chunk.offset + #chunk[1])
|
|
end
|
|
end
|
|
|
|
line = line + 1
|
|
end
|
|
|
|
print(string.format("Installed packages (%s):", #packages))
|
|
indent = 1
|
|
|
|
local loaded = {}
|
|
|
|
local function dry_load(package)
|
|
if loaded[package.id] then
|
|
return
|
|
end
|
|
|
|
for i = 1, #package.dependencies do
|
|
if not loaded[package.dependencies[i].id] then
|
|
return
|
|
end
|
|
end
|
|
|
|
loaded[package.id], loaded[#loaded + 1] = true, package
|
|
|
|
local chunk = {
|
|
{ string.format("[%s] ", commits[package.id] or " "), "Comment" },
|
|
{ package.id, "Underlined" },
|
|
}
|
|
|
|
if not package.exists then
|
|
chunk[#chunk + 1] = { " *not installed", "Comment" }
|
|
end
|
|
|
|
if not package.loaded then
|
|
chunk[#chunk + 1] = { " *not loaded", "Comment" }
|
|
end
|
|
|
|
if not package.enabled then
|
|
chunk[#chunk + 1] = { " *disabled", "Comment" }
|
|
end
|
|
|
|
if package.pin then
|
|
chunk[#chunk + 1] = { " *pinned", "Comment" }
|
|
end
|
|
|
|
print(chunk)
|
|
|
|
for i = 1, #package.dependents do
|
|
dry_load(package.dependents[i])
|
|
end
|
|
end
|
|
|
|
dry_load(root)
|
|
indent = 0
|
|
|
|
print()
|
|
print("Load time (μs):")
|
|
indent = 1
|
|
local profiles = {}
|
|
|
|
for i = 1, #packages do
|
|
local package = packages[i]
|
|
local profile = {
|
|
package = package,
|
|
total = 0,
|
|
setup = package.perf.on_setup or 0,
|
|
load = package.perf.on_load or 0,
|
|
pack = package.perf.pack or 0,
|
|
|
|
"total",
|
|
"setup",
|
|
"pack",
|
|
"load",
|
|
}
|
|
|
|
if package == root then
|
|
for k, v in pairs(perf) do
|
|
if profile[k] then
|
|
profile[k] = profile[k] + v
|
|
end
|
|
end
|
|
end
|
|
|
|
for j = 1, #profile do
|
|
profile.total = profile.total + profile[profile[j]]
|
|
end
|
|
|
|
profiles[#profiles + 1] = profile
|
|
end
|
|
|
|
table.sort(profiles, function(a, b)
|
|
return a.total > b.total
|
|
end)
|
|
|
|
for i = 1, #profiles do
|
|
local profile = profiles[i]
|
|
local chunk = {
|
|
{ "- ", "Comment" },
|
|
{ profile.package.id, "Underlined" },
|
|
{ string.rep(" ", 40 - #profile.package.id) },
|
|
}
|
|
|
|
for j = 1, #profile do
|
|
local key, value = profile[j], profile[profile[j]]
|
|
chunk[#chunk + 1] = { string.format(" %5s ", key), "Comment" }
|
|
chunk[#chunk + 1] = { string.format("%4d", value * 1000000) }
|
|
end
|
|
|
|
print(chunk)
|
|
end
|
|
|
|
indent = 0
|
|
print()
|
|
print("Dependency graph:")
|
|
|
|
local function walk_graph(package)
|
|
local chunk = {
|
|
{ "| ", "Comment" },
|
|
{ package.id, "Underlined" },
|
|
}
|
|
|
|
local function add_edges(p)
|
|
for i = 1, #p.dependencies do
|
|
local dependency = p.dependencies[i]
|
|
|
|
if dependency ~= root and not chunk[dependency.id] then -- don't convolute the list
|
|
chunk[#chunk + 1] = { " " .. dependency.id, "Comment" }
|
|
chunk[dependency.id] = true
|
|
add_edges(dependency)
|
|
end
|
|
end
|
|
end
|
|
|
|
add_edges(package)
|
|
print(chunk)
|
|
|
|
for i = 1, #package.dependents do
|
|
indent = indent + 1
|
|
walk_graph(package.dependents[i])
|
|
indent = indent - 1
|
|
end
|
|
end
|
|
|
|
walk_graph(root)
|
|
|
|
print()
|
|
print("Debug information:")
|
|
|
|
local debug = {}
|
|
for l in vim.inspect(packages):gmatch("[^\n]+") do
|
|
debug[#debug + 1] = l
|
|
end
|
|
|
|
vim.api.nvim_buf_set_lines(buffer, line, -1, false, debug)
|
|
vim.api.nvim_buf_set_name(buffer, "packages.dep")
|
|
vim.api.nvim_buf_set_option(buffer, "bufhidden", "wipe")
|
|
vim.api.nvim_buf_set_option(buffer, "modifiable", false)
|
|
|
|
vim.cmd("sp")
|
|
vim.api.nvim_win_set_buf(0, buffer)
|
|
|
|
if cb then
|
|
cb()
|
|
end
|
|
end)
|
|
end
|
|
|
|
vim.cmd([[
|
|
command! DepSync lua require("dep").sync()
|
|
command! DepReload lua require("dep").reload()
|
|
command! DepClean lua require("dep").clean()
|
|
command! DepList lua require("dep").list()
|
|
command! DepLog lua require("dep").open_log()
|
|
command! DepConfig lua require("dep").open_config()
|
|
]])
|
|
|
|
local function wrap_api(name, fn)
|
|
return function(...)
|
|
if initialized then
|
|
local ok, err = pcall(fn, ...)
|
|
if not ok then
|
|
logger:log("error", err)
|
|
end
|
|
else
|
|
logger:log("error", string.format("cannot call %s; dep is not initialized", name))
|
|
end
|
|
end
|
|
end
|
|
|
|
--todo: prevent multiple execution of async routines
|
|
return setmetatable({
|
|
sync = wrap_api("dep.sync", function()
|
|
sync_list(packages)
|
|
end),
|
|
|
|
reload = wrap_api("dep.reload", reload_all),
|
|
clean = wrap_api("dep.clean", clean),
|
|
list = wrap_api("dep.list", print_list),
|
|
|
|
open_log = wrap_api("dep.open_log", function()
|
|
vim.cmd("sp " .. logger.path)
|
|
end),
|
|
|
|
open_config = wrap_api("dep.open_config", function()
|
|
vim.cmd("sp " .. config_path)
|
|
end),
|
|
}, {
|
|
__call = function(_, config)
|
|
local err
|
|
perf = {}
|
|
config_path = debug.getinfo(2, "S").source:sub(2)
|
|
|
|
initialized, err = pcall(function()
|
|
base_dir = config.base_dir or (vim.fn.stdpath("data") .. "/site/pack/deps/opt/")
|
|
packages = {}
|
|
|
|
bench("load", function()
|
|
root = register("chiyadev/dep")
|
|
register_recursive(config)
|
|
sort_dependencies()
|
|
ensure_acyclic()
|
|
end)
|
|
|
|
reload()
|
|
|
|
local should_sync = function(package)
|
|
if config.sync == "new" or config.sync == nil then
|
|
return not package.exists
|
|
else
|
|
return config.sync == "always"
|
|
end
|
|
end
|
|
|
|
local targets = {}
|
|
|
|
for i = 1, #packages do
|
|
local package = packages[i]
|
|
if should_sync(package) then
|
|
targets[#targets + 1] = package
|
|
end
|
|
end
|
|
|
|
sync_list(targets)
|
|
end)
|
|
|
|
if not initialized then
|
|
logger:log("error", err)
|
|
end
|
|
end,
|
|
})
|