Compare commits

..

No commits in common. "daf58bd4dcd8a023e5fb6ffef7473387999f1c7c" and "69274317266fd40202da370fb67e7b5cd9ae4bb9" have entirely different histories.

5 changed files with 26 additions and 91 deletions

View file

@ -189,7 +189,7 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
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();
// Arena for all temporaries - freed in one shot at the end. // Arena for all temporaries freed in one shot at the end.
var arena = std.heap.ArenaAllocator.init(allocator); var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit(); defer arena.deinit();
const tmp = arena.allocator(); const tmp = arena.allocator();

View file

@ -173,7 +173,7 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
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();
// Arena for all temporaries - freed in one shot at the end. // Arena for all temporaries freed in one shot at the end.
var arena = std.heap.ArenaAllocator.init(allocator); var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit(); defer arena.deinit();
const tmp = arena.allocator(); const tmp = arena.allocator();
@ -242,13 +242,13 @@ fn scan_dir(self: *@This(), allocator: std.mem.Allocator, dir_path: []const u8)
var cit = current_files.iterator(); var cit = current_files.iterator();
while (cit.next()) |entry| { while (cit.next()) |entry| {
if (snapshot.getPtr(entry.key_ptr.*)) |stored_mtime| { if (snapshot.getPtr(entry.key_ptr.*)) |stored_mtime| {
// File exists in both - check for modification via mtime change. // File exists in both check for modification via mtime change.
if (stored_mtime.* != entry.value_ptr.*) { if (stored_mtime.* != entry.value_ptr.*) {
stored_mtime.* = entry.value_ptr.*; stored_mtime.* = entry.value_ptr.*;
try to_modify.append(tmp, entry.key_ptr.*); // from current_files (tmp) try to_modify.append(tmp, entry.key_ptr.*); // from current_files (tmp)
} }
} else { } else {
// New file - add to snapshot and to_create list. // New file add to snapshot and to_create list.
const owned = allocator.dupe(u8, entry.key_ptr.*) catch |e| { const owned = allocator.dupe(u8, entry.key_ptr.*) catch |e| {
return e; return e;
}; };

View file

@ -18,25 +18,22 @@ pub const EventType = enum {
/// ///
/// Delivery varies by backend: /// Delivery varies by backend:
/// ///
/// - **INotify**: all watches share a single inotify file descriptor, so /// - **INotify**: renames within the watched tree are delivered as a
/// moves are paired by cookie across all watched roots. Renames between /// single atomic `rename` callback with both source and destination
/// two watched directories - even separate watch roots on the same /// paths. A move out of the tree appears as `deleted`; a move into
/// watcher instance - are delivered as a single atomic `rename` /// the tree appears as `created`.
/// callback. A move out of all watched paths appears as `deleted`; a
/// move in from an unwatched path appears as `created`.
///
/// - **Windows**: renames within a single watched root are delivered as a
/// single atomic `rename` callback. However, each root uses an
/// independent `ReadDirectoryChangesW` handle with no shared cookie, so
/// a move between two separately watched roots cannot be paired: it
/// appears as `deleted` on the source side and `created` on the
/// destination side.
/// ///
/// - **kqueue / kqueuedir**: when a watched *directory* is itself /// - **kqueue / kqueuedir**: when a watched *directory* is itself
/// renamed, a `renamed` change event is emitted for the old directory /// renamed, a `renamed` change event is emitted for the old directory
/// path (the new path is not known). Renames of *files inside* a /// path (the new path is not known). Renames of *files inside* a
/// watched directory are detected indirectly via directory-level /// watched directory are detected indirectly via directory-level
/// `NOTE_WRITE` events and appear as `deleted` + `created`. /// `NOTE_WRITE` events and appear as a `deleted` event for the old
/// name followed by a `created` event for the new name.
///
/// - **Windows**: renames within the watched tree are delivered as a
/// single atomic `rename` callback, matching INotify behaviour. A
/// move out of the tree appears as `deleted`; a move into the tree
/// appears as `created`.
/// ///
/// - **FSEvents**: each path involved in a rename receives its own /// - **FSEvents**: each path involved in a rename receives its own
/// `renamed` change event; the two sides are not paired. /// `renamed` change event; the two sides are not paired.
@ -64,9 +61,9 @@ pub const Error = error{
/// Selects how the watcher delivers events to the caller. /// Selects how the watcher delivers events to the caller.
/// ///
/// - `.threaded` - the backend spawns an internal thread that calls the /// - `.threaded` the backend spawns an internal thread that calls the
/// handler directly. The caller just needs to keep the `Watcher` alive. /// handler directly. The caller just needs to keep the `Watcher` alive.
/// - `.polling` - no internal thread is created. The caller must poll /// - `.polling` no internal thread is created. The caller must poll
/// `poll_fd()` for readability and call `handle_read_ready()` whenever /// `poll_fd()` for readability and call `handle_read_ready()` whenever
/// data is available. Currently only supported on Linux (inotify). /// data is available. Currently only supported on Linux (inotify).
pub const InterfaceType = enum { polling, threaded }; pub const InterfaceType = enum { polling, threaded };

View file

@ -15,16 +15,14 @@ if (-not (Test-Path $NW)) {
} }
$TESTDIR = Join-Path $env:TEMP "nightwatch_manual_$PID" $TESTDIR = Join-Path $env:TEMP "nightwatch_manual_$PID"
$TESTDIR2 = Join-Path $env:TEMP "nightwatch_manual2_$PID"
New-Item -ItemType Directory -Path $TESTDIR | Out-Null New-Item -ItemType Directory -Path $TESTDIR | Out-Null
New-Item -ItemType Directory -Path $TESTDIR2 | Out-Null
Write-Host "--- watching $TESTDIR and $TESTDIR2 ---" Write-Host "--- watching $TESTDIR ---"
Write-Host "--- starting nightwatch (Ctrl-C to stop early) ---" Write-Host "--- starting nightwatch (Ctrl-C to stop early) ---"
Write-Host "" Write-Host ""
# Start nightwatch in background watching both dirs, events go to stdout # Start nightwatch in background, events go to stdout
$proc = Start-Process -FilePath $NW -ArgumentList $TESTDIR, $TESTDIR2 -NoNewWindow -PassThru $proc = Start-Process -FilePath $NW -ArgumentList $TESTDIR -NoNewWindow -PassThru
Start-Sleep -Milliseconds 500 Start-Sleep -Milliseconds 500
Write-Host "[op] touch file1.txt" Write-Host "[op] touch file1.txt"
@ -75,38 +73,8 @@ Write-Host "[op] rmdir dirB (and contents)"
Remove-Item -Recurse -Force -Path "$TESTDIR\dirB" Remove-Item -Recurse -Force -Path "$TESTDIR\dirB"
Start-Sleep -Milliseconds 500 Start-Sleep -Milliseconds 500
Write-Host ""
Write-Host "# cross-root renames (both dirs watched)"
Write-Host ""
Write-Host "[op] mkdir subA in both roots"
New-Item -ItemType Directory -Path "$TESTDIR\subA" | Out-Null
New-Item -ItemType Directory -Path "$TESTDIR2\subA" | Out-Null
Start-Sleep -Milliseconds 400
Write-Host "[op] touch crossfile.txt in dir1"
New-Item -ItemType File -Path "$TESTDIR\crossfile.txt" | Out-Null
Start-Sleep -Milliseconds 400
Write-Host "[op] rename crossfile.txt: dir1 -> dir2 (root to root)"
Move-Item -Path "$TESTDIR\crossfile.txt" -Destination "$TESTDIR2\crossfile.txt"
Start-Sleep -Milliseconds 400
Write-Host "[op] touch subA\crosssub.txt in dir1"
New-Item -ItemType File -Path "$TESTDIR\subA\crosssub.txt" | Out-Null
Start-Sleep -Milliseconds 400
Write-Host "[op] rename subA\crosssub.txt: dir1\subA -> dir2\subA (subdir to subdir)"
Move-Item -Path "$TESTDIR\subA\crosssub.txt" -Destination "$TESTDIR2\subA\crosssub.txt"
Start-Sleep -Milliseconds 400
Write-Host "[op] rename subA: dir1 -> dir2 (subdir across roots)"
Move-Item -Path "$TESTDIR\subA" -Destination "$TESTDIR2\subA2"
Start-Sleep -Milliseconds 500
Write-Host "" Write-Host ""
Write-Host "--- done, stopping nightwatch ---" Write-Host "--- done, stopping nightwatch ---"
Stop-Process -Id $proc.Id -ErrorAction SilentlyContinue Stop-Process -Id $proc.Id -ErrorAction SilentlyContinue
$proc.WaitForExit() $proc.WaitForExit()
Remove-Item -Recurse -Force -Path $TESTDIR Remove-Item -Recurse -Force -Path $TESTDIR
Remove-Item -Recurse -Force -Path $TESTDIR2

View file

@ -14,13 +14,12 @@ if [ ! -x "$NW" ]; then
fi fi
TESTDIR=$(mktemp -d) TESTDIR=$(mktemp -d)
TESTDIR2=$(mktemp -d) echo "--- watching $TESTDIR ---"
echo "--- watching $TESTDIR and $TESTDIR2 ---"
echo "--- starting nightwatch (Ctrl-C to stop early) ---" echo "--- starting nightwatch (Ctrl-C to stop early) ---"
echo "" echo ""
# Start nightwatch in background watching both dirs, events go to stdout # Start nightwatch in background, events go to stdout
"$NW" "$TESTDIR" "$TESTDIR2" & "$NW" "$TESTDIR" &
NW_PID=$! NW_PID=$!
sleep 0.5 sleep 0.5
@ -72,37 +71,8 @@ echo "[op] rmdir dirB (and contents)"
rm -rf "$TESTDIR/dirB" rm -rf "$TESTDIR/dirB"
sleep 0.5 sleep 0.5
echo ""
echo "# cross-root renames (both dirs watched)"
echo ""
echo "[op] mkdir subA in both roots"
mkdir "$TESTDIR/subA"
mkdir "$TESTDIR2/subA"
sleep 0.4
echo "[op] touch crossfile.txt in dir1"
touch "$TESTDIR/crossfile.txt"
sleep 0.4
echo "[op] rename crossfile.txt: dir1 -> dir2 (root to root)"
mv "$TESTDIR/crossfile.txt" "$TESTDIR2/crossfile.txt"
sleep 0.4
echo "[op] touch subA/crosssub.txt in dir1"
touch "$TESTDIR/subA/crosssub.txt"
sleep 0.4
echo "[op] rename subA/crosssub.txt: dir1/subA -> dir2/subA (subdir to subdir)"
mv "$TESTDIR/subA/crosssub.txt" "$TESTDIR2/subA/crosssub.txt"
sleep 0.4
echo "[op] rename subA: dir1 -> dir2 (subdir across roots)"
mv "$TESTDIR/subA" "$TESTDIR2/subA2"
sleep 0.5
echo "" echo ""
echo "--- done, stopping nightwatch ---" echo "--- done, stopping nightwatch ---"
kill $NW_PID 2>/dev/null kill $NW_PID 2>/dev/null
wait $NW_PID 2>/dev/null wait $NW_PID 2>/dev/null
rm -rf "$TESTDIR" "$TESTDIR2" rm -rf "$TESTDIR"