mirror of
https://github.com/neovim/neovim.git
synced 2026-07-15 13:50:33 +00:00
feat(pack): 'packlockfile' option #40562
Problem: No way to configure the lockfile location. Solution: Add 'packlockfile' option.
This commit is contained in:
committed by
GitHub
parent
ef130902cf
commit
0653e7a338
@@ -293,6 +293,7 @@ OPTIONS
|
||||
The same applies to 'rulerformat', 'statuscolumn', 'tabline', 'winbar',
|
||||
'titlestring', and 'iconstring'.
|
||||
• 'winpinned' prevents window from closing unless specifically targeted.
|
||||
• 'packlockfile' sets the path used for |vim.pack-lockfile|.
|
||||
|
||||
PERFORMANCE
|
||||
|
||||
|
||||
@@ -4784,6 +4784,13 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
the name of a function, a |lambda| or a |Funcref|. See
|
||||
|option-value-function| for more information.
|
||||
|
||||
*'packlockfile'* *'plf'*
|
||||
'packlockfile' 'plf' string (default "$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json")
|
||||
global
|
||||
Disallowed in |modeline|. |no-modeline-option|
|
||||
Path of |vim.pack-lockfile|. Must be set before the first usage of any
|
||||
|vim.pack| function. Environment variables are expanded |:set_env|.
|
||||
|
||||
*'packpath'* *'pp'*
|
||||
'packpath' 'pp' string (default see 'runtimepath')
|
||||
global
|
||||
|
||||
@@ -224,15 +224,15 @@ semver convention `v<major>.<minor>.<patch>` (with or without `v` prefix).
|
||||
Like `v1.2.0` or `1.2.0`, but not `1.2` or `v1`.
|
||||
|
||||
The latest state of all managed plugins is stored inside a *vim.pack-lockfile*
|
||||
located at `$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json`. It is a JSON file that
|
||||
is used to persistently track data about plugins. For a more robust config
|
||||
treat lockfile like its part: put under version control, etc. In this case all
|
||||
plugins from the lockfile will be installed at once (in alphabetical order)
|
||||
and at lockfile's revision (instead of inferring from `version`). This is done
|
||||
on the very first `vim.pack` function call to ensure that lockfile is aligned
|
||||
with what is actually on the disk. Lockfile should not be edited by hand.
|
||||
Corrupted data for installed plugins is repaired (including after deleting
|
||||
whole file), but `version` fields will be missing for not yet added plugins.
|
||||
located at |'packlockfile'|. It is a JSON file that is used to persistently
|
||||
track data about plugins. For a more robust config treat lockfile like its
|
||||
part: put under version control, etc. In this case all plugins from the
|
||||
lockfile will be installed at once (in alphabetical order) and at lockfile's
|
||||
revision (instead of inferring from `version`). This is done on the very first
|
||||
`vim.pack` function call to ensure that lockfile is aligned with what is
|
||||
actually on the disk. Lockfile should not be edited by hand. Corrupted data
|
||||
for installed plugins is repaired (including after deleting whole file), but
|
||||
`version` fields will be missing for not yet added plugins.
|
||||
|
||||
*vim.pack-examples*
|
||||
|
||||
|
||||
9
runtime/lua/vim/_meta/options.gen.lua
generated
9
runtime/lua/vim/_meta/options.gen.lua
generated
@@ -4888,6 +4888,15 @@ vim.o.opfunc = vim.o.operatorfunc
|
||||
vim.go.operatorfunc = vim.o.operatorfunc
|
||||
vim.go.opfunc = vim.go.operatorfunc
|
||||
|
||||
--- Path of `vim.pack-lockfile`. Must be set before the first usage of any
|
||||
--- `vim.pack` function. Environment variables are expanded `:set_env`.
|
||||
---
|
||||
--- @type string
|
||||
vim.o.packlockfile = "$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json"
|
||||
vim.o.plf = vim.o.packlockfile
|
||||
vim.go.packlockfile = vim.o.packlockfile
|
||||
vim.go.plf = vim.go.packlockfile
|
||||
|
||||
--- Directories used to find packages.
|
||||
--- See `packages` and `packages-runtimepath`.
|
||||
--- Environment variables are expanded `:set_env`.
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
---Like `v1.2.0` or `1.2.0`, but not `1.2` or `v1`.
|
||||
---
|
||||
---The latest state of all managed plugins is stored inside a [vim.pack-lockfile]()
|
||||
---located at `$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json`. It is a JSON file that
|
||||
---is used to persistently track data about plugins.
|
||||
---located at |'packlockfile'|.
|
||||
---It is a JSON file that is used to persistently track data about plugins.
|
||||
---For a more robust config treat lockfile like its part: put under version control, etc.
|
||||
---In this case all plugins from the lockfile will be installed at once (in alphabetical order) and
|
||||
---at lockfile's revision (instead of inferring from `version`). This is done on the very first
|
||||
@@ -258,10 +258,6 @@ local function get_plug_dir()
|
||||
return vim.fs.joinpath(vim.fn.stdpath('data'), 'site', 'pack', 'core', 'opt')
|
||||
end
|
||||
|
||||
local function lock_get_path()
|
||||
return vim.fs.joinpath(vim.fn.stdpath('config'), 'nvim-pack-lock.json')
|
||||
end
|
||||
|
||||
-- Git ------------------------------------------------------------------------
|
||||
|
||||
--- @async
|
||||
@@ -871,9 +867,8 @@ local function lock_write()
|
||||
end
|
||||
end
|
||||
|
||||
local path = lock_get_path()
|
||||
vim.fn.mkdir(vim.fs.dirname(path), 'p')
|
||||
local fd = assert(uv.fs_open(path, 'w', 438))
|
||||
vim.fn.mkdir(vim.fs.dirname(M._plugin_lock_path), 'p')
|
||||
local fd = assert(uv.fs_open(M._plugin_lock_path, 'w', 438))
|
||||
|
||||
local data = vim.json.encode(lock, { indent = ' ', sort_keys = true })
|
||||
assert(uv.fs_write(fd, data .. '\n'))
|
||||
@@ -998,7 +993,8 @@ local function lock_read(confirm, specs)
|
||||
return
|
||||
end
|
||||
|
||||
local fd = uv.fs_open(lock_get_path(), 'r', 438)
|
||||
M._plugin_lock_path = vim.go.packlockfile
|
||||
local fd = uv.fs_open(M._plugin_lock_path, 'r', 438)
|
||||
if fd then
|
||||
local stat = assert(uv.fs_fstat(fd))
|
||||
local data = assert(uv.fs_read(fd, stat.size, 0))
|
||||
|
||||
@@ -3,7 +3,7 @@ local M = {}
|
||||
local health = vim.health
|
||||
|
||||
local function get_lockfile_path()
|
||||
return vim.fs.joinpath(vim.fn.stdpath('config'), 'nvim-pack-lock.json')
|
||||
return vim.pack._plugin_lock_path or vim.go.packlockfile
|
||||
end
|
||||
|
||||
local function get_plug_dir()
|
||||
@@ -159,7 +159,8 @@ end
|
||||
local function check_lockfile()
|
||||
health.start('vim.pack: lockfile')
|
||||
|
||||
local can_read, text = pcall(vim.fn.readblob, get_lockfile_path())
|
||||
local path = get_lockfile_path()
|
||||
local can_read, text = pcall(vim.fn.readblob, path)
|
||||
if not can_read then
|
||||
health.error('Could not read lockfile. Delete it and restart Nvim.')
|
||||
return
|
||||
@@ -177,6 +178,18 @@ local function check_lockfile()
|
||||
end
|
||||
|
||||
local is_good = true
|
||||
if path ~= vim.go.packlockfile then
|
||||
health.warn(
|
||||
"Lockfile path is not the same as 'packlockfile' option value. "
|
||||
.. "Set 'packlockfile' before the first usage of `vim.pack` function."
|
||||
)
|
||||
is_good = false
|
||||
end
|
||||
if path ~= vim.fs.abspath(path) then
|
||||
health.warn('Lockfile path is not absolute. Make sure that this is intentional.')
|
||||
is_good = false
|
||||
end
|
||||
|
||||
--- @cast data { plugins: table<string,table> }
|
||||
for plug_name, lock_data in pairs(data.plugins) do
|
||||
is_good = check_plugin_lock_data(plug_name, lock_data) and is_good
|
||||
|
||||
@@ -456,6 +456,7 @@ local options_list = {
|
||||
{ 'termpastefilter', N_ 'characters removed when pasting into terminal window' },
|
||||
{ 'scrollback', N_ 'number of lines kept beyond the visible screen in terminal buffer' },
|
||||
{ 'ttyfast', N_ 'assume terminal responds quickly, enabling more features' },
|
||||
{ 'packlockfile', N_ 'sets the path used for vim.pack lockfile' },
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -467,6 +467,7 @@ EXTERN int p_ari; ///< 'allowrevins'
|
||||
EXTERN int p_ri; ///< 'revins'
|
||||
EXTERN int p_ru; ///< 'ruler'
|
||||
EXTERN char *p_ruf; ///< 'rulerformat'
|
||||
EXTERN char *p_plf; ///< 'packlockfile'
|
||||
EXTERN char *p_pp; ///< 'packpath'
|
||||
EXTERN char *p_qftf; ///< 'quickfixtextfunc'
|
||||
EXTERN char *p_rtp; ///< 'runtimepath'
|
||||
|
||||
@@ -6418,6 +6418,22 @@ local options = {
|
||||
type = 'string',
|
||||
varname = 'p_opfunc',
|
||||
},
|
||||
{
|
||||
abbreviation = 'plf',
|
||||
defaults = '$XDG_CONFIG_HOME/nvim/nvim-pack-lock.json',
|
||||
deny_duplicates = true,
|
||||
desc = [=[
|
||||
Path of |vim.pack-lockfile|. Must be set before the first usage of any
|
||||
|vim.pack| function. Environment variables are expanded |:set_env|.
|
||||
]=],
|
||||
expand = true,
|
||||
full_name = 'packlockfile',
|
||||
scope = { 'global' },
|
||||
secure = true,
|
||||
short_desc = N_('path of vim.pack lockfile'),
|
||||
type = 'string',
|
||||
varname = 'p_plf',
|
||||
},
|
||||
{
|
||||
abbreviation = 'pp',
|
||||
cb = 'did_set_runtimepackpath',
|
||||
|
||||
@@ -385,6 +385,10 @@ local function get_lock_path()
|
||||
return vim.fs.joinpath(fn.stdpath('config'), 'nvim-pack-lock.json')
|
||||
end
|
||||
|
||||
local function get_other_lock_path()
|
||||
return vim.fs.joinpath(fn.stdpath('state'), 'test-pack-lock')
|
||||
end
|
||||
|
||||
--- @return {plugins:table<string, {rev:string, src:string, version?:string}>}
|
||||
local function get_lock_tbl()
|
||||
return vim.json.decode(fn.readblob(get_lock_path()))
|
||||
@@ -407,6 +411,7 @@ describe('vim.pack', function()
|
||||
after_each(function()
|
||||
local pack_dir = pack_get_dir()
|
||||
local lock_path = get_lock_path()
|
||||
local other_lock_path = get_other_lock_path()
|
||||
local log_path = vim.fs.joinpath(fn.stdpath('log'), 'nvim-pack.log')
|
||||
|
||||
-- Wait for neovim to close before removing directories so it can release
|
||||
@@ -416,6 +421,7 @@ describe('vim.pack', function()
|
||||
|
||||
n.rmdir(pack_dir)
|
||||
pcall(vim.fs.rm, lock_path, { force = true })
|
||||
pcall(vim.fs.rm, other_lock_path, { force = true })
|
||||
pcall(vim.fs.rm, log_path, { force = true })
|
||||
end)
|
||||
|
||||
@@ -775,6 +781,29 @@ describe('vim.pack', function()
|
||||
assert()
|
||||
end)
|
||||
|
||||
it("respects 'packlockfile'", function()
|
||||
local other_lock_path = get_other_lock_path()
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
exec_lua(function()
|
||||
vim.pack.add({ repos_src.basic })
|
||||
end)
|
||||
local ref_lockfile = {
|
||||
plugins = {
|
||||
basic = { rev = git_get_hash('main', 'basic'), src = repos_src.basic },
|
||||
},
|
||||
}
|
||||
eq(ref_lockfile, vim.json.decode(fn.readblob(other_lock_path)))
|
||||
eq(false, vim.uv.fs_stat(get_lock_path()) ~= nil)
|
||||
|
||||
n.clear()
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
exec_lua(function()
|
||||
vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' } })
|
||||
end)
|
||||
ref_lockfile.plugins.basic.version = "'feat-branch'"
|
||||
eq(ref_lockfile, vim.json.decode(fn.readblob(other_lock_path)))
|
||||
end)
|
||||
|
||||
it('removes unrepairable corrupted data and plugins', function()
|
||||
vim_pack_add({ repos_src.basic, repos_src.defbranch, repos_src.semver, repos_src.helptags })
|
||||
|
||||
@@ -2039,6 +2068,37 @@ describe('vim.pack', function()
|
||||
pack_assert_content('fetch', 'return "fetch dev"')
|
||||
end)
|
||||
|
||||
it("respects 'packlockfile'", function()
|
||||
n.rmdir(pack_get_dir())
|
||||
pcall(vim.fs.rm, get_lock_path(), { force = true })
|
||||
|
||||
n.clear()
|
||||
local other_lock_path = get_other_lock_path()
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
|
||||
exec_lua(function()
|
||||
vim.pack.add({ repos_src.basic })
|
||||
end)
|
||||
|
||||
eq(true, vim.uv.fs_stat(other_lock_path) ~= nil)
|
||||
eq(false, vim.uv.fs_stat(get_lock_path()) ~= nil)
|
||||
|
||||
n.clear()
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
|
||||
exec_lua(function()
|
||||
vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' } })
|
||||
vim.pack.update({ 'basic' }, { force = true })
|
||||
end)
|
||||
pack_assert_content('basic', 'return "basic feat-branch"')
|
||||
local basic_lock = {
|
||||
rev = git_get_hash('feat-branch', 'basic'),
|
||||
src = repos_src.basic,
|
||||
version = "'feat-branch'",
|
||||
}
|
||||
eq({ plugins = { basic = basic_lock } }, vim.json.decode(fn.readblob(other_lock_path)))
|
||||
end)
|
||||
|
||||
it('validates input', function()
|
||||
local function assert(err_pat, input)
|
||||
local function update_input()
|
||||
@@ -2287,6 +2347,23 @@ describe('vim.pack', function()
|
||||
eq(2, exec_lua('return #vim.pack.get()'))
|
||||
eq(2, vim.tbl_count(get_lock_tbl().plugins))
|
||||
end)
|
||||
|
||||
it("respects 'packlockfile'", function()
|
||||
n.rmdir(pack_get_dir())
|
||||
pcall(vim.fs.rm, get_lock_path(), { force = true })
|
||||
|
||||
n.clear()
|
||||
local other_lock_path = get_other_lock_path()
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
|
||||
exec_lua(function()
|
||||
vim.pack.add({ { src = repos_src.basic, version = 'feat-branch' } })
|
||||
end)
|
||||
|
||||
local basic_data = make_basic_data(true, true)
|
||||
eq({ basic_data }, exec_lua('return vim.pack.get()'))
|
||||
eq(false, vim.uv.fs_stat(get_lock_path()) ~= nil)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('del()', function()
|
||||
@@ -2396,6 +2473,24 @@ describe('vim.pack', function()
|
||||
eq({ 'plugindirs' }, vim.tbl_keys(get_lock_tbl().plugins))
|
||||
end)
|
||||
|
||||
it("respects 'packlockfile'", function()
|
||||
n.rmdir(pack_get_dir())
|
||||
pcall(vim.fs.rm, get_lock_path(), { force = true })
|
||||
|
||||
n.clear()
|
||||
local other_lock_path = vim.fs.joinpath(fn.stdpath('data'), 'test-pack-lock')
|
||||
api.nvim_set_option_value('packlockfile', other_lock_path, { scope = 'global' })
|
||||
|
||||
exec_lua(function()
|
||||
vim.pack.add({ repos_src.basic })
|
||||
end)
|
||||
|
||||
exec_lua('vim.pack.del({ "basic" }, { force = true })')
|
||||
eq({ plugins = {} }, vim.json.decode(fn.readblob(other_lock_path)))
|
||||
eq(false, pack_exists('basic'))
|
||||
eq(false, vim.uv.fs_stat(get_lock_path()) ~= nil)
|
||||
end)
|
||||
|
||||
it('validates input', function()
|
||||
local function assert(err_pat, input)
|
||||
local function del_input()
|
||||
|
||||
Reference in New Issue
Block a user