feat: added lockfile support

This commit is contained in:
Folke Lemaitre 2022-11-29 00:15:13 +01:00
parent bbad0cb891
commit 4384d0e6d9
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
7 changed files with 127 additions and 44 deletions

View File

@ -2,51 +2,37 @@
## ✨ Features ## ✨ Features
- Partial clones instead of shallow clones - [x] Partial clones instead of shallow clones
- Async - [x] waits till missing deps are installed (bootstrap Neovim and start using it right away)
- No need for compile - [x] Async
- Fast - [x] No need for compile
- Correct sequencing of dependencies (deps should always be opt. Maybe make everything opt?) - [x] Fast
- [x] Correct sequencing of dependencies (deps should always be opt. Maybe make everything opt?)
- [ ] Import specs from Packer - [ ] Import specs from Packer
- Config in multiple files - [x] Config in multiple files
- Patterns for local packages - [x] Patterns for local packages
- [x] Profiling
- [ ] lockfile - [ ] lockfile
- [ ] check for updates
- [ ] package.lua - [ ] package.lua
- [ ] package-lock.lua - [ ] package-lock.lua
- [ ] tag/version support `git tag --sort version:refname` - [x] tag/version support `git tag --sort version:refname`
- [ ] auto-loading on completion for lazy-loaded commands - [x] auto-loading on completion for lazy-loaded commands
- [ ] semver https://devhints.io/semver - [x] semver https://devhints.io/semver
https://semver.npmjs.com/ https://semver.npmjs.com/
## ✅ TODO ## ✅ TODO
- [ ] show time taken for op in view - [ ] view keybindings for update/clean/...
- [ ] add profiler to view
- [ ] add buttons for actions
- [x] show time taken for op in view
- [ ] package meta index (package.lua cache for all packages) - [ ] package meta index (package.lua cache for all packages)
- [ ] migrate from Packer - [ ] migrate from Packer
- [ ] auto lazy-loading of lua modules - [ ] auto lazy-loading of lua modules
- [ ] use uv file watcher to check for config changes - [ ] use uv file watcher to check for config changes
- [x] clear errors - [x] clear errors
- [ ] add support for versions `git tag --sort v:refname` - [x] add support for versions `git tag --sort v:refname`
- [ ] rename requires to deps - [ ] rename requires to deps
- [ ] move tasks etc to Plugin.state - [x] move tasks etc to Plugin.state
- loaded - [ ] allow setting up plugins through config
- installed
- updated
- changed: just installed or updated (dirty)
- is_local
https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
## 🖥️ Git Operations
1. **install**:
- run `git clone` with given `branch`,`--single-branch`, `filter=blob:none`
and `--no-checkout`
- run `git checkout` with correct `branch`, `tag` or `commit`
2. **update**:
- if branch is missing `git remote set-branches --add origin MISSING_BRANCH`
- `git switch MISSING_BRANCH`
- run `git fetch`
- run `git checkout` with correct `branch`, `tag` or `commit`

View File

@ -13,6 +13,7 @@ M.defaults = {
}, },
interactive = true, interactive = true,
packpath = vim.fn.stdpath("data") .. "/site/pack/lazy", packpath = vim.fn.stdpath("data") .. "/site/pack/lazy",
lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json",
view = { view = {
icons = { icons = {
start = "", start = "",
@ -23,6 +24,7 @@ M.defaults = {
keys = "", keys = "",
cmd = "", cmd = "",
ft = "", ft = "",
task = "",
}, },
}, },
} }

View File

@ -18,11 +18,11 @@ M.dirty = false
---@class LazyPluginState ---@class LazyPluginState
---@field loaded? {[string]:string, time:number} ---@field loaded? {[string]:string, time:number}
---@field installed? boolean ---@field installed boolean
---@field tasks? LazyTask[] ---@field tasks? LazyTask[]
---@field dirty? boolean ---@field dirty? boolean
---@field updated? {from:string, to:string} ---@field updated? {from:string, to:string}
---@field is_local? boolean ---@field is_local boolean
---@field is_symlink? boolean ---@field is_symlink? boolean
---@field cloned? boolean ---@field cloned? boolean

View File

