Skip to content

Commit 51c23b6

Browse files
committed
fix(spec): allow a spec module to be on the rtp and not only in config
1 parent 963e6f7 commit 51c23b6

File tree

5 files changed

+131
-19
lines changed

5 files changed

+131
-19
lines changed

lua/lazy/core/cache.lua

+42-3
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ function M.check_path(modname, modpath)
6262

6363
-- the correct lazy path should be part of rtp.
6464
-- so if we get here, this is folke using the local dev instance ;)
65-
if modname:sub(1, 4) == "lazy" then
65+
if modname and modname:sub(1, 4) == "lazy" then
6666
return false
6767
end
6868

69-
return M.check_autoload(modname, modpath)
69+
return modname and M.check_autoload(modname, modpath)
7070
end
7171

7272
function M.check_autoload(modname, modpath)
@@ -246,8 +246,43 @@ function M.get_topmods(path)
246246
end
247247

248248
---@param modname string
249+
---@return string?, string?
250+
function M.find_dir(modname)
251+
if M.cache[modname] then
252+
-- check if modname is in cache
253+
local modpath = M.cache[modname].modpath
254+
if M.check_path(modname, modpath) then
255+
local root = modpath:gsub("/init%.lua$", ""):gsub("%.lua$", "")
256+
return root, modpath
257+
end
258+
else
259+
-- in case modname is just a directory and not a real mod,
260+
-- check for any children in the cache
261+
for child, entry in pairs(M.cache) do
262+
if child:find(modname, 1, true) == 1 and M.check_path(nil, entry.modpath) then
263+
local basename = modname:gsub("%.", "/")
264+
local childbase = child:gsub("%.", "/")
265+
local ret = entry.modpath:gsub("/init%.lua$", ""):gsub("%.lua$", "")
266+
local idx = assert(ret:find(childbase, 1, true))
267+
return ret:sub(1, idx - 1) .. basename
268+
end
269+
end
270+
end
271+
272+
-- not found in cache, so find the root with the special pattern
273+
local modpath = M.find(modname, { patterns = { "" } })
274+
if modpath then
275+
local root = modpath:gsub("/init%.lua$", ""):gsub("%.lua$", "")
276+
return root, root ~= modpath and modpath or nil
277+
end
278+
end
279+
280+
---@param modname string
281+
---@param opts? {patterns?:string[]}
249282
---@return string?
250-
function M.find(modname)
283+
function M.find(modname, opts)
284+
opts = opts or {}
285+
251286
M.stats.find.total = M.stats.find.total + 1
252287
local start = uv.hrtime()
253288
local basename = modname:gsub("%.", "/")
@@ -257,6 +292,10 @@ function M.find(modname)
257292
-- search for a directory first when topmod == modname
258293
local patterns = topmod == modname and { "/init.lua", ".lua" } or { ".lua", "/init.lua" }
259294

295+
if opts.patterns then
296+
vim.list_extend(patterns, opts.patterns)
297+
end
298+
260299
-- check top-level mods to find the module
261300
local function _find()
262301
for _, toppath in ipairs(M.topmods[topmod] or {}) do

lua/lazy/core/util.lua

+11-15
Original file line numberDiff line numberDiff line change
@@ -176,25 +176,21 @@ function M.walk(path, fn)
176176
end
177177

