aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/pack.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/pack.lua')
-rw-r--r--runtime/lua/vim/pack.lua47
1 files changed, 36 insertions, 11 deletions
diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua
index 6180f23db5..9ef3d38b34 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`).
@@ -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