diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/file_watch.zig | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/src/file_watch.zig b/src/file_watch.zig index 71a4680d..d028488e 100644 --- a/src/file_watch.zig +++ b/src/file_watch.zig @@ -225,8 +225,10 @@ fn markDir(fd: c_int, dir_z: [:0]const u8, watches: *const Table) c_int { switch (builtin.os.tag) { .linux => { // CLOSE_WRITE coalesces one writer's writes; MOVED_TO and CREATE - // cover rename-over and delete-then-recreate saves. - const mask = linux.IN.CLOSE_WRITE | linux.IN.MOVED_TO | linux.IN.CREATE | linux.IN.ONLYDIR; + // cover rename-over and delete-then-recreate saves; DELETE and + // MOVED_FROM a file going away, said at once (File.deleted), not + // when something else next changes in the directory. + const mask = linux.IN.CLOSE_WRITE | linux.IN.MOVED_TO | linux.IN.CREATE | linux.IN.DELETE | linux.IN.MOVED_FROM | linux.IN.ONLYDIR; return libc.inotify_add_watch(fd, dir_z, mask); }, .macos => { @@ -838,3 +840,36 @@ test "theme watch reloads valid ZON and keeps the last theme across a bad save" try std.testing.expect(!reloadTheme(core, gpa, &watches, false)); try std.testing.expectEqual(@as(?[3]u8, .{ 9, 8, 7 }), core.theme().bg); } + +test "a watched file deleted wakes the watch at once, and its pane says so" { + if (comptime !supported or !filesystem.platform_has_fs or builtin.os.tag != .linux) return; + const io = std.testing.io; + const gpa = std.testing.allocator; + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + try tmp.dir.writeFile(io, .{ .sub_path = "watched", .data = "here\n" }); + var path_buf: [256]u8 = undefined; + const path = try std.fmt.bufPrint(&path_buf, ".zig-cache/tmp/{s}/watched", .{tmp.sub_path}); + const core = try pardes.Pardes.init(gpa, .{ .tty_only = true }); + defer core.deinit(); + while (core.nextEffect()) |_| {} + const id: u8 = @intCast(core.freeSlot().?); + const pane = try pardes.panes.File.open(core, id, path, 0); + const fd = init(true); + if (fd < 0) return error.NoWatcher; + defer _ = libc.close(fd); + var watches: Table = @splat(null); + defer watchPane(fd, &watches, id, null, pane.serial, .{ .text = 0 }); + while (core.nextEffect()) |effect| switch (effect) { + .watch => |watch| if (watch.pane == id and watch.on) { + _ = applyEffect(core, io, fd, &watches, id, watch.on, watch.mode); + }, + else => {}, + }; + _ = drain(fd); + try tmp.dir.deleteFile(io, "watched"); + var pfd = [_]libc.pollfd{.{ .fd = fd, .events = libc.POLL.IN, .revents = 0 }}; + try std.testing.expect(libc.poll(&pfd, 1, 1000) > 0); + _ = reloadChanged(core, io, gpa, &watches); + try std.testing.expect(pane.file.?.disk_gone); +} |
