From 4326d4b487d4facc19b375ca30cd633cf56d88ed Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 23 Jun 2024 17:49:19 +0200 Subject: [PATCH] fix(pkg): correctly pre-load package specs and remove them when needed during resolve --- lua/lazy/core/meta.lua | 42 +++++++++++++++++++++++++++++++++++++++ lua/lazy/core/plugin.lua | 33 ++++++------------------------ lua/lazy/pkg/init.lua | 21 ++++++++++++++++++++ lua/lazy/pkg/rockspec.lua | 25 +++++++++++++---------- lua/lazy/types.lua | 1 + selene.toml | 3 +++ 6 files changed, 87 insertions(+), 38 deletions(-) diff --git a/lua/lazy/core/meta.lua b/lua/lazy/core/meta.lua index 0deeb89..533ec27 100644 --- a/lua/lazy/core/meta.lua +++ b/lua/lazy/core/meta.lua @@ -1,4 +1,5 @@ local Config = require("lazy.core.config") +local Pkg = require("lazy.pkg") local Util = require("lazy.core.util") --- This class is used to manage the plugins. @@ -10,6 +11,7 @@ local Util = require("lazy.core.util") ---@field dirty table ---@field spec LazySpecLoader ---@field fragments LazyFragments +---@field pkgs table local M = {} ---@param spec LazySpecLoader @@ -22,9 +24,30 @@ function M.new(spec) self.frag_to_meta = {} self.str_to_meta = {} self.dirty = {} + self.pkgs = {} return self end +-- import package specs +function M:load_pkgs() + if not Config.options.pkg.enabled then + return + end + local specs = Pkg.spec() + for dir, spec in pairs(specs) do + local meta, fragment = self:add(spec) + if meta and fragment then + -- tag all package fragments as optional + for _, fid in ipairs(meta._.frags) do + local frag = self.fragments:get(fid) + frag.spec.optional = true + end + -- keep track of the top-level package fragment + self.pkgs[dir] = fragment.id + end + end +end + --- Remove a plugin and all its fragments. ---@param name string function M:del(name) @@ -88,6 +111,7 @@ function M:add(plugin) self.plugins[meta.name] = meta self.frag_to_meta[fragment.id] = meta self.dirty[meta.name] = true + return meta, fragment end --- Rebuild all plugins based on dirty fragments, @@ -101,6 +125,7 @@ function M:rebuild() self.dirty[meta.name] = true else -- fragment was deleted, so remove it from plugin + self.frag_to_meta[fid] = nil ---@param f number meta._.frags = vim.tbl_filter(function(f) return f ~= fid @@ -260,11 +285,28 @@ function M:fix_disabled() return changes end +--- Removes package fragments for plugins that no longer use the same directory. +function M:fix_pkgs() + for dir, fid in pairs(self.pkgs) do + local plugin = self.frag_to_meta[fid] + plugin = plugin and self.plugins[plugin.name] + if plugin then + -- check if plugin is still in the same directory + if plugin.dir ~= dir then + self.fragments:del(fid) + end + end + end + self:rebuild() +end + --- Resolve all plugins, based on cond, enabled and optional. function M:resolve() Util.track("resolve plugins") self:rebuild() + self:fix_pkgs() + self:fix_cond() -- selene: allow(empty_loop) diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index 355d3d5..713e54c 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -1,6 +1,5 @@ local Config = require("lazy.core.config") local Meta = require("lazy.core.meta") -local Pkg = require("lazy.pkg") local Util = require("lazy.core.util") ---@class LazyCorePlugin @@ -16,7 +15,6 @@ M.loading = false ---@field notifs {msg:string, level:number, file?:string}[] ---@field importing? string ---@field optional? boolean ----@field pkgs table local Spec = {} M.Spec = Spec M.LOCAL_SPEC = ".lazy.lua" @@ -30,8 +28,8 @@ function Spec.new(spec, opts) self.modules = {} self.notifs = {} self.ignore_installed = {} - self.pkgs = {} self.optional = opts and opts.optional + self.meta:load_pkgs() if spec then self:parse(spec) end @@ -62,25 +60,6 @@ function Spec.get_name(pkg) return slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_") end ----@param plugin LazyPluginSpec -function Spec:add(plugin) - self.meta:add(plugin) - - ---@diagnostic disable-next-line: cast-type-mismatch - ---@cast plugin LazyPlugin - - -- import the plugin's spec - if Config.options.pkg.enabled and plugin.dir and not self.pkgs[plugin.dir] then - self.pkgs[plugin.dir] = true - local pkg = Pkg.get_spec(plugin) - if pkg then - self:normalize(pkg) - end - end - - return plugin -end - function Spec:error(msg) self:log(msg, vim.log.levels.ERROR) end @@ -110,7 +89,7 @@ end ---@param spec LazySpec|LazySpecImport function Spec:normalize(spec) if type(spec) == "string" then - self:add({ spec }) + self.meta:add({ spec }) elseif #spec > 1 or Util.is_list(spec) then ---@cast spec LazySpec[] for _, s in ipairs(spec) do @@ -118,11 +97,11 @@ function Spec:normalize(spec) end elseif spec[1] or spec.dir or spec.url then ---@cast spec LazyPluginSpec - local plugin = self:add(spec) + self.meta:add(spec) ---@diagnostic disable-next-line: cast-type-mismatch - ---@cast plugin LazySpecImport - if plugin and plugin.import then - self:import(plugin) + ---@cast spec LazySpecImport + if spec and spec.import then + self:import(spec) end elseif spec.import then ---@cast spec LazySpecImport diff --git a/lua/lazy/pkg/init.lua b/lua/lazy/pkg/init.lua index 9858ad7..bee9b42 100644 --- a/lua/lazy/pkg/init.lua +++ b/lua/lazy/pkg/init.lua @@ -7,6 +7,7 @@ local M = {} ---@class LazyPkg ---@field source string +---@field name string ---@field file string ---@field spec? LazySpec ---@field chunk? string|fun():LazySpec @@ -30,6 +31,7 @@ function M.update() for _, source in ipairs(sources) do local spec = source.get(plugin) if spec then + spec.name = plugin.name if type(spec.chunk) == "function" then spec.chunk = string.dump(spec.chunk) end @@ -81,6 +83,25 @@ function M.get(plugin) return ret end +function M.spec() + if not M.cache then + _load() + end + ---@type table + local ret = {} + + for dir in pairs(M.cache) do + local pkg = M.get({ dir = dir }) + local spec = pkg and pkg.spec + if pkg and spec then + spec = type(spec) == "table" and vim.deepcopy(spec) or spec + ret[dir] = { pkg.name, specs = spec } + end + end + + return ret +end + ---@param plugin LazyPlugin ---@return LazySpec? function M.get_spec(plugin) diff --git a/lua/lazy/pkg/rockspec.lua b/lua/lazy/pkg/rockspec.lua index 7a0c752..5732fbf 100644 --- a/lua/lazy/pkg/rockspec.lua +++ b/lua/lazy/pkg/rockspec.lua @@ -29,24 +29,27 @@ function M.get(plugin) end ---@type RockSpec? + ---@diagnostic disable-next-line: missing-fields local rockspec = {} - local ret, err = loadfile(rockspec_file, "t", rockspec) - if not ret then + local load, err = loadfile(rockspec_file, "t", rockspec) + if not load then error(err) end - ret() - return rockspec - and rockspec.package + load() + + ---@param dep string + local rocks = vim.tbl_filter(function(dep) + local name = dep:gsub("%s.*", "") + return not vim.tbl_contains(M.skip, name) + end, rockspec and rockspec.dependencies or {}) + + return #rocks > 0 and { source = "rockspec", file = rockspec_file, spec = { - dir = plugin.dir, - url = plugin.url, - rocks = vim.tbl_filter(function(dep) - local name = dep:gsub("%s.*", "") - return not vim.tbl_contains(M.skip, name) - end, rockspec.dependencies), + plugin.name, + rocks = rocks, }, } or nil diff --git a/lua/lazy/types.lua b/lua/lazy/types.lua index dabfa58..cbff124 100644 --- a/lua/lazy/types.lua +++ b/lua/lazy/types.lua @@ -86,6 +86,7 @@ ---@class LazyFragment ---@field id number +---@field pkg? boolean ---@field pid? number ---@field deps? number[] ---@field frags? number[] diff --git a/selene.toml b/selene.toml index 7312a91..5867a2a 100644 --- a/selene.toml +++ b/selene.toml @@ -1 +1,4 @@ std="vim" + +[lints] +mixed_table="allow"