diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/File.zig | 31 | ||||
| -rw-r--r-- | src/dump.zig | 4 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 10 |
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).?].?; |
