diff --git a/runtime/doc/pack.txt b/runtime/doc/pack.txt index f3a8cf2948..14de2bba30 100644 --- a/runtime/doc/pack.txt +++ b/runtime/doc/pack.txt @@ -280,6 +280,10 @@ Switch plugin's version: changes in 'init.lua' as well or you will be prompted again next time you run |vim.pack.update()|. +Switch plugin's source: +• Update 'init.lua' for plugin to have desired `src`. +• |:restart|. This will cleanly reinstall plugin from the new source. + Freeze plugin from being updated: • Update 'init.lua' for plugin to have `version` set to current revision. Get it from |vim.pack-lockfile| (plugin's field `rev`; looks like `abc12345`). @@ -354,10 +358,12 @@ add({specs}, {opts}) *vim.pack.add()* Add plugin to current session • For each specification check that plugin exists on disk in |vim.pack-directory|: - • If exists, do nothing in this step. + • If exists, check if its `src` is the same as input. If not - delete + immediately to clean install from the new source. Otherwise do + nothing. • If doesn't exist, install it by downloading from `src` into `name` - subdirectory (via `git clone`) and update revision to follow `version` - (via `git checkout`). + subdirectory (via partial blobless `git clone`) and update revision to + match `version` (via `git checkout`). • For each plugin execute |:packadd| (or customizable `load` function) making it reachable by Nvim. diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua index 265a366d48..793d712479 100644 --- a/runtime/lua/vim/pack.lua +++ b/runtime/lua/vim/pack.lua @@ -77,6 +77,10 @@ ---any changes in 'init.lua' as well or you will be prompted again next time ---you run |vim.pack.update()|. --- +---Switch plugin's source: +---- Update 'init.lua' for plugin to have desired `src`. +---- |:restart|. This will cleanly reinstall plugin from the new source. +--- ---Freeze plugin from being updated: ---- Update 'init.lua' for plugin to have `version` set to current revision. ---Get it from |vim.pack-lockfile| (plugin's field `rev`; looks like `abc12345`). @@ -769,9 +773,11 @@ end --- Add plugin to current session --- --- - For each specification check that plugin exists on disk in |vim.pack-directory|: ---- - If exists, do nothing in this step. +--- - If exists, check if its `src` is the same as input. If not - delete +--- immediately to clean install from the new source. Otherwise do nothing. --- - If doesn't exist, install it by downloading from `src` into `name` ---- subdirectory (via `git clone`) and update revision to follow `version` (via `git checkout`). +--- subdirectory (via partial blobless `git clone`) and update revision +--- to match `version` (via `git checkout`). --- - For each plugin execute |:packadd| (or customizable `load` function) making --- it reachable by Nvim. --- @@ -804,13 +810,19 @@ function M.add(specs, opts) local plugs_to_install = {} --- @type vim.pack.Plug[] local needs_lock_write = false for _, p in ipairs(plugs) do - -- TODO(echasnovski): check that lock's `src` is the same as in spec. - -- If not - cleanly reclone (delete directory and mark as not installed). + -- Allow to cleanly change `src` of an already installed plugin + if p.info.installed and plugin_lock.plugins[p.spec.name].src ~= p.spec.src then + M.del({ p.spec.name }) + p.info.installed = false + end + + -- Detect `version` change local p_lock = plugin_lock.plugins[p.spec.name] or {} needs_lock_write = needs_lock_write or p_lock.version ~= p.spec.version p_lock.version = p.spec.version plugin_lock.plugins[p.spec.name] = p_lock + -- Register for install if not p.info.installed then plugs_to_install[#plugs_to_install + 1] = p needs_lock_write = true diff --git a/test/functional/plugin/pack_spec.lua b/test/functional/plugin/pack_spec.lua index 82e0277775..48155e2743 100644 --- a/test/functional/plugin/pack_spec.lua +++ b/test/functional/plugin/pack_spec.lua @@ -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()