fix(cache): do a fast check to see if a cached modpath is still valid. find it again otherwise

This commit is contained in:
Folke Lemaitre 2022-12-19 12:21:20 +01:00
parent 1fe43f3e29
commit 32f2b71ff8
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
2 changed files with 63 additions and 24 deletions

View File

@ -4,6 +4,7 @@ local uv = vim.loop
local M = {} local M = {}
M.dirty = false M.dirty = false
M.VERSION = "1"
---@class LazyCacheConfig ---@class LazyCacheConfig
M.config = { M.config = {
@ -28,15 +29,36 @@ M.cache = {}
M.loader_idx = 2 -- 2 so preload still works M.loader_idx = 2 -- 2 so preload still works
M.enabled = true M.enabled = true
M.ttl = 3600 * 24 * 5 -- keep unused modules for up to 5 days M.ttl = 3600 * 24 * 5 -- keep unused modules for up to 5 days
---@type string[]
M.rtp = nil
-- Check if we need to load this plugin -- checks wether the cached modpath is still valid
---@param modname string function M.check_path(modname, modpath)
---@param modpath string -- check rtp exlcuding plugins. This is a very small list, so should be fast
function M.check_load(modname, modpath) for _, path in ipairs(M.get_rtp()) do
if modname:sub(1, 4) == "lazy" then if modpath:find(path, 1, true) == 1 then
return return true
end end
require("lazy.core.loader").check_load(modname, modpath) end
-- the correct lazy path should be part of rtp.
-- so if we get here, this is folke using the local dev instance ;)
if modname:sub(1, 4) == "lazy" then
return false
end
-- check plugins. Again fast, since we check the plugin name from the path.
-- only needed when the plugin mod has been loaded
if package.loaded["lazy.core.plugin"] then
local plugin = require("lazy.core.plugin").find(modpath)
if plugin and modpath:find(plugin.dir, 1, true) == 1 then
if not plugin._.loaded then
require("lazy.core.loader").load(plugin, { require = modname })
end
return true
end
end
return false
end end
function M.disable() function M.disable()
@ -56,8 +78,7 @@ function M.loader(modname)
local entry = M.cache[modname] local entry = M.cache[modname]
local chunk, err local chunk, err
if entry then if entry and M.check_path(modname, entry.modpath) then
M.check_load(modname, entry.modpath)
entry.used = os.time() entry.used = os.time()
local hash = M.hash(entry.modpath) local hash = M.hash(entry.modpath)
if not hash then if not hash then
@ -126,6 +147,28 @@ function M.find(modname)
end end
end end
function M.get_rtp()
if not M.rtp then
M.rtp = {}
local skip = {}
-- only skip plugins once Config has been setup
if package.loaded["lazy.core.config"] then
local Config = require("lazy.core.config")
for _, plugin in ipairs(Config.plugins) do
if plugin.name ~= "lazy.nvim" then
skip[plugin.dir] = true
end
end
end
for _, path in ipairs(vim.api.nvim_list_runtime_paths()) do
if not skip[path] then
M.rtp[#M.rtp + 1] = path
end
end
end
return M.rtp
end
---@param opts? LazyConfig ---@param opts? LazyConfig
function M.setup(opts) function M.setup(opts)
-- no fancy deep extend here. just set the options -- no fancy deep extend here. just set the options
@ -139,6 +182,14 @@ function M.setup(opts)
M.load_cache() M.load_cache()
table.insert(package.loaders, M.loader_idx, M.loader) table.insert(package.loaders, M.loader_idx, M.loader)
-- reset rtp when it changes
vim.api.nvim_create_autocmd("OptionSet", {
pattern = "runtimepath",
callback = function()
M.rtp = nil
end,
})
if #M.config.disable_events > 0 then if #M.config.disable_events > 0 then
vim.api.nvim_create_autocmd(M.config.disable_events, { once = true, callback = M.disable }) vim.api.nvim_create_autocmd(M.config.disable_events, { once = true, callback = M.disable })
end end
@ -159,7 +210,7 @@ end
function M.save_cache() function M.save_cache()
local f = assert(uv.fs_open(M.config.path, "w", 438)) local f = assert(uv.fs_open(M.config.path, "w", 438))
uv.fs_write(f, vim.env.VIMRUNTIME) uv.fs_write(f, M.VERSION)
uv.fs_write(f, "\0") uv.fs_write(f, "\0")
for modname, entry in pairs(M.cache) do for modname, entry in pairs(M.cache) do
if entry.used > os.time() - M.ttl then if entry.used > os.time() - M.ttl then
@ -195,7 +246,7 @@ function M.load_cache()
return return
end end
if vim.env.VIMRUNTIME ~= data:sub(1, zero - 1) then if M.VERSION ~= data:sub(1, zero - 1) then
return return
end end

View File

@ -1,6 +1,7 @@
local Util = require("lazy.core.util") local Util = require("lazy.core.util")
local Config = require("lazy.core.config") local Config = require("lazy.core.config")
local Handler = require("lazy.core.handler") local Handler = require("lazy.core.handler")
local Cache = require("lazy.core.cache")
local M = {} local M = {}
@ -214,17 +215,4 @@ function M.autoload(modname)
return modname .. " not found in lazy plugins" return modname .. " not found in lazy plugins"
end end
-- lazy.cache will call this when loading a cached file with modpath set.
---@param modname string
---@param modpath string
function M.check_load(modname, modpath)
-- no need to check anything before init
if M.init_done then
local plugin = require("lazy.core.plugin").find(modpath)
if plugin and not plugin._.loaded then
M.load(plugin, { require = modname })
end
end
end
return M return M