From 73ea05fedad97be8871fa38523244ce9a1ad58d7 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Mon, 24 Jun 2024 14:14:41 +0200 Subject: [PATCH] feat: spec.rocks is no longer needed & added support for installing any luarock --- lua/lazy/core/config.lua | 14 ------ lua/lazy/core/loader.lua | 16 +++++- lua/lazy/core/meta.lua | 32 +++++++----- lua/lazy/core/plugin.lua | 27 ++++++++-- lua/lazy/manage/init.lua | 6 +-- lua/lazy/manage/rocks.lua | 90 ---------------------------------- lua/lazy/manage/task/rocks.lua | 57 --------------------- lua/lazy/pkg/init.lua | 89 +++++++++++++++++---------------- lua/lazy/pkg/rockspec.lua | 18 +++++-- lua/lazy/types.lua | 6 +-- 10 files changed, 120 insertions(+), 235 deletions(-) delete mode 100644 lua/lazy/manage/rocks.lua delete mode 100644 lua/lazy/manage/task/rocks.lua diff --git a/lua/lazy/core/config.lua b/lua/lazy/core/config.lua index 1fb28bb..624ce35 100644 --- a/lua/lazy/core/config.lua +++ b/lua/lazy/core/config.lua @@ -226,9 +226,6 @@ M.mapleader = nil ---@type string M.maplocalleader = nil ----@type {specs:string, tree:string, path:string, cpath:string} -M.rocks = {} - function M.headless() return #vim.api.nvim_list_uis() == 0 end @@ -279,17 +276,6 @@ function M.setup(opts) M.mapleader = vim.g.mapleader M.maplocalleader = vim.g.maplocalleader - M.rocks = { - specs = M.options.rocks.root .. "/specs", - tree = M.options.rocks.root .. "/tree", - path = M.options.rocks.root .. "/tree/share/lua/5.1", - cpath = M.options.rocks.root .. "/tree/lib/lua/5.1", - } - vim.fn.mkdir(M.rocks.specs, "p") - vim.fn.mkdir(M.rocks.tree, "p") - package.path = package.path .. ";" .. M.rocks.path .. "/?.lua;" .. M.rocks.path .. "/?/init.lua;" - package.cpath = package.cpath .. ";" .. M.rocks.cpath .. "/?." .. (jit.os:find("Windows") and "dll" or "so") .. ";" - if M.headless() then require("lazy.view.commands").setup() end diff --git a/lua/lazy/core/loader.lua b/lua/lazy/core/loader.lua index a0233ad..6f426d9 100644 --- a/lua/lazy/core/loader.lua +++ b/lua/lazy/core/loader.lua @@ -69,9 +69,8 @@ function M.install_missing() for _, plugin in pairs(Config.plugins) do local installed = plugin._.installed local has_errors = Plugin.has_errors(plugin) - local rocks_installed = plugin._.rocks_installed ~= false - if not has_errors and not (installed and rocks_installed) then + if not has_errors and not (installed and not plugin._.build) then for _, colorscheme in ipairs(Config.options.install.colorscheme) do if colorscheme == "default" then break @@ -344,6 +343,10 @@ function M._load(plugin, reason, opts) M.add_to_rtp(plugin) + if plugin._.pkg and plugin._.pkg.source == "rockspec" then + M.add_to_luapath(plugin) + end + if plugin.dependencies then Util.try(function() M.load(plugin.dependencies, {}) @@ -487,6 +490,15 @@ function M.add_to_rtp(plugin) vim.opt.rtp = rtp end +---@param plugin LazyPlugin +function M.add_to_luapath(plugin) + local root = Config.options.rocks.root .. "/" .. plugin.name + local path = root .. "/share/lua/5.1" + local cpath = root .. "/lib/lua/5.1" + package.path = package.path .. ";" .. path .. "/?.lua;" .. path .. "/?/init.lua;" + package.cpath = package.cpath .. ";" .. cpath .. "/?." .. (jit.os:find("Windows") and "dll" or "so") .. ";" +end + function M.source(path) Util.track({ runtime = path }) Util.try(function() diff --git a/lua/lazy/core/meta.lua b/lua/lazy/core/meta.lua index 533ec27..43bd642 100644 --- a/lua/lazy/core/meta.lua +++ b/lua/lazy/core/meta.lua @@ -33,10 +33,11 @@ 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) + local specs = Pkg.get() + for dir, pkg in pairs(specs) do + local meta, fragment = self:add(pkg.spec) if meta and fragment then + meta._.pkg = pkg -- tag all package fragments as optional for _, fid in ipairs(meta._.frags) do local frag = self.fragments:get(fid) @@ -165,18 +166,23 @@ function M:_rebuild(name) assert(#plugin._.frags > 0, "no fragments found for plugin " .. name) + ---@type table + local done = {} for _, fid in ipairs(plugin._.frags) do - local fragment = self.fragments:get(fid) - assert(fragment, "fragment " .. fid .. " not found, for plugin " .. name) - ---@diagnostic disable-next-line: no-unknown - super = setmetatable(fragment.spec, super and { __index = super } or nil) - plugin._.dep = plugin._.dep and fragment.dep - plugin.optional = plugin.optional and (rawget(fragment.spec, "optional") == true) - plugin.url = fragment.url or plugin.url + if not done[fid] then + done[fid] = true + local fragment = self.fragments:get(fid) + assert(fragment, "fragment " .. fid .. " not found, for plugin " .. name) + ---@diagnostic disable-next-line: no-unknown + super = setmetatable(fragment.spec, super and { __index = super } or nil) + plugin._.dep = plugin._.dep and fragment.dep + plugin.optional = plugin.optional and (rawget(fragment.spec, "optional") == true) + plugin.url = fragment.url or plugin.url - -- dependencies - for _, dep in ipairs(fragment.deps or {}) do - table.insert(plugin.dependencies, self.fragments:get(dep).name) + -- dependencies + for _, dep in ipairs(fragment.deps or {}) do + table.insert(plugin.dependencies, self.fragments:get(dep).name) + end end end diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index 878ed3f..875b580 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -236,7 +236,7 @@ function M.update_state() installed[name] = nil end - require("lazy.manage.rocks").update_state() + M.update_rocks_state() Config.to_clean = {} for pack, dir_type in pairs(installed) do @@ -253,6 +253,23 @@ function M.update_state() end end +function M.update_rocks_state() + local root = Config.options.rocks.root + ---@type table + local installed = {} + Util.ls(root, function(_, name, type) + if type == "directory" then + installed[name] = name + end + end) + + for _, plugin in pairs(Config.plugins) do + if plugin._.pkg and plugin._.pkg.source == "rockspec" then + plugin._.build = not installed[plugin.name] + end + end +end + ---@param path string function M.local_spec(path) local file = vim.secure.read(path) @@ -321,11 +338,11 @@ function M.load() -- copy state. This wont do anything during startup for name, plugin in pairs(existing) do if Config.plugins[name] then - local dep = Config.plugins[name]._.dep - local frags = Config.plugins[name]._.frags + local new_state = Config.plugins[name]._ Config.plugins[name]._ = plugin._ - Config.plugins[name]._.dep = dep - Config.plugins[name]._.frags = frags + Config.plugins[name]._.dep = new_state.dep + Config.plugins[name]._.frags = new_state.frags + -- Config.plugins[name]._.tasks = new_state.tasks end end Util.track() diff --git a/lua/lazy/manage/init.lua b/lua/lazy/manage/init.lua index 3e145c8..01c9a54 100644 --- a/lua/lazy/manage/init.lua +++ b/lua/lazy/manage/init.lua @@ -82,13 +82,12 @@ function M.install(opts) pipeline = { "git.clone", { "git.checkout", lockfile = opts.lockfile }, - "rocks.install", "plugin.docs", "wait", "plugin.build", }, plugins = function(plugin) - return plugin.url and not (plugin._.installed and plugin._.rocks_installed ~= false) + return plugin.url and not (plugin._.installed and not plugin._.build) end, }, opts):wait(function() require("lazy.manage.lock").update() @@ -107,7 +106,6 @@ function M.update(opts) "git.fetch", "git.status", { "git.checkout", lockfile = opts.lockfile }, - "rocks.install", "plugin.docs", "wait", "plugin.build", @@ -224,7 +222,7 @@ function M.clear(plugins) if plugin._.tasks then ---@param task LazyTask plugin._.tasks = vim.tbl_filter(function(task) - return task:is_running() + return task:is_running() or task.error end, plugin._.tasks) end end diff --git a/lua/lazy/manage/rocks.lua b/lua/lazy/manage/rocks.lua deleted file mode 100644 index 3e1bc6e..0000000 --- a/lua/lazy/manage/rocks.lua +++ /dev/null @@ -1,90 +0,0 @@ ---# selene:allow(incorrect_standard_library_use) - -local Config = require("lazy.core.config") -local Util = require("lazy.core.util") - ----@class LazyRock ----@field plugin string ----@field name string ----@field spec string ----@field installed boolean - -local M = {} ----@type LazyRock[] -M.rocks = {} - ----@param ... string ----@return string[] -function M.args(...) - local ret = { - "--tree", - Config.rocks.tree, - "--server", - Config.options.rocks.server, - "--dev", - "--lua-version", - "5.1", - } - vim.list_extend(ret, { ... }) - return ret -end - ----@param plugin LazyPlugin -function M.get_rockspec(plugin) - local rocks = vim.tbl_map(function(rock) - return rock.name - end, plugin._.rocks) - assert(rocks and #rocks > 0, plugin.name .. " has no rocks") - local rockspec_file = Config.rocks.specs .. "/lazy-" .. plugin.name .. "-scm-1.rockspec" - require("lazy.util").write_file( - rockspec_file, - ([[ -rockspec_format = "3.0" -package = "lazy-%s" -version = "scm-1" -source = { url = "%s" } -dependencies = %s -build = { type = "builtin" } -]]):format(plugin.name, plugin.url, vim.inspect(plugin.rocks)) - ) - return rockspec_file -end - -function M.update_state() - local root = Config.rocks.tree .. "/lib/luarocks/rocks-5.1" - ---@type table - local installed = {} - Util.ls(root, function(_, name, type) - if type == "directory" then - installed[name] = name - end - end) - - ---@type LazyRock[] - local rocks = {} - M.rocks = rocks - - for _, plugin in pairs(Config.plugins) do - if plugin.rocks then - plugin._.rocks = {} - plugin._.rocks_installed = true - for _, spec in ipairs(plugin.rocks) do - spec = vim.trim(spec) - local name = spec:gsub("%s.*", "") - local rock = { - plugin = plugin.name, - name = name, - spec = spec, - installed = installed[name] ~= nil, - } - if rock.name ~= "lua" then - plugin._.rocks_installed = plugin._.rocks_installed and rock.installed - table.insert(plugin._.rocks, rock) - table.insert(rocks, rock) - end - end - end - end -end - -return M diff --git a/lua/lazy/manage/task/rocks.lua b/lua/lazy/manage/task/rocks.lua deleted file mode 100644 index b2f61bf..0000000 --- a/lua/lazy/manage/task/rocks.lua +++ /dev/null @@ -1,57 +0,0 @@ -local Rocks = require("lazy.manage.rocks") - ----@type table -local M = {} - -local running = false -local has_rocks = nil ---@type boolean? - -M.install = { - skip = function(plugin) - return plugin._.rocks_installed ~= false - end, - run = function(self) - if has_rocks == nil then - has_rocks = vim.fn.executable("luarocks") == 1 - end - if not has_rocks then - self.error = "This plugin has luarocks dependencies,\nbut the `luarocks` executable is not found.\nPlease install https://luarocks.org/ to continue.\n" - .. "luarock deps: " - .. vim.inspect(self.plugin.rocks) - return - end - - local started = false - - local function install() - started = true - self.status = "luarocks (install)" - vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false }) - self:spawn("luarocks", { - args = Rocks.args("install", "--deps-mode", "one", "--deps-only", Rocks.get_rockspec(self.plugin)), - on_exit = function(ok) - running = false - if ok then - self.plugin._.rocks_installed = true - end - end, - }) - end - - local timer = vim.uv.new_timer() - timer:start(0, 100, function() - if not running then - running = true - timer:stop() - vim.schedule(install) - end - end) - self.status = "luarocks (pending)" - - table.insert(self._running, function() - return not started - end) - end, -} - -return M diff --git a/lua/lazy/pkg/init.lua b/lua/lazy/pkg/init.lua index c43a53f..48e755c 100644 --- a/lua/lazy/pkg/init.lua +++ b/lua/lazy/pkg/init.lua @@ -2,23 +2,28 @@ local Config = require("lazy.core.config") local Util = require("lazy.util") local M = {} -M.VERSION = 7 +M.VERSION = 8 M.dirty = false ----@alias LazyPkgSpec LazySpec | fun():LazySpec - ---@class LazyPkg ----@field source string ---@field name string +---@field dir string +---@field source "lazy" | "packspec" | "rockspec" +---@field file string +---@field spec LazyPluginSpec + +---@class LazyPkgSpec ---@field file string ---@field spec? LazySpec - ----@class LazyPkgInput: LazyPkg ----@field spec? LazySpec|fun():LazySpec ---@field code? string ---@class LazyPkgSource ----@field get fun(plugin:LazyPlugin):LazyPkgInput? +---@field name string +---@field get fun(plugin:LazyPlugin):LazyPkgSpec? + +---@class LazyPkgCache +---@field pkgs LazyPkg[] +---@field version number ---@type table? M.cache = nil @@ -27,27 +32,40 @@ function M.update() ---@type LazyPkgSource[] local sources = {} for _, s in ipairs(Config.options.pkg.sources) do - sources[#sources + 1] = require("lazy.pkg." .. s) + sources[#sources + 1] = { + name = s, + get = require("lazy.pkg." .. s).get, + } end - M.cache = {} + ---@type LazyPkgCache + local ret = { + version = M.VERSION, + pkgs = {}, + } for _, plugin in pairs(Config.plugins) do if plugin._.installed then for _, source in ipairs(sources) do local spec = source.get(plugin) if spec then - spec.name = plugin.name + ---@type LazyPkg + local pkg = { + name = plugin.name, + dir = plugin.dir, + source = source.name, + file = spec.file, + spec = spec.spec or {}, + } if type(spec.code) == "string" then - spec.spec = { _raw = spec.code } - spec.code = nil + pkg.spec = { _raw = spec.code } end - M.cache[plugin.dir] = spec + table.insert(ret.pkgs, pkg) break end end end end - local code = "return " .. Util.dump({ version = M.VERSION, specs = M.cache }) + local code = "return " .. Util.dump(ret) vim.fn.mkdir(vim.fn.fnamemodify(Config.options.pkg.cache, ":h"), "p") Util.write_file(Config.options.pkg.cache, code) M.dirty = false @@ -63,9 +81,18 @@ local function _load() if not chunk then error(err) end + ---@type LazyPkgCache? local ret = chunk() if ret and ret.version == M.VERSION then - M.cache = ret.specs + M.cache = {} + for _, pkg in ipairs(ret.pkgs) do + if type(pkg.spec) == "function" then + pkg.spec = pkg.spec() + end + -- wrap in the scope of the plugin + pkg.spec = { pkg.name, specs = pkg.spec } + M.cache[pkg.dir] = pkg + end end end, "Error loading pkg:") end @@ -80,34 +107,12 @@ end ---@param dir string ---@return LazyPkg? +---@overload fun():table function M.get(dir) - local ret = M.cache[dir] - if not ret then - return + if dir then + return M.cache[dir] end - - if type(ret.spec) == "function" then - ret.spec = ret.spec() - end - - return ret -end - -function M.spec() - ---@type table - local ret = {} - - for dir in pairs(M.cache) do - local pkg = M.get(dir) - local spec = pkg and pkg.spec - if pkg and spec then - spec = type(spec) == "table" and vim.deepcopy(spec) or spec - ---@cast spec LazySpec - ret[dir] = { pkg.name, specs = spec } - end - end - - return ret + return M.cache end return setmetatable(M, { diff --git a/lua/lazy/pkg/rockspec.lua b/lua/lazy/pkg/rockspec.lua index c0e5ec3..ba4a692 100644 --- a/lua/lazy/pkg/rockspec.lua +++ b/lua/lazy/pkg/rockspec.lua @@ -4,7 +4,7 @@ local Util = require("lazy.core.util") local M = {} -M.dev_suffix = "-scm-1.rockspec" +M.dev_suffix = "-1.rockspec" M.skip = { "lua" } ---@class RockSpec @@ -14,7 +14,7 @@ M.skip = { "lua" } ---@field dependencies string[] ---@param plugin LazyPlugin ----@return LazyPkg? +---@return LazyPkgSpec? function M.get(plugin) local rockspec_file ---@type string? Util.ls(plugin.dir, function(path, name, t) @@ -43,13 +43,21 @@ function M.get(plugin) return not vim.tbl_contains(M.skip, name) end, rockspec and rockspec.dependencies or {}) - return #rocks > 0 + local use = #rocks > 0 + use = true + + local lazy = nil + if not vim.uv.fs_stat(plugin.dir .. "/lua") then + lazy = false + end + + return use and { - source = "rockspec", file = vim.fn.fnamemodify(rockspec_file, ":t"), spec = { plugin.name, - rocks = rocks, + build = "rockspec", + lazy = lazy, }, } or nil diff --git a/lua/lazy/types.lua b/lua/lazy/types.lua index cbff124..4fd033c 100644 --- a/lua/lazy/types.lua +++ b/lua/lazy/types.lua @@ -8,6 +8,7 @@ ---@field dep? boolean True if this plugin is only in the spec as a dependency ---@field dir? string Explicit dir or dev set for this plugin ---@field dirty? boolean +---@field build? boolean ---@field frags? number[] ---@field handlers? LazyPluginHandlers ---@field installed? boolean @@ -15,13 +16,12 @@ ---@field kind? LazyPluginKind ---@field loaded? {[string]:string}|{time:number} ---@field outdated? boolean ----@field rocks? LazyRock[] ----@field rocks_installed? boolean ---@field rtp_loaded? boolean ---@field tasks? LazyTask[] ---@field updated? {from:string, to:string} ---@field updates? {from:GitInfo, to:GitInfo} ---@field working? boolean +---@field pkg? LazyPkg ---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table? @@ -29,7 +29,7 @@ ---@field init? fun(self:LazyPlugin) Will always be run ---@field deactivate? fun(self:LazyPlugin) Unload/Stop a plugin ---@field config? fun(self:LazyPlugin, opts:table)|true Will be executed when loading the plugin ----@field build? string|fun(self:LazyPlugin)|(string|fun(self:LazyPlugin))[] +---@field build? string|async fun(self:LazyPlugin)|(string|async fun(self:LazyPlugin))[] ---@field opts? PluginOpts ---@class LazyPluginHandlers