| ... | @@ -3,7 +3,6 @@ const native_os = builtin.os.tag; | ... | @@ -3,7 +3,6 @@ const native_os = builtin.os.tag; |
| 3 | | 3 | |
| 4 | const std = @import("../std.zig"); | 4 | const std = @import("../std.zig"); |
| 5 | const Io = std.Io; | 5 | const Io = std.Io; |
| 6 | const fs = std.fs; | | |
| 7 | const mem = std.mem; | 6 | const mem = std.mem; |
| 8 | const wasi = std.os.wasi; | 7 | const wasi = std.os.wasi; |
| 9 | const windows = std.os.windows; | 8 | const windows = std.os.windows; |
| ... | @@ -14,11 +13,11 @@ const SymLinkFlags = std.Io.Dir.SymLinkFlags; | ... | @@ -14,11 +13,11 @@ const SymLinkFlags = std.Io.Dir.SymLinkFlags; |
| 14 | | 13 | |
| 15 | const testing = std.testing; | 14 | const testing = std.testing; |
| 16 | const expect = std.testing.expect; | 15 | const expect = std.testing.expect; |
| 17 | const expectError = std.testing.expectError; | | |
| 18 | const expectEqual = std.testing.expectEqual; | 16 | const expectEqual = std.testing.expectEqual; |
| 19 | const tmpDir = std.testing.tmpDir; | | |
| 20 | const expectEqualStrings = std.testing.expectEqualStrings; | | |
| 21 | const expectEqualSlices = std.testing.expectEqualSlices; | 17 | const expectEqualSlices = std.testing.expectEqualSlices; |
| | 18 | const expectEqualStrings = std.testing.expectEqualStrings; |
| | 19 | const expectError = std.testing.expectError; |
| | 20 | const tmpDir = std.testing.tmpDir; |
| 22 | | 21 | |
| 23 | const PathType = enum { | 22 | const PathType = enum { |
| 24 | relative, | 23 | relative, |
| ... | @@ -33,7 +32,7 @@ const PathType = enum { | ... | @@ -33,7 +32,7 @@ const PathType = enum { |
| 33 | }; | 32 | }; |
| 34 | } | 33 | } |
| 35 | | 34 | |
| 36 | pub const TransformError = Io.Dir.RealPathError || error{OutOfMemory}; | 35 | pub const TransformError = Dir.RealPathError || error{OutOfMemory}; |
| 37 | pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; | 36 | pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; |
| 38 | | 37 | |
| 39 | pub fn getTransformFn(comptime path_type: PathType) TransformFn { | 38 | pub fn getTransformFn(comptime path_type: PathType) TransformFn { |
| ... | @@ -49,24 +48,24 @@ const PathType = enum { | ... | @@ -49,24 +48,24 @@ const PathType = enum { |
| 49 | fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { | 48 | fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { |
| 50 | // The final path may not actually exist which would cause realpath to fail. | 49 | // The final path may not actually exist which would cause realpath to fail. |
| 51 | // So instead, we get the path of the dir and join it with the relative path. | 50 | // So instead, we get the path of the dir and join it with the relative path. |
| 52 | var fd_path_buf: [fs.max_path_bytes]u8 = undefined; | 51 | var fd_path_buf: [Dir.max_path_bytes]u8 = undefined; |
| 53 | const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); | 52 | const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); |
| 54 | return fs.path.joinZ(allocator, &.{ dir_path, relative_path }); | 53 | return Dir.path.joinZ(allocator, &.{ dir_path, relative_path }); |
| 55 | } | 54 | } |
| 56 | }.transform, | 55 | }.transform, |
| 57 | .unc => return struct { | 56 | .unc => return struct { |
| 58 | fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { | 57 | fn transform(allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8 { |
| 59 | // Any drive absolute path (C:\foo) can be converted into a UNC path by | 58 | // Any drive absolute path (C:\foo) can be converted into a UNC path by |
| 60 | // using '127.0.0.1' as the server name and '<drive letter>$' as the share name. | 59 | // using '127.0.0.1' as the server name and '<drive letter>$' as the share name. |
| 61 | var fd_path_buf: [fs.max_path_bytes]u8 = undefined; | 60 | var fd_path_buf: [Dir.max_path_bytes]u8 = undefined; |
| 62 | const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); | 61 | const dir_path = try std.os.getFdPath(dir.handle, &fd_path_buf); |
| 63 | const windows_path_type = windows.getWin32PathType(u8, dir_path); | 62 | const windows_path_type = windows.getWin32PathType(u8, dir_path); |
| 64 | switch (windows_path_type) { | 63 | switch (windows_path_type) { |
| 65 | .unc_absolute => return fs.path.joinZ(allocator, &.{ dir_path, relative_path }), | 64 | .unc_absolute => return Dir.path.joinZ(allocator, &.{ dir_path, relative_path }), |
| 66 | .drive_absolute => { | 65 | .drive_absolute => { |
| 67 | // `C:\<...>` -> `\\127.0.0.1\C$\<...>` | 66 | // `C:\<...>` -> `\\127.0.0.1\C$\<...>` |
| 68 | const prepended = "\\\\127.0.0.1\\"; | 67 | const prepended = "\\\\127.0.0.1\\"; |
| 69 | var path = try fs.path.joinZ(allocator, &.{ prepended, dir_path, relative_path }); | 68 | var path = try Dir.path.joinZ(allocator, &.{ prepended, dir_path, relative_path }); |
| 70 | path[prepended.len + 1] = '$'; | 69 | path[prepended.len + 1] = '$'; |
| 71 | return path; | 70 | return path; |
| 72 | }, | 71 | }, |
| ... | @@ -84,7 +83,7 @@ const TestContext = struct { | ... | @@ -84,7 +83,7 @@ const TestContext = struct { |
| 84 | path_sep: u8, | 83 | path_sep: u8, |
| 85 | arena: ArenaAllocator, | 84 | arena: ArenaAllocator, |
| 86 | tmp: testing.TmpDir, | 85 | tmp: testing.TmpDir, |
| 87 | dir: Io.Dir, | 86 | dir: Dir, |
| 88 | transform_fn: *const PathType.TransformFn, | 87 | transform_fn: *const PathType.TransformFn, |
| 89 | | 88 | |
| 90 | pub fn init(path_type: PathType, path_sep: u8, allocator: mem.Allocator, transform_fn: *const PathType.TransformFn) TestContext { | 89 | pub fn init(path_type: PathType, path_sep: u8, allocator: mem.Allocator, transform_fn: *const PathType.TransformFn) TestContext { |
| ... | @@ -154,7 +153,7 @@ fn testWithAllSupportedPathTypes(test_func: anytype) !void { | ... | @@ -154,7 +153,7 @@ fn testWithAllSupportedPathTypes(test_func: anytype) !void { |
| 154 | | 153 | |
| 155 | fn testWithPathTypeIfSupported(comptime path_type: PathType, comptime path_sep: u8, test_func: anytype) !void { | 154 | fn testWithPathTypeIfSupported(comptime path_type: PathType, comptime path_sep: u8, test_func: anytype) !void { |
| 156 | if (!(comptime path_type.isSupported(builtin.os))) return; | 155 | if (!(comptime path_type.isSupported(builtin.os))) return; |
| 157 | if (!(comptime fs.path.isSep(path_sep))) return; | 156 | if (!(comptime Dir.path.isSep(path_sep))) return; |
| 158 | | 157 | |
| 159 | var ctx = TestContext.init(path_type, path_sep, testing.allocator, path_type.getTransformFn()); | 158 | var ctx = TestContext.init(path_type, path_sep, testing.allocator, path_type.getTransformFn()); |
| 160 | defer ctx.deinit(); | 159 | defer ctx.deinit(); |
| ... | @@ -174,8 +173,8 @@ fn setupSymlink(io: Io, dir: Dir, target: []const u8, link: []const u8, flags: S | ... | @@ -174,8 +173,8 @@ fn setupSymlink(io: Io, dir: Dir, target: []const u8, link: []const u8, flags: S |
| 174 | | 173 | |
| 175 | // For use in test setup. If the symlink creation fails on Windows with | 174 | // For use in test setup. If the symlink creation fails on Windows with |
| 176 | // AccessDenied, then make the test failure silent (it is not a Zig failure). | 175 | // AccessDenied, then make the test failure silent (it is not a Zig failure). |
| 177 | fn setupSymlinkAbsolute(target: []const u8, link: []const u8, flags: SymLinkFlags) !void { | 176 | fn setupSymlinkAbsolute(io: Io, target: []const u8, link: []const u8, flags: SymLinkFlags) !void { |
| 178 | return fs.symLinkAbsolute(target, link, flags) catch |err| switch (err) { | 177 | return Dir.symLinkAbsolute(io, target, link, flags) catch |err| switch (err) { |
| 179 | error.AccessDenied => if (native_os == .windows) return error.SkipZigTest else return err, | 178 | error.AccessDenied => if (native_os == .windows) return error.SkipZigTest else return err, |
| 180 | else => return err, | 179 | else => return err, |
| 181 | }; | 180 | }; |
| ... | @@ -211,7 +210,7 @@ test "Dir.readLink" { | ... | @@ -211,7 +210,7 @@ test "Dir.readLink" { |
| 211 | } | 210 | } |
| 212 | | 211 | |
| 213 | // test 3: relative path symlink | 212 | // test 3: relative path symlink |
| 214 | const parent_file = ".." ++ fs.path.sep_str ++ "target.txt"; | 213 | const parent_file = ".." ++ Dir.path.sep_str ++ "target.txt"; |
| 215 | const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); | 214 | const canonical_parent_file = try ctx.toCanonicalPathSep(parent_file); |
| 216 | var subdir = try ctx.dir.makeOpenPath(io, "subdir", .{}); | 215 | var subdir = try ctx.dir.makeOpenPath(io, "subdir", .{}); |
| 217 | defer subdir.close(io); | 216 | defer subdir.close(io); |
| ... | @@ -251,7 +250,7 @@ test "Dir.readLink on non-symlinks" { | ... | @@ -251,7 +250,7 @@ test "Dir.readLink on non-symlinks" { |
| 251 | } | 250 | } |
| 252 | | 251 | |
| 253 | fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { | 252 | fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { |
| 254 | var buffer: [fs.max_path_bytes]u8 = undefined; | 253 | var buffer: [Dir.max_path_bytes]u8 = undefined; |
| 255 | const actual = try dir.readLink(io, symlink_path, &buffer); | 254 | const actual = try dir.readLink(io, symlink_path, &buffer); |
| 256 | try expectEqualStrings(target_path, actual); | 255 | try expectEqualStrings(target_path, actual); |
| 257 | } | 256 | } |
| ... | @@ -267,9 +266,9 @@ fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, sy | ... | @@ -267,9 +266,9 @@ fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, sy |
| 267 | try expectEqualSlices(u16, target_path_w, actual); | 266 | try expectEqualSlices(u16, target_path_w, actual); |
| 268 | } | 267 | } |
| 269 | | 268 | |
| 270 | fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void { | 269 | fn testReadLinkAbsolute(io: Io, target_path: []const u8, symlink_path: []const u8) !void { |
| 271 | var buffer: [fs.max_path_bytes]u8 = undefined; | 270 | var buffer: [Dir.max_path_bytes]u8 = undefined; |
| 272 | const given = try fs.readLinkAbsolute(symlink_path, buffer[0..]); | 271 | const given = try Dir.readLinkAbsolute(io, symlink_path, buffer[0..]); |
| 273 | try expectEqualStrings(target_path, given); | 272 | try expectEqualStrings(target_path, given); |
| 274 | } | 273 | } |
| 275 | | 274 | |
| ... | @@ -309,7 +308,7 @@ test "openDir" { | ... | @@ -309,7 +308,7 @@ test "openDir" { |
| 309 | try ctx.dir.makeDir(io, subdir_path, .default_dir); | 308 | try ctx.dir.makeDir(io, subdir_path, .default_dir); |
| 310 | | 309 | |
| 311 | for ([_][]const u8{ "", ".", ".." }) |sub_path| { | 310 | for ([_][]const u8{ "", ".", ".." }) |sub_path| { |
| 312 | const dir_path = try fs.path.join(allocator, &.{ subdir_path, sub_path }); | 311 | const dir_path = try Dir.path.join(allocator, &.{ subdir_path, sub_path }); |
| 313 | var dir = try ctx.dir.openDir(io, dir_path, .{}); | 312 | var dir = try ctx.dir.openDir(io, dir_path, .{}); |
| 314 | defer dir.close(io); | 313 | defer dir.close(io); |
| 315 | } | 314 | } |
| ... | @@ -321,13 +320,16 @@ test "accessAbsolute" { | ... | @@ -321,13 +320,16 @@ test "accessAbsolute" { |
| 321 | if (native_os == .wasi) return error.SkipZigTest; | 320 | if (native_os == .wasi) return error.SkipZigTest; |
| 322 | if (native_os == .openbsd) return error.SkipZigTest; | 321 | if (native_os == .openbsd) return error.SkipZigTest; |
| 323 | | 322 | |
| | 323 | const io = testing.io; |
| | 324 | const gpa = testing.allocator; |
| | 325 | |
| 324 | var tmp = tmpDir(.{}); | 326 | var tmp = tmpDir(.{}); |
| 325 | defer tmp.cleanup(); | 327 | defer tmp.cleanup(); |
| 326 | | 328 | |
| 327 | const base_path = try tmp.dir.realpathAlloc(testing.allocator, "."); | 329 | const base_path = try tmp.dir.realPathAlloc(io, ".", gpa); |
| 328 | defer testing.allocator.free(base_path); | 330 | defer gpa.free(base_path); |
| 329 | | 331 | |
| 330 | try fs.accessAbsolute(base_path, .{}); | 332 | try Dir.accessAbsolute(io, base_path, .{}); |
| 331 | } | 333 | } |
| 332 | | 334 | |
| 333 | test "openDirAbsolute" { | 335 | test "openDirAbsolute" { |
| ... | @@ -335,6 +337,7 @@ test "openDirAbsolute" { | ... | @@ -335,6 +337,7 @@ test "openDirAbsolute" { |
| 335 | if (native_os == .openbsd) return error.SkipZigTest; | 337 | if (native_os == .openbsd) return error.SkipZigTest; |
| 336 | | 338 | |
| 337 | const io = testing.io; | 339 | const io = testing.io; |
| | 340 | const gpa = testing.allocator; |
| 338 | | 341 | |
| 339 | var tmp = tmpDir(.{}); | 342 | var tmp = tmpDir(.{}); |
| 340 | defer tmp.cleanup(); | 343 | defer tmp.cleanup(); |
| ... | @@ -342,8 +345,8 @@ test "openDirAbsolute" { | ... | @@ -342,8 +345,8 @@ test "openDirAbsolute" { |
| 342 | const tmp_ino = (try tmp.dir.stat(io)).inode; | 345 | const tmp_ino = (try tmp.dir.stat(io)).inode; |
| 343 | | 346 | |
| 344 | try tmp.dir.makeDir(io, "subdir", .default_dir); | 347 | try tmp.dir.makeDir(io, "subdir", .default_dir); |
| 345 | const sub_path = try tmp.dir.realpathAlloc(testing.allocator, "subdir"); | 348 | const sub_path = try tmp.dir.realPathAlloc(io, "subdir", gpa); |
| 346 | defer testing.allocator.free(sub_path); | 349 | defer gpa.free(sub_path); |
| 347 | | 350 | |
| 348 | // Can open sub_path | 351 | // Can open sub_path |
| 349 | var tmp_sub = try Dir.openDirAbsolute(io, sub_path, .{}); | 352 | var tmp_sub = try Dir.openDirAbsolute(io, sub_path, .{}); |
| ... | @@ -353,7 +356,7 @@ test "openDirAbsolute" { | ... | @@ -353,7 +356,7 @@ test "openDirAbsolute" { |
| 353 | | 356 | |
| 354 | { | 357 | { |
| 355 | // Can open sub_path + ".." | 358 | // Can open sub_path + ".." |
| 356 | const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".." }); | 359 | const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, ".." }); |
| 357 | defer testing.allocator.free(dir_path); | 360 | defer testing.allocator.free(dir_path); |
| 358 | | 361 | |
| 359 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); | 362 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); |
| ... | @@ -365,7 +368,7 @@ test "openDirAbsolute" { | ... | @@ -365,7 +368,7 @@ test "openDirAbsolute" { |
| 365 | | 368 | |
| 366 | { | 369 | { |
| 367 | // Can open sub_path + "." | 370 | // Can open sub_path + "." |
| 368 | const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, "." }); | 371 | const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, "." }); |
| 369 | defer testing.allocator.free(dir_path); | 372 | defer testing.allocator.free(dir_path); |
| 370 | | 373 | |
| 371 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); | 374 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); |
| ... | @@ -377,7 +380,7 @@ test "openDirAbsolute" { | ... | @@ -377,7 +380,7 @@ test "openDirAbsolute" { |
| 377 | | 380 | |
| 378 | { | 381 | { |
| 379 | // Can open subdir + "..", with some extra "." | 382 | // Can open subdir + "..", with some extra "." |
| 380 | const dir_path = try fs.path.join(testing.allocator, &.{ sub_path, ".", "..", "." }); | 383 | const dir_path = try Dir.path.join(testing.allocator, &.{ sub_path, ".", "..", "." }); |
| 381 | defer testing.allocator.free(dir_path); | 384 | defer testing.allocator.free(dir_path); |
| 382 | | 385 | |
| 383 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); | 386 | var dir = try Dir.openDirAbsolute(io, dir_path, .{}); |
| ... | @@ -391,7 +394,7 @@ test "openDirAbsolute" { | ... | @@ -391,7 +394,7 @@ test "openDirAbsolute" { |
| 391 | test "openDir cwd parent '..'" { | 394 | test "openDir cwd parent '..'" { |
| 392 | const io = testing.io; | 395 | const io = testing.io; |
| 393 | | 396 | |
| 394 | var dir = Io.Dir.cwd().openDir(io, "..", .{}) catch |err| { | 397 | var dir = Dir.cwd().openDir(io, "..", .{}) catch |err| { |
| 395 | if (native_os == .wasi and err == error.PermissionDenied) { | 398 | if (native_os == .wasi and err == error.PermissionDenied) { |
| 396 | return; // This is okay. WASI disallows escaping from the fs sandbox | 399 | return; // This is okay. WASI disallows escaping from the fs sandbox |
| 397 | } | 400 | } |
| ... | @@ -407,6 +410,7 @@ test "openDir non-cwd parent '..'" { | ... | @@ -407,6 +410,7 @@ test "openDir non-cwd parent '..'" { |
| 407 | } | 410 | } |
| 408 | | 411 | |
| 409 | const io = testing.io; | 412 | const io = testing.io; |
| | 413 | const gpa = testing.allocator; |
| 410 | | 414 | |
| 411 | var tmp = tmpDir(.{}); | 415 | var tmp = tmpDir(.{}); |
| 412 | defer tmp.cleanup(); | 416 | defer tmp.cleanup(); |
| ... | @@ -417,11 +421,11 @@ test "openDir non-cwd parent '..'" { | ... | @@ -417,11 +421,11 @@ test "openDir non-cwd parent '..'" { |
| 417 | var dir = try subdir.openDir(io, "..", .{}); | 421 | var dir = try subdir.openDir(io, "..", .{}); |
| 418 | defer dir.close(io); | 422 | defer dir.close(io); |
| 419 | | 423 | |
| 420 | const expected_path = try tmp.dir.realpathAlloc(testing.allocator, "."); | 424 | const expected_path = try tmp.dir.realPathAlloc(io, ".", gpa); |
| 421 | defer testing.allocator.free(expected_path); | 425 | defer gpa.free(expected_path); |
| 422 | | 426 | |
| 423 | const actual_path = try dir.realpathAlloc(testing.allocator, "."); | 427 | const actual_path = try dir.realPathAlloc(io, ".", gpa); |
| 424 | defer testing.allocator.free(actual_path); | 428 | defer gpa.free(actual_path); |
| 425 | | 429 | |
| 426 | try expectEqualStrings(expected_path, actual_path); | 430 | try expectEqualStrings(expected_path, actual_path); |
| 427 | } | 431 | } |
| ... | @@ -440,27 +444,27 @@ test "readLinkAbsolute" { | ... | @@ -440,27 +444,27 @@ test "readLinkAbsolute" { |
| 440 | try tmp.dir.makeDir(io, "subdir", .default_dir); | 444 | try tmp.dir.makeDir(io, "subdir", .default_dir); |
| 441 | | 445 | |
| 442 | // Get base abs path | 446 | // Get base abs path |
| 443 | var arena = ArenaAllocator.init(testing.allocator); | 447 | var arena_allocator = ArenaAllocator.init(testing.allocator); |
| 444 | defer arena.deinit(); | 448 | defer arena_allocator.deinit(); |
| 445 | const allocator = arena.allocator(); | 449 | const arena = arena_allocator.allocator(); |
| 446 | | 450 | |
| 447 | const base_path = try tmp.dir.realpathAlloc(allocator, "."); | 451 | const base_path = try tmp.dir.realPathAlloc(io, ".", arena); |
| 448 | | 452 | |
| 449 | { | 453 | { |
| 450 | const target_path = try fs.path.join(allocator, &.{ base_path, "file.txt" }); | 454 | const target_path = try Dir.path.join(arena, &.{ base_path, "file.txt" }); |
| 451 | const symlink_path = try fs.path.join(allocator, &.{ base_path, "symlink1" }); | 455 | const symlink_path = try Dir.path.join(arena, &.{ base_path, "symlink1" }); |
| 452 | | 456 | |
| 453 | // Create symbolic link by path | 457 | // Create symbolic link by path |
| 454 | try setupSymlinkAbsolute(target_path, symlink_path, .{}); | 458 | try setupSymlinkAbsolute(io, target_path, symlink_path, .{}); |
| 455 | try testReadLinkAbsolute(target_path, symlink_path); | 459 | try testReadLinkAbsolute(io, target_path, symlink_path); |
| 456 | } | 460 | } |
| 457 | { | 461 | { |
| 458 | const target_path = try fs.path.join(allocator, &.{ base_path, "subdir" }); | 462 | const target_path = try Dir.path.join(arena, &.{ base_path, "subdir" }); |
| 459 | const symlink_path = try fs.path.join(allocator, &.{ base_path, "symlink2" }); | 463 | const symlink_path = try Dir.path.join(arena, &.{ base_path, "symlink2" }); |
| 460 | | 464 | |
| 461 | // Create symbolic link to a directory by path | 465 | // Create symbolic link to a directory by path |
| 462 | try setupSymlinkAbsolute(target_path, symlink_path, .{ .is_directory = true }); | 466 | try setupSymlinkAbsolute(io, target_path, symlink_path, .{ .is_directory = true }); |
| 463 | try testReadLinkAbsolute(target_path, symlink_path); | 467 | try testReadLinkAbsolute(io, target_path, symlink_path); |
| 464 | } | 468 | } |
| 465 | } | 469 | } |
| 466 | | 470 | |
| ... | @@ -492,8 +496,8 @@ test "Dir.Iterator" { | ... | @@ -492,8 +496,8 @@ test "Dir.Iterator" { |
| 492 | } | 496 | } |
| 493 | | 497 | |
| 494 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 498 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 495 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 499 | try expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 496 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 500 | try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 497 | } | 501 | } |
| 498 | | 502 | |
| 499 | test "Dir.Iterator many entries" { | 503 | test "Dir.Iterator many entries" { |
| ... | @@ -529,7 +533,7 @@ test "Dir.Iterator many entries" { | ... | @@ -529,7 +533,7 @@ test "Dir.Iterator many entries" { |
| 529 | i = 0; | 533 | i = 0; |
| 530 | while (i < num) : (i += 1) { | 534 | while (i < num) : (i += 1) { |
| 531 | const name = try std.fmt.bufPrint(&buf, "{}", .{i}); | 535 | const name = try std.fmt.bufPrint(&buf, "{}", .{i}); |
| 532 | try testing.expect(contains(&entries, .{ .name = name, .kind = .file })); | 536 | try expect(contains(&entries, .{ .name = name, .kind = .file })); |
| 533 | } | 537 | } |
| 534 | } | 538 | } |
| 535 | | 539 | |
| ... | @@ -563,8 +567,8 @@ test "Dir.Iterator twice" { | ... | @@ -563,8 +567,8 @@ test "Dir.Iterator twice" { |
| 563 | } | 567 | } |
| 564 | | 568 | |
| 565 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 569 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 566 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 570 | try expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 567 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 571 | try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 568 | } | 572 | } |
| 569 | } | 573 | } |
| 570 | | 574 | |
| ... | @@ -599,8 +603,8 @@ test "Dir.Iterator reset" { | ... | @@ -599,8 +603,8 @@ test "Dir.Iterator reset" { |
| 599 | } | 603 | } |
| 600 | | 604 | |
| 601 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 605 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 602 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 606 | try expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 603 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 607 | try expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 604 | | 608 | |
| 605 | iter.reset(); | 609 | iter.reset(); |
| 606 | } | 610 | } |
| ... | @@ -619,7 +623,7 @@ test "Dir.Iterator but dir is deleted during iteration" { | ... | @@ -619,7 +623,7 @@ test "Dir.Iterator but dir is deleted during iteration" { |
| 619 | var iterator = subdir.iterate(); | 623 | var iterator = subdir.iterate(); |
| 620 | | 624 | |
| 621 | // Create something to iterate over within the subdir | 625 | // Create something to iterate over within the subdir |
| 622 | try tmp.dir.makePath(io, "subdir" ++ fs.path.sep_str ++ "b"); | 626 | try tmp.dir.makePath(io, "subdir" ++ Dir.path.sep_str ++ "b"); |
| 623 | | 627 | |
| 624 | // Then, before iterating, delete the directory that we're iterating. | 628 | // Then, before iterating, delete the directory that we're iterating. |
| 625 | // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. | 629 | // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. |
| ... | @@ -629,7 +633,7 @@ test "Dir.Iterator but dir is deleted during iteration" { | ... | @@ -629,7 +633,7 @@ test "Dir.Iterator but dir is deleted during iteration" { |
| 629 | | 633 | |
| 630 | // Now, when we try to iterate, the next call should return null immediately. | 634 | // Now, when we try to iterate, the next call should return null immediately. |
| 631 | const entry = try iterator.next(); | 635 | const entry = try iterator.next(); |
| 632 | try std.testing.expect(entry == null); | 636 | try std.expect(entry == null); |
| 633 | | 637 | |
| 634 | // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` | 638 | // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` |
| 635 | if (native_os == .linux) { | 639 | if (native_os == .linux) { |
| ... | @@ -657,25 +661,25 @@ test "Dir.realpath smoke test" { | ... | @@ -657,25 +661,25 @@ test "Dir.realpath smoke test" { |
| 657 | const allocator = ctx.arena.allocator(); | 661 | const allocator = ctx.arena.allocator(); |
| 658 | const test_file_path = try ctx.transformPath("test_file"); | 662 | const test_file_path = try ctx.transformPath("test_file"); |
| 659 | const test_dir_path = try ctx.transformPath("test_dir"); | 663 | const test_dir_path = try ctx.transformPath("test_dir"); |
| 660 | var buf: [fs.max_path_bytes]u8 = undefined; | 664 | var buf: [Dir.max_path_bytes]u8 = undefined; |
| 661 | | 665 | |
| 662 | // FileNotFound if the path doesn't exist | 666 | // FileNotFound if the path doesn't exist |
| 663 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); | 667 | try expectError(error.FileNotFound, ctx.dir.realPathAlloc(io, test_file_path, allocator)); |
| 664 | try expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); | 668 | try expectError(error.FileNotFound, ctx.dir.realPath(io, test_file_path, &buf)); |
| 665 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); | 669 | try expectError(error.FileNotFound, ctx.dir.realPathAlloc(io, test_dir_path, allocator)); |
| 666 | try expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); | 670 | try expectError(error.FileNotFound, ctx.dir.realPath(io, test_dir_path, &buf)); |
| 667 | | 671 | |
| 668 | // Now create the file and dir | 672 | // Now create the file and dir |
| 669 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); | 673 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); |
| 670 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); | 674 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); |
| 671 | | 675 | |
| 672 | const base_path = try ctx.transformPath("."); | 676 | const base_path = try ctx.transformPath("."); |
| 673 | const base_realpath = try ctx.dir.realpathAlloc(allocator, base_path); | 677 | const base_realpath = try ctx.dir.realPathAlloc(io, base_path, allocator); |
| 674 | const expected_file_path = try fs.path.join( | 678 | const expected_file_path = try Dir.path.join( |
| 675 | allocator, | 679 | allocator, |
| 676 | &.{ base_realpath, "test_file" }, | 680 | &.{ base_realpath, "test_file" }, |
| 677 | ); | 681 | ); |
| 678 | const expected_dir_path = try fs.path.join( | 682 | const expected_dir_path = try Dir.path.join( |
| 679 | allocator, | 683 | allocator, |
| 680 | &.{ base_realpath, "test_dir" }, | 684 | &.{ base_realpath, "test_dir" }, |
| 681 | ); | 685 | ); |
| ... | @@ -691,10 +695,10 @@ test "Dir.realpath smoke test" { | ... | @@ -691,10 +695,10 @@ test "Dir.realpath smoke test" { |
| 691 | | 695 | |
| 692 | // Next, test alloc version | 696 | // Next, test alloc version |
| 693 | { | 697 | { |
| 694 | const file_path = try ctx.dir.realpathAlloc(allocator, test_file_path); | 698 | const file_path = try ctx.dir.realPathAlloc(io, test_file_path, allocator); |
| 695 | try expectEqualStrings(expected_file_path, file_path); | 699 | try expectEqualStrings(expected_file_path, file_path); |
| 696 | | 700 | |
| 697 | const dir_path = try ctx.dir.realpathAlloc(allocator, test_dir_path); | 701 | const dir_path = try ctx.dir.realPathAlloc(io, test_dir_path, allocator); |
| 698 | try expectEqualStrings(expected_dir_path, dir_path); | 702 | try expectEqualStrings(expected_dir_path, dir_path); |
| 699 | } | 703 | } |
| 700 | } | 704 | } |
| ... | @@ -715,7 +719,7 @@ test "readFileAlloc" { | ... | @@ -715,7 +719,7 @@ test "readFileAlloc" { |
| 715 | try expectEqualStrings("", buf1); | 719 | try expectEqualStrings("", buf1); |
| 716 | | 720 | |
| 717 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; | 721 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; |
| 718 | try file.writeAll(write_buf); | 722 | try file.writeStreamingAll(io, write_buf); |
| 719 | | 723 | |
| 720 | { | 724 | { |
| 721 | // max_bytes > file_size | 725 | // max_bytes > file_size |
| ... | @@ -779,7 +783,7 @@ test "statFile on dangling symlink" { | ... | @@ -779,7 +783,7 @@ test "statFile on dangling symlink" { |
| 779 | fn impl(ctx: *TestContext) !void { | 783 | fn impl(ctx: *TestContext) !void { |
| 780 | const io = ctx.io; | 784 | const io = ctx.io; |
| 781 | const symlink_name = try ctx.transformPath("dangling-symlink"); | 785 | const symlink_name = try ctx.transformPath("dangling-symlink"); |
| 782 | const symlink_target = "." ++ fs.path.sep_str ++ "doesnotexist"; | 786 | const symlink_target = "." ++ Dir.path.sep_str ++ "doesnotexist"; |
| 783 | | 787 | |
| 784 | try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); | 788 | try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); |
| 785 | | 789 | |
| ... | @@ -803,8 +807,8 @@ test "directory operations on files" { | ... | @@ -803,8 +807,8 @@ test "directory operations on files" { |
| 803 | try expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); | 807 | try expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); |
| 804 | | 808 | |
| 805 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { | 809 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 806 | try expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); | 810 | try expectError(error.PathAlreadyExists, Dir.makeDirAbsolute(io, test_file_name)); |
| 807 | try expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); | 811 | try expectError(error.NotDir, Dir.deleteDirAbsolute(io, test_file_name)); |
| 808 | } | 812 | } |
| 809 | | 813 | |
| 810 | // ensure the file still exists and is a file as a sanity check | 814 | // ensure the file still exists and is a file as a sanity check |
| ... | @@ -862,8 +866,8 @@ test "file operations on directories" { | ... | @@ -862,8 +866,8 @@ test "file operations on directories" { |
| 862 | try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = false, .mode = .read_only })); | 866 | try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = false, .mode = .read_only })); |
| 863 | | 867 | |
| 864 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { | 868 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 865 | try expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); | 869 | try expectError(error.IsDir, Dir.createFileAbsolute(io, test_dir_name, .{})); |
| 866 | try expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); | 870 | try expectError(error.IsDir, Dir.deleteFileAbsolute(io, test_dir_name)); |
| 867 | } | 871 | } |
| 868 | | 872 | |
| 869 | // ensure the directory still exists as a sanity check | 873 | // ensure the directory still exists as a sanity check |
| ... | @@ -892,7 +896,7 @@ test "deleteDir" { | ... | @@ -892,7 +896,7 @@ test "deleteDir" { |
| 892 | fn impl(ctx: *TestContext) !void { | 896 | fn impl(ctx: *TestContext) !void { |
| 893 | const io = ctx.io; | 897 | const io = ctx.io; |
| 894 | const test_dir_path = try ctx.transformPath("test_dir"); | 898 | const test_dir_path = try ctx.transformPath("test_dir"); |
| 895 | const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); | 899 | const test_file_path = try ctx.transformPath("test_dir" ++ Dir.path.sep_str ++ "test_file"); |
| 896 | | 900 | |
| 897 | // deleting a non-existent directory | 901 | // deleting a non-existent directory |
| 898 | try expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path)); | 902 | try expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path)); |
| ... | @@ -1097,11 +1101,12 @@ test "renameAbsolute" { | ... | @@ -1097,11 +1101,12 @@ test "renameAbsolute" { |
| 1097 | defer arena.deinit(); | 1101 | defer arena.deinit(); |
| 1098 | const allocator = arena.allocator(); | 1102 | const allocator = arena.allocator(); |
| 1099 | | 1103 | |
| 1100 | const base_path = try tmp_dir.dir.realpathAlloc(allocator, "."); | 1104 | const base_path = try tmp_dir.dir.realPathAlloc(io, ".", allocator); |
| 1101 | | 1105 | |
| 1102 | try expectError(error.FileNotFound, fs.renameAbsolute( | 1106 | try expectError(error.FileNotFound, Dir.renameAbsolute( |
| 1103 | try fs.path.join(allocator, &.{ base_path, "missing_file_name" }), | 1107 | io, |
| 1104 | try fs.path.join(allocator, &.{ base_path, "something_else" }), | 1108 | try Dir.path.join(allocator, &.{ base_path, "missing_file_name" }), |
| | 1109 | try Dir.path.join(allocator, &.{ base_path, "something_else" }), |
| 1105 | )); | 1110 | )); |
| 1106 | | 1111 | |
| 1107 | // Renaming files | 1112 | // Renaming files |
| ... | @@ -1109,9 +1114,10 @@ test "renameAbsolute" { | ... | @@ -1109,9 +1114,10 @@ test "renameAbsolute" { |
| 1109 | const renamed_test_file_name = "test_file_renamed"; | 1114 | const renamed_test_file_name = "test_file_renamed"; |
| 1110 | var file = try tmp_dir.dir.createFile(io, test_file_name, .{ .read = true }); | 1115 | var file = try tmp_dir.dir.createFile(io, test_file_name, .{ .read = true }); |
| 1111 | file.close(io); | 1116 | file.close(io); |
| 1112 | try fs.renameAbsolute( | 1117 | try Dir.renameAbsolute( |
| 1113 | try fs.path.join(allocator, &.{ base_path, test_file_name }), | 1118 | io, |
| 1114 | try fs.path.join(allocator, &.{ base_path, renamed_test_file_name }), | 1119 | try Dir.path.join(allocator, &.{ base_path, test_file_name }), |
| | 1120 | try Dir.path.join(allocator, &.{ base_path, renamed_test_file_name }), |
| 1115 | ); | 1121 | ); |
| 1116 | | 1122 | |
| 1117 | // ensure the file was renamed | 1123 | // ensure the file was renamed |
| ... | @@ -1125,9 +1131,10 @@ test "renameAbsolute" { | ... | @@ -1125,9 +1131,10 @@ test "renameAbsolute" { |
| 1125 | const test_dir_name = "test_dir"; | 1131 | const test_dir_name = "test_dir"; |
| 1126 | const renamed_test_dir_name = "test_dir_renamed"; | 1132 | const renamed_test_dir_name = "test_dir_renamed"; |
| 1127 | try tmp_dir.dir.makeDir(io, test_dir_name, .default_dir); | 1133 | try tmp_dir.dir.makeDir(io, test_dir_name, .default_dir); |
| 1128 | try fs.renameAbsolute( | 1134 | try Dir.renameAbsolute( |
| 1129 | try fs.path.join(allocator, &.{ base_path, test_dir_name }), | 1135 | io, |
| 1130 | try fs.path.join(allocator, &.{ base_path, renamed_test_dir_name }), | 1136 | try Dir.path.join(allocator, &.{ base_path, test_dir_name }), |
| | 1137 | try Dir.path.join(allocator, &.{ base_path, renamed_test_dir_name }), |
| 1131 | ); | 1138 | ); |
| 1132 | | 1139 | |
| 1133 | // ensure the directory was renamed | 1140 | // ensure the directory was renamed |
| ... | @@ -1149,7 +1156,7 @@ test "executablePath" { | ... | @@ -1149,7 +1156,7 @@ test "executablePath" { |
| 1149 | if (native_os == .wasi) return error.SkipZigTest; | 1156 | if (native_os == .wasi) return error.SkipZigTest; |
| 1150 | | 1157 | |
| 1151 | const io = testing.io; | 1158 | const io = testing.io; |
| 1152 | var buf: [fs.max_path_bytes]u8 = undefined; | 1159 | var buf: [Dir.max_path_bytes]u8 = undefined; |
| 1153 | const buf_self_exe_path = try std.process.executablePath(io, &buf); | 1160 | const buf_self_exe_path = try std.process.executablePath(io, &buf); |
| 1154 | const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); | 1161 | const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); |
| 1155 | defer testing.allocator.free(alloc_self_exe_path); | 1162 | defer testing.allocator.free(alloc_self_exe_path); |
| ... | @@ -1206,13 +1213,13 @@ test "makePath, put some files in it, deleteTree" { | ... | @@ -1206,13 +1213,13 @@ test "makePath, put some files in it, deleteTree" { |
| 1206 | const allocator = ctx.arena.allocator(); | 1213 | const allocator = ctx.arena.allocator(); |
| 1207 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1214 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1208 | | 1215 | |
| 1209 | try ctx.dir.makePath(io, try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); | 1216 | try ctx.dir.makePath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); |
| 1210 | try ctx.dir.writeFile(io, .{ | 1217 | try ctx.dir.writeFile(io, .{ |
| 1211 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), | 1218 | .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), |
| 1212 | .data = "nonsense", | 1219 | .data = "nonsense", |
| 1213 | }); | 1220 | }); |
| 1214 | try ctx.dir.writeFile(io, .{ | 1221 | try ctx.dir.writeFile(io, .{ |
| 1215 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), | 1222 | .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), |
| 1216 | .data = "blah", | 1223 | .data = "blah", |
| 1217 | }); | 1224 | }); |
| 1218 | | 1225 | |
| ... | @@ -1229,13 +1236,13 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { | ... | @@ -1229,13 +1236,13 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { |
| 1229 | const allocator = ctx.arena.allocator(); | 1236 | const allocator = ctx.arena.allocator(); |
| 1230 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1237 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1231 | | 1238 | |
| 1232 | try ctx.dir.makePath(io, try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); | 1239 | try ctx.dir.makePath(io, try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); |
| 1233 | try ctx.dir.writeFile(io, .{ | 1240 | try ctx.dir.writeFile(io, .{ |
| 1234 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), | 1241 | .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), |
| 1235 | .data = "nonsense", | 1242 | .data = "nonsense", |
| 1236 | }); | 1243 | }); |
| 1237 | try ctx.dir.writeFile(io, .{ | 1244 | try ctx.dir.writeFile(io, .{ |
| 1238 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), | 1245 | .sub_path = try Dir.path.join(allocator, &.{ "os_test_tmp", "b", "file2.txt" }), |
| 1239 | .data = "blah", | 1246 | .data = "blah", |
| 1240 | }); | 1247 | }); |
| 1241 | | 1248 | |
| ... | @@ -1285,7 +1292,7 @@ test "makepath existing directories" { | ... | @@ -1285,7 +1292,7 @@ test "makepath existing directories" { |
| 1285 | defer tmpA.close(io); | 1292 | defer tmpA.close(io); |
| 1286 | try tmpA.makeDir(io, "B", .default_dir); | 1293 | try tmpA.makeDir(io, "B", .default_dir); |
| 1287 | | 1294 | |
| 1288 | const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; | 1295 | const testPath = "A" ++ Dir.path.sep_str ++ "B" ++ Dir.path.sep_str ++ "C"; |
| 1289 | try tmp.dir.makePath(io, testPath); | 1296 | try tmp.dir.makePath(io, testPath); |
| 1290 | | 1297 | |
| 1291 | try expectDir(io, tmp.dir, testPath); | 1298 | try expectDir(io, tmp.dir, testPath); |
| ... | @@ -1298,11 +1305,11 @@ test "makepath through existing valid symlink" { | ... | @@ -1298,11 +1305,11 @@ test "makepath through existing valid symlink" { |
| 1298 | defer tmp.cleanup(); | 1305 | defer tmp.cleanup(); |
| 1299 | | 1306 | |
| 1300 | try tmp.dir.makeDir(io, "realfolder", .default_dir); | 1307 | try tmp.dir.makeDir(io, "realfolder", .default_dir); |
| 1301 | try setupSymlink(io, tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); | 1308 | try setupSymlink(io, tmp.dir, "." ++ Dir.path.sep_str ++ "realfolder", "working-symlink", .{}); |
| 1302 | | 1309 | |
| 1303 | try tmp.dir.makePath(io, "working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); | 1310 | try tmp.dir.makePath(io, "working-symlink" ++ Dir.path.sep_str ++ "in-realfolder"); |
| 1304 | | 1311 | |
| 1305 | try expectDir(io, tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); | 1312 | try expectDir(io, tmp.dir, "realfolder" ++ Dir.path.sep_str ++ "in-realfolder"); |
| 1306 | } | 1313 | } |
| 1307 | | 1314 | |
| 1308 | test "makepath relative walks" { | 1315 | test "makepath relative walks" { |
| ... | @@ -1311,7 +1318,7 @@ test "makepath relative walks" { | ... | @@ -1311,7 +1318,7 @@ test "makepath relative walks" { |
| 1311 | var tmp = tmpDir(.{}); | 1318 | var tmp = tmpDir(.{}); |
| 1312 | defer tmp.cleanup(); | 1319 | defer tmp.cleanup(); |
| 1313 | | 1320 | |
| 1314 | const relPath = try fs.path.join(testing.allocator, &.{ | 1321 | const relPath = try Dir.path.join(testing.allocator, &.{ |
| 1315 | "first", "..", "second", "..", "third", "..", "first", "A", "..", "B", "..", "C", | 1322 | "first", "..", "second", "..", "third", "..", "first", "A", "..", "B", "..", "C", |
| 1316 | }); | 1323 | }); |
| 1317 | defer testing.allocator.free(relPath); | 1324 | defer testing.allocator.free(relPath); |
| ... | @@ -1323,14 +1330,14 @@ test "makepath relative walks" { | ... | @@ -1323,14 +1330,14 @@ test "makepath relative walks" { |
| 1323 | .windows => { | 1330 | .windows => { |
| 1324 | // On Windows, .. is resolved before passing the path to NtCreateFile, | 1331 | // On Windows, .. is resolved before passing the path to NtCreateFile, |
| 1325 | // meaning everything except `first/C` drops out. | 1332 | // meaning everything except `first/C` drops out. |
| 1326 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); | 1333 | try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "C"); |
| 1327 | try expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); | 1334 | try expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); |
| 1328 | try expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); | 1335 | try expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); |
| 1329 | }, | 1336 | }, |
| 1330 | else => { | 1337 | else => { |
| 1331 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "A"); | 1338 | try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "A"); |
| 1332 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "B"); | 1339 | try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "B"); |
| 1333 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); | 1340 | try expectDir(io, tmp.dir, "first" ++ Dir.path.sep_str ++ "C"); |
| 1334 | try expectDir(io, tmp.dir, "second"); | 1341 | try expectDir(io, tmp.dir, "second"); |
| 1335 | try expectDir(io, tmp.dir, "third"); | 1342 | try expectDir(io, tmp.dir, "third"); |
| 1336 | }, | 1343 | }, |
| ... | @@ -1344,13 +1351,13 @@ test "makepath ignores '.'" { | ... | @@ -1344,13 +1351,13 @@ test "makepath ignores '.'" { |
| 1344 | defer tmp.cleanup(); | 1351 | defer tmp.cleanup(); |
| 1345 | | 1352 | |
| 1346 | // Path to create, with "." elements: | 1353 | // Path to create, with "." elements: |
| 1347 | const dotPath = try fs.path.join(testing.allocator, &.{ | 1354 | const dotPath = try Dir.path.join(testing.allocator, &.{ |
| 1348 | "first", ".", "second", ".", "third", | 1355 | "first", ".", "second", ".", "third", |
| 1349 | }); | 1356 | }); |
| 1350 | defer testing.allocator.free(dotPath); | 1357 | defer testing.allocator.free(dotPath); |
| 1351 | | 1358 | |
| 1352 | // Path to expect to find: | 1359 | // Path to expect to find: |
| 1353 | const expectedPath = try fs.path.join(testing.allocator, &.{ | 1360 | const expectedPath = try Dir.path.join(testing.allocator, &.{ |
| 1354 | "first", "second", "third", | 1361 | "first", "second", "third", |
| 1355 | }); | 1362 | }); |
| 1356 | defer testing.allocator.free(expectedPath); | 1363 | defer testing.allocator.free(expectedPath); |
| ... | @@ -1473,7 +1480,7 @@ test "access file" { | ... | @@ -1473,7 +1480,7 @@ test "access file" { |
| 1473 | fn impl(ctx: *TestContext) !void { | 1480 | fn impl(ctx: *TestContext) !void { |
| 1474 | const io = ctx.io; | 1481 | const io = ctx.io; |
| 1475 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1482 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1476 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); | 1483 | const file_path = try ctx.transformPath("os_test_tmp" ++ Dir.path.sep_str ++ "file.txt"); |
| 1477 | | 1484 | |
| 1478 | try ctx.dir.makePath(io, dir_path); | 1485 | try ctx.dir.makePath(io, dir_path); |
| 1479 | try expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); | 1486 | try expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); |
| ... | @@ -1546,7 +1553,7 @@ test "sendfile with buffered data" { | ... | @@ -1546,7 +1553,7 @@ test "sendfile with buffered data" { |
| 1546 | var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); | 1553 | var src_file = try dir.createFile(io, "sendfile1.txt", .{ .read = true }); |
| 1547 | defer src_file.close(io); | 1554 | defer src_file.close(io); |
| 1548 | | 1555 | |
| 1549 | try src_file.writeAll("AAAABBBB"); | 1556 | try src_file.writeStreamingAll(io, "AAAABBBB"); |
| 1550 | | 1557 | |
| 1551 | var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); | 1558 | var dest_file = try dir.createFile(io, "sendfile2.txt", .{ .read = true }); |
| 1552 | defer dest_file.close(io); | 1559 | defer dest_file.close(io); |
| ... | @@ -1691,7 +1698,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { | ... | @@ -1691,7 +1698,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { |
| 1691 | errdefer file.close(io); | 1698 | errdefer file.close(io); |
| 1692 | | 1699 | |
| 1693 | const S = struct { | 1700 | const S = struct { |
| 1694 | fn checkFn(dir: *Io.Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { | 1701 | fn checkFn(dir: *Dir, path: []const u8, started: *std.Thread.ResetEvent, locked: *std.Thread.ResetEvent) !void { |
| 1695 | started.set(); | 1702 | started.set(); |
| 1696 | const file1 = try dir.createFile(io, path, .{ .lock = .exclusive }); | 1703 | const file1 = try dir.createFile(io, path, .{ .lock = .exclusive }); |
| 1697 | | 1704 | |
| ... | @@ -1731,8 +1738,8 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { | ... | @@ -1731,8 +1738,8 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1731 | var random_bytes: [12]u8 = undefined; | 1738 | var random_bytes: [12]u8 = undefined; |
| 1732 | std.crypto.random.bytes(&random_bytes); | 1739 | std.crypto.random.bytes(&random_bytes); |
| 1733 | | 1740 | |
| 1734 | var random_b64: [fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; | 1741 | var random_b64: [std.fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; |
| 1735 | _ = fs.base64_encoder.encode(&random_b64, &random_bytes); | 1742 | _ = std.fs.base64_encoder.encode(&random_b64, &random_bytes); |
| 1736 | | 1743 | |
| 1737 | const sub_path = random_b64 ++ "-zig-test-absolute-paths.txt"; | 1744 | const sub_path = random_b64 ++ "-zig-test-absolute-paths.txt"; |
| 1738 | | 1745 | |
| ... | @@ -1741,16 +1748,16 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { | ... | @@ -1741,16 +1748,16 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1741 | const cwd = try std.process.getCwdAlloc(gpa); | 1748 | const cwd = try std.process.getCwdAlloc(gpa); |
| 1742 | defer gpa.free(cwd); | 1749 | defer gpa.free(cwd); |
| 1743 | | 1750 | |
| 1744 | const filename = try fs.path.resolve(gpa, &.{ cwd, sub_path }); | 1751 | const filename = try Dir.path.resolve(gpa, &.{ cwd, sub_path }); |
| 1745 | defer gpa.free(filename); | 1752 | defer gpa.free(filename); |
| 1746 | | 1753 | |
| 1747 | defer fs.deleteFileAbsolute(filename) catch {}; // createFileAbsolute can leave files on failures | 1754 | defer Dir.deleteFileAbsolute(io, filename) catch {}; // createFileAbsolute can leave files on failures |
| 1748 | const file1 = try fs.createFileAbsolute(filename, .{ | 1755 | const file1 = try Dir.createFileAbsolute(io, filename, .{ |
| 1749 | .lock = .exclusive, | 1756 | .lock = .exclusive, |
| 1750 | .lock_nonblocking = true, | 1757 | .lock_nonblocking = true, |
| 1751 | }); | 1758 | }); |
| 1752 | | 1759 | |
| 1753 | const file2 = fs.createFileAbsolute(filename, .{ | 1760 | const file2 = Dir.createFileAbsolute(io, filename, .{ |
| 1754 | .lock = .exclusive, | 1761 | .lock = .exclusive, |
| 1755 | .lock_nonblocking = true, | 1762 | .lock_nonblocking = true, |
| 1756 | }); | 1763 | }); |
| ... | @@ -1802,9 +1809,9 @@ test "walker" { | ... | @@ -1802,9 +1809,9 @@ test "walker" { |
| 1802 | .{ "dir2", 1 }, | 1809 | .{ "dir2", 1 }, |
| 1803 | .{ "dir3", 1 }, | 1810 | .{ "dir3", 1 }, |
| 1804 | .{ "dir4", 1 }, | 1811 | .{ "dir4", 1 }, |
| 1805 | .{ "dir3" ++ fs.path.sep_str ++ "sub1", 2 }, | 1812 | .{ "dir3" ++ Dir.path.sep_str ++ "sub1", 2 }, |
| 1806 | .{ "dir3" ++ fs.path.sep_str ++ "sub2", 2 }, | 1813 | .{ "dir3" ++ Dir.path.sep_str ++ "sub2", 2 }, |
| 1807 | .{ "dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1", 3 }, | 1814 | .{ "dir3" ++ Dir.path.sep_str ++ "sub2" ++ Dir.path.sep_str ++ "subsub1", 3 }, |
| 1808 | }); | 1815 | }); |
| 1809 | | 1816 | |
| 1810 | const expected_basenames = std.StaticStringMap(void).initComptime(.{ | 1817 | const expected_basenames = std.StaticStringMap(void).initComptime(.{ |
| ... | @@ -1826,11 +1833,11 @@ test "walker" { | ... | @@ -1826,11 +1833,11 @@ test "walker" { |
| 1826 | | 1833 | |
| 1827 | var num_walked: usize = 0; | 1834 | var num_walked: usize = 0; |
| 1828 | while (try walker.next()) |entry| { | 1835 | while (try walker.next()) |entry| { |
| 1829 | testing.expect(expected_basenames.has(entry.basename)) catch |err| { | 1836 | expect(expected_basenames.has(entry.basename)) catch |err| { |
| 1830 | std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); | 1837 | std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); |
| 1831 | return err; | 1838 | return err; |
| 1832 | }; | 1839 | }; |
| 1833 | testing.expect(expected_paths.has(entry.path)) catch |err| { | 1840 | expect(expected_paths.has(entry.path)) catch |err| { |
| 1834 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1841 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1835 | return err; | 1842 | return err; |
| 1836 | }; | 1843 | }; |
| ... | @@ -1863,11 +1870,11 @@ test "selective walker, skip entries that start with ." { | ... | @@ -1863,11 +1870,11 @@ test "selective walker, skip entries that start with ." { |
| 1863 | | 1870 | |
| 1864 | const expected_paths = std.StaticStringMap(usize).initComptime(.{ | 1871 | const expected_paths = std.StaticStringMap(usize).initComptime(.{ |
| 1865 | .{ "dir1", 1 }, | 1872 | .{ "dir1", 1 }, |
| 1866 | .{ "dir1" ++ fs.path.sep_str ++ "foo", 2 }, | 1873 | .{ "dir1" ++ Dir.path.sep_str ++ "foo", 2 }, |
| 1867 | .{ "a", 1 }, | 1874 | .{ "a", 1 }, |
| 1868 | .{ "a" ++ fs.path.sep_str ++ "b", 2 }, | 1875 | .{ "a" ++ Dir.path.sep_str ++ "b", 2 }, |
| 1869 | .{ "a" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c", 3 }, | 1876 | .{ "a" ++ Dir.path.sep_str ++ "b" ++ Dir.path.sep_str ++ "c", 3 }, |
| 1870 | .{ "a" ++ fs.path.sep_str ++ "baz", 2 }, | 1877 | .{ "a" ++ Dir.path.sep_str ++ "baz", 2 }, |
| 1871 | }); | 1878 | }); |
| 1872 | | 1879 | |
| 1873 | const expected_basenames = std.StaticStringMap(void).initComptime(.{ | 1880 | const expected_basenames = std.StaticStringMap(void).initComptime(.{ |
| ... | @@ -1893,11 +1900,11 @@ test "selective walker, skip entries that start with ." { | ... | @@ -1893,11 +1900,11 @@ test "selective walker, skip entries that start with ." { |
| 1893 | try walker.enter(entry); | 1900 | try walker.enter(entry); |
| 1894 | } | 1901 | } |
| 1895 | | 1902 | |
| 1896 | testing.expect(expected_basenames.has(entry.basename)) catch |err| { | 1903 | expect(expected_basenames.has(entry.basename)) catch |err| { |
| 1897 | std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); | 1904 | std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)}); |
| 1898 | return err; | 1905 | return err; |
| 1899 | }; | 1906 | }; |
| 1900 | testing.expect(expected_paths.has(entry.path)) catch |err| { | 1907 | expect(expected_paths.has(entry.path)) catch |err| { |
| 1901 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1908 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1902 | return err; | 1909 | return err; |
| 1903 | }; | 1910 | }; |
| ... | @@ -1937,7 +1944,7 @@ test "walker without fully iterating" { | ... | @@ -1937,7 +1944,7 @@ test "walker without fully iterating" { |
| 1937 | try expectEqual(@as(usize, 1), num_walked); | 1944 | try expectEqual(@as(usize, 1), num_walked); |
| 1938 | } | 1945 | } |
| 1939 | | 1946 | |
| 1940 | test "'.' and '..' in Io.Dir functions" { | 1947 | test "'.' and '..' in Dir functions" { |
| 1941 | if (native_os == .windows and builtin.cpu.arch == .aarch64) { | 1948 | if (native_os == .windows and builtin.cpu.arch == .aarch64) { |
| 1942 | // https://github.com/ziglang/zig/issues/17134 | 1949 | // https://github.com/ziglang/zig/issues/17134 |
| 1943 | return error.SkipZigTest; | 1950 | return error.SkipZigTest; |
| ... | @@ -1970,7 +1977,7 @@ test "'.' and '..' in Io.Dir functions" { | ... | @@ -1970,7 +1977,7 @@ test "'.' and '..' in Io.Dir functions" { |
| 1970 | try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); | 1977 | try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); |
| 1971 | var dir = ctx.dir; | 1978 | var dir = ctx.dir; |
| 1972 | const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{}); | 1979 | const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{}); |
| 1973 | try expectEqual(Io.Dir.PrevStatus.stale, prev_status); | 1980 | try expectEqual(Dir.PrevStatus.stale, prev_status); |
| 1974 | | 1981 | |
| 1975 | try ctx.dir.deleteDir(io, subdir_path); | 1982 | try ctx.dir.deleteDir(io, subdir_path); |
| 1976 | } | 1983 | } |
| ... | @@ -1990,28 +1997,28 @@ test "'.' and '..' in absolute functions" { | ... | @@ -1990,28 +1997,28 @@ test "'.' and '..' in absolute functions" { |
| 1990 | defer arena.deinit(); | 1997 | defer arena.deinit(); |
| 1991 | const allocator = arena.allocator(); | 1998 | const allocator = arena.allocator(); |
| 1992 | | 1999 | |
| 1993 | const base_path = try tmp.dir.realpathAlloc(allocator, "."); | 2000 | const base_path = try tmp.dir.realPathAlloc(io, ".", allocator); |
| 1994 | | 2001 | |
| 1995 | const subdir_path = try fs.path.join(allocator, &.{ base_path, "./subdir" }); | 2002 | const subdir_path = try Dir.path.join(allocator, &.{ base_path, "./subdir" }); |
| 1996 | try fs.makeDirAbsolute(subdir_path); | 2003 | try Dir.makeDirAbsolute(io, subdir_path); |
| 1997 | try fs.accessAbsolute(subdir_path, .{}); | 2004 | try Dir.accessAbsolute(io, subdir_path, .{}); |
| 1998 | var created_subdir = try Dir.openDirAbsolute(io, subdir_path, .{}); | 2005 | var created_subdir = try Dir.openDirAbsolute(io, subdir_path, .{}); |
| 1999 | created_subdir.close(io); | 2006 | created_subdir.close(io); |
| 2000 | | 2007 | |
| 2001 | const created_file_path = try fs.path.join(allocator, &.{ subdir_path, "../file" }); | 2008 | const created_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../file" }); |
| 2002 | const created_file = try fs.createFileAbsolute(created_file_path, .{}); | 2009 | const created_file = try Dir.createFileAbsolute(io, created_file_path, .{}); |
| 2003 | created_file.close(io); | 2010 | created_file.close(io); |
| 2004 | try fs.accessAbsolute(created_file_path, .{}); | 2011 | try Dir.accessAbsolute(io, created_file_path, .{}); |
| 2005 | | 2012 | |
| 2006 | const copied_file_path = try fs.path.join(allocator, &.{ subdir_path, "../copy" }); | 2013 | const copied_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../copy" }); |
| 2007 | try fs.copyFileAbsolute(created_file_path, copied_file_path, .{}); | 2014 | try Dir.copyFileAbsolute(io, created_file_path, copied_file_path, .{}); |
| 2008 | const renamed_file_path = try fs.path.join(allocator, &.{ subdir_path, "../rename" }); | 2015 | const renamed_file_path = try Dir.path.join(allocator, &.{ subdir_path, "../rename" }); |
| 2009 | try fs.renameAbsolute(copied_file_path, renamed_file_path); | 2016 | try Dir.renameAbsolute(io, copied_file_path, renamed_file_path); |
| 2010 | const renamed_file = try Dir.openFileAbsolute(renamed_file_path, .{}); | 2017 | const renamed_file = try Dir.openFileAbsolute(renamed_file_path, .{}); |
| 2011 | renamed_file.close(io); | 2018 | renamed_file.close(io); |
| 2012 | try fs.deleteFileAbsolute(renamed_file_path); | 2019 | try Dir.deleteFileAbsolute(io, renamed_file_path); |
| 2013 | | 2020 | |
| 2014 | try fs.deleteDirAbsolute(subdir_path); | 2021 | try Dir.deleteDirAbsolute(io, subdir_path); |
| 2015 | } | 2022 | } |
| 2016 | | 2023 | |
| 2017 | test "chmod" { | 2024 | test "chmod" { |
| ... | @@ -2114,8 +2121,8 @@ test "invalid UTF-8/WTF-8 paths" { | ... | @@ -2114,8 +2121,8 @@ test "invalid UTF-8/WTF-8 paths" { |
| 2114 | try expectError(expected_err, ctx.dir.statFile(invalid_path)); | 2121 | try expectError(expected_err, ctx.dir.statFile(invalid_path)); |
| 2115 | | 2122 | |
| 2116 | if (native_os != .wasi) { | 2123 | if (native_os != .wasi) { |
| 2117 | try expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); | 2124 | try expectError(expected_err, ctx.dir.realPath(io, invalid_path, &[_]u8{})); |
| 2118 | try expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); | 2125 | try expectError(expected_err, ctx.dir.realPathAlloc(io, invalid_path, testing.allocator)); |
| 2119 | } | 2126 | } |
| 2120 | | 2127 | |
| 2121 | try expectError(expected_err, Dir.rename(ctx.dir, invalid_path, ctx.dir, invalid_path, io)); | 2128 | try expectError(expected_err, Dir.rename(ctx.dir, invalid_path, ctx.dir, invalid_path, io)); |
| ... | @@ -2133,7 +2140,7 @@ test "invalid UTF-8/WTF-8 paths" { | ... | @@ -2133,7 +2140,7 @@ test "invalid UTF-8/WTF-8 paths" { |
| 2133 | var readlink_buf: [Dir.max_path_bytes]u8 = undefined; | 2140 | var readlink_buf: [Dir.max_path_bytes]u8 = undefined; |
| 2134 | try expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); | 2141 | try expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); |
| 2135 | try expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); | 2142 | try expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); |
| 2136 | try expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path)); | 2143 | try expectError(expected_err, Dir.realPathAlloc(io, invalid_path, testing.allocator)); |
| 2137 | } | 2144 | } |
| 2138 | } | 2145 | } |
| 2139 | }.impl); | 2146 | }.impl); |
| ... | @@ -2303,7 +2310,7 @@ test "readlink on Windows" { | ... | @@ -2303,7 +2310,7 @@ test "readlink on Windows" { |
| 2303 | } | 2310 | } |
| 2304 | | 2311 | |
| 2305 | fn testReadLinkWindows(io: Io, target_path: []const u8, symlink_path: []const u8) !void { | 2312 | fn testReadLinkWindows(io: Io, target_path: []const u8, symlink_path: []const u8) !void { |
| 2306 | var buffer: [fs.max_path_bytes]u8 = undefined; | 2313 | var buffer: [Dir.max_path_bytes]u8 = undefined; |
| 2307 | const given = try Dir.readLinkAbsolute(io, symlink_path, &buffer); | 2314 | const given = try Dir.readLinkAbsolute(io, symlink_path, &buffer); |
| 2308 | try expect(mem.eql(u8, target_path, given)); | 2315 | try expect(mem.eql(u8, target_path, given)); |
| 2309 | } | 2316 | } |
| ... | @@ -2326,7 +2333,7 @@ test "readlinkat" { | ... | @@ -2326,7 +2333,7 @@ test "readlinkat" { |
| 2326 | }; | 2333 | }; |
| 2327 | | 2334 | |
| 2328 | // read the link | 2335 | // read the link |
| 2329 | var buffer: [fs.max_path_bytes]u8 = undefined; | 2336 | var buffer: [Dir.max_path_bytes]u8 = undefined; |
| 2330 | const read_link = try tmp.dir.readLink(io, "link", &buffer); | 2337 | const read_link = try tmp.dir.readLink(io, "link", &buffer); |
| 2331 | try expectEqualStrings("file.txt", read_link); | 2338 | try expectEqualStrings("file.txt", read_link); |
| 2332 | } | 2339 | } |
| ... | @@ -2387,3 +2394,239 @@ fn expectMode(io: Io, dir: Dir, file: []const u8, permissions: File.Permissions) | ... | @@ -2387,3 +2394,239 @@ fn expectMode(io: Io, dir: Dir, file: []const u8, permissions: File.Permissions) |
| 2387 | const st = try dir.statFile(io, file, .{ .follow_symlinks = false }); | 2394 | const st = try dir.statFile(io, file, .{ .follow_symlinks = false }); |
| 2388 | try expectEqual(mode, st.mode & 0b111_111_111); | 2395 | try expectEqual(mode, st.mode & 0b111_111_111); |
| 2389 | } | 2396 | } |
| | 2397 | |
| | 2398 | test "isatty" { |
| | 2399 | const io = testing.io; |
| | 2400 | |
| | 2401 | var tmp = tmpDir(.{}); |
| | 2402 | defer tmp.cleanup(); |
| | 2403 | |
| | 2404 | var file = try tmp.dir.createFile(io, "foo", .{}); |
| | 2405 | defer file.close(io); |
| | 2406 | |
| | 2407 | try expectEqual(false, try file.isTty(io)); |
| | 2408 | } |
| | 2409 | |
| | 2410 | test "read positional empty buffer" { |
| | 2411 | const io = testing.io; |
| | 2412 | |
| | 2413 | var tmp = tmpDir(.{}); |
| | 2414 | defer tmp.cleanup(); |
| | 2415 | |
| | 2416 | var file = try tmp.dir.createFile(io, "pread_empty", .{ .read = true }); |
| | 2417 | defer file.close(io); |
| | 2418 | |
| | 2419 | var buffer: [0]u8 = undefined; |
| | 2420 | try expectEqual(0, try file.readPositional(io, &buffer, 0)); |
| | 2421 | } |
| | 2422 | |
| | 2423 | test "write streaming empty buffer" { |
| | 2424 | const io = testing.io; |
| | 2425 | |
| | 2426 | var tmp = tmpDir(.{}); |
| | 2427 | defer tmp.cleanup(); |
| | 2428 | |
| | 2429 | var file = try tmp.dir.createFile(io, "write_empty", .{}); |
| | 2430 | defer file.close(io); |
| | 2431 | |
| | 2432 | var buffer: [0]u8 = &.{}; |
| | 2433 | try expectEqual(0, try file.writeStreaming(io, &buffer)); |
| | 2434 | } |
| | 2435 | |
| | 2436 | test "write positional empty buffer" { |
| | 2437 | const io = testing.io; |
| | 2438 | |
| | 2439 | var tmp = tmpDir(.{}); |
| | 2440 | defer tmp.cleanup(); |
| | 2441 | |
| | 2442 | var file = try tmp.dir.createFile(io, "pwrite_empty", .{}); |
| | 2443 | defer file.close(io); |
| | 2444 | |
| | 2445 | var buffer: [0]u8 = &.{}; |
| | 2446 | try expectEqual(0, try file.writePositional(io, &buffer, 0)); |
| | 2447 | } |
| | 2448 | |
| | 2449 | test "access smoke test" { |
| | 2450 | if (native_os == .wasi) return error.SkipZigTest; |
| | 2451 | if (native_os == .windows) return error.SkipZigTest; |
| | 2452 | if (native_os == .openbsd) return error.SkipZigTest; |
| | 2453 | |
| | 2454 | const io = testing.io; |
| | 2455 | const gpa = testing.allocator; |
| | 2456 | |
| | 2457 | var tmp = tmpDir(.{}); |
| | 2458 | defer tmp.cleanup(); |
| | 2459 | |
| | 2460 | const base_path = try tmp.dir.realPathAlloc(io, ".", gpa); |
| | 2461 | defer gpa.free(base_path); |
| | 2462 | |
| | 2463 | { |
| | 2464 | // Create some file using `open`. |
| | 2465 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); |
| | 2466 | defer gpa.free(file_path); |
| | 2467 | const file = Dir.cwd().createFile(io, file_path, .{ .read = true, .exclusive = true }); |
| | 2468 | file.close(io); |
| | 2469 | } |
| | 2470 | |
| | 2471 | { |
| | 2472 | // Try to access() the file |
| | 2473 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_file" }); |
| | 2474 | defer gpa.free(file_path); |
| | 2475 | if (native_os == .windows) { |
| | 2476 | try Dir.cwd().access(io, file_path, .{}); |
| | 2477 | } else { |
| | 2478 | try Dir.cwd().access(io, file_path, .{ .read = true, .write = true }); |
| | 2479 | } |
| | 2480 | } |
| | 2481 | |
| | 2482 | { |
| | 2483 | // Try to access() a non-existent file - should fail with error.FileNotFound |
| | 2484 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_other_file" }); |
| | 2485 | defer gpa.free(file_path); |
| | 2486 | try expectError(error.FileNotFound, Dir.cwd().access(io, file_path, .{})); |
| | 2487 | } |
| | 2488 | |
| | 2489 | { |
| | 2490 | // Create some directory |
| | 2491 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); |
| | 2492 | defer gpa.free(file_path); |
| | 2493 | try Dir.makeDir(io, file_path, .default_file); |
| | 2494 | } |
| | 2495 | |
| | 2496 | { |
| | 2497 | // Try to access() the directory |
| | 2498 | const file_path = try Dir.path.join(gpa, &.{ base_path, "some_dir" }); |
| | 2499 | defer gpa.free(file_path); |
| | 2500 | |
| | 2501 | try Dir.access(io, file_path, .{}); |
| | 2502 | } |
| | 2503 | } |
| | 2504 | |
| | 2505 | test "write streaming a long vector" { |
| | 2506 | const io = testing.io; |
| | 2507 | |
| | 2508 | var tmp = tmpDir(.{}); |
| | 2509 | defer tmp.cleanup(); |
| | 2510 | |
| | 2511 | var file = try tmp.dir.createFile(io, "pwritev", .{}); |
| | 2512 | defer file.close(io); |
| | 2513 | |
| | 2514 | var vecs: [2000][]const u8 = undefined; |
| | 2515 | for (&vecs) |*v| v.* = "a"; |
| | 2516 | |
| | 2517 | const n = try file.writePositional(io, &vecs, 0); |
| | 2518 | try expect(n <= vecs.len); |
| | 2519 | } |
| | 2520 | |
| | 2521 | test "open smoke test" { |
| | 2522 | if (native_os == .wasi) return error.SkipZigTest; |
| | 2523 | if (native_os == .windows) return error.SkipZigTest; |
| | 2524 | if (native_os == .openbsd) return error.SkipZigTest; |
| | 2525 | |
| | 2526 | // TODO verify file attributes using `fstat` |
| | 2527 | |
| | 2528 | var tmp = tmpDir(.{}); |
| | 2529 | defer tmp.cleanup(); |
| | 2530 | |
| | 2531 | const io = testing.io; |
| | 2532 | |
| | 2533 | { |
| | 2534 | // Create some file using `open`. |
| | 2535 | const file = try tmp.dir.createFile(io, "some_file", .{ .exclusive = true }); |
| | 2536 | file.close(io); |
| | 2537 | } |
| | 2538 | |
| | 2539 | // Try this again with the same flags. This op should fail with error.PathAlreadyExists. |
| | 2540 | try expectError( |
| | 2541 | error.PathAlreadyExists, |
| | 2542 | tmp.dir.createFile(io, "some_file", .{ .exclusive = true }), |
| | 2543 | ); |
| | 2544 | |
| | 2545 | { |
| | 2546 | // Try opening without exclusive flag. |
| | 2547 | const file = try tmp.dir.createFile(io, "some_file", .{}); |
| | 2548 | file.close(io); |
| | 2549 | } |
| | 2550 | |
| | 2551 | try expectError(error.NotDir, tmp.dir.openDir(io, "some_file", .{})); |
| | 2552 | try tmp.dir.makeDir(io, "some_dir", .default_dir); |
| | 2553 | |
| | 2554 | { |
| | 2555 | const dir = try tmp.dir.openDir("some_dir", .{}); |
| | 2556 | dir.close(io); |
| | 2557 | } |
| | 2558 | |
| | 2559 | // Try opening as file which should fail. |
| | 2560 | try expectError(error.IsDir, tmp.dir.openFile("some_dir", .{})); |
| | 2561 | } |
| | 2562 | |
| | 2563 | test "hard link with different directories" { |
| | 2564 | const io = testing.io; |
| | 2565 | |
| | 2566 | var tmp = tmpDir(.{}); |
| | 2567 | defer tmp.cleanup(); |
| | 2568 | |
| | 2569 | const target_name = "link-target"; |
| | 2570 | const link_name = "newlink"; |
| | 2571 | |
| | 2572 | const subdir = try tmp.dir.makeOpenPath(io, "subdir", .{}); |
| | 2573 | |
| | 2574 | defer tmp.dir.deleteFile(io, target_name) catch {}; |
| | 2575 | try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); |
| | 2576 | |
| | 2577 | // Test 1: link from file in subdir back up to target in parent directory |
| | 2578 | tmp.dir.hardLink(target_name, subdir, link_name, 0) catch |err| switch (err) { |
| | 2579 | error.OperationUnsupported => return error.SkipZigTest, |
| | 2580 | else => |e| return e, |
| | 2581 | }; |
| | 2582 | |
| | 2583 | const efd = try tmp.dir.openFile(io, target_name, .{}); |
| | 2584 | defer efd.close(io); |
| | 2585 | |
| | 2586 | const nfd = try subdir.openFile(io, link_name, .{}); |
| | 2587 | defer nfd.close(io); |
| | 2588 | |
| | 2589 | { |
| | 2590 | const e_stat = try efd.stat(io); |
| | 2591 | const n_stat = try nfd.stat(io); |
| | 2592 | |
| | 2593 | try expectEqual(e_stat.inode, n_stat.inode); |
| | 2594 | try expectEqual(2, e_stat.nlink); |
| | 2595 | try expectEqual(2, n_stat.nlink); |
| | 2596 | } |
| | 2597 | |
| | 2598 | // Test 2: remove link |
| | 2599 | try subdir.deleteFile(io, link_name, .{}); |
| | 2600 | const e_stat = try efd.stat(io); |
| | 2601 | try expectEqual(1, e_stat.nlink); |
| | 2602 | } |
| | 2603 | |
| | 2604 | test "stat smoke test" { |
| | 2605 | if (native_os == .wasi and !builtin.link_libc) return error.SkipZigTest; |
| | 2606 | |
| | 2607 | const io = testing.io; |
| | 2608 | |
| | 2609 | var tmp = tmpDir(.{}); |
| | 2610 | defer tmp.cleanup(); |
| | 2611 | |
| | 2612 | // create dummy file |
| | 2613 | const contents = "nonsense"; |
| | 2614 | try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = contents }); |
| | 2615 | |
| | 2616 | // fetch file's info on the opened fd directly |
| | 2617 | const file = try tmp.dir.openFile(io, "file.txt", .{}); |
| | 2618 | const stat = try file.stat(io); |
| | 2619 | defer file.close(io); |
| | 2620 | |
| | 2621 | // now repeat but using directory handle instead |
| | 2622 | const statat = try tmp.dir.statFile(io, "file.txt", .{ .follow_symlinks = false }); |
| | 2623 | |
| | 2624 | try expectEqual(stat.inode, statat.inode); |
| | 2625 | try expectEqual(stat.nlink, statat.nlink); |
| | 2626 | try expectEqual(stat.size, statat.size); |
| | 2627 | try expectEqual(stat.permissions, statat.permissions); |
| | 2628 | try expectEqual(stat.kind, statat.kind); |
| | 2629 | try expectEqual(stat.atime, statat.atime); |
| | 2630 | try expectEqual(stat.mtime, statat.mtime); |
| | 2631 | try expectEqual(stat.ctime, statat.ctime); |
| | 2632 | } |