From ab220b89afcfda848cf84c18cc135a2e5c392b79 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 12:14:13 -0300 Subject: Recent goes on across a Restore, and is kept after it A Restore makes a new session, which never loaded the kept list, and saveRecent gives up until it has: Recent was empty after a Restore and nothing opened afterwards was kept. The new session now takes the old one's list (a boot from a dump reads the kept file). Co-Authored-By: Claude Opus 5.5 --- src/dump.zig | 5 ++++- src/pardes.zig | 2 +- src/recent.zig | 17 +++++++++++++++++ test/fs.py | 7 +++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/dump.zig b/src/dump.zig index 7b27876e..4db3df24 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -802,7 +802,10 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo p.cell_pixels = old.cell_pixels; p.row_metrics = old.row_metrics; p.native_images = old.native_images; - } + // Recent goes on across a Restore, the old session's own list. + p.recent = old.recent.clone(p.recentGpa()); + p.recent_loaded = old.recent_loaded; + } else p.loadRecent(); for (opts.mounts) |mount| try p.fs.mount(gpa, mount.name, mount.dial); p.opts.mounts = &.{}; var parsed = try readZon(gpa, zon_bytes, "load"); diff --git a/src/pardes.zig b/src/pardes.zig index f6032ac5..ba9a1f90 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -4675,7 +4675,7 @@ pub const Pardes = struct { } /// The kept list of files opened lately, read once at start. - fn loadRecent(p: *Pardes) void { + pub fn loadRecent(p: *Pardes) void { const path = p.opts.recent_path orelse return; if (comptime !hosted) return; defer p.recent_loaded = true; diff --git a/src/recent.zig b/src/recent.zig index 91c0afeb..112cb59f 100644 --- a/src/recent.zig +++ b/src/recent.zig @@ -83,6 +83,23 @@ pub const List = struct { l.dirty = true; } + /// A copy, for the session a Restore makes: its files closed until it + /// opens them again. Out of memory, what was copied so far. + pub fn clone(l: *const List, gpa: std.mem.Allocator) List { + var copy: List = .{ .dirty = true }; + for (l.entries.items) |e| { + const path = gpa.dupe(u8, e.path) catch break; + var kept = e; + kept.path = path; + kept.open = false; + copy.entries.append(gpa, kept) catch { + gpa.free(path); + break; + }; + } + return copy; + } + pub fn get(l: *const List, path: []const u8) ?Entry { return l.entries.items[l.find(path) orelse return null]; } diff --git a/test/fs.py b/test/fs.py index 6edfeb0f..75d03d40 100644 --- a/test/fs.py +++ b/test/fs.py @@ -723,6 +723,13 @@ def workflow_canary(binary): wait(lambda: f'restore {saved}' in restored.read('/log').decode(), 'Restore not logged') names = restored.read('/index').decode() assert f'{root}/a.txt' in names and f'{root}/b.txt' in names, names + # Recent goes on across the Restore, and is kept after it. + assert f'{root}/a.txt\n' in restored.read('/recent').decode(), restored.read('/recent') + (root / 'after.txt').write_bytes(b'after\n') + look(restored, str(root / 'after.txt')) + assert f'open {root}/after.txt\n' in restored.read('/recent').decode() + state = root / '.local' / 'state' / 'pardes' / 'recent' + wait(lambda: f'{root}/after.txt'.encode() in state.read_bytes(), 'Recent not kept after Restore') assert time.monotonic() - started < 30, 'the canary took too long' -- cgit v1.3