• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 9304060604

30 May 2024 02:07PM UTC coverage: 74.124% (-0.6%) from 74.707%
9304060604

push

github

alerque
style: Reformat Lua with stylua

8104 of 11995 new or added lines in 184 files covered. (67.56%)

15 existing lines in 11 files now uncovered.

12444 of 16788 relevant lines covered (74.12%)

7175.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.99
/core/packagemanager.lua
1
local lfs = require("lfs")
181✔
2

3
local catalogueURL = "https://raw.githubusercontent.com/sile-typesetter/sile-packages/master/packages.lua"
181✔
4
local packageHome = tostring(SYSTEM_SILE_PATH) .. "/packagemanager/"
181✔
5
local catalogueHome = packageHome .. "catalogue.lua"
181✔
6
local installedCatalogue = packageHome .. "installed.lua"
181✔
7

8
local http = require("ssl.https")
181✔
9
local recentlyUpdated = false
181✔
10
local recentlyReloaded = false
181✔
11
local origcpath = package.cpath -- for idempotence
181✔
12
local origpath = package.path
181✔
13

14
SILE.PackageManager = {
181✔
15
   installed = {},
181✔
16
   Catalogue = {},
181✔
17
}
181✔
18

19
local _deprecated = function ()
NEW
20
   SU.deprecated(
×
21
      "SILE.PackageManager",
22
      nil,
23
      "0.13.2",
24
      "0.15.0",
NEW
25
      [[
×
26
  The built in SILE package manager has been completely deprecated. In its place
27
    SILE can now load classes, packages, and other resources installed via
28
    LuaRocks. Any SILE package may be published on LuaRocks.org or any private
29
    repository. Rocks may be installed to the host system root filesystem, a user
30
    directory, or a custom location. Please see the SILE manual for usage
31
    instructions. Package authors especially can review the template repository
32
    on GitHub for how to create a package.
NEW
33
  ]]
×
34
   )
35
end
36

37
local function loadInSandbox (untrusted_code)
NEW
38
   _deprecated()
×
39
   -- luacheck: ignore _ENV
NEW
40
   if _ENV then -- simple Lua 5.2 version check
×
NEW
41
      local env = {}
×
NEW
42
      local untrusted_function, message = load(untrusted_code, nil, "t", env)
×
NEW
43
      if not untrusted_function then
×
NEW
44
         return nil, message
×
45
      end
NEW
46
      return pcall(untrusted_function)
×
47
   else
NEW
48
      if untrusted_code:byte(1) == 27 then
×
NEW
49
         return nil, "binary bytecode prohibited"
×
50
      end
NEW
51
      local untrusted_function, message = load(untrusted_code)
×
NEW
52
      if not untrusted_function then
×
NEW
53
         return nil, message
×
54
      end
55
      -- luacheck: globals setfenv env
56
      -- (At least there is in Lua 5.1)
NEW
57
      setfenv(untrusted_function, env)
×
NEW
58
      return pcall(untrusted_function)
×
59
   end
60
end
61

62
local function dumpTable (tbl)
NEW
63
   _deprecated()
×
NEW
64
   if type(tbl) == "table" then
×
NEW
65
      local str = "{ "
×
NEW
66
      for k, v in pairs(tbl) do
×
NEW
67
         if type(k) ~= "number" then
×
NEW
68
            k = '"' .. k .. '"'
×
69
         end
NEW
70
         str = str .. "[" .. k .. "] = " .. dumpTable(v) .. ","
×
71
      end
NEW
72
      return str .. "} "
×
73
   else
74
      -- This only works because we are only storing strings!
NEW
75
      return '"' .. tostring(tbl) .. '"'
×
76
   end
77
end
78

79
local function fixupPaths ()
80
   local paths = ""
181✔
81
   local cpaths = ""
181✔
82
   for pkg, _ in pairs(SILE.PackageManager.installed) do
181✔
NEW
83
      _deprecated()
×
NEW
84
      paths = paths .. packageHome .. pkg .. "/?.lua;"
×
NEW
85
      cpaths = cpaths .. packageHome .. pkg .. "/?." .. SHARED_LIB_EXT .. ";"
×
86
   end
87
   if paths:len() >= 1 then
362✔
NEW
88
      package.path = paths .. ";" .. origpath
×
89
   end
90
   if cpaths:len() >= 1 then
362✔
NEW
91
      package.cpath = cpaths .. ";" .. origcpath
×
92
   end
93
end
94

95
local function saveInstalled ()
NEW
96
   _deprecated()
×
NEW
97
   local dump = dumpTable(SILE.PackageManager.installed)
×
NEW
98
   local file, err = io.open(installedCatalogue, "w")
×
NEW
99
   if err then
×
NEW
100
      SU.error("Could not write installed package list at" .. installedCatalogue .. ": " .. err)
×
101
   end
NEW
102
   file:write("return " .. dump)
×
NEW
103
   file:close()
×
NEW
104
   fixupPaths()
×
105
end
106

107
local function updateCatalogue ()
NEW
108
   if not lfs.attributes(packageHome) then
×
NEW
109
      if not lfs.mkdir(packageHome) then
×
NEW
110
         SU.error("Error making package manager home directory: " .. packageHome)
×
111
      end
112
   end
NEW
113
   print("Loading catalogue from " .. catalogueURL)
×
NEW
114
   local result, statuscode, _ = http.request(catalogueURL)
