Skip to content

Instantly share code, notes, and snippets.

@Flagro
Last active January 8, 2024 13:44
Show Gist options
  • Save Flagro/2ee33bb58fd2708379edcc936518dae5 to your computer and use it in GitHub Desktop.
Save Flagro/2ee33bb58fd2708379edcc936518dae5 to your computer and use it in GitHub Desktop.
The implementation of recursive fsntify directory watcher that i used in my https://github.com/Flagro/ProjectTextAgent project. Implements a composite class and utilizes the goroutines and channels.
package watcher
import (
"log"
"os"
"path/filepath"
"github.com/fsnotify/fsnotify"
)
type Watcher struct {
fsWatcher *fsnotify.Watcher
FileModified chan string
FileCreated chan string
FileDeleted chan string
}
// NewWatcher creates and initializes a new Watcher instance.
func NewWatcher() (*Watcher, error) {
fsWatcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
return &Watcher{
fsWatcher: fsWatcher,
FileModified: make(chan string),
FileCreated: make(chan string),
FileDeleted: make(chan string),
}, nil
}
// WatchDirectory starts watching the specified directory and its subdirectories.
func (w *Watcher) WatchDirectory(rootPath string) error {
err := w.addDirectory(rootPath)
if err != nil {
return err
}
go w.watchEvents()
return nil
}
// addDirectory adds the specified directory and its subdirectories to the watcher.
func (w *Watcher) addDirectory(path string) error {
return filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if info.Mode().IsDir() {
return w.fsWatcher.Add(path)
}
return nil
})
}
// watchEvents handles the file system events and sends notifications.
func (w *Watcher) watchEvents() {
for {
select {
case event, ok := <-w.fsWatcher.Events:
if !ok {
return
}
w.handleEvent(event)
case err, ok := <-w.fsWatcher.Errors:
if !ok {
return
}
log.Println("Watcher error:", err)
}
}
}
// handleEvent processes the received fsnotify event.
func (w *Watcher) handleEvent(event fsnotify.Event) {
// You could include more cases here
switch {
case event.Op&fsnotify.Write == fsnotify.Write:
w.FileModified <- event.Name
case event.Op&fsnotify.Create == fsnotify.Create:
fi, err := os.Stat(event.Name)
if err != nil {
log.Println("Error stating file:", err)
return
}
if fi.Mode().IsDir() {
w.addDirectory(event.Name)
} else {
w.FileCreated <- event.Name
}
case event.Op&fsnotify.Remove == fsnotify.Remove:
w.FileDeleted <- event.Name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment