authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-15 13:05:16+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-15 14:39:21+03:00
log262f4c7b3a850594a75ec154db2ba8d5f9f517ab
treeca0cb887465d5a332e288427e1851710fdcb570f
parent2b67f56c35d0a61be43f8ca23535096ae3ca4948

std.fs: remove `OpenDirOptions.iterate`


5 files changed, 88 insertions(+), 54 deletions(-)

lib/std/fs.zig+29-34
...@@ -956,14 +956,11 @@ pub const IterableDir = struct {...@@ -956,14 +956,11 @@ pub const IterableDir = struct {
956956
957pub const Dir = struct {957pub const Dir = struct {
958 fd: os.fd_t,958 fd: os.fd_t,
959 iterable: @TypeOf(iterable_safety) = iterable_safety,
960959
961 const iterable_safety = if (builtin.mode == .Debug) false else {};960 pub const iterate = @compileError("only 'IterableDir' can be iterated; 'IterableDir' can be obtained with 'openIterableDir'");
962961 pub const walk = @compileError("only 'IterableDir' can be walked; 'IterableDir' can be obtained with 'openIterableDir'");
963 pub const iterate = @compileError("only 'IterableDir' can be iterated; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'");962 pub const chmod = @compileError("only 'IterableDir' can have its mode changed; 'IterableDir' can be obtained with 'openIterableDir'");
964 pub const walk = @compileError("only 'IterableDir' can be walked; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'");963 pub const chown = @compileError("only 'IterableDir' can have its owner changed; 'IterableDir' can be obtained with 'openIterableDir'");
965 pub const chmod = @compileError("only 'IterableDir' can have its mode changed; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'");
966 pub const chown = @compileError("only 'IterableDir' can have its owner changed; 'IterableDir' can be obtained with 'openIterableDir' or by opening with 'iterate = true' and using 'intoIterable'");
967964
968 pub const OpenError = error{965 pub const OpenError = error{
969 FileNotFound,966 FileNotFound,
...@@ -1381,6 +1378,15 @@ pub const Dir = struct {...@@ -1381,6 +1378,15 @@ pub const Dir = struct {
1381 return self.openDir(sub_path, open_dir_options);1378 return self.openDir(sub_path, open_dir_options);
1382 }1379 }
13831380
1381 /// This function performs `makePath`, followed by `openIterableDir`.
1382 /// If supported by the OS, this operation is atomic. It is not atomic on
1383 /// all operating systems.
1384 pub fn makeOpenPathIterable(self: Dir, sub_path: []const u8, open_dir_options: OpenDirOptions) !IterableDir {
1385 // TODO improve this implementation on Windows; we can avoid 1 call to NtClose
1386 try self.makePath(sub_path);
1387 return self.openIterableDir(sub_path, open_dir_options);
1388 }
1389
1384 /// This function returns the canonicalized absolute pathname of1390 /// This function returns the canonicalized absolute pathname of
1385 /// `pathname` relative to this `Dir`. If `pathname` is absolute, ignores this1391 /// `pathname` relative to this `Dir`. If `pathname` is absolute, ignores this
1386 /// `Dir` handle and returns the canonicalized absolute pathname of `pathname`1392 /// `Dir` handle and returns the canonicalized absolute pathname of `pathname`
...@@ -1530,10 +1536,6 @@ pub const Dir = struct {...@@ -1530,10 +1536,6 @@ pub const Dir = struct {
1530 /// such operations are Illegal Behavior.1536 /// such operations are Illegal Behavior.
1531 access_sub_paths: bool = true,1537 access_sub_paths: bool = true,
15321538
1533 /// `true` means the opened directory can be scanned for the files and sub-directories
1534 /// of the result. It means the `iterate` function can be called.
1535 iterate: bool = false,
1536
1537 /// `true` means it won't dereference the symlinks.1539 /// `true` means it won't dereference the symlinks.
1538 no_follow: bool = false,1540 no_follow: bool = false,
1539 };1541 };
...@@ -1545,12 +1547,12 @@ pub const Dir = struct {...@@ -1545,12 +1547,12 @@ pub const Dir = struct {
1545 pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {1547 pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {
1546 if (builtin.os.tag == .windows) {1548 if (builtin.os.tag == .windows) {
1547 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);1549 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
1548 return self.openDirW(sub_path_w.span().ptr, args);1550 return self.openDirW(sub_path_w.span().ptr, args, false);
1549 } else if (builtin.os.tag == .wasi and !builtin.link_libc) {1551 } else if (builtin.os.tag == .wasi and !builtin.link_libc) {
1550 return self.openDirWasi(sub_path, args);1552 return self.openDirWasi(sub_path, args);
1551 } else {1553 } else {
1552 const sub_path_c = try os.toPosixPath(sub_path);1554 const sub_path_c = try os.toPosixPath(sub_path);
1553 return self.openDirZ(&sub_path_c, args);1555 return self.openDirZ(&sub_path_c, args, false);
1554 }1556 }
1555 }1557 }
15561558
...@@ -1559,19 +1561,15 @@ pub const Dir = struct {...@@ -1559,19 +1561,15 @@ pub const Dir = struct {
1559 ///1561 ///
1560 /// Asserts that the path parameter has no null bytes.1562 /// Asserts that the path parameter has no null bytes.
1561 pub fn openIterableDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!IterableDir {1563 pub fn openIterableDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!IterableDir {
1562 var adjusted_args = args;1564 if (builtin.os.tag == .windows) {
1563 adjusted_args.iterate = true;1565 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
1564 const new_dir = try self.openDir(sub_path, adjusted_args);1566 return IterableDir{ .dir = try self.openDirW(sub_path_w.span().ptr, args, true) };
1565 return IterableDir{ .dir = new_dir };1567 } else if (builtin.os.tag == .wasi and !builtin.link_libc) {
1566 }1568 return IterableDir{ .dir = try self.openDirWasi(sub_path, args) };
15671569 } else {
1568 /// Convert `self` into an iterable directory.1570 const sub_path_c = try os.toPosixPath(sub_path);
1569 /// Asserts that `self` was opened with `iterate = true`.1571 return IterableDir{ .dir = try self.openDirZ(&sub_path_c, args, true) };
1570 pub fn intoIterable(self: Dir) IterableDir {
1571 if (builtin.mode == .Debug) {
1572 assert(self.iterable);
1573 }1572 }
1574 return .{ .dir = self };
1575 }1573 }
15761574
1577 /// Same as `openDir` except only WASI.1575 /// Same as `openDir` except only WASI.
...@@ -1619,36 +1617,33 @@ pub const Dir = struct {...@@ -1619,36 +1617,33 @@ pub const Dir = struct {
1619 error.FileBusy => unreachable, // can't happen for directories1617 error.FileBusy => unreachable, // can't happen for directories
1620 else => |e| return e,1618 else => |e| return e,
1621 };1619 };
1622 return Dir{ .fd = fd, .iterable = if (builtin.mode == .Debug) args.iterate else {} };1620 return Dir{ .fd = fd };
1623 }1621 }
16241622
1625 /// Same as `openDir` except the parameter is null-terminated.1623 /// Same as `openDir` except the parameter is null-terminated.
1626 pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir {1624 pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions, iterable: bool) OpenError!Dir {
1627 if (builtin.os.tag == .windows) {1625 if (builtin.os.tag == .windows) {
1628 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);1626 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
1629 return self.openDirW(sub_path_w.span().ptr, args);1627 return self.openDirW(sub_path_w.span().ptr, args);
1630 }1628 }
1631 const symlink_flags: u32 = if (args.no_follow) os.O.NOFOLLOW else 0x0;1629 const symlink_flags: u32 = if (args.no_follow) os.O.NOFOLLOW else 0x0;
1632 if (!args.iterate) {1630 if (!iterable) {
1633 const O_PATH = if (@hasDecl(os.O, "PATH")) os.O.PATH else 0;1631 const O_PATH = if (@hasDecl(os.O, "PATH")) os.O.PATH else 0;
1634 return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | O_PATH | symlink_flags);1632 return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | O_PATH | symlink_flags);
1635 } else {1633 } else {
1636 var dir = try self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | symlink_flags);1634 return self.openDirFlagsZ(sub_path_c, os.O.DIRECTORY | os.O.RDONLY | os.O.CLOEXEC | symlink_flags);
1637 if (builtin.mode == .Debug) dir.iterable = true;
1638 return dir;
1639 }1635 }
1640 }1636 }
16411637
1642 /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed.1638 /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed.
1643 /// This function asserts the target OS is Windows.1639 /// This function asserts the target OS is Windows.
1644 pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) OpenError!Dir {1640 pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions, iterable: bool) OpenError!Dir {
1645 const w = os.windows;1641 const w = os.windows;
1646 // TODO remove some of these flags if args.access_sub_paths is false1642 // TODO remove some of these flags if args.access_sub_paths is false
1647 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |1643 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
1648 w.SYNCHRONIZE | w.FILE_TRAVERSE;1644 w.SYNCHRONIZE | w.FILE_TRAVERSE;
1649 const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags;1645 const flags: u32 = if (iterable) base_flags | w.FILE_LIST_DIRECTORY else base_flags;
1650 var dir = try self.openDirAccessMaskW(sub_path_w, flags, args.no_follow);1646 var dir = try self.openDirAccessMaskW(sub_path_w, flags, args.no_follow);
1651 if (builtin.mode == .Debug) dir.iterable = args.iterate;
1652 return dir;1647 return dir;
1653 }1648 }
16541649
lib/std/fs/test.zig+14-13
...@@ -11,6 +11,7 @@ const Dir = std.fs.Dir;...@@ -11,6 +11,7 @@ const Dir = std.fs.Dir;
11const IterableDir = std.fs.IterableDir;11const IterableDir = std.fs.IterableDir;
12const File = std.fs.File;12const File = std.fs.File;
13const tmpDir = testing.tmpDir;13const tmpDir = testing.tmpDir;
14const tmpIterableDir = testing.tmpIterableDir;
1415
15test "Dir.readLink" {16test "Dir.readLink" {
16 var tmp = tmpDir(.{});17 var tmp = tmpDir(.{});
...@@ -156,14 +157,14 @@ fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void...@@ -156,14 +157,14 @@ fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void
156}157}
157158
158test "Dir.Iterator" {159test "Dir.Iterator" {
159 var tmp_dir = tmpDir(.{ .iterate = true });160 var tmp_dir = tmpIterableDir(.{});
160 defer tmp_dir.cleanup();161 defer tmp_dir.cleanup();
161162
162 // First, create a couple of entries to iterate over.163 // First, create a couple of entries to iterate over.
163 const file = try tmp_dir.dir.createFile("some_file", .{});164 const file = try tmp_dir.iterable_dir.dir.createFile("some_file", .{});
164 file.close();165 file.close();
165166
166 try tmp_dir.dir.makeDir("some_dir");167 try tmp_dir.iterable_dir.dir.makeDir("some_dir");
167168
168 var arena = ArenaAllocator.init(testing.allocator);169 var arena = ArenaAllocator.init(testing.allocator);
169 defer arena.deinit();170 defer arena.deinit();
...@@ -172,7 +173,7 @@ test "Dir.Iterator" {...@@ -172,7 +173,7 @@ test "Dir.Iterator" {
172 var entries = std.ArrayList(IterableDir.Entry).init(allocator);173 var entries = std.ArrayList(IterableDir.Entry).init(allocator);
173174
174 // Create iterator.175 // Create iterator.
175 var iter = tmp_dir.dir.intoIterable().iterate();176 var iter = tmp_dir.iterable_dir.iterate();
176 while (try iter.next()) |entry| {177 while (try iter.next()) |entry| {
177 // We cannot just store `entry` as on Windows, we're re-using the name buffer178 // We cannot just store `entry` as on Windows, we're re-using the name buffer
178 // which means we'll actually share the `name` pointer between entries!179 // which means we'll actually share the `name` pointer between entries!
...@@ -186,14 +187,14 @@ test "Dir.Iterator" {...@@ -186,14 +187,14 @@ test "Dir.Iterator" {
186}187}
187188
188test "Dir.Iterator twice" {189test "Dir.Iterator twice" {
189 var tmp_dir = tmpDir(.{ .iterate = true });190 var tmp_dir = tmpIterableDir(.{});
190 defer tmp_dir.cleanup();191 defer tmp_dir.cleanup();
191192
192 // First, create a couple of entries to iterate over.193 // First, create a couple of entries to iterate over.
193 const file = try tmp_dir.dir.createFile("some_file", .{});194 const file = try tmp_dir.iterable_dir.dir.createFile("some_file", .{});
194 file.close();195 file.close();
195196
196 try tmp_dir.dir.makeDir("some_dir");197 try tmp_dir.iterable_dir.dir.makeDir("some_dir");
197198
198 var arena = ArenaAllocator.init(testing.allocator);199 var arena = ArenaAllocator.init(testing.allocator);
199 defer arena.deinit();200 defer arena.deinit();
...@@ -204,7 +205,7 @@ test "Dir.Iterator twice" {...@@ -204,7 +205,7 @@ test "Dir.Iterator twice" {
204 var entries = std.ArrayList(IterableDir.Entry).init(allocator);205 var entries = std.ArrayList(IterableDir.Entry).init(allocator);
205206
206 // Create iterator.207 // Create iterator.
207 var iter = tmp_dir.dir.intoIterable().iterate();208 var iter = tmp_dir.iterable_dir.iterate();
208 while (try iter.next()) |entry| {209 while (try iter.next()) |entry| {
209 // We cannot just store `entry` as on Windows, we're re-using the name buffer210 // We cannot just store `entry` as on Windows, we're re-using the name buffer
210 // which means we'll actually share the `name` pointer between entries!211 // which means we'll actually share the `name` pointer between entries!
...@@ -986,7 +987,7 @@ test "walker" {...@@ -986,7 +987,7 @@ test "walker" {
986 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;987 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
987 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");988 if (builtin.os.tag == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/");
988989
989 var tmp = tmpDir(.{ .iterate = true });990 var tmp = tmpIterableDir(.{});
990 defer tmp.cleanup();991 defer tmp.cleanup();
991992
992 // iteration order of walker is undefined, so need lookup maps to check against993 // iteration order of walker is undefined, so need lookup maps to check against
...@@ -1012,10 +1013,10 @@ test "walker" {...@@ -1012,10 +1013,10 @@ test "walker" {
1012 });1013 });
10131014
1014 for (expected_paths.kvs) |kv| {1015 for (expected_paths.kvs) |kv| {
1015 try tmp.dir.makePath(kv.key);1016 try tmp.iterable_dir.dir.makePath(kv.key);
1016 }1017 }
10171018
1018 var walker = try tmp.dir.intoIterable().walk(testing.allocator);1019 var walker = try tmp.iterable_dir.walk(testing.allocator);
1019 defer walker.deinit();1020 defer walker.deinit();
10201021
1021 var num_walked: usize = 0;1022 var num_walked: usize = 0;
...@@ -1126,7 +1127,7 @@ test "chmod" {...@@ -1126,7 +1127,7 @@ test "chmod" {
1126 defer iterable_dir.close();1127 defer iterable_dir.close();
11271128
1128 try iterable_dir.chmod(0o700);1129 try iterable_dir.chmod(0o700);
1129 try testing.expect((try iterable_dir.stat()).mode & 0o7777 == 0o700);1130 try testing.expect((try iterable_dir.dir.stat()).mode & 0o7777 == 0o700);
1130}1131}
11311132
1132test "chown" {1133test "chown" {
...@@ -1142,7 +1143,7 @@ test "chown" {...@@ -1142,7 +1143,7 @@ test "chown" {
11421143
1143 try tmp.dir.makeDir("test_dir");1144 try tmp.dir.makeDir("test_dir");
11441145
1145 var iterable_dir = try tmp.dir.openDir("test_dir", .{});1146 var iterable_dir = try tmp.dir.openIterableDir("test_dir", .{});
1146 defer iterable_dir.close();1147 defer iterable_dir.close();
1147 try iterable_dir.chown(null, null);1148 try iterable_dir.chown(null, null);
1148}1149}
lib/std/os.zig+2-2
...@@ -308,7 +308,7 @@ pub fn fchmod(fd: fd_t, mode: mode_t) FChmodError!void {...@@ -308,7 +308,7 @@ pub fn fchmod(fd: fd_t, mode: mode_t) FChmodError!void {
308 switch (system.getErrno(res)) {308 switch (system.getErrno(res)) {
309 .SUCCESS => return,309 .SUCCESS => return,
310 .INTR => continue,310 .INTR => continue,
311 .BADF => unreachable, // Can be reached if the fd refers to a directory opened without `OpenDirOptions{ .iterate = true }`311 .BADF => unreachable, // Can be reached if the fd refers to a non-iterable directory.
312312
313 .FAULT => unreachable,313 .FAULT => unreachable,
314 .INVAL => unreachable,314 .INVAL => unreachable,
...@@ -349,7 +349,7 @@ pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void {...@@ -349,7 +349,7 @@ pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void {
349 switch (system.getErrno(res)) {349 switch (system.getErrno(res)) {
350 .SUCCESS => return,350 .SUCCESS => return,
351 .INTR => continue,351 .INTR => continue,
352 .BADF => unreachable, // Can be reached if the fd refers to a directory opened without `OpenDirOptions{ .iterate = true }`352 .BADF => unreachable, // Can be reached if the fd refers to a non-iterable directory.
353353
354 .FAULT => unreachable,354 .FAULT => unreachable,
355 .INVAL => unreachable,355 .INVAL => unreachable,
lib/std/testing.zig+38
...@@ -363,6 +363,22 @@ pub const TmpDir = struct {...@@ -363,6 +363,22 @@ pub const TmpDir = struct {
363 }363 }
364};364};
365365
366pub const TmpIterableDir = struct {
367 iterable_dir: std.fs.IterableDir,
368 parent_dir: std.fs.Dir,
369 sub_path: [sub_path_len]u8,
370
371 const random_bytes_count = 12;
372 const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
373
374 pub fn cleanup(self: *TmpIterableDir) void {
375 self.iterable_dir.close();
376 self.parent_dir.deleteTree(&self.sub_path) catch {};
377 self.parent_dir.close();
378 self.* = undefined;
379 }
380};
381
366fn getCwdOrWasiPreopen() std.fs.Dir {382fn getCwdOrWasiPreopen() std.fs.Dir {
367 if (builtin.os.tag == .wasi and !builtin.link_libc) {383 if (builtin.os.tag == .wasi and !builtin.link_libc) {
368 var preopens = std.fs.wasi.PreopenList.init(allocator);384 var preopens = std.fs.wasi.PreopenList.init(allocator);
...@@ -400,6 +416,28 @@ pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir {...@@ -400,6 +416,28 @@ pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir {
400 };416 };
401}417}
402418
419pub fn tmpIterableDir(opts: std.fs.Dir.OpenDirOptions) TmpIterableDir {
420 var random_bytes: [TmpIterableDir.random_bytes_count]u8 = undefined;
421 std.crypto.random.bytes(&random_bytes);
422 var sub_path: [TmpIterableDir.sub_path_len]u8 = undefined;
423 _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
424
425 var cwd = getCwdOrWasiPreopen();
426 var cache_dir = cwd.makeOpenPath("zig-cache", .{}) catch
427 @panic("unable to make tmp dir for testing: unable to make and open zig-cache dir");
428 defer cache_dir.close();
429 var parent_dir = cache_dir.makeOpenPath("tmp", .{}) catch
430 @panic("unable to make tmp dir for testing: unable to make and open zig-cache/tmp dir");
431 var dir = parent_dir.makeOpenPathIterable(&sub_path, opts) catch
432 @panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
433
434 return .{
435 .iterable_dir = dir,
436 .parent_dir = parent_dir,
437 .sub_path = sub_path,
438 };
439}
440
403test "expectEqual nested array" {441test "expectEqual nested array" {
404 const a = [2][2]f32{442 const a = [2][2]f32{
405 [_]f32{ 1.0, 0.0 },443 [_]f32{ 1.0, 0.0 },
src/test.zig+5-5
...@@ -54,7 +54,7 @@ test {...@@ -54,7 +54,7 @@ test {
54 std.fs.path.dirname(@src().file).?, "..", "test", "cases",54 std.fs.path.dirname(@src().file).?, "..", "test", "cases",
55 });55 });
5656
57 var dir = try std.fs.cwd().openDir(dir_path, .{ .iterate = true });57 var dir = try std.fs.cwd().openIterableDir(dir_path, .{});
58 defer dir.close();58 defer dir.close();
5959
60 ctx.addTestCasesFromDir(dir);60 ctx.addTestCasesFromDir(dir);
...@@ -1080,7 +1080,7 @@ pub const TestContext = struct {...@@ -1080,7 +1080,7 @@ pub const TestContext = struct {
1080 /// Each file should include a test manifest as a contiguous block of comments at1080 /// Each file should include a test manifest as a contiguous block of comments at
1081 /// the end of the file. The first line should be the test type, followed by a set of1081 /// the end of the file. The first line should be the test type, followed by a set of
1082 /// key-value config values, followed by a blank line, then the expected output.1082 /// key-value config values, followed by a blank line, then the expected output.
1083 pub fn addTestCasesFromDir(ctx: *TestContext, dir: std.fs.Dir) void {1083 pub fn addTestCasesFromDir(ctx: *TestContext, dir: std.fs.IterableDir) void {
1084 var current_file: []const u8 = "none";1084 var current_file: []const u8 = "none";
1085 ctx.addTestCasesFromDirInner(dir, &current_file) catch |err| {1085 ctx.addTestCasesFromDirInner(dir, &current_file) catch |err| {
1086 std.debug.panic("test harness failed to process file '{s}': {s}\n", .{1086 std.debug.panic("test harness failed to process file '{s}': {s}\n", .{
...@@ -1091,12 +1091,12 @@ pub const TestContext = struct {...@@ -1091,12 +1091,12 @@ pub const TestContext = struct {
10911091
1092 fn addTestCasesFromDirInner(1092 fn addTestCasesFromDirInner(
1093 ctx: *TestContext,1093 ctx: *TestContext,
1094 dir: std.fs.Dir,1094 iterable_dir: std.fs.IterableDir,
1095 /// This is kept up to date with the currently being processed file so1095 /// This is kept up to date with the currently being processed file so
1096 /// that if any errors occur the caller knows it happened during this file.1096 /// that if any errors occur the caller knows it happened during this file.
1097 current_file: *[]const u8,1097 current_file: *[]const u8,
1098 ) !void {1098 ) !void {
1099 var it = try dir.intoIterable().walk(ctx.arena);1099 var it = try iterable_dir.walk(ctx.arena);
1100 var filenames = std.ArrayList([]const u8).init(ctx.arena);1100 var filenames = std.ArrayList([]const u8).init(ctx.arena);
11011101
1102 while (try it.next()) |entry| {1102 while (try it.next()) |entry| {
...@@ -1123,7 +1123,7 @@ pub const TestContext = struct {...@@ -1123,7 +1123,7 @@ pub const TestContext = struct {
1123 current_file.* = filename;1123 current_file.* = filename;
11241124
1125 const max_file_size = 10 * 1024 * 1024;1125 const max_file_size = 10 * 1024 * 1024;
1126 const src = try dir.readFileAllocOptions(ctx.arena, filename, max_file_size, null, 1, 0);1126 const src = try iterable_dir.dir.readFileAllocOptions(ctx.arena, filename, max_file_size, null, 1, 0);
11271127
1128 // Parse the manifest1128 // Parse the manifest
1129 var manifest = try TestManifest.parse(ctx.arena, src);1129 var manifest = try TestManifest.parse(ctx.arena, src);