Enhance VFS watch functionality to support upgrade from non-recursive to recursive watching

- Modified the `watch` method in `StdBackend` to allow upgrading a non-recursive watch to a recursive one, improving flexibility in file watching.
- Added a new test to verify that a non-recursive watch can be upgraded to recursive, ensuring correct behavior in directory watching scenarios.

These changes aim to enhance the VFS's ability to manage file system events more effectively.
This commit is contained in:
Joe 2026-03-06 17:49:50 -06:00
parent 9ddd9379ab
commit a1825f7c4a

View file

@ -332,7 +332,11 @@ impl VfsBackend for StdBackend {
fn watch(&mut self, path: &Path, recursive: bool) -> io::Result<()> { fn watch(&mut self, path: &Path, recursive: bool) -> io::Result<()> {
if self.watches.contains(path) { if self.watches.contains(path) {
return Ok(()); if !recursive || self.recursive_watches.contains(path) {
return Ok(());
}
// Upgrade: path was watched non-recursively, now needs recursive.
// Fall through to re-issue the watch with RecursiveMode::Recursive.
} }
if path if path
.ancestors() .ancestors()
@ -498,6 +502,39 @@ mod tests {
assert!(backend.watch(&file_path, true).is_ok()); assert!(backend.watch(&file_path, true).is_ok());
} }
#[test]
fn non_recursive_watch_upgrades_to_recursive() {
let dir = tempdir().unwrap();
let subdir = dir.path().join("subdir");
fs_err::create_dir(&subdir).unwrap();
let child = subdir.join("child.txt");
fs_err::write(&child, "content").unwrap();
let mut backend = StdBackend::new_for_testing();
// Watch non-recursively first
assert!(backend.watch(&subdir, false).is_ok());
assert!(backend.watches.contains(subdir.as_path()));
assert!(!backend.recursive_watches.contains(subdir.as_path()));
// Child should NOT be covered (parent is non-recursive)
assert!(!subdir
.ancestors()
.skip(1)
.any(|a| backend.recursive_watches.contains(a)));
// Upgrade to recursive
assert!(backend.watch(&subdir, true).is_ok());
assert!(backend.recursive_watches.contains(subdir.as_path()));
// Now a child path should be recognized as covered by the recursive ancestor
assert!(child
.ancestors()
.skip(1)
.any(|a| backend.recursive_watches.contains(a)));
assert!(backend.watch(&child, true).is_ok());
}
#[test] #[test]
fn critical_error_receiver_works() { fn critical_error_receiver_works() {
let error_received = Arc::new(AtomicBool::new(false)); let error_received = Arc::new(AtomicBool::new(false));