@@ -28,6 +28,7 @@ type Watcher struct {
2828
2929 mu sync.Mutex // Protects access to watcher data
3030 watches map [string ]int // Map of watched file descriptors (key: path).
31+ watchesByDir map [string ][]int // Map of watched file descriptors indexed by the parent directory (key: dirname(path)).
3132 externalWatches map [string ]bool // Map of watches added by user of the library.
3233 dirFlags map [string ]uint32 // Map of watched directories to fflags used in kqueue.
3334 paths map [int ]pathInfo // Map file descriptors to path names for processing kqueue events.
@@ -50,6 +51,7 @@ func NewWatcher() (*Watcher, error) {
5051 w := & Watcher {
5152 kq : kq ,
5253 watches : make (map [string ]int ),
54+ watchesByDir : make (map [string ][]int ),
5355 dirFlags : make (map [string ]uint32 ),
5456 paths : make (map [int ]pathInfo ),
5557 fileExists : make (map [string ]bool ),
@@ -119,6 +121,16 @@ func (w *Watcher) Remove(name string) error {
119121 w .mu .Lock ()
120122 isDir := w .paths [watchfd ].isDir
121123 delete (w .watches , name )
124+
125+ parentName := filepath .Clean (filepath .Dir (name ))
126+ parentWatches := w .watchesByDir [parentName ]
127+ for i , fd := range parentWatches {
128+ if fd == watchfd {
129+ w .watchesByDir [parentName ] = append (parentWatches [:i ], parentWatches [i + 1 :]... )
130+ break
131+ }
132+ }
133+
122134 delete (w .paths , watchfd )
123135 delete (w .dirFlags , name )
124136 w .mu .Unlock ()
@@ -127,12 +139,10 @@ func (w *Watcher) Remove(name string) error {
127139 if isDir {
128140 var pathsToRemove []string
129141 w .mu .Lock ()
130- for _ , path := range w .paths {
131- wdir , _ := filepath .Split (path .name )
132- if filepath .Clean (wdir ) == name {
133- if ! w .externalWatches [path .name ] {
134- pathsToRemove = append (pathsToRemove , path .name )
135- }
142+ for _ , fd := range w .watchesByDir [name ] {
143+ path := w .paths [fd ]
144+ if ! w .externalWatches [path .name ] {
145+ pathsToRemove = append (pathsToRemove , path .name )
136146 }
137147 }
138148 w .mu .Unlock ()
@@ -231,7 +241,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
231241
232242 if ! alreadyWatching {
233243 w .mu .Lock ()
244+ parentName := filepath .Clean (filepath .Dir (name ))
234245 w .watches [name ] = watchfd
246+ w .watchesByDir [parentName ] = append (w .watchesByDir [parentName ], watchfd )
235247 w .paths [watchfd ] = pathInfo {name : name , isDir : isDir }
236248 w .mu .Unlock ()
237249 }
0 commit comments