summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 21:40:57 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit45609211f5047b5aec9964807cd5c98242cc70d7 (patch)
tree8093bccf27e3e0f10d2c268ea03800c74e18602d
parent30cda150dff03bb1ca7e50f4b79a04775ea7a98d (diff)
downloadpardes-45609211f5047b5aec9964807cd5c98242cc70d7.tar.gz
pardes-45609211f5047b5aec9964807cd5c98242cc70d7.zip
A session restored from a dump is built as a fresh one is: its column and workspace tags take several selections, and its 9P files have a time
dump.initDump copied Pardes.init's construction and had drifted from it: it never gave the column and workspace tags their allocator, so after -l or Restore they could not hold more than one selection, and never set fs.started, so every 9P mtime read 0. Pardes.create is now the one construction, allocators, tags, the tree's clock and the mounts, that init and initDump both start from. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/dump.zig35
-rw-r--r--src/pardes.zig22
2 files changed, 31 insertions, 26 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 73d4e4ed..78c2bd7a 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -848,23 +848,7 @@ const OldSerials = struct {
};
fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previous: ?*const Pardes, old_serials: ?*OldSerials) !*Pardes {
- const image_gpa = opts.image_allocator orelse gpa;
- const pdf_gpa = opts.pdf_allocator orelse gpa;
- const tree_sitter_gpa = opts.tree_sitter_allocator orelse gpa;
- const p = try gpa.create(Pardes);
- p.* = .{
- .gpa = gpa,
- .image_gpa = image_gpa,
- .pdf_gpa = pdf_gpa,
- .tree_sitter_gpa = tree_sitter_gpa,
- .opts = opts,
- .fs = .{},
- .screen_w = opts.cols,
- .screen_h = opts.rows,
- .scratch = .init(gpa),
- .frame_arena = .init(opts.frame_allocator orelse gpa),
- .fallback = .{ .gpa = gpa },
- };
+ const p = try Pardes.create(gpa, opts);
errdefer p.deinit();
if (previous) |old| {
p.next_serial = old.next_serial;
@@ -879,8 +863,6 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo
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");
defer parsed.deinit();
const st = parsed.value;
@@ -1027,6 +1009,21 @@ test "a session with every column it may hold dumps and restores them all" {
try std.testing.expectEqual(@as(usize, MAX_COLS), restored.ncol);
}
+test "a restored session's column and workspace tags take more than one selection, and its 9P files have a time" {
+ const th = @import("ninep/testing.zig");
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true });
+ defer p.deinit();
+ try dumpState(p);
+ const restored = try initFromDump(gpa, .{ .tty_only = true }, p.dump_out.?);
+ defer restored.deinit();
+ try std.testing.expect(restored.col_tags[0].reserveSels());
+ try std.testing.expect(restored.global_tag.reserveSels());
+ try std.testing.expect(restored.fs.started != 0);
+ const stat = th.call(restored, .{ .tag = 1, .op = .getattr, .node = @intFromEnum(pardes.ctlfs.TopFile.index) });
+ try std.testing.expect(stat.reply.attr.mtime != 0);
+}
+
test "a restored pane keeps its dot, as acme's dump keeps a window's" {
const gpa = std.testing.allocator;
const p = try Pardes.init(gpa, .{ .tty_only = true });
diff --git a/src/pardes.zig b/src/pardes.zig
index 623af3c9..3ecc80ae 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -4594,16 +4594,18 @@ pub const Pardes = struct {
/// `p.executeBuiltinLine(...)`; it lives with the rest of exec in exec.zig.
pub const executeBuiltinLine = exec.executeBuiltinLine;
- pub fn init(gpa: std.mem.Allocator, opts: Options) !*Pardes {
- const image_gpa = opts.image_allocator orelse gpa;
- const pdf_gpa = opts.pdf_allocator orelse gpa;
- const tree_sitter_gpa = opts.tree_sitter_allocator orelse gpa;
+ /// The one construction of a session, empty: its allocators, its column
+ /// and workspace tags, the 9P tree's clock and its mounts. `init` boots
+ /// a layout into it and a dump's restore (dump.initDump) its panes; a
+ /// second copy of this drifted once, leaving restored tags without an
+ /// allocator and every 9P mtime 0.
+ pub fn create(gpa: std.mem.Allocator, opts: Options) !*Pardes {
const p = try gpa.create(Pardes);
p.* = .{
.gpa = gpa,
- .image_gpa = image_gpa,
- .pdf_gpa = pdf_gpa,
- .tree_sitter_gpa = tree_sitter_gpa,
+ .image_gpa = opts.image_allocator orelse gpa,
+ .pdf_gpa = opts.pdf_allocator orelse gpa,
+ .tree_sitter_gpa = opts.tree_sitter_allocator orelse gpa,
.opts = opts,
.col_tags = @splat(.{ .what = .column, .gpa = gpa }),
.global_tag = .{ .what = .workspace, .gpa = gpa },
@@ -4618,6 +4620,12 @@ pub const Pardes = struct {
p.fs.started = ctlfs.events.now();
for (opts.mounts) |mount| try p.fs.mount(gpa, mount.name, mount.dial);
p.opts.mounts = &.{};
+ return p;
+ }
+
+ pub fn init(gpa: std.mem.Allocator, opts: Options) !*Pardes {
+ const p = try create(gpa, opts);
+ errdefer p.deinit();
p.boot = Boot.of(opts);
switch (p.boot) {
.document => {