diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 05:15:57 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 32198b59020e295efbc48de343a9de69c952dcfc (patch) | |
| tree | 41e2c98839e844193fcd06f04f0f3aca4af3e252 /src/pardes.zig | |
| parent | 429c1e5e65afa4c65fa42bbb117c4b32a46a9470 (diff) | |
| download | pardes-32198b59020e295efbc48de343a9de69c952dcfc.tar.gz pardes-32198b59020e295efbc48de343a9de69c952dcfc.zip | |
A Save that fails logs its err, not a save record
The save record was logged as soon as the host was asked to write, so a
Save into a read-only directory logged save and then failed. It is now
logged only once the write is done; a failure's err record (the write's,
naming the path) stands alone, the msg it was also said as dropped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/pardes.zig')
| -rw-r--r-- | src/pardes.zig | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/src/pardes.zig b/src/pardes.zig index 5d709679..b488ec1c 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -5239,9 +5239,12 @@ pub const Pardes = struct { p.hostWriteFile(sf.pane, f.path, f.content); const saved_pane = p.panes[sf.pane] orelse return; if (saved_pane.serial != serial) return; - ctlfs.events.noteLog(p, .save, saved_pane); const saved = if (saved_pane.file) |*file| file else return; - if (saved.saved_revision != saved.revision or !saved.watch_after_save) return; + // A save the host could not do (saveFailed) is its err + // record alone, not a `save`. + if (saved.saved_revision != saved.revision) return; + ctlfs.events.noteLog(p, .save, saved_pane); + if (!saved.watch_after_save) return; saved.watch_after_save = false; if (filesystem.localPath(saved.path) != null) p.emit(.{ .watch = .{ .pane = sf.pane, .on = true } }); @@ -7983,3 +7986,27 @@ test "a pane closed while its question stands ends the question in the log" { var want: [64]u8 = undefined; try std.testing.expect(th.logHas(p, try std.fmt.bufPrint(&want, "answer {d} -\ndel {d}", .{ serial, serial }))); } + +test "a Save the host could not do logs no save record" { + const th = @import("ninep/testing.zig"); + const p = try th.withFile(std.testing.allocator, "x\n"); + defer p.deinit(); + const Failing = struct { + core: *Pardes, + const vtable: Host.VTable = .{ .write_file = write }; + fn write(ctx: ?*anyopaque, pane: u8, path: []const u8, _: []const u8) void { + const f: *@This() = @ptrCast(@alignCast(ctx.?)); + f.core.saveFailed(pane, path, error.AccessDenied); + } + }; + var host: Failing = .{ .core = p }; + p.host = .{ .ctx = &host, .vtable = &Failing.vtable }; + _ = th.wr(p, ctlfs.Node.of(p.panes[0].?.serial, .body), "more\n"); + p.perform(.{ .save_file = .{ .pane = 0 } }); + try std.testing.expect(!th.logHas(p, "\nsave ")); + try std.testing.expect(p.panes[0].?.file.?.saved_revision != p.panes[0].?.file.?.revision); + // With the host's write done, it is logged. + p.host = .{}; + p.perform(.{ .save_file = .{ .pane = 0 } }); + try std.testing.expect(th.logHas(p, "\nsave ")); +} |
