summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/File.zig31
-rw-r--r--src/dump.zig4
-rw-r--r--src/ninep/ctl.zig10
3 files changed, 42 insertions, 3 deletions
diff --git a/src/File.zig b/src/File.zig
index a89db613..d16d4fc0 100644
--- a/src/File.zig
+++ b/src/File.zig
@@ -127,6 +127,7 @@ pub fn dumpPane(
.content = file.content,
.content_b64 = try dump.encodeBytes(arena, file.content),
.dirty = file.revision != file.saved_revision,
+ .on_disk = onDisk(file.path),
.origin = origin,
.origin_arg = origin_arg,
.mini_source = if (file.mini) |mini| mini.source else "",
@@ -220,6 +221,24 @@ fn restoreLocationRows(gpa: std.mem.Allocator, content: []const u8, saved: []con
return rows;
}
+test "a clean pane whose file was never on disk comes back clean from a Restore; one whose file has gone is said deleted" {
+ if (comptime !pardes.hosted) return;
+ for ([_]bool{ false, true }) |was_on_disk| {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const id = p.freeSlot().?;
+ const pane = try restore(p, id, .{
+ .kind = .file,
+ .tag = "",
+ .body = "",
+ .file = .{ .path = "/tmp/pardes-never-written/init", .content = "", .on_disk = was_on_disk },
+ });
+ try std.testing.expectEqual(was_on_disk, pane.file.?.disk_gone);
+ try std.testing.expectEqual(pane.file.?.saved_revision, pane.file.?.revision);
+ }
+}
+
test "location metadata restore rejects offsets and invalid syntax bytes" {
const gpa = std.testing.allocator;
var row: dump.LocationRow = .{
@@ -898,11 +917,19 @@ pub fn restore(p: *Pardes, id: usize, src: dump.Pane) !*Pane {
// Its file gone from disk since the dump: its text is nowhere else now,
// so it comes back as one deleted on disk, dirty, and Del, Exit and
// Restore ask before throwing it away.
- if (comptime pardes.hosted) if (output == null) if (filesystem.localPath(path)) |local|
- if (@import("exec.zig").kindOf(local) == null) deleted(p, @intCast(id));
+ // One never on disk (Config's new file, a name not yet saved) is
+ // restored as it was: clean, and nothing deleted.
+ if (output == null and saved.on_disk and !onDisk(path)) deleted(p, @intCast(id));
return pane;
}
+/// Whether `path` names a file on this host's disk now.
+fn onDisk(path: []const u8) bool {
+ if (comptime !pardes.hosted) return false;
+ const local = filesystem.localPath(path) orelse return false;
+ return @import("exec.zig").kindOf(local) != null;
+}
+
pub fn deinit(p: *Pardes, pane: *Pane, file: *State) void {
if (file.output == null) for (p.panes, 0..) |slot, id| {
if (slot == pane) p.emit(.{ .watch = .{ .pane = @intCast(id), .on = false } });
diff --git a/src/dump.zig b/src/dump.zig
index 4194f628..983d5894 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -209,6 +209,10 @@ pub const File = struct {
content: []const u8 = "",
content_b64: []const u8 = "",
dirty: bool = false,
+ /// Its file was on disk when dumped: one gone by the Restore is said
+ /// deleted, one never written (Config's new file) is not. True in
+ /// older dumps.
+ on_disk: bool = true,
tree_context: bool = false,
location_rows: []const LocationRow = &.{},
// Builtin names remain stable when enum ordinals change.
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index a14b1efb..63f89cdf 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -2691,8 +2691,16 @@ test "a restored pane whose file is gone from disk comes back dirty, and Del ask
if (comptime !pardes.hosted) return error.SkipZigTest;
const p = try withFile(testing.allocator, "kept text\n");
defer p.deinit();
- try pane_files.nameBuffer(p, 0, "/tmp/pardes-restore-gone-xyz/f.txt", false);
+ // On disk when dumped, gone by the Restore.
+ var tmp = testing.tmpDir(.{});
+ defer tmp.cleanup();
+ try tmp.dir.writeFile(testing.io, .{ .sub_path = "f.txt", .data = "kept text\n" });
+ var dir_buf: [4096]u8 = undefined;
+ const dir = dir_buf[0..try tmp.dir.realPath(testing.io, &dir_buf)];
+ var path_buf: [4200]u8 = undefined;
+ try pane_files.nameBuffer(p, 0, try std.fmt.bufPrint(&path_buf, "{s}/f.txt", .{dir}), false);
try pardes.dump.dumpState(p);
+ try tmp.dir.deleteFile(testing.io, "f.txt");
const restored = try pardes.dump.restore(p, p.dump_out.?, "/tmp/pardes.dump.zon");
defer restored.deinit();
const again = restored.panes[restored.paneBySerial(restored.panes[0].?.serial).?].?;