diff --git a/runtime/doc/pack.txt b/runtime/doc/pack.txt index 19f7a89377..d15754b56e 100644 --- a/runtime/doc/pack.txt +++ b/runtime/doc/pack.txt @@ -272,19 +272,15 @@ Basic install and management: updates execute |:quit|. • (Optionally) |:restart| to start using code from updated plugins. -Switch plugin's version: -• Update 'init.lua' for plugin to have desired `version`. Let's say, plugin - named 'plugin1' has changed to `vim.version.range('*')`. -• |:restart|. The plugin's actual revision on disk is not yet changed. Only - plugin's `version` in |vim.pack-lockfile| is updated. -• Execute `vim.pack.update({ 'plugin1' })`. -• Review changes and either confirm or discard them. If discarded, revert 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. +Switch plugin's version and/or source: +• Update 'init.lua' for plugin to have desired `version` and/or `src`. Let's + say, the switch is for plugin named 'plugin1'. +• |:restart|. The plugin's state on disk (revision and/or tracked source) is + not yet changed. Only plugin's `version` in |vim.pack-lockfile| is updated. +• Execute `vim.pack.update({ 'plugin1' })`. The plugin's source is updated. +• Review changes and either confirm or discard them. If discarded, revert + `version` change in 'init.lua' as well or you will be prompted again next + time you run |vim.pack.update()|. Freeze plugin from being updated: • Update 'init.lua' for plugin to have `version` set to current revision. Get diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua index 26cffb8606..660745e120 100644 --- a/runtime/lua/vim/pack.lua +++ b/runtime/lua/vim/pack.lua @@ -70,19 +70,15 @@ --- To discard updates execute |:quit|. --- - (Optionally) |:restart| to start using code from updated plugins. --- ----Switch plugin's version: ----- Update 'init.lua' for plugin to have desired `version`. Let's say, plugin ----named 'plugin1' has changed to `vim.version.range('*')`. ----- |:restart|. The plugin's actual revision on disk is not yet changed. ---- Only plugin's `version` in |vim.pack-lockfile| is updated. ----- Execute `vim.pack.update({ 'plugin1' })`. +---Switch plugin's version and/or source: +---- Update 'init.lua' for plugin to have desired `version` and/or `src`. +--- Let's say, the switch is for plugin named 'plugin1'. +---- |:restart|. The plugin's state on disk (revision and/or tracked source) +--- is not yet changed. Only plugin's `version` in |vim.pack-lockfile| is updated. +---- Execute `vim.pack.update({ 'plugin1' })`. The plugin's source is updated. ---- Review changes and either confirm or discard them. If discarded, revert ----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. +--- `version` change in 'init.lua' as well or you will be prompted again next time +--- you run |vim.pack.update()|. --- ---Freeze plugin from being updated: ---- Update 'init.lua' for plugin to have `version` set to current revision. @@ -922,12 +918,6 @@ function M.add(specs, opts) local plugs_to_install = {} --- @type vim.pack.Plug[] local needs_lock_write = false for _, p in ipairs(plugs) do - -- 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 @@ -1172,10 +1162,18 @@ function M.update(names, opts) -- Perform update local timestamp = get_timestamp() + local needs_lock_write = opts.force --- @type boolean --- @async --- @param p vim.pack.Plug local function do_update(p) + -- Ensure proper `origin` if needed + if plugin_lock.plugins[p.spec.name].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 + end + -- Fetch if not opts._offline then -- Using '--tags --force' means conflicting tags will be synced with remote @@ -1197,8 +1195,11 @@ function M.update(names, opts) or 'Downloading updates' run_list(plug_list, do_update, progress_title) - if opts.force then + if needs_lock_write then lock_write() + end + + if opts.force then feedback_log(plug_list) return end diff --git a/test/functional/plugin/pack_spec.lua b/test/functional/plugin/pack_spec.lua index 0c99ac280f..6c84f31796 100644 --- a/test/functional/plugin/pack_spec.lua +++ b/test/functional/plugin/pack_spec.lua @@ -790,46 +790,6 @@ describe('vim.pack', function() eq(false, pack_exists('basic')) 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() @@ -1142,7 +1102,7 @@ describe('vim.pack', function() describe('update()', function() -- Lua source code for the tested plugin named "fetch" - local fetch_lua_file = vim.fs.joinpath(pack_get_plug_path('fetch'), 'lua', 'fetch.lua') + local fetch_lua_file -- Tables with hashes used to test confirmation buffer and log content local hashes --- @type table local short_hashes --- @type table @@ -1157,6 +1117,7 @@ describe('vim.pack', function() repo_write_file('fetch', 'lua/fetch.lua', 'return "fetch main"') git_add_commit('Commit from `main` to be removed', 'fetch') + fetch_lua_file = vim.fs.joinpath(pack_get_plug_path('fetch'), 'lua', 'fetch.lua') hashes = { fetch_head = git_get_hash('HEAD', 'fetch') } short_hashes = { fetch_head = git_get_short_hash('HEAD', 'fetch') } @@ -1726,6 +1687,52 @@ describe('vim.pack', function() eq(hashes.fetch_new, get_lock_tbl().plugins.fetch.rev) end) + it('can change `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) + + local function assert_origin(ref) + -- Should be in sync both on disk and in lockfile + local opts = { cwd = pack_get_plug_path('basic') } + local real_origin = system_sync({ 'git', 'remote', 'get-url', 'origin' }, opts) + eq(ref, vim.trim(real_origin.stdout)) + + eq(ref, get_lock_tbl().plugins.basic.src) + end + + n.clear() + watch_events({ 'PackChangedPre', 'PackChanged' }) + + assert_origin(basic_src) + exec_lua(function() + vim.pack.add({ { src = defbranch_src, name = 'basic' } }) + end) + -- Should not yet (after `add()`) affect plugin source + assert_origin(basic_src) + + -- Should update source immediately (to work if updates are discarded) + exec_lua(function() + vim.pack.update({ 'basic' }) + end) + assert_origin(defbranch_src) + + -- Should not revert source change even if update is discarded + n.exec('quit') + assert_origin(defbranch_src) + eq({}, exec_lua('return _G.event_log')) + + -- Should work with forced update + n.clear() + exec_lua(function() + vim.pack.add({ basic_src }) + vim.pack.update({ 'basic' }, { force = true }) + end) + assert_origin(basic_src) + end) + it('shows progress report', function() track_nvim_echo() exec_lua(function()