| ... | ... | @@ -545,7 +545,7 @@ test "Dir.Iterator but dir is deleted during iteration" { |
| 545 | 545 | var iterator = subdir.iterate(); |
| 546 | 546 | |
| 547 | 547 | // Create something to iterate over within the subdir |
| 548 | | try tmp.dir.makePath("subdir/b"); |
| 548 | try tmp.dir.makePath("subdir" ++ fs.path.sep_str ++ "b"); |
| 549 | 549 | |
| 550 | 550 | // Then, before iterating, delete the directory that we're iterating. |
| 551 | 551 | // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. |
| ... | ... | @@ -754,7 +754,7 @@ test "deleteDir" { |
| 754 | 754 | try testWithAllSupportedPathTypes(struct { |
| 755 | 755 | fn impl(ctx: *TestContext) !void { |
| 756 | 756 | const test_dir_path = try ctx.transformPath("test_dir"); |
| 757 | | const test_file_path = try ctx.transformPath("test_dir" ++ std.fs.path.sep_str ++ "test_file"); |
| 757 | const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); |
| 758 | 758 | |
| 759 | 759 | // deleting a non-existent directory |
| 760 | 760 | try testing.expectError(error.FileNotFound, ctx.dir.deleteDir(test_dir_path)); |
| ... | ... | @@ -1089,6 +1089,88 @@ test "makePath in a directory that no longer exists" { |
| 1089 | 1089 | try testing.expectError(error.FileNotFound, tmp.dir.makePath("sub-path")); |
| 1090 | 1090 | } |
| 1091 | 1091 | |
| 1092 | fn expectDir(dir: Dir, path: []const u8) !void { |
| 1093 | var d = try dir.openDir(path, .{}); |
| 1094 | d.close(); |
| 1095 | } |
| 1096 | |
| 1097 | test "makepath existing directories" { |
| 1098 | var tmp = tmpDir(.{}); |
| 1099 | defer tmp.cleanup(); |
| 1100 | |
| 1101 | try tmp.dir.makeDir("A"); |
| 1102 | const tmpA = try tmp.dir.openDir("A", .{}); |
| 1103 | try tmpA.makeDir("B"); |
| 1104 | |
| 1105 | const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; |
| 1106 | try tmp.dir.makePath(testPath); |
| 1107 | |
| 1108 | try expectDir(tmp.dir, testPath); |
| 1109 | } |
| 1110 | |
| 1111 | test "makepath through existing valid symlink" { |
| 1112 | var tmp = tmpDir(.{}); |
| 1113 | defer tmp.cleanup(); |
| 1114 | |
| 1115 | try tmp.dir.makeDir("realfolder"); |
| 1116 | try tmp.dir.symLink("." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); |
| 1117 | |
| 1118 | try tmp.dir.makePath("working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); |
| 1119 | |
| 1120 | try expectDir(tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); |
| 1121 | } |
| 1122 | |
| 1123 | test "makepath relative walks" { |
| 1124 | var tmp = tmpDir(.{}); |
| 1125 | defer tmp.cleanup(); |
| 1126 | |
| 1127 | const relPath = try fs.path.join(testing.allocator, &.{ |
| 1128 | "first", "..", "second", "..", "third", "..", "first", "A", "..", "B", "..", "C", |
| 1129 | }); |
| 1130 | defer testing.allocator.free(relPath); |
| 1131 | |
| 1132 | try tmp.dir.makePath(relPath); |
| 1133 | |
| 1134 | // How .. is handled is different on Windows than non-Windows |
| 1135 | switch (builtin.os.tag) { |
| 1136 | .windows => { |
| 1137 | // On Windows, .. is resolved before passing the path to NtCreateFile, |
| 1138 | // meaning everything except `first/C` drops out. |
| 1139 | try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); |
| 1140 | try testing.expectError(error.FileNotFound, tmp.dir.access("second", .{})); |
| 1141 | try testing.expectError(error.FileNotFound, tmp.dir.access("third", .{})); |
| 1142 | }, |
| 1143 | else => { |
| 1144 | try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "A"); |
| 1145 | try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "B"); |
| 1146 | try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C"); |
| 1147 | try expectDir(tmp.dir, "second"); |
| 1148 | try expectDir(tmp.dir, "third"); |
| 1149 | }, |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1153 | test "makepath ignores '.'" { |
| 1154 | var tmp = tmpDir(.{}); |
| 1155 | defer tmp.cleanup(); |
| 1156 | |
| 1157 | // Path to create, with "." elements: |
| 1158 | const dotPath = try fs.path.join(testing.allocator, &.{ |
| 1159 | "first", ".", "second", ".", "third", |
| 1160 | }); |
| 1161 | defer testing.allocator.free(dotPath); |
| 1162 | |
| 1163 | // Path to expect to find: |
| 1164 | const expectedPath = try fs.path.join(testing.allocator, &.{ |
| 1165 | "first", "second", "third", |
| 1166 | }); |
| 1167 | defer testing.allocator.free(expectedPath); |
| 1168 | |
| 1169 | try tmp.dir.makePath(dotPath); |
| 1170 | |
| 1171 | try expectDir(tmp.dir, expectedPath); |
| 1172 | } |
| 1173 | |
| 1092 | 1174 | fn testFilenameLimits(iterable_dir: Dir, maxed_filename: []const u8) !void { |
| 1093 | 1175 | // setup, create a dir and a nested file both with maxed filenames, and walk the dir |
| 1094 | 1176 | { |
| ... | ... | @@ -1496,6 +1578,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1496 | 1578 | .lock = .exclusive, |
| 1497 | 1579 | .lock_nonblocking = true, |
| 1498 | 1580 | }); |
| 1581 | defer fs.deleteFileAbsolute(filename) catch {}; |
| 1499 | 1582 | |
| 1500 | 1583 | const file2 = fs.createFileAbsolute(filename, .{ |
| 1501 | 1584 | .lock = .exclusive, |
| ... | ... | @@ -1503,8 +1586,6 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1503 | 1586 | }); |
| 1504 | 1587 | file1.close(); |
| 1505 | 1588 | try testing.expectError(error.WouldBlock, file2); |
| 1506 | | |
| 1507 | | try fs.deleteFileAbsolute(filename); |
| 1508 | 1589 | } |
| 1509 | 1590 | |
| 1510 | 1591 | test "walker" { |
| ... | ... | @@ -1520,9 +1601,9 @@ test "walker" { |
| 1520 | 1601 | .{"dir2"}, |
| 1521 | 1602 | .{"dir3"}, |
| 1522 | 1603 | .{"dir4"}, |
| 1523 | | .{"dir3" ++ std.fs.path.sep_str ++ "sub1"}, |
| 1524 | | .{"dir3" ++ std.fs.path.sep_str ++ "sub2"}, |
| 1525 | | .{"dir3" ++ std.fs.path.sep_str ++ "sub2" ++ std.fs.path.sep_str ++ "subsub1"}, |
| 1604 | .{"dir3" ++ fs.path.sep_str ++ "sub1"}, |
| 1605 | .{"dir3" ++ fs.path.sep_str ++ "sub2"}, |
| 1606 | .{"dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1"}, |
| 1526 | 1607 | }); |
| 1527 | 1608 | |
| 1528 | 1609 | const expected_basenames = std.ComptimeStringMap(void, .{ |