commit e9bf8014bd29360353a9bfdff4aa9d5a45bc59f6 (tree)
parent fcf2ce0ffee549ac882879364cd7e743ac10be20
Author: Veikka Tuominen <git@vexu.eu>
Date: Sat, 14 Aug 2021 11:08:10 +0300
Merge pull request #9559 from squeek502/walker-basename
fs.Dir.Walker: Fix basename missing its first character for direct children of the initial directory
Diffstat:
3 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/lib/std/comptime_string_map.zig b/lib/std/comptime_string_map.zig
@@ -13,21 +13,21 @@ const mem = std.mem;
/// `kvs` expects a list literal containing list literals or an array/slice of structs
/// where `.@"0"` is the `[]const u8` key and `.@"1"` is the associated value of type `V`.
/// TODO: https://github.com/ziglang/zig/issues/4335
-pub fn ComptimeStringMap(comptime V: type, comptime kvs: anytype) type {
+pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type {
const precomputed = comptime blk: {
@setEvalBranchQuota(2000);
const KV = struct {
key: []const u8,
value: V,
};
- var sorted_kvs: [kvs.len]KV = undefined;
+ var sorted_kvs: [kvs_list.len]KV = undefined;
const lenAsc = (struct {
fn lenAsc(context: void, a: KV, b: KV) bool {
_ = context;
return a.key.len < b.key.len;
}
}).lenAsc;
- for (kvs) |kv, i| {
+ for (kvs_list) |kv, i| {
if (V != void) {
sorted_kvs[i] = .{ .key = kv.@"0", .value = kv.@"1" };
} else {
@@ -56,6 +56,8 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs: anytype) type {
};
return struct {
+ pub const kvs = precomputed.sorted_kvs;
+
pub fn has(str: []const u8) bool {
return get(str) != null;
}
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
@@ -766,11 +766,12 @@ pub const Dir = struct {
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;
+ var 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);
+ dirname_len += 1;
}
try self.name_buffer.appendSlice(base.name);
if (base.kind == .Directory) {
@@ -789,7 +790,7 @@ pub const Dir = struct {
}
return WalkerEntry{
.dir = top.iter.dir,
- .basename = self.name_buffer.items[dirname_len + 1 ..],
+ .basename = self.name_buffer.items[dirname_len..],
.path = self.name_buffer.items,
.kind = base.kind,
};
diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig
@@ -916,14 +916,30 @@ test "walker" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
- const nb_dirs = 8;
-
- var i: usize = 0;
- var sub_dir = tmp.dir;
- while (i < nb_dirs) : (i += 1) {
- const dir_name = try std.fmt.allocPrint(allocator, "{}", .{i});
- try sub_dir.makeDir(dir_name);
- sub_dir = try sub_dir.openDir(dir_name, .{});
+ // iteration order of walker is undefined, so need lookup maps to check against
+
+ const expected_paths = std.ComptimeStringMap(void, .{
+ .{"dir1"},
+ .{"dir2"},
+ .{"dir3"},
+ .{"dir4"},
+ .{"dir3" ++ std.fs.path.sep_str ++ "sub1"},
+ .{"dir3" ++ std.fs.path.sep_str ++ "sub2"},
+ .{"dir3" ++ std.fs.path.sep_str ++ "sub2" ++ std.fs.path.sep_str ++ "subsub1"},
+ });
+
+ const expected_basenames = std.ComptimeStringMap(void, .{
+ .{"dir1"},
+ .{"dir2"},
+ .{"dir3"},
+ .{"dir4"},
+ .{"sub1"},
+ .{"sub2"},
+ .{"subsub1"},
+ });
+
+ for (expected_paths.kvs) |kv| {
+ try tmp.dir.makePath(kv.key);
}
const tmp_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
@@ -932,18 +948,19 @@ test "walker" {
var walker = try tmp_dir.walk(testing.allocator);
defer walker.deinit();
- i = 0;
- var expected_dir_name: []const u8 = "";
- while (i < nb_dirs) : (i += 1) {
- const name = try std.fmt.allocPrint(allocator, "{}", .{i});
- expected_dir_name = if (expected_dir_name.len == 0)
- name
- else
- try fs.path.join(allocator, &[_][]const u8{ expected_dir_name, name });
-
- var entry = (try walker.next()).?;
- try testing.expectEqualStrings(expected_dir_name, entry.path);
+ var num_walked: usize = 0;
+ while (try walker.next()) |entry| {
+ testing.expect(expected_basenames.has(entry.basename)) catch |err| {
+ std.debug.print("found unexpected basename: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.basename)});
+ return err;
+ };
+ testing.expect(expected_paths.has(entry.path)) catch |err| {
+ std.debug.print("found unexpected path: {s}\n", .{std.fmt.fmtSliceEscapeLower(entry.path)});
+ return err;
+ };
+ num_walked += 1;
}
+ try testing.expectEqual(expected_paths.kvs.len, num_walked);
}
test ". and .. in fs.Dir functions" {