aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/pack.lua
diff options
context:
space:
mode:
authorEvgeni Chasnovski <evgeni.chasnovski@gmail.com>2025-12-26 17:35:25 +0200
committerEvgeni Chasnovski <evgeni.chasnovski@gmail.com>2025-12-26 18:32:59 +0200
commit8c28507fcf6fa5e39adba2a7f9dc07442aa3bbeb (patch)
tree72cb0cae91820689107b41b47f45a775ddc190a1 /runtime/lua/vim/pack.lua
parent899ec829be85b52202f0ce32c455ae4f4d60b85b (diff)
downloadrneovim-8c28507fcf6fa5e39adba2a7f9dc07442aa3bbeb.tar.gz
rneovim-8c28507fcf6fa5e39adba2a7f9dc07442aa3bbeb.tar.bz2
rneovim-8c28507fcf6fa5e39adba2a7f9dc07442aa3bbeb.zip
feat(pack): allow choosing update target in `update()`
Problem: There are two fairly common workflows that involve lockfile and can be made more straightforward in `vim.pack`: 1. Revert latest update. Like if it introduced unwanted behavior. 2. Update to a revision in the lockfile. Like if already updated on another machine, verified that everything works, `git add` + `git commit` + `git push` the config, and want to have the same plugin states on current machine. Solution: Make `update` allow `opts.target`. By default it uses `version` from a plugin specification (like a regular "get new changes from source" workflow). But it also allows `"lockfile"` value to indicate that target revision after update should be taken from the current lockfile verbatim. With this, the workflows are: 1. Revert (somehow) to the lockfile before the update, restart, and `vim.pack.update({ 'plugin' }, { target = 'lockfile' })`. If Git tracked, revert with `git checkout HEAD -- nvim-pack-lock.json`. For non-VCS tracked lockfile, the revisions can be taken from the log file. It would be nicer if `update()` would backup a lockfile before doing an update, but that might require discussions. 2. `git pull` + `:restart` + `vim.pack.update(nil, { target = 'lockfile' })`. The only caveats are for new and deleted plugins: - New plugins (not present locally but present in the lockfile) will be installed at lockfile revision during restart. - Deleted plugins (present locally but not present in the lockfile) will still be present: both locally *and* in the lockfile. They can be located by `git diff -- nvim-pack-lock.json` and require manual `vim.pack.del({ 'old-plugin1', 'old-plugin2' })`.
Diffstat (limited to 'runtime/lua/vim/pack.lua')
-rw-r--r--runtime/lua/vim/pack.lua47
1 files changed, 35 insertions, 12 deletions
diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua
index 736e78335a..a808ce8683 100644
--- a/runtime/lua/vim/pack.lua
+++ b/runtime/lua/vim/pack.lua
@@ -113,16 +113,28 @@
---
---Revert plugin after an update ~
---
----- Locate plugin's revision at working state. For example:
---- - If there is a previous version of |vim.pack-lockfile| (like from version
---- control history), use it to get plugin's `rev` field.
---- - If there is a log file ("nvim-pack.log" at "log" |stdpath()|), open it
---- and navigate to latest updates (at the bottom). Locate lines about plugin
---- update details and use revision from "State before".
----- Freeze plugin to target revision (set `version` and |:restart|).
----- Run `vim.pack.update({ 'plugin-name' }, { force = true })` to make plugin
---- state on disk follow target revision. |:restart|.
----- When ready to deal with updating plugin, unfreeze it.
+---- Revert the |vim.pack-lockfile| to the state before the update:
+--- - If Git tracked: `git checkout HEAD -- nvim-pack-lock.json`
+--- - If not tracked: examine log file ("nvim-pack.log" at "log" |stdpath()|),
+--- locate the revisions before the latest update, and (carefully) adjust
+--- current lockfile to have those revisions.
+---- |:restart|.
+---- `vim.pack.update({ 'plugin' }, { target = 'lockfile' })`. Read and confirm.
+---
+---Synchronize config across machines ~
+---
+---- On main machine:
+--- - Add |vim.pack-lockfile| to VCS.
+--- - Push to the remote server.
+---- On secondary machine:
+--- - Pull from the server.
+--- - |:restart|. New plugins (not present locally, but present in the lockfile)
+--- are installed at proper revision.
+--- - `vim.pack.update(nil, { target = 'lockfile' })`. Read and confirm.
+--- - Manually delete outdated plugins (present locally, but were not present
+--- in the lockfile prior to restart) with `vim.pack.del( { 'plugin' })`.
+--- They can be located by examining the VCS difference of the lockfile
+--- (`git diff -- nvim-pack-lock.json` for Git).
---
---Remove plugins from disk ~
---
@@ -1139,6 +1151,12 @@ end
--- @class vim.pack.keyset.update
--- @inlinedoc
--- @field force? boolean Whether to skip confirmation and make updates immediately. Default `false`.
+---
+--- How to compute a new plugin revision. One of:
+--- - "version" (default) - use latest revision matching `version` from plugin specification.
+--- - "lockfile" - use revision from the lockfile. Useful for reverting or performing controlled
+--- update.
+--- @field target? string
--- Update plugins
---
@@ -1173,7 +1191,7 @@ end
--- @param opts? vim.pack.keyset.update
function M.update(names, opts)
vim.validate('names', names, vim.islist, true, 'list')
- opts = vim.tbl_extend('force', { force = false }, opts or {})
+ opts = vim.tbl_extend('force', { force = false, target = 'version' }, opts or {})
local plug_list = plug_list_from_names(names)
if #plug_list == 0 then
@@ -1190,8 +1208,9 @@ function M.update(names, opts)
--- @async
--- @param p vim.pack.Plug
local function do_update(p)
+ local l_data = plugin_lock.plugins[p.spec.name]
-- Ensure proper `origin` if needed
- if plugin_lock.plugins[p.spec.name].src ~= p.spec.src then
+ if l_data.src ~= p.spec.src then
git_cmd({ 'remote', 'set-url', 'origin', p.spec.src }, p.path)
plugin_lock.plugins[p.spec.name].src = p.spec.src
needs_lock_write = true
@@ -1205,6 +1224,10 @@ function M.update(names, opts)
end
-- Compute change info: changelog if any, new tags if nothing to update
+ if opts.target == 'lockfile' then
+ p.info.version_str = '*lockfile*'
+ p.info.sha_target = l_data.rev
+ end
infer_update_details(p)
-- Checkout immediately if no need to confirm