From 9d6da1036d80a29862f6bdfb51e6f51eee235c35 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Wed, 7 Aug 2024 18:15:57 +0200 Subject: [PATCH] fix: `rename` watch event missing (#24893) This PR ensures that we forward a `rename` event in our file watcher. The rust lib we use combines that with the `modify` event. This fixes a compatibility issue with Node too, which sends the `rename` event as well. Fixes https://github.com/denoland/deno/issues/24880 --- cli/tsc/dts/lib.deno.ns.d.ts | 9 ++++++++- ext/node/polyfills/_fs/_fs_watch.ts | 2 ++ runtime/ops/fs_events.rs | 9 ++++++++- tests/unit/fs_events_test.ts | 20 ++++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index 084dc1b76a..0cc96d5429 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -4149,7 +4149,14 @@ declare namespace Deno { * @category File System */ export interface FsEvent { /** The kind/type of the file system event. */ - kind: "any" | "access" | "create" | "modify" | "remove" | "other"; + kind: + | "any" + | "access" + | "create" + | "modify" + | "rename" + | "remove" + | "other"; /** An array of paths that are associated with the file system event. */ paths: string[]; /** Any additional flags associated with the event. */ diff --git a/ext/node/polyfills/_fs/_fs_watch.ts b/ext/node/polyfills/_fs/_fs_watch.ts index acdaff800b..eb2cd8bfa2 100644 --- a/ext/node/polyfills/_fs/_fs_watch.ts +++ b/ext/node/polyfills/_fs/_fs_watch.ts @@ -368,6 +368,8 @@ function convertDenoFsEventToNodeFsEvent( ): NodeFsEventType { if (kind === "create" || kind === "remove") { return "rename"; + } else if (kind === "rename") { + return "rename"; } else { return "change"; } diff --git a/runtime/ops/fs_events.rs b/runtime/ops/fs_events.rs index 367866162f..58fe9d5fd2 100644 --- a/runtime/ops/fs_events.rs +++ b/runtime/ops/fs_events.rs @@ -14,6 +14,7 @@ use deno_core::op2; use deno_permissions::PermissionsContainer; use notify::event::Event as NotifyEvent; +use notify::event::ModifyKind; use notify::Error as NotifyError; use notify::EventKind; use notify::RecommendedWatcher; @@ -71,7 +72,13 @@ impl From for FsEvent { EventKind::Any => "any", EventKind::Access(_) => "access", EventKind::Create(_) => "create", - EventKind::Modify(_) => "modify", + EventKind::Modify(modify_kind) => match modify_kind { + ModifyKind::Name(_) => "rename", + ModifyKind::Any + | ModifyKind::Data(_) + | ModifyKind::Metadata(_) + | ModifyKind::Other => "modify", + }, EventKind::Remove(_) => "remove", EventKind::Other => "other", }; diff --git a/tests/unit/fs_events_test.ts b/tests/unit/fs_events_test.ts index 4f7cdc4d5a..3a867f07ee 100644 --- a/tests/unit/fs_events_test.ts +++ b/tests/unit/fs_events_test.ts @@ -70,6 +70,26 @@ Deno.test( }, ); +Deno.test( + { permissions: { read: true, write: true } }, + async function watchFsRename() { + const testDir = await makeTempDir(); + const watcher = Deno.watchFs(testDir); + async function waitForRename() { + for await (const event of watcher) { + if (event.kind === "rename") { + break; + } + } + } + const eventPromise = waitForRename(); + const file = testDir + "/file.txt"; + await Deno.writeTextFile(file, "hello"); + await Deno.rename(file, testDir + "/file2.txt"); + await eventPromise; + }, +); + // TODO(kt3k): This test is for the backward compatibility of `.return` method. // This should be removed at 2.0 Deno.test(