music-library/watch_dir.go

110 lines
2.1 KiB
Go
Raw Normal View History

2025-01-15 12:48:20 +01:00
package main
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/fsnotify/fsnotify"
)
func WatchDirectory(ctx context.Context, path string, op ...fsnotify.Op) (<-chan string, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
ops := fsnotify.Op(0)
for _, op := range op {
ops |= op
}
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, 1000)
// close channel on app shutdown
go func() {
<-ctx.Done()
watcher.Close()
}()
go func(watcher *fsnotify.Watcher, ch chan<- string) {
defer watcher.Close()
defer close(ch)
for _, file := range files {
path := filepath.Join(path, file.Name())
2025-01-15 21:06:45 +01:00
if PathIsExcluded(path) {
continue
}
2025-01-15 12:48:20 +01:00
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
}
2025-01-15 21:06:45 +01:00
if PathIsExcluded(event.Name) {
continue
}
2025-01-15 12:48:20 +01:00
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 change 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&ops > 0 {
ch <- event.Name
}
case err, ok := <-watcher.Errors:
if ok {
fmt.Println(err, ok)
}
close(ch)
return
}
}
}(watcher, ch)
return ch, nil
}