feat: added support for plugin packages by lazy, rockspec and packspec

This commit is contained in:
Folke Lemaitre 2024-06-18 21:54:54 +02:00
parent f1ba2e3d05
commit 3be55a4615
11 changed files with 281 additions and 171 deletions

92
lua/lazy/pkg/init.lua Normal file
View file

@ -0,0 +1,92 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local M = {}
---@alias LazyPkgSpec LazySpec | fun():LazySpec
---@class LazyPkg
---@field source string
---@field file string
---@field spec? LazySpec
---@field chunk? string|fun():LazySpec
---@class LazyPkgSource
---@field get fun(plugin:LazyPlugin):LazyPkg
---@type table<string, LazyPkg>?
M.cache = nil
function M.update()
---@type LazyPkgSource[]
local sources = {}
for _, s in ipairs(Config.options.pkg.sources) do
sources[#sources + 1] = require("lazy.pkg." .. s)
end
---@type table<string, LazyPkg>
local ret = {}
for _, plugin in pairs(Config.plugins) do
for _, source in ipairs(sources) do
local spec = source.get(plugin)
if spec then
if type(spec.chunk) == "function" then
spec.chunk = string.dump(spec.chunk)
end
ret[plugin.dir] = spec
break
end
end
end
local code = "return " .. Util.dump(ret)
Util.write_file(Config.options.pkg.cache, code)
M.cache = nil
end
local function _load()
Util.track("pkg")
M.cache = {}
if vim.uv.fs_stat(Config.options.pkg.cache) then
Util.try(function()
local chunk, err = loadfile(Config.options.pkg.cache)
if not chunk then
error(err)
end
M.cache = chunk()
end, "Error loading pkg:")
end
Util.track()
end
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
if not M.cache then
_load()
end
local ret = M.cache[plugin.dir]
if not ret then
return
end
if ret.chunk and not ret.spec then
if type(ret.chunk) == "string" then
ret.chunk = load(ret.chunk, "@" .. plugin.dir)
end
ret.spec = ret.chunk()
ret.chunk = nil
end
return ret
end
---@param plugin LazyPlugin
---@return LazySpec?
function M.get_spec(plugin)
local pkg = M.get(plugin)
local spec = pkg and pkg.spec
return spec and type(spec) == "table" and vim.deepcopy(spec) or spec
end
return M

28
lua/lazy/pkg/lazy.lua Normal file
View file

@ -0,0 +1,28 @@
local Util = require("lazy.util")
local M = {}
M.lazy_file = "lazy.lua"
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
local file = Util.norm(plugin.dir .. "/" .. M.lazy_file)
if Util.file_exists(file) then
---@type fun(): LazySpec
local chunk = Util.try(function()
local ret, err = loadfile(file)
return err and error(err) or ret
end, "`" .. M.lazy_file .. "` for **" .. plugin.name .. "** has errors:")
if not chunk then
Util.error("Invalid `" .. M.lazy_file .. "` for **" .. plugin.name .. "**")
end
return {
source = "lazy",
file = M.lazy_file,
chunk = chunk,
}
end
end
return M

54
lua/lazy/pkg/packspec.lua Normal file
View file

@ -0,0 +1,54 @@
local Util = require("lazy.util")
---@class PackSpec
---@field dependencies? table<string, string>
---@field lazy? LazyPluginSpec
---
local M = {}
M.pkg_file = "pkg.json"
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
local file = Util.norm(plugin.dir .. "/" .. M.pkg_file)
if not Util.file_exists(file) then
return
end
---@type PackSpec
local pkg = Util.try(function()
return vim.json.decode(Util.read_file(file))
end, "`" .. M.pkg_file .. "` for **" .. plugin.name .. "** has errors:")
if not pkg then
return
end
---@type LazySpec
local ret = {}
if pkg.dependencies then
for url, version in pairs(pkg.dependencies) do
-- HACK: Add `.git` to github urls
if url:find("github") and not url:match("%.git$") then
url = url .. ".git"
end
ret[#ret + 1] = { url = url, version = version }
end
end
local p = pkg.lazy
if p then
p.url = p.url or plugin.url
p.dir = p.dir or plugin.dir
ret[#ret + 1] = p
end
if pkg.lazy then
ret[#ret + 1] = pkg.lazy
end
return {
source = "lazy",
file = M.pkg_file,
spec = ret,
}
end
return M

55
lua/lazy/pkg/rockspec.lua Normal file
View file

@ -0,0 +1,55 @@
--# selene:allow(incorrect_standard_library_use)
local Util = require("lazy.core.util")
local M = {}
M.dev_suffix = "-scm-1.rockspec"
M.skip = { "lua" }
---@class RockSpec
---@field rockspec_format string
---@field package string
---@field version string
---@field dependencies string[]
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
local rockspec_file ---@type string?
Util.ls(plugin.dir, function(path, name, t)
if t == "file" and name:sub(-#M.dev_suffix) == M.dev_suffix then
rockspec_file = path
return false
end
end)
if not rockspec_file then
return
end
---@type RockSpec?
local rockspec = {}
local ret, err = loadfile(rockspec_file, "t", rockspec)
if not ret then
error(err)
end
ret()
return rockspec
and rockspec.package
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),
},
}
or nil
end
return M