×
NEW
115
   if statuscode ~= 200 then
×
NEW
116
      SU.error("Could not load catalogue from " .. catalogueURL .. ": " .. statuscode)
×
117
   end
NEW
118
   local file, err = io.open(catalogueHome, "w")
×
NEW
119
   if err then
×
NEW
120
      SU.error("Could not write package catalogue at" .. catalogueHome .. ": " .. err)
×
121
   end
NEW
122
   print("Writing " .. #result .. " bytes to " .. catalogueHome)
×
NEW
123
   file:write(result)
×
NEW
124
   file:close()
×
NEW
125
   recentlyUpdated = true
×
NEW
126
   recentlyReloaded = false
×
127
end
128

129
local function loadInstalledCatalogue ()
130
   local file = io.open(installedCatalogue, "r")
181✔
131
   if file ~= nil then
181✔
NEW
132
      local contents = file:read("*all")
×
NEW
133
      local success, res = loadInSandbox(contents)
×
NEW
134
      if not success then
×
NEW
135
         SU.error("Error loading installed package list: " .. res)
×
136
      end
NEW
137
      SILE.PackageManager.installed = res
×
138
   end
139
end
140

141
local function reloadCatalogue ()
NEW
142
   local file = io.open(catalogueHome, "r")
×
NEW
143
   if file ~= nil then
×
NEW
144
      local contents = file:read("*all")
×
NEW
145
      local success, res = loadInSandbox(contents)
×
NEW
146
      if not success then
×
NEW
147
         SU.error("Error loading package catalogue: " .. res)
×
148
      end
NEW
149
      SILE.PackageManager.Catalogue = res
×
150
   end
NEW
151
   loadInstalledCatalogue()
×
NEW
152
   print("Package catalogue reloaded")
×
NEW
153
   recentlyReloaded = true
×
154
end
155

156
-- These functions are global so they can be used from the REPL
157
-- luacheck: ignore updatePackage
158
-- luacheck: ignore installPackage
159

160
function updatePackage (packageName, branch)
181✔
NEW
161
   _deprecated()
×
NEW
162
   local target = packageHome .. packageName
×
163
   -- Are we already there?
NEW
164
   if SILE.PackageManager.installed[packageName] == branch and branch ~= "master" then
×
NEW
165
      print("Nothing to do!")
×
NEW
166
      return true
×
167
   end
NEW
168
   local cwd = lfs.currentdir()
×
NEW
169
   local _, err = lfs.chdir(target)
×
NEW
170
   if err then
×
NEW
171
      SU.warn("Package directory " .. target .. " went away! Trying again...")
×
NEW
172
      SILE.PackageManager.installed[packageName] = nil
×
NEW
173
      saveInstalled()
×
NEW
174
      installPackage(packageName)
×
175
   end
176

NEW
177
   local ret = os.execute("git pull")
×
NEW
178
   if not ret then
×
NEW
179
      SU.error("Error updating repository for package " .. packageName .. ": " .. ret)
×
180
   end
NEW
181
   ret = os.execute("git checkout " .. branch)
×
NEW
182
   if not ret then
×
NEW
183
      SU.error("Error updating repository for package " .. packageName .. ": " .. ret)
×
184
   end
NEW
185
   lfs.chdir(cwd)
×
NEW
186
   SILE.PackageManager.installed[packageName] = branch
×
NEW
187
   saveInstalled()
×
188
end
189

190
function installPackage (packageName)
181✔
NEW
191
   _deprecated()
×
NEW
192
   if not recentlyUpdated then
×
NEW
193
      updateCatalogue()
×
194
   end
NEW
195
   if not recentlyReloaded then
×
NEW
196
      reloadCatalogue()
×
197
   end
NEW
198
   if not SILE.PackageManager.Catalogue[packageName] then
×
199
      -- Add support for URL-based package names later.
NEW
200
      SU.error("Can't install " .. packageName .. ": package not known")
×
201
   end
202

NEW
203
   local metadata = SILE.PackageManager.Catalogue[packageName]
×
204

205
   -- Check dependencies
NEW
206
   if metadata.depends then
×
NEW
207
      for _, pkg in ipairs(metadata.depends) do
×
NEW
208
         if not SILE.PackageManager.installed[pkg] then
×
NEW
209
            print(packageName .. " requires " .. pkg .. ", installing that...")
×
NEW
210
            installPackage(pkg)
×
211
         end
212
      end
213
   end
214

215
   -- Clone repo in temp directory
NEW
216
   if metadata.repository then
×
NEW
217
      local branch = metadata.version or "master"
×
NEW
218
      local target = packageHome .. packageName
×
NEW
219
      if lfs.attributes(target) then
×
NEW
220
         updatePackage(packageName, branch)
×
221
      else
NEW
222
         local ret = os.execute(
×
NEW
223
            "git clone -c advice.detachedHead=false -b " .. branch .. " " .. metadata.repository .. " " .. target
×
224
         )
NEW
225
         if not ret then -- This should return status code but it's returning true for me...
×
NEW
226
            SU.error("Error cloning repository for package " .. packageName .. ": " .. ret)
×
227
         end
228
      end
NEW
229
      SILE.PackageManager.installed[packageName] = branch
×
NEW
230
      saveInstalled()
×
231
   end
232
end
233

234
-- Set up the world
235
loadInstalledCatalogue()
181✔
236
fixupPaths()
362✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc