@@ -10,7 +10,7 @@ use std::{
1010 time:: Duration ,
1111} ;
1212
13- use anyhow:: { Context , Result } ;
13+ use anyhow:: { Context , Result , anyhow } ;
1414use dashmap:: DashSet ;
1515use 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