diff options
Diffstat (limited to 'src/dump.zig')
| -rw-r--r-- | src/dump.zig | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/dump.zig b/src/dump.zig index 194c1ed3..a2efb95d 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -31,7 +31,8 @@ const Pardes = pardes.Pardes; /// Where the next dump goes. $PARDES_DUMP wins verbatim (the snapshot harness /// pins it for deterministic goldens); else $XDG_DATA_HOME|~/.local/share /// /pardes/pardes-<utc>.zon — timestamped so dumps never overwrite each other. -/// Creates the pardes dir (parents assumed; a failure surfaces at open). +/// Creates the directory and any parent missing (a fresh HOME has no +/// ~/.local/share); a failure surfaces at open. pub fn outPath(buf: *[1024:0]u8, dir_setting: []const u8) ?[:0]const u8 { if (std.c.getenv("PARDES_DUMP")) |p| return std.fmt.bufPrintSentinel(buf, "{s}", .{std.mem.span(p)}, 0) catch null; @@ -40,7 +41,13 @@ pub fn outPath(buf: *[1024:0]u8, dir_setting: []const u8) ?[:0]const u8 { var dz: [901:0]u8 = undefined; @memcpy(dz[0..dir.len], dir); dz[dir.len] = 0; - _ = std.c.mkdir(dz[0..dir.len :0], 0o755); // EEXIST is fine + // Each missing directory on the way, as `mkdir -p`: EEXIST is fine. + for (dz[1..dir.len], 1..) |c, i| if (c == '/') { + dz[i] = 0; + _ = std.c.mkdir(dz[0..i :0], 0o755); + dz[i] = '/'; + }; + _ = std.c.mkdir(dz[0..dir.len :0], 0o755); var ts: std.c.timespec = undefined; _ = std.c.clock_gettime(.REALTIME, &ts); const es: std.time.epoch.EpochSeconds = .{ .secs = @intCast(@max(0, ts.sec)) }; @@ -109,6 +116,21 @@ pub fn directory(buf: []u8, dir_setting: []const u8) ?[]const u8 { return std.fmt.bufPrint(buf, "{s}", .{resolved}) catch null; } +test "a dump makes every directory missing on the way to its DumpDir" { + if (std.c.getenv("PARDES_DUMP") != null) return error.SkipZigTest; + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + var at: [4096]u8 = undefined; + const base = at[0..try tmp.dir.realPath(std.testing.io, &at)]; + var setting: [4200]u8 = undefined; + const dir = try std.fmt.bufPrint(&setting, "{s}/fresh/.local/share/pardes", .{base}); + var out: [1024:0]u8 = undefined; + const path = outPath(&out, dir).?; + try std.testing.expect(std.mem.startsWith(u8, path, dir)); + var made = try tmp.dir.openDir(std.testing.io, "fresh/.local/share/pardes", .{}); + made.close(std.testing.io); +} + test "a DumpDir reads back absolute, however it was written" { var buf: [4096]u8 = undefined; try std.testing.expectEqualStrings("/tmp/dumps", directory(&buf, "/tmp/dumps/").?); |