@ -39,6 +39,7 @@ function M.run(ropts, opts)
if opts.wait then if opts.wait then
runner:wait() runner:wait()
end end
return runner
end end
---@param opts? ManagerOpts ---@param opts? ManagerOpts
@ -58,23 +59,26 @@ function M.install(opts)
}, opts) }, opts)
end end
---@param opts? ManagerOpts ---@param opts? ManagerOpts|{lockfile?:boolean}
function M.update(opts) function M.update(opts)
opts = opts or {}
M.run({ M.run({
pipeline = { pipeline = {
"fs.symlink", "fs.symlink",
"git.branch", "git.branch",
"git.fetch", "git.fetch",
"git.checkout", { "git.checkout", lockfile = opts.lockfile },
"plugin.docs", "plugin.docs",
"plugin.run",
"wait", "wait",
"plugin.run",
{ "git.log", updated = true }, { "git.log", updated = true },
}, },
plugins = function(plugin) plugins = function(plugin)
return plugin.uri and plugin._.installed return plugin.uri and plugin._.installed
end, end,
}, opts) }, opts):wait(function()
require("lazy.manage.lock").update()
end)
end end
---@param opts? ManagerOpts ---@param opts? ManagerOpts
@ -97,9 +101,11 @@ function M.clean(opts)
end end
function M.clear() function M.clear()
Plugin.update_state(true)
for _, plugin in pairs(Config.plugins) do for _, plugin in pairs(Config.plugins) do
-- clear updated status
plugin._.updated = nil plugin._.updated = nil
plugin._.cloned = nil
plugin._.dirty = nil
-- clear finished tasks -- clear finished tasks
if plugin._.tasks then if plugin._.tasks then
---@param task LazyTask ---@param task LazyTask

73
lua/lazy/manage/lock.lua Normal file
View File

@ -0,0 +1,73 @@
local Config = require("lazy.core.config")
local Git = require("lazy.manage.git")
local M = {}
---@type table<string, {commit:string, branch:string}>
M.lock = {}
M._loaded = false
function M.update()
local f = assert(io.open(Config.options.lockfile, "w"))
f:write("{\n")
M.lock = {}
---@param plugin LazyPlugin
local plugins = vim.tbl_filter(function(plugin)
return not plugin._.is_local and plugin._.installed
end, Config.plugins)
---@param plugin LazyPlugin
---@type string[]
local names = vim.tbl_map(function(plugin)
return plugin.name
end, plugins)
table.sort(names)
for n, name in ipairs(names) do
local plugin = Config.plugins[name]
if not plugin._.is_local and plugin._.installed then
local info = assert(Git.info(plugin.dir))
if not info.branch then
local branch = assert(Git.get_branch(plugin))
info.branch = branch.branch
end
info.commit = info.commit
-- f:write(([[ [%q] = { branch = %q, commit = %q },]]):format(name, info.branch, info.commit) .. "\n")
f:write(([[ %q: { "branch": %q, "commit": %q }]]):format(name, info.branch, info.commit))
if n ~= #names then
f:write(",\n")
end
---@diagnostic disable-next-line: assign-type-mismatch
M.lock[plugin.name] = info
end
end
f:write("\n}")
f:close()
end
function M.load()
M.lock = {}
M._loaded = true
local f = io.open(Config.options.lockfile, "r")
if f then
---@type string
local data = f:read("*a")
local ok, lock = pcall(vim.json.decode, data)
if ok then
M.lock = lock
end
f:close()
end
end
---@param plugin LazyPlugin
---@return {commit:string, branch:string}
function M.get(plugin)
if not M._loaded then
M.load()
end
return M.lock[plugin.name]
end
return M

View File

@ -1,5 +1,6 @@
local Util = require("lazy.util") local Util = require("lazy.util")
local Git = require("lazy.manage.git") local Git = require("lazy.manage.git")
local Lock = require("lazy.manage.lock")
---@type table<string, LazyTaskDef> ---@type table<string, LazyTaskDef>
local M = {} local M = {}
@ -118,11 +119,21 @@ M.checkout = {
skip = function(plugin) skip = function(plugin)
return not plugin._.installed or plugin._.is_local return not plugin._.installed or plugin._.is_local
end, end,
run = function(self) ---@param opts {lockfile?:boolean}
run = function(self, opts)
local info = assert(Git.info(self.plugin.dir)) local info = assert(Git.info(self.plugin.dir))
local target = assert(Git.get_target(self.plugin)) local target = assert(Git.get_target(self.plugin))
if not self.plugin._.cloned and info.commit == target.commit then local lock
if opts.lockfile then
lock = Lock.get(self.plugin)
if lock then
---@diagnostic disable-next-line: cast-local-type
target = lock
end
end
if not self.plugin._.cloned and info.commit == target.commit and info.branch == target.branch then
return return
end end
@ -131,7 +142,9 @@ M.checkout = {
"--progress", "--progress",
} }
if target.tag then if lock then
table.insert(args, lock.commit)
elseif target.tag then
table.insert(args, "tags/" .. target.tag) table.insert(args, "tags/" .. target.tag)
elseif self.plugin.commit then elseif self.plugin.commit then
table.insert(args, self.plugin.commit) table.insert(args, self.plugin.commit)

View File

@ -40,6 +40,9 @@ M.commands = {
update = function() update = function()
Manage.update({ clear = true, interactive = true }) Manage.update({ clear = true, interactive = true })
end, end,
reset = function()
Manage.update({ clear = true, interactive = true, lockfile = true })
end,
} }
function M.setup() function M.setup()