| author | |
| committer | |
| log | e9bf8014bd29360353a9bfdff4aa9d5a45bc59f6 |
| tree | 5bf91e0cb5e2489c297a5ccf1c8efcfe5d73e966 |
| parent | fcf2ce0ffee549ac882879364cd7e743ac10be20 |
| parent | f6bb56f8c7bd173982d48925d952afb0fd1cd6e5 |
| signature |
fs.Dir.Walker: Fix basename missing its first character for direct children of the initial directory3 files changed, 44 insertions(+), 24 deletions(-)
lib/std/comptime_string_map.zig+5-3| ... | @@ -13,21 +13,21 @@ const mem = std.mem; | ... | @@ -13,21 +13,21 @@ const mem = std.mem; |
| 13 | /// `kvs` expects a list literal containing list literals or an array/slice of structs | 13 | /// `kvs` expects a list literal containing list literals or an array/slice of structs |
| 14 | /// where `.@"0"` is the `[]const u8` key and `.@"1"` is the associated value of type `V`. | 14 | /// where `.@"0"` is the `[]const u8` key and `.@"1"` is the associated value of type `V`. |
| 15 | /// TODO: https://github.com/ziglang/zig/issues/4335 | 15 | /// TODO: https://github.com/ziglang/zig/issues/4335 |
| 16 | pub fn ComptimeStringMap(comptime V: type, comptime kvs: anytype) type { | 16 | pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type { |
| 17 | const precomputed = comptime blk: { | 17 | const precomputed = comptime blk: { |
| 18 | @setEvalBranchQuota(2000); | 18 | @setEvalBranchQuota(2000); |
| 19 | const KV = struct { | 19 | const KV = struct { |
| 20 | key: []const u8, | 20 | key: []const u8, |
| 21 | value: V, | 21 | value: V, |
| 22 | }; | 22 | }; |
| 23 | var sorted_kvs: [kvs.len]KV = undefined; | 23 | var sorted_kvs: [kvs_list.len]KV = undefined; |
| 24 | const lenAsc = (struct { | 24 | const lenAsc = (struct { |
| 25 | fn lenAsc(context: void, a: KV, b: KV) bool { | 25 | fn lenAsc(context: void, a: KV, b: KV) bool { |
| 26 | _ = context; | 26 | _ = context; |
| 27 | return a.key.len < b.key.len; | 27 | return a.key.len < b.key.len; |
| 28 | } | 28 | } |
| 29 | }).lenAsc; | 29 | }).lenAsc; |
| 30 | for (kvs) |kv, i| { | 30 | for (kvs_list) |kv, i| { |
| 31 | if (V != void) { | 31 | if (V != void) { |
| 32 | sorted_kvs[i] = .{ .key = kv.@"0", .value = kv.@"1" }; | 32 | sorted_kvs[i] = .{ .key = kv.@"0", .value = kv.@"1" }; |
| 33 | } else { | 33 | } else { |
| ... | @@ -56,6 +56,8 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs: anytype) type { | ... | @@ -56,6 +56,8 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs: anytype) type { |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | return struct { | 58 | return struct { |
| 59 | pub const kvs = precomputed.sorted_kvs; | ||
| 60 | |||
| 59 | pub fn has(str: []const u8) bool { | 61 | pub fn has(str: []const u8) bool { |
| 60 | return get(str) != null; | 62 | return get(str) != null; |
| 61 | } | 63 | } |
lib/std/fs.zig+3-2| ... | @@ -766,11 +766,12 @@ pub const Dir = struct { | ... | @@ -766,11 +766,12 @@ pub const Dir = struct { |
| 766 | while (self.stack.items.len != 0) { | 766 | while (self.stack.items.len != 0) { |
| 767 | // `top` becomes invalid after appending to `self.stack` | 767 | // `top` becomes invalid after appending to `self.stack` |
| 768 | var top = &self.stack.items[self.stack.items.len - 1]; | 768 | var top = &self.stack.items[self.stack.items.len - 1]; |
| 769 | const dirname_len = top.dirname_len; | 769 | var dirname_len = top.dirname_len; |
| 770 | if (try top.iter.next()) |base| { | 770 | if (try top.iter.next()) |base| { |
| 771 | self.name_buffer.shrinkRetainingCapacity(dirname_len); | 771 | self.name_buffer.shrinkRetainingCapacity(dirname_len); |
| 772 | if (self.name_buffer.items.len != 0) { | 772 | if (self.name_buffer.items.len != 0) { |
| 773 | try self.name_buffer.append(path.sep); | 773 | try self.name_buffer.append(path.sep); |
| 774 | dirname_len += 1; | ||
| 774 | } | 775 | } |
| 775 | try self.name_buffer.appendSlice(base.name); | 776 | try self.name_buffer.appendSlice(base.name); |
| 776 | if (base.kind == .Directory) { | 777 | if (base.kind == .Directory) { |
| ... | @@ -789,7 +790,7 @@ pub const Dir = struct { | ... | @@ -789,7 +790,7 @@ pub const Dir = struct { |
| 789 | } | 790 | } |
| 790 | return WalkerEntry{ | 791 | return WalkerEntry{ |
| 791 | .dir = top.iter.dir, | 792 | .dir = top.iter.dir, |
| 792 | .basename = self.name_buffer.items[dirname_len + 1 ..], | 793 | .basename = self.name_buffer.items[dirname_len..], |
| 793 | .path = self.name_buffer.items, | 794 | .path = self.name_buffer.items, |
| 794 | .kind = base.kind, | 795 | .kind = base.kind, |
| 795 | }; | 796 | }; |
lib/std/fs/test.zig+36-19| ... | @@ -916,14 +916,30 @@ test "walker" { | ... | @@ -916,14 +916,30 @@ test "walker" { |
| 916 | var tmp = tmpDir(.{}); | 916 | var tmp = tmpDir(.{}); |
| 917 | defer tmp.cleanup(); | 917 | defer tmp.cleanup(); |
| 918 | 918 | ||
| 919 | const nb_dirs = 8; | 919 | // iteration order of walker is undefined, so need lookup maps to check against |
| 920 | 920 | ||
| 921 | var i: usize = 0; | 921 | const expected_paths = std.ComptimeStringMap(void, .{ |
| 922 | var sub_dir = tmp.dir; | 922 | .{"dir1"}, |
| 923 | while (i < nb_dirs) : (i += 1) { | 923 | .{"dir2"}, |
| 924 | const dir_name = try std.fmt.allocPrint(allocator, "{}", .{i}); | 924 | .{"dir3"}, |
| 925 | try sub_dir.makeDir(dir_name); | 925 | .{"dir4"}, |
| 926 | sub_dir = try sub_dir.openDir(dir_name, .{}); | 926 | .{"dir3" ++ std.fs.path.sep_str ++ "sub1"}, |
| 927 | .{"dir3" ++ std.fs.path.sep_str ++ "sub2"}, | ||
| 928 | .{"dir3" ++ std.fs.path.sep_str ++ "sub2" ++ std.fs.path.sep_str ++ "subsub1"}, | ||
| 929 | }); | ||
| 930 | |||
| 931 | const expected_basenames = std.ComptimeStringMap(void, .{ | ||
| 932 | .{"dir1"}, | ||
| 933 | .{"dir2"}, | ||
| 934 | .{"dir3"}, | ||
| 935 | .{"dir4"}, | ||
| 936 | .{"sub1"}, | ||
| 937 | .{"sub2"}, | ||
| 938 | .{"subsub1"}, | ||
| 939 | }); | ||
| 940 | |||
| 941 | for (expected_paths.kvs) |kv| { | ||
| 942 | try tmp.dir.makePath(kv.key); | ||
| 927 | } | 943 | } |
| 928 | 944 | ||
| 929 | const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] }); | 945 | const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] }); |
| ... | @@ -932,18 +948,19 @@ test "walker" { | ... | @@ -932,18 +948,19 @@ test "walker" { |
| 932 | var walker = try tmp_dir.walk(testing.allocator); | 948 | var walker = try tmp_dir.walk(testing.allocator); |
| 933 | defer walker.deinit(); | 949 | defer walker.deinit(); |
| 934 | 950 | ||
| 935 | i = 0; | 951 | var num_walked: usize = 0; |
| 936 | var expected_dir_name: []const u8 = ""; | 952 | while (try walker.next()) |entry| { |
| 937 | while (i < nb_dirs) : (i += 1) { | 953 | testing.expect(expected_basenames.has(entry.basename)) catch |err| { |
| 938 | const name = try std.fmt.allocPrint(allocator, "{}", .{i}); | 954 | std.debug.print("found unexpected basename: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.basename)}); |
| 939 | expected_dir_name = if (expected_dir_name.len == 0) | 955 | return err; |
| 940 | name | 956 | }; |
| 941 | else | 957 | testing.expect(expected_paths.has(entry.path)) catch |err| { |
| 942 | try fs.path.join(allocator, &[_][]const u8{ expected_dir_name, name }); | 958 | std.debug.print("found unexpected path: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.path)}); |
| 943 | 959 | return err; | |
| 944 | var entry = (try walker.next()).?; | 960 | }; |
| 945 | try testing.expectEqualStrings(expected_dir_name, entry.path); | 961 | num_walked += 1; |
| 946 | } | 962 | } |
| 963 | try testing.expectEqual(expected_paths.kvs.len, num_walked); | ||
| 947 | } | 964 | } |
| 948 | 965 | ||
| 949 | test ". and .. in fs.Dir functions" { | 966 | test ". and .. in fs.Dir functions" { |