Skip to content

Commit 2d79e1c

Browse files
committed
fix: use vim.pack.get() as source of truth for ZClean
ZClean was not detecting orphan plugins (removed from spec but still installed) because it only checked plugins in state.registered_plugins. Now ZClean calls vim.pack.get() directly to get all installed plugins and compares against spec_registry to find orphans.
1 parent 89a5a0c commit 2d79e1c

File tree

4 files changed

+118
-7
lines changed

4 files changed

+118
-7
lines changed

lua/zpack/commands.lua

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,12 @@ end
7070

7171
M.clean_unused = function()
7272
local to_delete = {}
73+
local installed = vim.pack.get() or {}
7374

74-
for _, spec in ipairs(state.registered_plugins) do
75-
if not state.spec_registry[spec.src] and not string.find(spec.src, 'zpack') then
76-
table.insert(to_delete, spec.name)
75+
for _, pack in ipairs(installed) do
76+
local src = pack.spec.src
77+
if not state.spec_registry[src] and not string.find(src, 'zpack') then
78+
table.insert(to_delete, pack.spec.name)
7779
end
7880
end
7981

tests/helpers.lua

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,27 @@ function M.setup_test_env()
151151
_G.test_state.registered_pack_specs = {}
152152
vim.pack.get = function(names)
153153
local results = {}
154-
for _, name in ipairs(names) do
155-
local pack_spec = _G.test_state.registered_pack_specs[name]
156-
if pack_spec then
154+
if names == nil or #names == 0 then
155+
for name, pack_spec in pairs(_G.test_state.registered_pack_specs) do
157156
table.insert(results, {
158157
spec = pack_spec,
159158
path = vim.fn.stdpath('data') .. '/site/pack/zpack/opt/' .. name,
160159
name = name,
161160
})
162161
end
162+
else
163+
for _, name in ipairs(names) do
164+
local pack_spec = _G.test_state.registered_pack_specs[name]
165+
if pack_spec then
166+
table.insert(results, {
167+
spec = pack_spec,
168+
path = vim.fn.stdpath('data') .. '/site/pack/zpack/opt/' .. name,
169+
name = name,
170+
})
171+
end
172+
end
163173
end
164-
return #results > 0 and results or nil
174+
return #results > 0 and results or {}
165175
end
166176

167177
_G.test_state.original_vim_pack_del = vim.pack.del

tests/run_all.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ local test_modules = {
2525
'dependencies_test',
2626
'module_loader_test',
2727
'zdelete_test',
28+
'zclean_test',
2829
}
2930

3031
print("\n" .. string.rep("=", 60))

tests/zclean_test.lua

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
local helpers = require('helpers')
2+
3+
return function()
4+
helpers.describe("ZClean Command", function()
5+
helpers.test("ZClean detects orphan plugins not in spec", function()
6+
helpers.setup_test_env()
7+
8+
require('zpack').setup({
9+
spec = {
10+
{ 'test/plugin-a' },
11+
{ 'test/plugin-b' },
12+
},
13+
defaults = { confirm = false },
14+
})
15+
16+
helpers.flush_pending()
17+
18+
_G.test_state.registered_pack_specs['orphan-plugin'] = {
19+
src = 'test/orphan-plugin',
20+
name = 'orphan-plugin',
21+
}
22+
23+
vim.cmd('ZClean')
24+
helpers.flush_pending()
25+
26+
helpers.assert_equal(#_G.test_state.vim_pack_del_calls, 1, "vim.pack.del should be called")
27+
local call = _G.test_state.vim_pack_del_calls[1]
28+
helpers.assert_table_contains(call.names, 'orphan-plugin', "orphan plugin should be in delete list")
29+
helpers.assert_equal(#call.names, 1, "only orphan plugin should be deleted")
30+
31+
helpers.cleanup_test_env()
32+
helpers.delete_zpack_commands()
33+
end)
34+
35+
helpers.test("ZClean does not delete plugins in spec", function()
36+
helpers.setup_test_env()
37+
38+
require('zpack').setup({
39+
spec = {
40+
{ 'test/plugin-a' },
41+
{ 'test/plugin-b' },
42+
},
43+
defaults = { confirm = false },
44+
})
45+
46+
helpers.flush_pending()
47+
48+
vim.cmd('ZClean')
49+
helpers.flush_pending()
50+
51+
helpers.assert_equal(#_G.test_state.vim_pack_del_calls, 0, "vim.pack.del should not be called")
52+
53+
local found_info = false
54+
for _, notif in ipairs(_G.test_state.notifications) do
55+
if notif.msg:find('No unused plugins') and notif.level == vim.log.levels.INFO then
56+
found_info = true
57+
break
58+
end
59+
end
60+
helpers.assert_true(found_info, "Should show info that no unused plugins exist")
61+
62+
helpers.cleanup_test_env()
63+
helpers.delete_zpack_commands()
64+
end)
65+
66+
helpers.test("ZClean detects multiple orphan plugins", function()
67+
helpers.setup_test_env()
68+
69+
require('zpack').setup({
70+
spec = {
71+
{ 'test/plugin-a' },
72+
},
73+
defaults = { confirm = false },
74+
})
75+
76+
helpers.flush_pending()
77+
78+
_G.test_state.registered_pack_specs['orphan-1'] = {
79+
src = 'test/orphan-1',
80+
name = 'orphan-1',
81+
}
82+
_G.test_state.registered_pack_specs['orphan-2'] = {
83+
src = 'test/orphan-2',
84+
name = 'orphan-2',
85+
}
86+
87+
vim.cmd('ZClean')
88+
helpers.flush_pending()
89+
90+
helpers.assert_equal(#_G.test_state.vim_pack_del_calls, 1, "vim.pack.del should be called once")
91+
local call = _G.test_state.vim_pack_del_calls[1]
92+
helpers.assert_equal(#call.names, 2, "both orphan plugins should be deleted")
93+
94+
helpers.cleanup_test_env()
95+
helpers.delete_zpack_commands()
96+
end)
97+
end)
98+
end

0 commit comments

Comments
 (0)