mirror of
https://github.com/neovim/neovim.git
synced 2026-04-23 07:45:32 +00:00
Merge #36435 vim.pack: improve default opts.load, handle src change
This commit is contained in:
@@ -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`).
|
||||
@@ -290,6 +294,18 @@ Unfreeze plugin to start receiving updates:
|
||||
want it to be updated.
|
||||
• |:restart|.
|
||||
|
||||
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.
|
||||
|
||||
Remove plugins from disk:
|
||||
• Use |vim.pack.del()| with a list of plugin names to remove. Make sure their
|
||||
specs are not included in |vim.pack.add()| call in 'init.lua' or they will
|
||||
@@ -354,10 +370,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.
|
||||
|
||||
@@ -379,7 +397,7 @@ add({specs}, {opts}) *vim.pack.add()*
|
||||
Load `plugin/` files and `ftdetect/` scripts. If `false`,
|
||||
works like `:packadd!`. If function, called with plugin
|
||||
data and is fully responsible for loading plugin. Default
|
||||
`false` during startup and `true` afterwards.
|
||||
`false` during |init.lua| sourcing and `true` afterwards.
|
||||
• {confirm}? (`boolean`) Whether to ask user to confirm
|
||||
initial install. Default `true`.
|
||||
|
||||
|
||||
@@ -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`).
|
||||
@@ -87,6 +91,18 @@
|
||||
---you want it to be updated.
|
||||
---- |:restart|.
|
||||
---
|
||||
---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.
|
||||
---
|
||||
---Remove plugins from disk:
|
||||
---- Use |vim.pack.del()| with a list of plugin names to remove. Make sure their specs
|
||||
---are not included in |vim.pack.add()| call in 'init.lua' or they will be reinstalled.
|
||||
@@ -165,11 +181,11 @@ end
|
||||
local git_version = vim.version.parse('1')
|
||||
|
||||
local function git_ensure_exec()
|
||||
local sys_res = vim.system({ 'git', 'version' }):wait()
|
||||
git_version = vim.version.parse(sys_res.stdout)
|
||||
if sys_res.stderr ~= '' then
|
||||
local ok, sys = pcall(vim.system, { 'git', 'version' })
|
||||
if not ok then
|
||||
error('No `git` executable')
|
||||
end
|
||||
git_version = vim.version.parse(sys:wait().stdout)
|
||||
end
|
||||
|
||||
--- @async
|
||||
@@ -743,8 +759,9 @@ local function pack_add(plug, load)
|
||||
-- NOTE: The `:packadd` specifically seems to not handle spaces in dir name
|
||||
vim.cmd.packadd({ vim.fn.escape(plug.spec.name, ' '), bang = not load, magic = { file = false } })
|
||||
|
||||
-- Execute 'after/' scripts if not during startup (when they will be sourced
|
||||
-- automatically), as `:packadd` only sources plain 'plugin/' files.
|
||||
-- The `:packadd` only sources plain 'plugin/' files. Execute 'after/' scripts
|
||||
-- if not during startup (when they will be sourced later, even if
|
||||
-- `vim.pack.add` is inside user's 'plugin/')
|
||||
-- See https://github.com/vim/vim/issues/15584
|
||||
-- Deliberately do so after executing all currently known 'plugin/' files.
|
||||
if vim.v.vim_did_enter == 1 and load then
|
||||
@@ -760,7 +777,7 @@ end
|
||||
--- @inlinedoc
|
||||
--- Load `plugin/` files and `ftdetect/` scripts. If `false`, works like `:packadd!`.
|
||||
--- If function, called with plugin data and is fully responsible for loading plugin.
|
||||
--- Default `false` during startup and `true` afterwards.
|
||||
--- Default `false` during |init.lua| sourcing and `true` afterwards.
|
||||
--- @field load? boolean|fun(plug_data: {spec: vim.pack.Spec, path: string})
|
||||
---
|
||||
--- @field confirm? boolean Whether to ask user to confirm initial install. Default `true`.
|
||||
@@ -768,9 +785,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.
|
||||
---
|
||||
@@ -788,7 +807,7 @@ end
|
||||
--- @param opts? vim.pack.keyset.add
|
||||
function M.add(specs, opts)
|
||||
vim.validate('specs', specs, vim.islist, false, 'list')
|
||||
opts = vim.tbl_extend('force', { load = vim.v.vim_did_enter == 1, confirm = true }, opts or {})
|
||||
opts = vim.tbl_extend('force', { load = vim.v.vim_did_init == 1, confirm = true }, opts or {})
|
||||
vim.validate('opts', opts, 'table')
|
||||
|
||||
local plug_dir = get_plug_dir()
|
||||
@@ -803,13 +822,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
|
||||
|
||||
@@ -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()
|
||||
@@ -620,35 +660,42 @@ describe('vim.pack', function()
|
||||
end)
|
||||
|
||||
describe('startup', function()
|
||||
local init_lua = ''
|
||||
local config_dir, pack_add_cmd = '', ''
|
||||
|
||||
before_each(function()
|
||||
init_lua = vim.fs.joinpath(fn.stdpath('config'), 'init.lua')
|
||||
fn.mkdir(vim.fs.dirname(init_lua), 'p')
|
||||
config_dir = fn.stdpath('config')
|
||||
fn.mkdir(vim.fs.joinpath(config_dir, 'plugin'), 'p')
|
||||
|
||||
pack_add_cmd = ('vim.pack.add({ %s })'):format(vim.inspect(repos_src.plugindirs))
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
pcall(vim.fs.rm, init_lua, { force = true })
|
||||
vim.fs.rm(config_dir, { recursive = true, force = true })
|
||||
end)
|
||||
|
||||
it('works in init.lua', function()
|
||||
local pack_add_cmd = ('vim.pack.add({ %s })'):format(vim.inspect(repos_src.plugindirs))
|
||||
fn.writefile({ pack_add_cmd, '_G.done = true' }, init_lua)
|
||||
local function assert_loaded()
|
||||
eq('plugindirs main', exec_lua('return require("plugindirs")'))
|
||||
|
||||
local function assert_loaded()
|
||||
eq('plugindirs main', exec_lua('return require("plugindirs")'))
|
||||
|
||||
-- Should source 'plugin/' and 'after/plugin/' exactly once
|
||||
eq({ true, true }, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }'))
|
||||
eq({ 'p', 'a' }, n.exec_lua('return _G.DL'))
|
||||
end
|
||||
-- Should source 'plugin/' and 'after/plugin/' exactly once
|
||||
eq({ true, true }, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }'))
|
||||
eq({ 'p', 'a' }, n.exec_lua('return _G.DL'))
|
||||
end
|
||||
|
||||
local function assert_works()
|
||||
-- Should auto-install but wait before executing code after it
|
||||
n.clear({ args_rm = { '-u' } })
|
||||
n.exec_lua('vim.wait(500, function() return _G.done end, 50)')
|
||||
assert_loaded()
|
||||
|
||||
-- Should only `:packadd!` already installed plugin
|
||||
-- Should only `:packadd!`/`:packadd` already installed plugin
|
||||
n.clear({ args_rm = { '-u' } })
|
||||
assert_loaded()
|
||||
end
|
||||
|
||||
it('works in init.lua', function()
|
||||
local init_lua = vim.fs.joinpath(config_dir, 'init.lua')
|
||||
fn.writefile({ pack_add_cmd, '_G.done = true' }, init_lua)
|
||||
assert_works()
|
||||
|
||||
-- Should not load plugins if `--noplugin`, only adjust 'runtimepath'
|
||||
n.clear({ args = { '--noplugin' }, args_rm = { '-u' } })
|
||||
@@ -656,6 +703,13 @@ describe('vim.pack', function()
|
||||
eq({}, n.exec_lua('return { vim.g._plugin, vim.g._after_plugin }'))
|
||||
eq(vim.NIL, n.exec_lua('return _G.DL'))
|
||||
end)
|
||||
|
||||
it('works in plugin/', function()
|
||||
local plugin_file = vim.fs.joinpath(config_dir, 'plugin', 'mine.lua')
|
||||
fn.writefile({ pack_add_cmd, '_G.done = true' }, plugin_file)
|
||||
-- Should source plugin's 'plugin/' files without explicit `load=true`
|
||||
assert_works()
|
||||
end)
|
||||
end)
|
||||
|
||||
it('shows progress report during installation', function()
|
||||
|
||||
Reference in New Issue
Block a user