authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-10-03 14:25:12-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-10-03 16:29:09-07:00
log894a99171491c9b054ae93b10ca3dc6fa6d8c125
tree7f6c87c201d7f96d8d9d7800f53c6e78a5d050aa
parent98dd8856ef901b99f198d992146abd0545adb5b2

Add depth function to `Walker.Entry`

This enables depth-related use cases without any dependency on the Walker's internal stack which doesn't always pertain to the actual depth of the current entry (i.e. recursing into a directory immediately affects the stack).

3 files changed, 28 insertions(+), 20 deletions(-)

lib/std/fs/Dir.zig+9-4
...@@ -732,16 +732,14 @@ pub const SelectiveWalker = struct {...@@ -732,16 +732,14 @@ pub const SelectiveWalker = struct {
732 });732 });
733 }733 }
734734
735 pub fn depth(self: *SelectiveWalker) usize {
736 return self.stack.items.len;
737 }
738
739 pub fn deinit(self: *SelectiveWalker) void {735 pub fn deinit(self: *SelectiveWalker) void {
740 self.name_buffer.deinit(self.allocator);736 self.name_buffer.deinit(self.allocator);
741 self.stack.deinit(self.allocator);737 self.stack.deinit(self.allocator);
742 }738 }
743739
744 /// Leaves the current directory, continuing walking one level up.740 /// Leaves the current directory, continuing walking one level up.
741 /// If the current entry is a directory entry, then the "current directory"
742 /// will pertain to that entry if `enter` is called before `leave`.
745 pub fn leave(self: *SelectiveWalker) void {743 pub fn leave(self: *SelectiveWalker) void {
746 var item = self.stack.pop().?;744 var item = self.stack.pop().?;
747 if (self.stack.items.len != 0) {745 if (self.stack.items.len != 0) {
...@@ -789,6 +787,13 @@ pub const Walker = struct {...@@ -789,6 +787,13 @@ pub const Walker = struct {
789 basename: [:0]const u8,787 basename: [:0]const u8,
790 path: [:0]const u8,788 path: [:0]const u8,
791 kind: Dir.Entry.Kind,789 kind: Dir.Entry.Kind,
790
791 /// Returns the depth of the entry relative to the initial directory.
792 /// Returns 1 for a direct child of the initial directory, 2 for an entry
793 /// within a direct child of the initial directory, etc.
794 pub fn depth(self: Walker.Entry) usize {
795 return mem.countScalar(u8, self.path, fs.path.sep) + 1;
796 }
792 };797 };
793798
794 const StackItem = struct {799 const StackItem = struct {
lib/std/fs/test.zig+18-15
...@@ -1765,14 +1765,14 @@ test "walker" {...@@ -1765,14 +1765,14 @@ test "walker" {
17651765
1766 // iteration order of walker is undefined, so need lookup maps to check against1766 // iteration order of walker is undefined, so need lookup maps to check against
17671767
1768 const expected_paths = std.StaticStringMap(void).initComptime(.{1768 const expected_paths = std.StaticStringMap(usize).initComptime(.{
1769 .{"dir1"},1769 .{ "dir1", 1 },
1770 .{"dir2"},1770 .{ "dir2", 1 },
1771 .{"dir3"},1771 .{ "dir3", 1 },
1772 .{"dir4"},1772 .{ "dir4", 1 },
1773 .{"dir3" ++ fs.path.sep_str ++ "sub1"},1773 .{ "dir3" ++ fs.path.sep_str ++ "sub1", 2 },
1774 .{"dir3" ++ fs.path.sep_str ++ "sub2"},1774 .{ "dir3" ++ fs.path.sep_str ++ "sub2", 2 },
1775 .{"dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1"},1775 .{ "dir3" ++ fs.path.sep_str ++ "sub2" ++ fs.path.sep_str ++ "subsub1", 3 },
1776 });1776 });
17771777
1778 const expected_basenames = std.StaticStringMap(void).initComptime(.{1778 const expected_basenames = std.StaticStringMap(void).initComptime(.{
...@@ -1802,6 +1802,10 @@ test "walker" {...@@ -1802,6 +1802,10 @@ test "walker" {
1802 std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});1802 std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
1803 return err;1803 return err;
1804 };1804 };
1805 testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| {
1806 std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
1807 return err;
1808 };
1805 // make sure that the entry.dir is the containing dir1809 // make sure that the entry.dir is the containing dir
1806 var entry_dir = try entry.dir.openDir(entry.basename, .{});1810 var entry_dir = try entry.dir.openDir(entry.basename, .{});
1807 defer entry_dir.close();1811 defer entry_dir.close();
...@@ -1851,6 +1855,10 @@ test "selective walker, skip entries that start with ." {...@@ -1851,6 +1855,10 @@ test "selective walker, skip entries that start with ." {
1851 var num_walked: usize = 0;1855 var num_walked: usize = 0;
1852 while (try walker.next()) |entry| {1856 while (try walker.next()) |entry| {
1853 if (entry.basename[0] == '.') continue;1857 if (entry.basename[0] == '.') continue;
1858 if (entry.kind == .directory) {
1859 try walker.enter(entry);
1860 }
1861
1854 testing.expect(expected_basenames.has(entry.basename)) catch |err| {1862 testing.expect(expected_basenames.has(entry.basename)) catch |err| {
1855 std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)});1863 std.debug.print("found unexpected basename: {f}\n", .{std.ascii.hexEscape(entry.basename, .lower)});
1856 return err;1864 return err;
...@@ -1859,16 +1867,11 @@ test "selective walker, skip entries that start with ." {...@@ -1859,16 +1867,11 @@ test "selective walker, skip entries that start with ." {
1859 std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});1867 std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
1860 return err;1868 return err;
1861 };1869 };
18621870 testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| {
1863 testing.expectEqual(expected_paths.get(entry.path).?, walker.depth()) catch |err| {1871 std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)});
1864 std.debug.print("path reported unexpected depth: {f}, {d}, expected {d}\n", .{ std.ascii.hexEscape(entry.path, .lower), walker.depth(), expected_paths.get(entry.path).? });
1865 return err;1872 return err;
1866 };1873 };
18671874
1868 if (entry.kind == .directory) {
1869 try walker.enter(entry);
1870 }
1871
1872 // make sure that the entry.dir is the containing dir1875 // make sure that the entry.dir is the containing dir
1873 var entry_dir = try entry.dir.openDir(entry.basename, .{});1876 var entry_dir = try entry.dir.openDir(entry.basename, .{});
1874 defer entry_dir.close();1877 defer entry_dir.close();
tools/update_mingw.zig+1-1
...@@ -117,7 +117,7 @@ pub fn main() !void {...@@ -117,7 +117,7 @@ pub fn main() !void {
117 while (try walker.next()) |entry| {117 while (try walker.next()) |entry| {
118 switch (entry.kind) {118 switch (entry.kind) {
119 .directory => {119 .directory => {
120 switch (walker.depth()) {120 switch (entry.depth()) {
121 1 => if (def_dirs.has(entry.basename)) {121 1 => if (def_dirs.has(entry.basename)) {
122 try walker.enter(entry);122 try walker.enter(entry);
123 continue;123 continue;