Skip to content

Commit 38c8592

Browse files
committed
Turbopack: Watch the root and every parent directory in non-recursive mode
1 parent 3063bda commit 38c8592

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

turbopack/crates/turbo-tasks-fs/src/watcher.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
time::Duration,
1111
};
1212

13-
use anyhow::{Context, Result};
13+
use anyhow::{Context, Result, anyhow};
1414
use dashmap::DashSet;
1515
use notify::{
1616
Config, EventKind, PollWatcher, RecommendedWatcher, RecursiveMode, Watcher,
@@ -160,42 +160,46 @@ impl NonRecursiveDiskWatcherState {
160160
dir_path: &Path,
161161
root_path: &Path,
162162
) -> Result<()> {
163-
if let Some(watcher_internal_guard) = watcher_internal_guard.as_mut() {
164-
let mut path = dir_path;
165-
let err_with_context = |err| {
166-
return Err(err).context(format!(
167-
"Unable to watch {} (tried up to {})",
168-
dir_path.display(),
169-
path.display()
170-
));
171-
};
172-
while let Err(err) = watcher_internal_guard.watch(path, RecursiveMode::NonRecursive) {
173-
match err {
174-
notify::Error {
175-
kind: notify::ErrorKind::PathNotFound,
176-
..
177-
} => {
178-
// The path was probably deleted before we could process the event. That's
179-
// okay, just make sure we're watching the parent directory, so we can know
180-
// if it gets recreated.
181-
let Some(parent_path) = path.parent() else {
182-
// this should never happen as we break before we reach the root path
183-
return err_with_context(err);
184-
};
185-
if parent_path == root_path {
186-
// assume there's already a root watcher
187-
break;
188-
}
189-
if !self.watching.insert(parent_path.to_owned()) {
190-
// we're already watching the parent path!
191-
break;
192-
}
193-
path = parent_path;
163+
let Some(watcher_internal_guard) = watcher_internal_guard.as_mut() else {
164+
return Ok(());
165+
};
166+
167+
let mut path = dir_path;
168+
let err_with_context = |err: anyhow::Error| {
169+
return Err(err).context(format!(
170+
"Unable to watch {} (tried up to {})",
171+
dir_path.display(),
172+
path.display()
173+
));
174+
};
175+
176+
// watch every parent: https://docs.rs/notify/latest/notify/#parent-folder-deletion
177+
while path != root_path {
178+
match watcher_internal_guard.watch(path, RecursiveMode::NonRecursive) {
179+
res @ Ok(())
180+
| res @ Err(notify::Error {
181+
// The path was probably deleted before we could process the event. That's
182+
// okay, just make sure we're watching the parent directory, so we can know
183+
// if it gets recreated.
184+
kind: notify::ErrorKind::PathNotFound,
185+
..
186+
}) => {
187+
let Some(parent_path) = path.parent() else {
188+
// this should never happen as we break before we reach the root path
189+
return err_with_context(res.err().map_or_else(
190+
|| anyhow!("failed to compute parent path"),
191+
|err| err.into(),
192+
));
193+
};
194+
if !self.watching.insert(parent_path.to_path_buf()) {
195+
break;
194196
}
195-
_ => return err_with_context(err),
197+
path = parent_path;
196198
}
199+
Err(err) => return err_with_context(err.into()),
197200
}
198201
}
202+
199203
Ok(())
200204
}
201205
}
@@ -251,6 +255,7 @@ impl DiskWatcher {
251255
};
252256

253257
if let Some(non_recursive) = &self.non_recursive_state {
258+
internal.watch(fs_inner.root_path(), RecursiveMode::NonRecursive)?;
254259
for dir_path in non_recursive.watching.iter() {
255260
internal.watch(&dir_path, RecursiveMode::NonRecursive)?;
256261
}

0 commit comments

Comments
 (0)