feat(pack): update add() to handle source change for installed plugin

Problem: Changing `src` of an existing plugin cleanly requires manual
  `vim.pack.del()` prior to executing `vim.pack.add()` with a new `src`.

Solution: Autodetect `src` change for an existing plugin (by comparing
  against lockfile data). If different - properly delete immediately and
  treat this as new plugin installation.

  Alternative solution might be to update `origin` remote in the
  installed plugin after calling `vim.pack.update()`. Although, doable,
  this 1) requires more code; and 2) works only for Git plugins (which
  might be not the only type of plugins in the future). Automatic
  "delete and clean install" feels more robust.
This commit is contained in:
Evgeni Chasnovski
2025-11-13 15:49:16 +02:00
parent a39171f532
commit 2e533e364e
3 changed files with 65 additions and 7 deletions

View File

@@ -611,6 +611,46 @@ describe('vim.pack', function()
eq({ { '.git', 'directory' } }, entries)
end)
it('allows changing `src` of installed plugin', function()
local basic_src = repos_src.basic
local defbranch_src = repos_src.defbranch
exec_lua(function()
vim.pack.add({ basic_src })
end)
eq('basic main', exec_lua('return require("basic")'))
n.clear()
watch_events({ 'PackChangedPre', 'PackChanged' })
exec_lua(function()
vim.pack.add({ { src = defbranch_src, name = 'basic' } })
end)
eq('defbranch dev', exec_lua('return require("defbranch")'))
-- Should first properly delete and then cleanly install
local log_simple = vim.tbl_map(function(x) --- @param x table
return { x.event, x.data.kind, x.data.spec }
end, exec_lua('return _G.event_log'))
local ref_log_simple = {
{ 'PackChangedPre', 'delete', { name = 'basic', src = basic_src } },
{ 'PackChanged', 'delete', { name = 'basic', src = basic_src } },
{ 'PackChangedPre', 'install', { name = 'basic', src = defbranch_src } },
{ 'PackChanged', 'install', { name = 'basic', src = defbranch_src } },
}
eq(ref_log_simple, log_simple)
local ref_messages = table.concat({
"vim.pack: Removed plugin 'basic'",
'vim.pack: Installing plugins (0/1)',
'vim.pack: 100% Installing plugins (1/1)',
}, '\n')
eq(ref_messages, n.exec_capture('messages'))
local defbranch_rev = git_get_hash('dev', 'defbranch')
local ref_lock_tbl = { plugins = { basic = { rev = defbranch_rev, src = defbranch_src } } }
eq(ref_lock_tbl, get_lock_tbl())
end)
it('can install from the Internet', function()
t.skip(skip_integ, 'NVIM_TEST_INTEG not set: skipping network integration test')
exec_lua(function()