178178
---@param modname string
179-
---@param root string
180179
---@param fn fun(modname:string, modpath:string)
181-
---@overload fun(modname:string, fn: fun(modname:string, modpath:string))
182-
function M.lsmod(modname, root, fn)
183-
if type(root) == "function" then
184-
fn = root
185-
root = vim.fn.stdpath("config") .. "/lua"
180+
function M.lsmod(modname, fn)
181+
local Cache = require("lazy.core.cache")
182+
local root, modpath = Cache.find_dir(modname)
183+
if not root then
184+
return
186185
end
187-
root = root .. "/" .. modname:gsub("%.", "/")
188-
if vim.loop.fs_stat(root .. ".lua") then
189-
fn(modname, root .. ".lua")
186+
187+
if modpath and vim.loop.fs_stat(modpath) then
188+
fn(modname, modpath)
190189
end
190+
191191
M.ls(root, function(path, name, type)
192-
if (type == "file" or type == "link") and name:sub(-4) == ".lua" then
193-
if name == "init.lua" then
194-
fn(modname, path)
195-
else
196-
fn(modname .. "." .. name:sub(1, -5), path)
197-
end
192+
if name ~= "init.lua" and (type == "file" or type == "link") and name:sub(-4) == ".lua" then
193+
fn(modname .. "." .. name:sub(1, -5), path)
198194
elseif type == "directory" and vim.loop.fs_stat(path .. "/init.lua") then
199195
fn(modname .. "." .. name, path .. "/init.lua")
200196
end

lua/lazy/manage/reloader.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function M.check(start)
5555
end
5656
end
5757

58-
Util.lsmod(Config.spec --[[@as string]], M.root, check)
58+
Util.lsmod(Config.spec --[[@as string]], check)
5959

6060
for file in pairs(M.files) do
6161
if not checked[file] then

tests/core/util_spec.lua

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
local Util = require("lazy.util")
2+
local Cache = require("lazy.core.cache")
3+
local Helpers = require("tests.helpers")
4+
5+
describe("util", function()
6+
before_each(function()
7+
Helpers.fs_rm("")
8+
end)
9+
10+
it("lsmod lists all mods in dir", function()
11+
local tests = {
12+
{
13+
files = { "lua/foo/one.lua", "lua/foo/two.lua", "lua/foo/init.lua" },
14+
mods = { "foo", "foo.one", "foo.two" },
15+
},
16+
{
17+
files = { "lua/foo/one.lua", "lua/foo/two.lua", "lua/foo.lua" },
18+
mods = { "foo", "foo.one", "foo.two" },
19+
},
20+
{
21+
files = { "lua/foo/one.lua", "lua/foo/two.lua" },
22+
mods = { "foo.one", "foo.two" },
23+
},
24+
}
25+
26+
vim.opt.rtp:append(Helpers.path(""))
27+
for _, test in ipairs(tests) do
28+
Cache.cache = {}
29+
table.sort(test.mods)
30+
Helpers.fs_rm("")
31+
Helpers.fs_create(test.files)
32+
local mods = {}
33+
Util.lsmod("foo", function(modname, modpath)
34+
mods[#mods + 1] = modname
35+
end)
36+
table.sort(mods)
37+
assert.same(test.mods, mods)
38+
end
39+
end)
40+
end)

tests/helpers.lua

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
local Util = require("lazy.util")
2+
3+
local M = {}
4+
5+
M.fs_root = vim.fn.fnamemodify("./.tests/fs", ":p")
6+
7+
function M.path(path)
8+
return Util.norm(M.fs_root .. "/" .. path)
9+
end
10+
11+
---@param files string[]
12+
function M.fs_create(files)
13+
---@type string[]
14+
local ret = {}
15+
16+
for _, file in ipairs(files) do
17+
ret[#ret + 1] = Util.norm(M.fs_root .. "/" .. file)
18+
local parent = vim.fn.fnamemodify(ret[#ret], ":h:p")
19+
vim.fn.mkdir(parent, "p")
20+
Util.write_file(ret[#ret], "")
21+
end
22+
return ret
23+
end
24+
25+
function M.fs_rm(dir)
26+
dir = Util.norm(M.fs_root .. dir)
27+
Util.walk(dir, function(path, _, type)
28+
if type == "directory" then
29+
vim.loop.fs_rmdir(path)
30+
else
31+
vim.loop.fs_unlink(path)
32+
end
33+
end)
34+
vim.loop.fs_rmdir(dir)
35+
end
36+
37+
return M

0 commit comments

Comments
 (0)