fix(kqueue): fix handling of move-in subdirs
This commit is contained in:
parent
7d7241170f
commit
7171ad1905
2 changed files with 25 additions and 3 deletions
|
|
@ -171,6 +171,9 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
// Clean up snapshot so that a new dir at the same path is not
|
||||||
|
// skipped by scan_dir's snapshots.contains() check.
|
||||||
|
self.remove_watch(allocator, dir_path);
|
||||||
} else if (ev.fflags & NOTE_RENAME != 0) {
|
} else if (ev.fflags & NOTE_RENAME != 0) {
|
||||||
self.handler.change(dir_path, EventType.renamed, .dir) catch |e| {
|
self.handler.change(dir_path, EventType.renamed, .dir) catch |e| {
|
||||||
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
||||||
|
|
@ -285,6 +288,10 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
|
||||||
// a rename (old disappears, new appears) reports the source path before the dest.
|
// a rename (old disappears, new appears) reports the source path before the dest.
|
||||||
for (new_dirs.items) |full_path| {
|
for (new_dirs.items) |full_path| {
|
||||||
try self.handler.change(full_path, EventType.created, .dir);
|
try self.handler.change(full_path, EventType.created, .dir);
|
||||||
|
// Start watching the moved-in dir so future changes inside it are detected
|
||||||
|
// and so its deletion fires NOTE_DELETE rather than being silently missed.
|
||||||
|
self.add_watch(allocator, full_path) catch |e|
|
||||||
|
std.log.err("nightwatch: add_watch on moved-in dir failed: {s}", .{@errorName(e)});
|
||||||
try self.emit_subtree_created(allocator, full_path);
|
try self.emit_subtree_created(allocator, full_path);
|
||||||
}
|
}
|
||||||
for (to_delete.items) |name| {
|
for (to_delete.items) |name| {
|
||||||
|
|
@ -322,6 +329,9 @@ fn emit_subtree_created(self: *@This(), allocator: std.mem.Allocator, dir_path:
|
||||||
if (ot == .file) {
|
if (ot == .file) {
|
||||||
self.register_file_watch(allocator, full_path);
|
self.register_file_watch(allocator, full_path);
|
||||||
} else {
|
} else {
|
||||||
|
// Watch nested subdirs so changes inside them are detected after move-in.
|
||||||
|
self.add_watch(allocator, full_path) catch |e|
|
||||||
|
std.log.err("nightwatch: add_watch on moved-in subdir failed: {s}", .{@errorName(e)});
|
||||||
try self.emit_subtree_created(allocator, full_path);
|
try self.emit_subtree_created(allocator, full_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,9 @@ fn thread_fn(self: *@This(), allocator: std.mem.Allocator) void {
|
||||||
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
// Clean up snapshot so that a new dir at the same path is not
|
||||||
|
// skipped by scan_dir's snapshots.contains() check.
|
||||||
|
self.remove_watch(allocator, watch_path);
|
||||||
} else if (ev.fflags & NOTE_RENAME != 0) {
|
} else if (ev.fflags & NOTE_RENAME != 0) {
|
||||||
self.handler.change(watch_path, EventType.renamed, .dir) catch |e| {
|
self.handler.change(watch_path, EventType.renamed, .dir) catch |e| {
|
||||||
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
std.log.err("nightwatch: handler returned {s}, stopping watch thread", .{@errorName(e)});
|
||||||
|
|
@ -279,7 +282,11 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
|
||||||
// Order: new dirs, deletions (source before dest for renames), creations, modifications.
|
// Order: new dirs, deletions (source before dest for renames), creations, modifications.
|
||||||
for (new_dirs.items) |full_path| {
|
for (new_dirs.items) |full_path| {
|
||||||
try self.handler.change(full_path, EventType.created, .dir);
|
try self.handler.change(full_path, EventType.created, .dir);
|
||||||
try self.emit_subtree_created(full_path);
|
// Start watching the moved-in dir so future changes inside it are detected
|
||||||
|
// and so its deletion fires NOTE_DELETE rather than being silently missed.
|
||||||
|
self.add_watch(allocator, full_path) catch |e|
|
||||||
|
std.log.err("nightwatch: add_watch on moved-in dir failed: {s}", .{@errorName(e)});
|
||||||
|
try self.emit_subtree_created(allocator, full_path);
|
||||||
}
|
}
|
||||||
for (to_delete.items) |name| {
|
for (to_delete.items) |name| {
|
||||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
|
@ -302,7 +309,7 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
|
||||||
// Walk dir_path recursively, emitting 'created' events for all contents.
|
// Walk dir_path recursively, emitting 'created' events for all contents.
|
||||||
// Called after a new dir appears in scan_dir so callers see individual
|
// Called after a new dir appears in scan_dir so callers see individual
|
||||||
// 'created' events for the pre-existing tree of a moved-in directory.
|
// 'created' events for the pre-existing tree of a moved-in directory.
|
||||||
fn emit_subtree_created(self: *@This(), dir_path: []const u8) error{HandlerFailed}!void {
|
fn emit_subtree_created(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8) !void {
|
||||||
var dir = std.fs.openDirAbsolute(dir_path, .{ .iterate = true }) catch return;
|
var dir = std.fs.openDirAbsolute(dir_path, .{ .iterate = true }) catch return;
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
var iter = dir.iterate();
|
var iter = dir.iterate();
|
||||||
|
|
@ -315,7 +322,12 @@ fn emit_subtree_created(self: *@This(), dir_path: []const u8) error{HandlerFaile
|
||||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
const full_path = std.fmt.bufPrint(&path_buf, "{s}/{s}", .{ dir_path, entry.name }) catch continue;
|
const full_path = std.fmt.bufPrint(&path_buf, "{s}/{s}", .{ dir_path, entry.name }) catch continue;
|
||||||
try self.handler.change(full_path, EventType.created, ot);
|
try self.handler.change(full_path, EventType.created, ot);
|
||||||
if (ot == .dir) try self.emit_subtree_created(full_path);
|
if (ot == .dir) {
|
||||||
|
// Watch nested subdirs so changes inside them are detected after move-in.
|
||||||
|
self.add_watch(allocator, full_path) catch |e|
|
||||||
|
std.log.err("nightwatch: add_watch on moved-in subdir failed: {s}", .{@errorName(e)});
|
||||||
|
try self.emit_subtree_created(allocator, full_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue