fix(pack): handle lockfile in case of install errors #36064

Problem: If plugin was intended to install but there were errors (like
  if there is a typo in `src`), lockfile still includes its entry.
  This leads to all source of problems (like not correct `get()` output,
  not working `update()`, etc.).

Solution: Explicitly account for plugins that were not installed.
  Alternative solution might be to write a safe
  `lock_set(plug, field, value)` wrapper (which sets field for a correct
  `plugins` entry in the lockfile Lua table) and use it after install
  to detect the change in `version`. However, this always requires
  an extra pass through plugins on every startup, which is suboptimal.
  Optimizing for the "happy path" should be a priority in `add()`.
This commit is contained in:
Evgeni Chasnovski
2025-10-07 22:24:23 +03:00
committed by GitHub
parent 006101360d
commit 3b860653ca
2 changed files with 28 additions and 0 deletions

View File

@@ -789,6 +789,11 @@ function M.add(specs, opts)
if #plugs_to_install > 0 then if #plugs_to_install > 0 then
git_ensure_exec() git_ensure_exec()
install_list(plugs_to_install, opts.confirm) install_list(plugs_to_install, opts.confirm)
for _, p in ipairs(plugs_to_install) do
if not p.info.installed then
plugin_lock.plugins[p.spec.name] = nil
end
end
end end
if needs_lock_write then if needs_lock_write then

View File

@@ -541,6 +541,29 @@ describe('vim.pack', function()
eq(ref_lockfile, get_lock_tbl()) eq(ref_lockfile, get_lock_tbl())
end) end)
it('handles lockfile during install errors', function()
local repo_not_exist = 'file://' .. repo_get_path('does-not-exist')
pcall_err(exec_lua, function()
vim.pack.add({
repo_not_exist,
{ src = repos_src.basic, version = 'not-exist' },
{ src = repos_src.pluginerr, version = 'main' },
})
end)
local pluginerr_hash = git_get_hash('main', 'pluginerr')
local ref_lockfile = {
-- Should be no entry for `repo_not_exist`
plugins = {
-- No `rev` because there was no relevant checkout
basic = { src = repos_src.basic, version = "'not-exist'" },
-- Error during sourcing 'plugin/' should not affect lockfile
pluginerr = { rev = pluginerr_hash, src = repos_src.pluginerr, version = "'main'" },
},
}
eq(ref_lockfile, get_lock_tbl())
end)
it('installs at proper version', function() it('installs at proper version', function()
local out = exec_lua(function() local out = exec_lua(function()
vim.pack.add({ vim.pack.add({