1
Jianw
9 天以前 70f29da38121b9a467841253e3268feb5df02902
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
local fs = require "luacheck.fs"
local utils = require "luacheck.utils"
 
local blacklist = utils.array_to_set({"spec", ".luarocks", "lua_modules", "test.lua", "tests.lua"})
 
-- This reimplements relevant parts of `luarocks.build.builtin.autodetect_modules`.
-- Autodetection works relatively to the directory containing the rockspec.
local function autodetect_modules(rockspec_path)
   rockspec_path = fs.normalize(rockspec_path)
   local base, rest = fs.split_base(rockspec_path)
   local project_dir = base .. (rest:match("^(.*)" .. utils.dir_sep .. ".*$") or "")
 
   if project_dir == "" then
      project_dir = "."
   end
 
   local module_dir = project_dir
 
   for _, module_subdir in ipairs({"src", "lua", "lib"}) do
      local full_module_dir = fs.join(project_dir, module_subdir)
 
      if fs.is_dir(full_module_dir) then
         module_dir = full_module_dir
         break
      end
   end
 
   local res = {}
 
   for _, file in ipairs((fs.extract_files(module_dir, "%.lua$"))) do
      -- Extract first part of the path from module_dir to the file, or file name itself.
      if not blacklist[file:match("^" .. module_dir:gsub("%p", "%%%0") .. "[\\/]*([^\\/]*)")] then
         table.insert(res, file)
      end
   end
 
   local bin_dir
 
   for _, bin_subdir in ipairs({"src/bin", "bin"}) do
      local full_bin_dir = fs.join(project_dir, bin_subdir)
 
      if fs.is_dir(full_bin_dir) then
         bin_dir = full_bin_dir
      end
   end
 
   if bin_dir then
      local iter, state, var = fs.dir_iter(bin_dir)
 
      if iter then
         for basename in iter, state, var do
            if basename:sub(-#".lua") == ".lua" then
               table.insert(res, fs.join(bin_dir, basename))
            end
         end
      end
   end
 
   return res
end
 
local function extract_lua_files(rockspec_path, rockspec)
   local build = rockspec.build
 
   if type(build) ~= "table" then
      return autodetect_modules(rockspec_path)
   end
 
   if not build.type or build.type == "builtin" or build.type == "module" then
      if not build.modules then
         return autodetect_modules(rockspec_path)
      end
   end
 
   local res = {}
 
   local function scan(t)
      if type(t) == "table" then
         for _, file in pairs(t) do
            if type(file) == "string" and file:sub(-#".lua") == ".lua" then
               table.insert(res, file)
            end
         end
      end
   end
 
   scan(build.modules)
 
   if type(build.install) == "table" then
      scan(build.install.lua)
      scan(build.install.bin)
   end
 
   table.sort(res)
   return res
end
 
-- Receives a name of a rockspec, returns list of related .lua files.
-- On error returns nil and "I/O", "syntax", or "runtime" and error message.
local function expand_rockspec(rockspec_path)
   local rockspec, err_type, err_msg = utils.load_config(rockspec_path)
 
   if not rockspec then
      return nil, err_type, err_msg
   end
 
   return extract_lua_files(rockspec_path, rockspec)
end
 
return expand_rockspec