summaryrefslogtreecommitdiff
path: root/src/host.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/host.zig')
-rw-r--r--src/host.zig24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/host.zig b/src/host.zig
index d5f5c983..2c6bd208 100644
--- a/src/host.zig
+++ b/src/host.zig
@@ -116,6 +116,17 @@ pub const Host = struct {
/// `pane` travels with the bytes only so a host that posts a "saved"
/// message row can name the right pane; the core already resolved the
/// path and the content, so save_file and save_text both land here.
+ ///
+ /// A HOST THAT COULD NOT WRITE MUST CALL `Pardes.saveFailed`, and the
+ /// reason it is a call rather than a return value is the rule twenty
+ /// lines below: a `push_` reaches every host in a fan-out, so there is
+ /// no single answer to give back. The core marks the pane saved
+ /// optimistically around this call and `saveFailed` takes it back, so a
+ /// write that could not happen — a read-only file, a directory removed
+ /// under the pane, a full disk — leaves the ` *` in the tag where it
+ /// was. Until that existed the pane came clean on a save that never
+ /// happened, and `Del` makes no dirty check: the edits were one click
+ /// from gone with the screen saying they were safe.
push_write_file: ?*const fn (ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void = null,
/// The session dump. Separate because the host also chooses WHERE it
/// goes (dump.outPath is libc-bound; the freestanding core cannot).
@@ -188,21 +199,26 @@ pub const Fallback = struct {
f.link.deinit(f.gpa);
}
- pub fn writeFile(f: *Fallback, path: []const u8, bytes: []const u8) void {
- const copy = f.gpa.dupe(u8, bytes) catch return;
+ /// True when the bytes are in the map. The core turns a false into the same
+ /// `saveFailed` a real host reports, so a virtual filesystem that could not
+ /// allocate does not leave a pane looking saved either.
+ pub fn writeFile(f: *Fallback, path: []const u8, bytes: []const u8) bool {
+ const copy = f.gpa.dupe(u8, bytes) catch return false;
if (f.files.getEntry(path)) |e| {
f.gpa.free(e.value_ptr.*);
e.value_ptr.* = copy;
- return;
+ return true;
}
const key = f.gpa.dupe(u8, path) catch {
f.gpa.free(copy);
- return;
+ return false;
};
f.files.put(f.gpa, key, copy) catch {
f.gpa.free(key);
f.gpa.free(copy);
+ return false;
};
+ return true;
}
/// What this path holds now: the session's own write, else the embedded