feat(pack): update get() to take rev from actual repo if info=true

Problem: `vim.pack.get()` always uses lockfile as the source for the
  `rev` field. This is fast, but may be misleading in case of
  a corrupted lockfile.

Solution: Compute revision from Git repo on disk if `info=true`
  (default), use lockfile otherwise. This does increase execution time
  (as a result of one extra `git ...` call for every plugin), but
  `info=true` is already designed to be informative and not necessarily
  fast.
This commit is contained in:
Evgeni Chasnovski
2026-05-17 10:49:48 +03:00
parent 7d99104058
commit 8d100483e0
3 changed files with 25 additions and 10 deletions

View File

@@ -496,7 +496,8 @@ get({names}, {opts}) *vim.pack.get()*
• {branches}? (`string[]`) Available Git branches (first is default).
Missing if `info=false`.
• {path} (`string`) Plugin's path on disk.
• {rev} (`string`) Current Git revision.
• {rev} (`string`) Current Git revision. Taken from
|vim.pack-lockfile| if `info=false`.
• {spec} (`vim.pack.SpecResolved`) A |vim.pack.Spec| with resolved
`name`.
• {tags}? (`string[]`) Available Git tags. Missing if `info=false`.

View File

@@ -1434,7 +1434,7 @@ end
--- @field active boolean Whether plugin was added via |vim.pack.add()| to current session.
--- @field branches? string[] Available Git branches (first is default). Missing if `info=false`.
--- @field path string Plugin's path on disk.
--- @field rev string Current Git revision.
--- @field rev string Current Git revision. Taken from |vim.pack-lockfile| if `info=false`.
--- @field spec vim.pack.SpecResolved A |vim.pack.Spec| with resolved `name`.
--- @field tags? string[] Available Git tags. Missing if `info=false`.
@@ -1450,6 +1450,7 @@ local function add_p_data_info(p_data_list)
--- @async
funs[i] = function()
p_data.branches = git_get_branches(path)
p_data.rev = git_get_hash('HEAD', path)
p_data.tags = git_get_tags(path)
end
end

View File

@@ -2073,11 +2073,13 @@ describe('vim.pack', function()
local function make_basic_data(active, info)
local spec = { name = 'basic', src = repos_src.basic, version = 'feat-branch' }
local path = pack_get_plug_path('basic')
local rev = git_get_hash('feat-branch', 'basic')
local res = { active = active, path = path, spec = spec, rev = rev }
local res = { active = active, path = path, spec = spec }
if info then
res.branches = { 'main', 'feat-branch' }
res.rev = git_get_hash('feat-branch', 'basic')
res.tags = { 'some-tag' }
else
res.rev = get_lock_tbl().plugins.basic.rev
end
return res
end
@@ -2085,11 +2087,13 @@ describe('vim.pack', function()
local function make_defbranch_data(active, info)
local spec = { name = 'defbranch', src = repos_src.defbranch }
local path = pack_get_plug_path('defbranch')
local rev = git_get_hash('dev', 'defbranch')
local res = { active = active, path = path, spec = spec, rev = rev }
local res = { active = active, path = path, spec = spec }
if info then
res.branches = { 'dev', 'main' }
res.rev = git_get_hash('dev', 'defbranch')
res.tags = {}
else
res.rev = get_lock_tbl().plugins.defbranch.rev
end
return res
end
@@ -2098,11 +2102,13 @@ describe('vim.pack', function()
local spec =
{ name = 'plugindirs', src = repos_src.plugindirs, version = vim.version.range('*') }
local path = pack_get_plug_path('plugindirs')
local rev = git_get_hash('v0.0.1', 'plugindirs')
local res = { active = active, path = path, spec = spec, rev = rev }
local res = { active = active, path = path, spec = spec }
if info then
res.branches = { 'main' }
res.rev = git_get_hash('v0.0.1', 'plugindirs')
res.tags = { 'v0.0.1' }
else
res.rev = get_lock_tbl().plugins.plugindirs.rev
end
return res
end
@@ -2124,8 +2130,15 @@ describe('vim.pack', function()
-- Should preserve order in which plugins were `vim.pack.add()`ed
eq({ defbranch_data, basic_data, plugindirs_data }, exec_lua('return vim.pack.get()'))
-- Should also list non-active plugins
-- Should also list non-active plugins and use proper source for `rev`
local lock_tbl = get_lock_tbl()
lock_tbl.plugins.defbranch.rev = 'aaa'
lock_tbl.plugins.basic.rev = 'bbb'
lock_tbl.plugins.plugindirs.rev = 'ccc'
local lockfile_text = vim.json.encode(lock_tbl, { indent = ' ', sort_keys = true })
fn.writefile(vim.split(lockfile_text, '\n'), get_lock_path())
n.clear()
vim_pack_add({ repos_src.defbranch })
defbranch_data = make_defbranch_data(true, true)
basic_data = make_basic_data(false, true)
@@ -2182,9 +2195,9 @@ describe('vim.pack', function()
-- Should not include removed plugins immediately after they are removed,
-- while still returning list without holes
exec_lua('vim.pack.del({ "defbranch" }, { force = true })')
local defbranch_data = make_defbranch_data(true, true)
local basic_data = make_basic_data(true, true)
exec_lua('vim.pack.del({ "defbranch" }, { force = true })')
eq({ { defbranch_data, basic_data }, { basic_data } }, exec_lua('return _G.get_log'))
end)