Commit c1285a1bbe

Ominitay <37453713+Ominitay@users.noreply.github.com>
2021-04-17 19:33:43
Move fs.Walker to fs.Dir.Walker
fs.Walker has been replaced with fs.Dir.Walker. Paths of entries returned are relative to the Dir.
1 parent f476463
Changed files (3)
lib/std/fs/test.zig
@@ -927,8 +927,9 @@ test "walker" {
     }
 
     const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
+    const tmp_dir = try fs.cwd().openDir(tmp_path, .{ .iterate = true });
 
-    var walker = try fs.walkPath(testing.allocator, tmp_path);
+    var walker = try tmp_dir.walk(testing.allocator);
     defer walker.deinit();
 
     i = 0;
@@ -941,7 +942,7 @@ test "walker" {
             try fs.path.join(allocator, &[_][]const u8{ expected_dir_name, name });
 
         var entry = (try walker.next()).?;
-        try testing.expectEqualStrings(expected_dir_name, try fs.path.relative(allocator, tmp_path, entry.path));
+        try testing.expectEqualStrings(expected_dir_name, entry.path);
     }
 }
 
lib/std/build.zig
@@ -3015,7 +3015,8 @@ pub const InstallDirStep = struct {
         const self = @fieldParentPtr(InstallDirStep, "step", step);
         const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir);
         const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);
-        var it = try fs.walkPath(self.builder.allocator, full_src_dir);
+        const src_dir = try std.fs.cwd().openDir(full_src_dir, .{ .iterate = true });
+        var it = try src_dir.walk(self.builder.allocator);
         next_entry: while (try it.next()) |entry| {
             for (self.options.exclude_extensions) |ext| {
                 if (mem.endsWith(u8, entry.path, ext)) {
@@ -3023,9 +3024,12 @@ pub const InstallDirStep = struct {
                 }
             }
 
-            const rel_path = entry.path[full_src_dir.len + 1 ..];
+            const full_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
+                full_src_dir, entry.path,
+            });
+
             const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
-                dest_prefix, rel_path,
+                dest_prefix, entry.path,
             });
 
             switch (entry.kind) {
@@ -3038,7 +3042,7 @@ pub const InstallDirStep = struct {
                         }
                     }
 
-                    try self.builder.updateFile(entry.path, dest_path);
+                    try self.builder.updateFile(full_path, dest_path);
                 },
                 else => continue,
             }
lib/std/fs.zig
@@ -737,6 +737,94 @@ pub const Dir = struct {
         }
     }
 
