Skip to content

Commit 740d8f5

Browse files
committed
Implement better error handling
1 parent 86b1cb2 commit 740d8f5

File tree

1 file changed

+42
-28
lines changed

1 file changed

+42
-28
lines changed

‎lua/paq.lua

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ local Filter = {
5656
to_reclone = function(p) return p.status == Status.TO_RECLONE end,
5757
}
5858

59+
local function file_write(path, flags, data)
60+
local err_msg = "Failed to %s '" .. path .. "'"
61+
local file = assert(uv.fs_open(path, flags, 0x1A4), err_msg:format("open"))
62+
assert(uv.fs_write(file, data), err_msg:format("write"))
63+
assert(uv.fs_close(file), err_msg:format("close"))
64+
end
65+
66+
local function file_read(path)
67+
local err_msg = "Failed to %s '" .. path .. "'"
68+
local file = assert(uv.fs_open(path, "r", 0x1A4), err_msg:format("open"))
69+
local stat = assert(uv.fs_stat(path), err_msg:format("get stats for"))
70+
local data = assert(uv.fs_read(file, stat.size, 0), err_msg:format("read"))
71+
assert(uv.fs_close(file), err_msg:format("close"))
72+
return data
73+
end
74+
5975
---@return Package
6076
local function find_unlisted()
6177
local unlisted = {}
@@ -78,13 +94,8 @@ end
7894
---@return string
7995
local function get_git_hash(dir)
8096
local first_line = function(path)
81-
local file = uv.fs_open(path, "r", 438)
82-
if file then
83-
local stat = assert(uv.fs_fstat(file))
84-
local data = assert(uv.fs_read(file, stat.size, 0))
85-
uv.fs_close(file)
86-
return vim.split(data, "\n")[1]
87-
end
97+
local data = file_read(path)
98+
return vim.split(data, "\n")[1]
8899
end
89100
local head_ref = first_line(vim.fs.joinpath(dir, ".git", "HEAD"))
90101
return head_ref and first_line(vim.fs.joinpath(dir, ".git", head_ref:sub(6, -1)))
@@ -119,15 +130,17 @@ end
119130
---@param prev_hash string
120131
---@param cur_hash string
121132
local function log_update_changes(pkg, prev_hash, cur_hash)
122-
local output = "\n\n" .. pkg.name .. " updated:\n"
123133
vim.system(
124134
{ "git", "log", "--pretty=format:* %s", ("%s..%s"):format(prev_hash, cur_hash) },
125135
{ cwd = pkg.dir, text = true },
126136
function(obj)
127-
assert(obj.code == 0, "Exited(" .. obj.code .. ")")
128-
local log = assert(uv.fs_open(Config.log, "a+", 0x1A4))
129-
uv.fs_write(log, output .. obj.stdout)
130-
uv.fs_close(log)
137+
if obj.code ~= 0 then
138+
local msg = "failed to execute git log into %q (code %d):\n%s"
139+
file_write(Config.log, "a+", msg:format(pkg.dir, obj.code, obj.stderr))
140+
return
141+
end
142+
local output = "\n\n%s updated:\n%s"
143+
file_write(Config.log, "a+", output:format(pkg.name, obj.stdout))
131144
end
132145
)
133146
end
@@ -171,25 +184,18 @@ local function lock_write()
171184
for p, _ in pairs(pkgs) do
172185
pkgs[p].build = nil
173186
end
174-
local file = uv.fs_open(Config.lock, "w", 438)
175-
if file then
176-
local ok, result = pcall(vim.json.encode, pkgs)
177-
if not ok then
178-
error(result)
179-
end
180-
assert(uv.fs_write(file, result))
181-
assert(uv.fs_close(file))
187+
local ok, result = pcall(vim.json.encode, pkgs)
188+
if not ok then
189+
error(result)
182190
end
191+
-- Ignore if fail
192+
pcall(file_write, Config.lock, "w", result)
183193
Lock = Packages
184194
end
185195

186196
local function lock_load()
187-
-- don't really know why 438 see ':h uv_fs_t'
188-
local file = uv.fs_open(Config.lock, "r", 438)
189-
if file then
190-
local stat = assert(uv.fs_fstat(file))
191-
local data = assert(uv.fs_read(file, stat.size, 0))
192-
assert(uv.fs_close(file))
197+
local exists, data = pcall(file_read, Config.lock)
198+
if exists then
193199
local ok, result = pcall(vim.json.decode, data)
194200
if ok then
195201
Lock = not vim.tbl_isempty(result) and result or Packages
@@ -253,7 +259,10 @@ local function pull(pkg, counter, build_queue)
253259
return
254260
end
255261
local cur_hash = get_git_hash(pkg.dir)
256-
if cur_hash == prev_hash then
262+
-- It can happen that the user has deleted manually a directory.
263+
-- Thus the pkg.hash is left blank and we need to update it.
264+
if cur_hash == prev_hash or prev_hash == "" then
265+
pkg.hash = cur_hash
257266
counter(pkg.name, Messages.update, "nop")
258267
return
259268
end
@@ -351,21 +360,26 @@ local function register(pkg)
351360
---@diagnostic disable-next-line: missing-fields
352361
pkg = { pkg }
353362
end
363+
354364
local url = pkg.url
355365
or (pkg[1]:match("^https?://") and pkg[1]) -- [1] is a URL
356366
or string.format(Config.url_format, pkg[1]) -- [1] is a repository name
367+
357368
local name = pkg.as or url:gsub("%.git$", ""):match("/([%w-_.]+)$") -- Infer name from `url`
358369
if not name then
359370
return vim.notify(" Paq: Failed to parse " .. vim.inspect(pkg), vim.log.levels.ERROR)
360371
end
361372
local opt = pkg.opt or Config.opt and pkg.opt == nil
362373
local dir = vim.fs.joinpath(Config.path, (opt and "opt" or "start"), name)
374+
local ok, hash = pcall(get_git_hash, dir)
375+
hash = ok and hash or ""
376+
363377
Packages[name] = {
364378
name = name,
365379
branch = pkg.branch,
366380
dir = dir,
367381
status = uv.fs_stat(dir) and Status.INSTALLED or Status.TO_INSTALL,
368-
hash = get_git_hash(dir),
382+
hash = hash,
369383
pin = pkg.pin,
370384
build = pkg.build,
371385
url = url,

0 commit comments

Comments
 (0)