mirror of
				https://github.com/folke/lazy.nvim.git
				synced 2025-11-04 08:21:13 +00:00 
			
		
		
		
	fix(pkg): correctly pre-load package specs and remove them when needed during resolve
This commit is contained in:
		
					parent
					
						
							
								ee2ca39f67
							
						
					
				
			
			
				commit
				
					
						4326d4b487
					
				
			
		
					 6 changed files with 87 additions and 38 deletions
				
			
		| 
						 | 
				
			
			@ -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<string, boolean>
 | 
			
		||||
---@field spec LazySpecLoader
 | 
			
		||||
---@field fragments LazyFragments
 | 
			
		||||
---@field pkgs table<string, number>
 | 
			
		||||
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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<string, boolean>
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue