96 lines
1.9 KiB
Go
96 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
)
|
|
|
|
func WatchDirectory(op fsnotify.Op, path string) (<-chan string, error) {
|
|
watcher, err := fsnotify.NewWatcher()
|
|
if err != nil {
|
|
panic(err) // TODO error handling
|
|
}
|
|
|
|
err = watcher.Add(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
files, err := os.ReadDir(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ch := make(chan string, 10)
|
|
|
|
// close channel on app shutdown
|
|
go func() {
|
|
<-AppCtx.Done()
|
|
watcher.Close()
|
|
}()
|
|
|
|
AppExitWg.Add(1)
|
|
go func(watcher *fsnotify.Watcher, ch chan<- string) {
|
|
defer AppExitWg.Done()
|
|
defer watcher.Close()
|
|
|
|
for _, file := range files {
|
|
path := filepath.Join(path, file.Name())
|
|
if file.IsDir() {
|
|
//fmt.Println("watching directory", path)
|
|
watcher.Add(path)
|
|
|
|
if dirFiles, err := os.ReadDir(path); err == nil {
|
|
for _, dirFile := range dirFiles {
|
|
ch <- filepath.Join(path, dirFile.Name())
|
|
}
|
|
}
|
|
} else {
|
|
ch <- path
|
|
}
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case event, ok := <-watcher.Events:
|
|
if !ok {
|
|
close(ch)
|
|
return
|
|
}
|
|
|
|
if fi, err := os.Stat(event.Name); err == nil && fi.IsDir() {
|
|
if event.Op&fsnotify.Create == fsnotify.Create {
|
|
//fmt.Println("watching directory", event.Name)
|
|
watcher.Add(event.Name)
|
|
}
|
|
|
|
// read dir immediately because directory files could simultanously with its parent directory
|
|
if dirFiles, err := os.ReadDir(event.Name); err == nil {
|
|
for _, dirFile := range dirFiles {
|
|
ch <- filepath.Join(event.Name, dirFile.Name())
|
|
}
|
|
}
|
|
} else if err != nil && event.Op&fsnotify.Remove == fsnotify.Remove {
|
|
//fmt.Println("stopped watching directory", event.Name)
|
|
watcher.Remove(event.Name)
|
|
}
|
|
|
|
if event.Op&op == op {
|
|
ch <- event.Name
|
|
}
|
|
case err, ok := <-watcher.Errors:
|
|
if ok {
|
|
fmt.Println(err, ok)
|
|
}
|
|
close(ch)
|
|
return
|
|
}
|
|
}
|
|
}(watcher, ch)
|
|
|
|
return ch, nil
|
|
}
|