Skip to content

Commit d0398d5

Browse files
committed
refactor(fs): align error returns with Lua
1 parent b70ec6d commit d0398d5

3 files changed

Lines changed: 89 additions & 67 deletions

File tree

spec/fs_spec.lua

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ describe("mods.fs", function()
2323
end)
2424

2525
it(fmt("%s() returns nil and an error for a missing path", fname), function()
26-
local value, err = fs[fname]("__mods_missing_path__")
26+
local value, errmsg, errcode = fs[fname]("__mods_missing_path__")
2727
assert.is_nil(value)
28-
assert.is_string(err)
28+
assert.is_string(errmsg)
29+
assert.is_number(errcode)
2930
end)
3031
end
3132

@@ -36,9 +37,10 @@ describe("mods.fs", function()
3637
end)
3738

3839
it("returns nil and an error for a missing path", function()
39-
local attrs, err = fs.stat("__mods_missing_path__")
40+
local attrs, errmsg, errcode = fs.stat("__mods_missing_path__")
4041
assert.is_nil(attrs)
41-
assert.is_string(err)
42+
assert.is_string(errmsg)
43+
assert.is_number(errcode)
4244
end)
4345
end)
4446

@@ -49,9 +51,10 @@ describe("mods.fs", function()
4951
end)
5052

5153
it("returns nil and an error for a missing path", function()
52-
local attrs, err = fs.lstat("__mods_missing_path__")
54+
local attrs, errmsg, errcode = fs.lstat("__mods_missing_path__")
5355
assert.is_nil(attrs)
54-
assert.is_string(err)
56+
assert.is_string(errmsg)
57+
assert.is_number(errcode)
5558
end)
5659
end)
5760

@@ -70,10 +73,11 @@ describe("mods.fs", function()
7073
assert.is_true(os.remove(to))
7174
end)
7275

73-
it("returns nil and an error for a missing path", function()
74-
local ok, err = fs.rename("__mods_missing_path__", tmpname())
76+
it("fails with an error for a missing path", function()
77+
local ok, errmsg, errcode = fs.rename("__mods_missing_path__", tmpname())
7578
assert.is_nil(ok)
76-
assert.is_string(err)
79+
assert.is_string(errmsg)
80+
assert.is_number(errcode)
7781
end)
7882
end)
7983

@@ -85,11 +89,12 @@ describe("mods.fs", function()
8589
assert.is_true(os.remove(target))
8690
end)
8791

88-
it("returns false and an error when the parent directory does not exist", function()
92+
it("fails with an error when the parent directory does not exist", function()
8993
local target = path.join(tmpname(), "missing", "file.bin")
90-
local ok, err = fs.write_bytes(target, "abc")
91-
assert.is_false(ok)
92-
assert.is_string(err)
94+
local ok, errmsg, errcode = fs.write_bytes(target, "abc")
95+
assert.is_nil(ok)
96+
assert.is_string(errmsg)
97+
assert.is_number(errcode)
9398
end)
9499
end)
95100

@@ -101,11 +106,12 @@ describe("mods.fs", function()
101106
assert.is_true(os.remove(target))
102107
end)
103108

104-
it("returns false and an error when the parent directory does not exist", function()
109+
it("fails with an error when the parent directory does not exist", function()
105110
local target = path.join(tmpname(), "missing", "file.txt")
106-
local ok, err = fs.write_text(target, "abc")
107-
assert.is_false(ok)
108-
assert.is_string(err)
111+
local ok, errmsg, errcode = fs.write_text(target, "abc")
112+
assert.is_nil(ok)
113+
assert.is_string(errmsg)
114+
assert.is_number(errcode)
109115
end)
110116
end)
111117

@@ -117,10 +123,11 @@ describe("mods.fs", function()
117123
assert.is_true(os.remove(target))
118124
end)
119125

120-
it("returns nil and an error for a missing path", function()
121-
local body, err = fs.read_bytes("__mods_missing_path__")
126+
it("fails with an error for a missing path", function()
127+
local body, errmsg, errcode = fs.read_bytes("__mods_missing_path__")
122128
assert.is_nil(body)
123-
assert.is_string(err)
129+
assert.is_string(errmsg)
130+
assert.is_number(errcode)
124131
end)
125132
end)
126133

@@ -132,10 +139,11 @@ describe("mods.fs", function()
132139
assert.is_true(os.remove(target))
133140
end)
134141

135-
it("returns nil and an error for a missing path", function()
136-
local body, err = fs.read_text("__mods_missing_path__")
142+
it("fails with an error for a missing path", function()
143+
local body, errmsg, errcode = fs.read_text("__mods_missing_path__")
137144
assert.is_nil(body)
138-
assert.is_string(err)
145+
assert.is_string(errmsg)
146+
assert.is_number(errcode)
139147
end)
140148
end)
141149

