authorgravatar for 37453713+Ominitay@users.noreply.github.comOminitay <37453713+Ominitay@users.noreply.github.com> 2021-04-17 18:33:43+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-07-28 21:39:36+03:00
logc1285a1bbe04ab9960768ed8eb583ba8eb32cbe1
treeb6e46ee8af362c2ad5a42cf52f0ca4e349c519db
parentf476463cd2552d384d0ef6f43f250b3abd45e4cd

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.

3 files changed, 100 insertions(+), 100 deletions(-)

lib/std/build.zig+8-4
......@@ -3015,7 +3015,8 @@ pub const InstallDirStep = struct {
30153015 const self = @fieldParentPtr(InstallDirStep, "step", step);
30163016 const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir);
30173017 const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);
3018 var it = try fs.walkPath(self.builder.allocator, full_src_dir);
3018 const src_dir = try std.fs.cwd().openDir(full_src_dir, .{ .iterate = true });
3019 var it = try src_dir.walk(self.builder.allocator);
30193020 next_entry: while (try it.next()) |entry| {
30203021 for (self.options.exclude_extensions) |ext| {
30213022 if (mem.endsWith(u8, entry.path, ext)) {
......@@ -3023,9 +3024,12 @@ pub const InstallDirStep = struct {
30233024 }
30243025 }
30253026
3026 const rel_path = entry.path[full_src_dir.len + 1 ..];
3027 const full_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
3028 full_src_dir, entry.path,
3029 });
3030
30273031 const dest_path = try fs.path.join(self.builder.allocator, &[_][]const u8{
3028 dest_prefix, rel_path,
3032 dest_prefix, entry.path,
30293033 });
30303034
30313035 switch (entry.kind) {
......@@ -3038,7 +3042,7 @@ pub const InstallDirStep = struct {
30383042 }
30393043 }
30403044
3041 try self.builder.updateFile(entry.path, dest_path);
3045 try self.builder.updateFile(full_path, dest_path);
30423046 },
30433047 else => continue,
30443048 }
lib/std/fs.zig+89-94
......@@ -737,6 +737,94 @@ pub const Dir = struct {
737737 }
738738 }
739739
740 pub const Walker = struct {
741 stack: std.ArrayList(StackItem),
742 name_buffer: std.ArrayList(u8),
743
744 pub const WalkerEntry = struct {
745 /// The containing directory. This can be used to operate directly on `basename`
746 /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
747 /// The directory remains open until `next` or `deinit` is called.
748 dir: Dir,
749 basename: []const u8,
750 path: []const u8,
751 kind: Dir.Entry.Kind,
752 };
753
754 const StackItem = struct {
755 iter: Dir.Iterator,
756 dirname_len: usize,
757 };
758
759 /// After each call to this function, and on deinit(), the memory returned
760 /// from this function becomes invalid. A copy must be made in order to keep
761 /// a reference to the path.
762 pub fn next(self: *Walker) !?WalkerEntry {
763 while (self.stack.items.len != 0) {
764 // `top` becomes invalid after appending to `self.stack`
765 var top = &self.stack.items[self.stack.items.len - 1];
766 const dirname_len = top.dirname_len;
767 if (try top.iter.next()) |base| {
768 self.name_buffer.shrinkRetainingCapacity(dirname_len);
769 if (self.name_buffer.items.len != 0) {
770 try self.name_buffer.append(path.sep);
771 }
772 try self.name_buffer.appendSlice(base.name);
773 if (base.kind == .Directory) {
774 var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
775 error.NameTooLong => unreachable, // no path sep in base.name
776 else => |e| return e,
777 };
778 {
779 errdefer new_dir.close();
780 try self.stack.append(StackItem{
781 .iter = new_dir.iterate(),
782 .dirname_len = self.name_buffer.items.len,
783 });
784 top = &self.stack.items[self.stack.items.len - 1];
785 }
786 }
787 return WalkerEntry{
788 .dir = top.iter.dir,
789 .basename = self.name_buffer.items[dirname_len + 1 ..],
790 .path = self.name_buffer.items,
791 .kind = base.kind,
792 };
793 } else {
794 self.stack.pop().iter.dir.close();
795 }
796 }
797 return null;
798 }
799
800 pub fn deinit(self: *Walker) void {
801 while (self.stack.popOrNull()) |*item| item.iter.dir.close();
802 self.stack.deinit();
803 self.name_buffer.deinit();
804 }
805 };
806
807 /// Recursively iterates over a directory.
808 /// Must call `Walker.deinit` when done.
809 /// The order of returned file system entries is undefined.
810 pub fn walk(self: Dir, allocator: *Allocator) !Walker {
811 var name_buffer = std.ArrayList(u8).init(allocator);
812 errdefer name_buffer.deinit();
813
814 var stack = std.ArrayList(Walker.StackItem).init(allocator);
815 errdefer stack.deinit();
816
817 try stack.append(Walker.StackItem{
818 .iter = self.iterate(),
819 .dirname_len = 0,
820 });
821
822 return Walker{
823 .stack = stack,
824 .name_buffer = name_buffer,
825 };
826 }
827
740828 pub const OpenError = error{
741829 FileNotFound,
742830 NotDir,
......@@ -2259,100 +2347,7 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons
22592347pub const symLink = @compileError("deprecated: use Dir.symLink or symLinkAbsolute");
22602348pub const symLinkC = @compileError("deprecated: use Dir.symLinkZ or symLinkAbsoluteZ");
22612349
2262pub const Walker = struct {
2263 stack: std.ArrayList(StackItem),
2264 name_buffer: std.ArrayList(u8),
2265
2266 pub const Entry = struct {
2267 /// The containing directory. This can be used to operate directly on `basename`
2268 /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths.
2269 /// The directory remains open until `next` or `deinit` is called.
2270 dir: Dir,
2271 /// TODO make this null terminated for API convenience
2272 basename: []const u8,
2273
2274 path: []const u8,
2275 kind: Dir.Entry.Kind,
2276 };
2277
2278 const StackItem = struct {
2279 dir_it: Dir.Iterator,
2280 dirname_len: usize,
2281 };
2282
2283 /// After each call to this function, and on deinit(), the memory returned
2284 /// from this function becomes invalid. A copy must be made in order to keep
2285 /// a reference to the path.
2286 pub fn next(self: *Walker) !?Entry {
2287 while (true) {
2288 if (self.stack.items.len == 0) return null;
2289 // `top` becomes invalid after appending to `self.stack`.
2290 var top = &self.stack.items[self.stack.items.len - 1];
2291 const dirname_len = top.dirname_len;
2292 if (try top.dir_it.next()) |base| {
2293 self.name_buffer.shrinkRetainingCapacity(dirname_len);
2294 try self.name_buffer.append(path.sep);
2295 try self.name_buffer.appendSlice(base.name);
2296 if (base.kind == .Directory) {
2297 var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
2298 error.NameTooLong => unreachable, // no path sep in base.name
2299 else => |e| return e,
2300 };
2301 {
2302 errdefer new_dir.close();
2303 try self.stack.append(StackItem{
2304 .dir_it = new_dir.iterate(),
2305 .dirname_len = self.name_buffer.items.len,
2306 });
2307 top = &self.stack.items[self.stack.items.len - 1];
2308 }
2309 }
2310 return Entry{
2311 .dir = top.dir_it.dir,
2312 .basename = self.name_buffer.items[dirname_len + 1 ..],
2313 .path = self.name_buffer.items,
2314 .kind = base.kind,
2315 };
2316 } else {
2317 self.stack.pop().dir_it.dir.close();
2318 }
2319 }
2320 }
2321
2322 pub fn deinit(self: *Walker) void {
2323 while (self.stack.popOrNull()) |*item| item.dir_it.dir.close();
2324 self.stack.deinit();
2325 self.name_buffer.deinit();
2326 }
2327};
2328
2329/// Recursively iterates over a directory.
2330/// Must call `Walker.deinit` when done.
2331/// `dir_path` must not end in a path separator.
2332/// The order of returned file system entries is undefined.
2333pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
2334 assert(!mem.endsWith(u8, dir_path, path.sep_str));
2335
2336 var dir = try cwd().openDir(dir_path, .{ .iterate = true });
2337 errdefer dir.close();
2338
2339 var name_buffer = std.ArrayList(u8).init(allocator);
2340 errdefer name_buffer.deinit();
2341
2342 try name_buffer.appendSlice(dir_path);
2343
2344 var walker = Walker{
2345 .stack = std.ArrayList(Walker.StackItem).init(allocator),
2346 .name_buffer = name_buffer,
2347 };
2348
2349 try walker.stack.append(Walker.StackItem{
2350 .dir_it = dir.iterate(),
2351 .dirname_len = dir_path.len,
2352 });
2353
2354 return walker;
2355}
2350pub const walkPath = @compileError("deprecated: use Dir.walk");
23562351
23572352pub const OpenSelfExeError = error{
23582353 SharingViolation,
lib/std/fs/test.zig+3-2
......@@ -927,8 +927,9 @@ test "walker" {
927927 }
928928
929929 const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
930 const tmp_dir = try fs.cwd().openDir(tmp_path, .{ .iterate = true });
930931
931 var walker = try fs.walkPath(testing.allocator, tmp_path);
932 var walker = try tmp_dir.walk(testing.allocator);
932933 defer walker.deinit();
933934
934935 i = 0;
......@@ -941,7 +942,7 @@ test "walker" {
941942 try fs.path.join(allocator, &[_][]const u8{ expected_dir_name, name });
942943
943944 var entry = (try walker.next()).?;
944 try testing.expectEqualStrings(expected_dir_name, try fs.path.relative(allocator, tmp_path, entry.path));
945 try testing.expectEqualStrings(expected_dir_name, entry.path);
945946 }
946947}
947948