From 513938c1cfb216a3bc4a3559cf7731b8e44a952f Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 6 Jul 2026 20:43:40 -0300 Subject: dumps: per-user data dir + timestamped names; Restore builtin loads a dump into the live session. dump.outPath resolves $PARDES_DUMP verbatim (the snapshot harness pins /tmp/pardes-dump.zon so dump/load/restore goldens stay deterministic), else $XDG_DATA_HOME|~/.local/share /pardes/pardes-YYYYMMDD-HHMMSS.zon (dir mkdir-ed; wall clock via libc clock_gettime — std.time.timestamp is gone in 0.16). After write_dump the shell reports the written path back (core.setLastDump) and the topbar grows "Restore ": middle-clicking Restore reloads the last dump, and "Restore " executed anywhere takes the path as its first argument (onSelect prefix match). Core stays sans-IO: the builtin stashes restore_req; each shell consumes takeRestore() after drainEffects and swaps in initFromDump at the current screen size (pre-sized: dump panes never greet), tearing down the live ptys (tty: cancel reader + close + gen bump; gui: SIGKILL, the gen-guarded eof closes the old fds). Web ignores it. New restore.snap golden: KEEPME survives the restore, GONESOON echoed after Dump does not, the topbar word appears then resets. 29/29. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dump.zig | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'src/dump.zig') diff --git a/src/dump.zig b/src/dump.zig index 9c1dceec..bff8af21 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -1,7 +1,36 @@ const std = @import("std"); const builtin = @import("builtin"); -pub const default_path = "/tmp/pardes-dump.zon"; +/// 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-.zon — timestamped so dumps never overwrite each other. +/// Creates the pardes dir (parents assumed; a failure surfaces at open). +pub fn outPath(buf: *[1024:0]u8) ?[:0]const u8 { + if (std.c.getenv("PARDES_DUMP")) |p| + return std.fmt.bufPrintSentinel(buf, "{s}", .{std.mem.span(p)}, 0) catch null; + var dir_buf: [900]u8 = undefined; + const dir = if (std.c.getenv("XDG_DATA_HOME")) |x| + std.fmt.bufPrint(&dir_buf, "{s}/pardes", .{std.mem.span(x)}) catch return null + else if (std.c.getenv("HOME")) |h| + std.fmt.bufPrint(&dir_buf, "{s}/.local/share/pardes", .{std.mem.span(h)}) catch return null + else + return null; + 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 + var ts: std.c.timespec = undefined; + _ = std.c.clock_gettime(.REALTIME, &ts); + const es: std.time.epoch.EpochSeconds = .{ .secs = @intCast(@max(0, ts.sec)) }; + const yd = es.getEpochDay().calculateYearDay(); + const md = yd.calculateMonthDay(); + const ds = es.getDaySeconds(); + return std.fmt.bufPrintSentinel(buf, "{s}/pardes-{d:0>4}{d:0>2}{d:0>2}-{d:0>2}{d:0>2}{d:0>2}.zon", .{ + dir, yd.year, md.month.numeric(), + @as(u8, md.day_index) + 1, ds.getHoursIntoDay(), ds.getMinutesIntoHour(), + ds.getSecondsIntoMinute(), + }, 0) catch null; +} pub const magic = "pardes-dump"; pub const version: u32 = 1; pub const max_panes: usize = 16; -- cgit v1.3