+    pub const Walker = struct {
+        stack: std.ArrayList(StackItem),
+        name_buffer: std.ArrayList(u8),
+
+        pub const WalkerEntry = struct {
+            /// The containing directory. This can be used to operate directly on `basename`
+            /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
+            /// The directory remains open until `next` or `deinit` is called.
+            dir: Dir,
+            basename: []const u8,
+            path: []const u8,
+            kind: Dir.Entry.Kind,
+        };
+
+        const StackItem = struct {
+            iter: Dir.Iterator,
+            dirname_len: usize,
+        };
+
+        /// After each call to this function, and on deinit(), the memory returned
+        /// from this function becomes invalid. A copy must be made in order to keep
+        /// a reference to the path.
+        pub fn next(self: *Walker) !?WalkerEntry {
+            while (self.stack.items.len != 0) {
+                // `top` becomes invalid after appending to `self.stack`
+                var top = &self.stack.items[self.stack.items.len - 1];
+                const dirname_len = top.dirname_len;
+                if (try top.iter.next()) |base| {
+                    self.name_buffer.shrinkRetainingCapacity(dirname_len);
+                    if (self.name_buffer.items.len != 0) {
+                        try self.name_buffer.append(path.sep);
+                    }
+                    try self.name_buffer.appendSlice(base.name);
+                    if (base.kind == .Directory) {
+                        var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
+                            error.NameTooLong => unreachable, // no path sep in base.name
+                            else => |e| return e,
+                        };
+                        {
+                            errdefer new_dir.close();
+                            try self.stack.append(StackItem{
+                                .iter = new_dir.iterate(),
+                                .dirname_len = self.name_buffer.items.len,
+                            });
+                            top = &self.stack.items[self.stack.items.len - 1];
+                        }
+                    }
+                    return WalkerEntry{
+                        .dir = top.iter.dir,
+                        .basename = self.name_buffer.items[dirname_len + 1 ..],
+                        .path = self.name_buffer.items,
+                        .kind = base.kind,
+                    };
+                } else {
+                    self.stack.pop().iter.dir.close();
+                }
+            }
+            return null;
+        }
+
+        pub fn deinit(self: *Walker) void {
+            while (self.stack.popOrNull()) |*item| item.iter.dir.close();
+            self.stack.deinit();
+            self.name_buffer.deinit();
+        }
+    };
+
+    /// Recursively iterates over a directory.
+    /// Must call `Walker.deinit` when done.
+    /// The order of returned file system entries is undefined.
+    pub fn walk(self: Dir, allocator: *Allocator) !Walker {
+        var name_buffer = std.ArrayList(u8).init(allocator);
+        errdefer name_buffer.deinit();
+
+        var stack = std.ArrayList(Walker.StackItem).init(allocator);
+        errdefer stack.deinit();
+
+        try stack.append(Walker.StackItem{
+            .iter = self.iterate(),
+            .dirname_len = 0,
+        });
+
+        return Walker{
+            .stack = stack,
+            .name_buffer = name_buffer,
+        };
+    }
+
     pub const OpenError = error{
         FileNotFound,
         NotDir,
@@ -2259,100 +2347,7 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons
 pub const symLink = @compileError("deprecated: use Dir.symLink or symLinkAbsolute");
 pub const symLinkC = @compileError("deprecated: use Dir.symLinkZ or symLinkAbsoluteZ");
 
-pub const Walker = struct {
-    stack: std.ArrayList(StackItem),
-    name_buffer: std.ArrayList(u8),
-
-    pub const Entry = struct {
-        /// The containing directory. This can be used to operate directly on `basename`
-        /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
-        /// The directory remains open until `next` or `deinit` is called.
-        dir: Dir,
-        /// TODO make this null terminated for API convenience
-        basename: []const u8,
-
-        path: []const u8,
-        kind: Dir.Entry.Kind,
-    };
-
-    const StackItem = struct {
-        dir_it: Dir.Iterator,
-        dirname_len: usize,
-    };
-
-    /// After each call to this function, and on deinit(), the memory returned
-    /// from this function becomes invalid. A copy must be made in order to keep
-    /// a reference to the path.
-    pub fn next(self: *Walker) !?Entry {
-        while (true) {
-            if (self.stack.items.len == 0) return null;
-            // `top` becomes invalid after appending to `self.stack`.
-            var top = &self.stack.items[self.stack.items.len - 1];
-            const dirname_len = top.dirname_len;
-            if (try top.dir_it.next()) |base| {
-                self.name_buffer.shrinkRetainingCapacity(dirname_len);
-                try self.name_buffer.append(path.sep);
-                try self.name_buffer.appendSlice(base.name);
-                if (base.kind == .Directory) {
-                    var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
-                        error.NameTooLong => unreachable, // no path sep in base.name
-                        else => |e| return e,
-                    };
-                    {
-                        errdefer new_dir.close();
-                        try self.stack.append(StackItem{
-                            .dir_it = new_dir.iterate(),
-                            .dirname_len = self.name_buffer.items.len,
-                        });
-                        top = &self.stack.items[self.stack.items.len - 1];
-                    }
-                }
-                return Entry{
-                    .dir = top.dir_it.dir,
-                    .basename = self.name_buffer.items[dirname_len + 1 ..],
-                    .path = self.name_buffer.items,
-                    .kind = base.kind,
-                };
-            } else {
-                self.stack.pop().dir_it.dir.close();
-            }
-        }
-    }
-
-    pub fn deinit(self: *Walker) void {
-        while (self.stack.popOrNull()) |*item| item.dir_it.dir.close();
-        self.stack.deinit();
-        self.name_buffer.deinit();
-    }
-};
-
-/// Recursively iterates over a directory.
-/// Must call `Walker.deinit` when done.
-/// `dir_path` must not end in a path separator.
-/// The order of returned file system entries is undefined.
-pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
-    assert(!mem.endsWith(u8, dir_path, path.sep_str));
-
-    var dir = try cwd().openDir(dir_path, .{ .iterate = true });
-    errdefer dir.close();
-
-    var name_buffer = std.ArrayList(u8).init(allocator);
-    errdefer name_buffer.deinit();
-
-    try name_buffer.appendSlice(dir_path);
-
-    var walker = Walker{
-        .stack = std.ArrayList(Walker.StackItem).init(allocator),
-        .name_buffer = name_buffer,
-    };
-
-    try walker.stack.append(Walker.StackItem{
-        .dir_it = dir.iterate(),
-        .dirname_len = dir_path.len,
-    });
-
-    return walker;
-}
+pub const walkPath = @compileError("deprecated: use Dir.walk");
 
 pub const OpenSelfExeError = error{
     SharingViolation,