@@ -167,9 +175,10 @@ describe("mods.fs", function()
167175
it("fails when the parent directory does not exist", function()
168176
local root = tmpname()
169177
local target = path.join(root, "missing", "file.txt")
170-
local ok, err = fs.touch(target)
171-
assert.is_false(ok)
172-
assert.is_string(err)
178+
local ok, errmsg, errcode = fs.touch(target)
179+
assert.is_nil(ok)
180+
assert.is_string(errmsg)
181+
assert.is_number(errcode)
173182
end)
174183

175184
if is_unix then
@@ -355,13 +364,15 @@ describe("mods.fs", function()
355364
assert.are_same({ false }, { fs.samefile(readme_file, spec_file) })
356365

357366
it("fails on missing path", function()
358-
local ok, err = fs.samefile(readme_file, "__mods_missing_path__")
367+
local ok, errmsg, errcode = fs.samefile(readme_file, "__mods_missing_path__")
359368
assert.is_nil(ok)
360-
assert.is_string(err)
369+
assert.is_string(errmsg)
370+
assert.is_number(errcode)
361371

362-
ok, err = fs.samefile("__mods_missing_path__", readme_file)
372+
ok, errmsg, errcode = fs.samefile("__mods_missing_path__", readme_file)
363373
assert.is_nil(ok)
364-
assert.is_string(err)
374+
assert.is_string(errmsg)
375+
assert.is_number(errcode)
365376
end)
366377

367378
if is_unix then

src/mods/fs.lua

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ end
3636

3737
---@param name LuaFileSystem.AttributeName
3838
local function get_attr(p, name)
39-
local value, err = lfs.attributes(p, name)
40-
if value == nil then
41-
return nil, err
39+
local value, errmsg, errcode = lfs.attributes(p, name)
40+
if not value then
41+
return nil, errmsg, errcode
4242
end
4343
return value
4444
end
4545

4646
---Read entire file contents using given mode.
47-
---@return string? body, string? err
47+
---@return string? body, string? err, integer? errcode
4848
local function read(p, mode)
49-
local f, err = open(p, mode)
49+
local f, errmsg, errcode = open(p, mode)
5050
if not f then
51-
return nil, err
51+
return nil, errmsg, errcode
5252
end
5353

5454
local body = f:read("*a")
@@ -58,15 +58,15 @@ end
5858

5959
---Write file contents using the given mode.
6060
local function write(p, data, mode)
61-
local f, err = open(p, mode)
61+
local f, errmsg, errcode = open(p, mode)
6262
if not f then
63-
return false, err
63+
return nil, errmsg, errcode
6464
end
6565

6666
local ok, write_err = f:write(data)
6767
f:close()
6868
if not ok then
69-
return false, write_err
69+
return nil, write_err
7070
end
7171

7272
return true
@@ -122,16 +122,16 @@ function M.samefile(path_a, path_b)
122122
assert_arg(1, path_a, "string")
123123
assert_arg(2, path_b, "string")
124124

125-
local a, b, err
125+
local a, b, errmsg, errcode
126126

127-
a, err = M.stat(path_a)
127+
a, errmsg, errcode = M.stat(path_a)
128128
if not a then
129-
return nil, err
129+
return nil, errmsg, errcode
130130
end
131131

132-
b, err = M.stat(path_b)
132+
b, errmsg, errcode = M.stat(path_b)
133133
if not b then
134-
return nil, err
134+
return nil, errmsg, errcode
135135
end
136136

137137
return a.dev == b.dev and a.ino == b.ino
@@ -142,14 +142,12 @@ function M.touch(p)
142142

143143
-- `lfs.touch` updates timestamps for existing files but does not create new ones.
144144
if M.exists(p) then
145-
local ok, err = lfs.touch(p)
146-
-- Normalize `lfs.touch` failure from `nil` to `false`.
147-
return ok == true, err
145+
return lfs.touch(p)
148146
end
149147

150-
local file, err = open(p, "ab")
148+
local file, errmsg, errcode = open(p, "ab")
151149
if not file then
152-
return false, err
150+
return nil, errmsg, errcode
153151
end
154152

155153
file:close()

types/fs.lua

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ local M = {}
1919
---
2020
---@param path string Input path.
2121
---@return string? body File contents read in binary mode, or `nil` on failure.
22-
---@return string? err Error message when the check fails.
22+
---@return string? errmsg Error message when the check fails.
23+
---@return integer? errcode OS error code when available.
2324
---@nodiscard
2425
function M.read_bytes(path) end
2526

@@ -32,7 +33,8 @@ function M.read_bytes(path) end
3233
---
3334
---@param path string Input path.
3435
---@return string? body File contents read in text mode, or `nil` on failure.
35-
---@return string? err Error message when the check fails.
36+
---@return string? errmsg Error message when the check fails.
37+
---@return integer? errcode OS error code when available.
3638
---@nodiscard
3739
function M.read_text(path) end
3840

@@ -49,8 +51,9 @@ function M.read_text(path) end
4951
---
5052
---@param path string Input path.
5153
---@param data string Input data.
52-
---@return boolean written `true` when writing succeeds, `false` on failure.
53-
---@return string? err Error message when the check fails.
54+
---@return true? written `true` when writing succeeds, or `nil` on failure.
55+
---@return string? errmsg Error message when the check fails.
56+
---@return integer? errcode OS error code when available.
5457
function M.write_bytes(path, data) end
5558

5659
---
@@ -62,8 +65,9 @@ function M.write_bytes(path, data) end
6265
---
6366
---@param path string Input path.
6467
---@param data string Input data.
65-
---@return boolean written `true` when writing succeeds, `false` on failure.
66-
---@return string? err Error message when the check fails.
68+
---@return true? written `true` when writing succeeds, or `nil` on failure.
69+
---@return string? errmsg Error message when the check fails.
70+
---@return integer? errcode OS error code when available.
6771
function M.write_text(path, data) end
6872

6973
---
@@ -74,8 +78,9 @@ function M.write_text(path, data) end
7478
---```
7579
---
7680
---@param path string Input path.
77-
---@return boolean touched `true` when the file exists after touch, `false` on failure.
78-
---@return string? err Error message when the check fails.
81+
---@return true? touched `true` when the file exists after touch, or `nil` on failure.
82+
---@return string? errmsg Error message when the check fails.
83+
---@return integer? errcode OS error code when available.
7984
function M.touch(path) end
8085

8186
---
@@ -90,8 +95,9 @@ function M.touch(path) end
9095
---
9196
---@param oldname string Existing path.
9297
---@param newname string Replacement path.
93-
---@return boolean renamed `true` when the rename succeeds, `false` on failure.
94-
---@return string? err Error message when the check fails.
98+
---@return true? renamed `true` when the rename succeeds, or `nil` on failure.
99+
---@return string? errmsg Error message when the check fails.
100+
---@return integer? errcode OS error code when available.
95101
function M.rename(oldname, newname) end
96102

97103
---
@@ -105,7 +111,7 @@ function M.rename(oldname, newname) end
105111
---@param path string Input path.
106112
---@param recursive? boolean Remove a directory tree recursively when `true`.
107113
---@return true? removed `true` when removal succeeds, or `nil` on failure.
108-
---@return string? err Error message when the check fails.
114+
---@return string? errmsg Error message when the check fails.
109115
---@return integer? errcode OS error code when available.
110116
function M.rm(path, recursive) end
111117

@@ -122,7 +128,8 @@ function M.rm(path, recursive) end
122128
---
123129
---@param path string Input path.
124130
---@return integer? size File size in bytes.
125-
---@return string? err Error message when the check fails.
131+
---@return string? errmsg Error message when the check fails.
132+
---@return integer? errcode OS error code when available.
126133
---@nodiscard
127134
function M.getsize(path) end
128135

@@ -135,7 +142,8 @@ function M.getsize(path) end
135142
---
136143
---@param path string Input path.
137144
---@return number? timestamp Access time (seconds since epoch).
138-
---@return string? err Error message when the check fails.
145+
---@return string? errmsg Error message when the check fails.
146+
---@return integer? errcode OS error code when available.
139147
---@nodiscard
140148
function M.getatime(path) end
141149

@@ -148,7 +156,8 @@ function M.getatime(path) end
148156
---
149157
---@param path string Input path.
150158
---@return number? timestamp Modification time (seconds since epoch).
151-
---@return string? err Error message when the check fails.
159+
---@return string? errmsg Error message when the check fails.
160+
---@return integer? errcode OS error code when available.
152161
---@nodiscard
153162
function M.getmtime(path) end
154163

@@ -161,7 +170,8 @@ function M.getmtime(path) end
161170
---
162171
---@param path string Input path.
163172
---@return number? timestamp Change time (seconds since epoch).
164-
---@return string? err Error message when the check fails.
173+
---@return string? errmsg Error message when the check fails.
174+
---@return integer? errcode OS error code when available.
165175
---@nodiscard
166176
function M.getctime(path) end
167177

@@ -174,7 +184,8 @@ function M.getctime(path) end
174184
---
175185
---@param path string Input path.
176186
---@return LuaFileSystem.Attributes? attrs Symlink-aware attributes, or `nil` on failure.
177-
---@return string? err Error message when the check fails.
187+
---@return string? errmsg Error message when the check fails.
188+
---@return integer? errcode OS error code when available.
178189
---@nodiscard
179190
function M.lstat(path) end
180191

@@ -187,7 +198,8 @@ function M.lstat(path) end
187198
---
188199
---@param path string Input path.
189200
---@return string|integer|LuaFileSystem.AttributeMode|LuaFileSystem.Attributes? attrs File attributes, or `nil` on failure.
190-
---@return string? err Error message when the check fails.
201+
---@return string? errmsg Error message when the check fails.
202+
---@return integer? errcode OS error code when available.
191203
---@nodiscard
192204
function M.stat(path) end
193205

@@ -201,7 +213,8 @@ function M.stat(path) end
201213
---@param path_a string Input path.
202214
---@param path_b string Input path.
203215
---@return boolean? isSameFile True when both paths refer to the same file.
204-
---@return string? err Error message when the check fails.
216+
---@return string? errmsg Error message when the check fails.
217+
---@return integer? errcode OS error code when available.
205218
---@nodiscard
206219
function M.samefile(path_a, path_b) end
207220

0 commit comments

Comments
 (0)