summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dump.zig26
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/").?);