Skip to content

Commit

Permalink
Watch directories and not files. (#506)
Browse files Browse the repository at this point in the history
Editors, like VIM, often save files by writing into a temporary file
first and then only replacing the original file. If we watch a file we
wouldn't get any notifications as we would watch a deleted file.

Watching directories is the recommended approach:

https://github.com/fsnotify/fsnotify?tab=readme-ov-file#watching-a-file-doesnt-work-well
  • Loading branch information
floitsch committed Mar 20, 2024
1 parent 568185e commit b9e9e32
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions cmd/jag/commands/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ type watcher struct {
sync.Mutex
watcher *fsnotify.Watcher

dirs map[string]struct{}
paths map[string]struct{}
}

Expand Down Expand Up @@ -125,29 +126,37 @@ func (w *watcher) CountPaths() int {
}

func (w *watcher) Watch(paths ...string) (err error) {
w.Mutex.Lock()
defer w.Mutex.Unlock()

for i, p := range paths {
if paths[i], err = filepath.EvalSymlinks(p); err != nil {
return err
}
}

candidateDirs := map[string]struct{}{}
candidates := map[string]struct{}{}
for _, p := range paths {
if _, ok := w.paths[p]; !ok {
w.Mutex.Lock()
w.watcher.Add(p)
w.paths[p] = struct{}{}
w.Mutex.Unlock()
dir := filepath.Dir(p)
w.paths[p] = struct{}{}
if _, ok := w.dirs[dir]; !ok {
w.watcher.Add(dir)
}
candidateDirs[dir] = struct{}{}
candidates[p] = struct{}{}
}

// Remove the files/watchers we don't need anymore.
for p := range w.paths {
if _, ok := candidates[p]; !ok {
w.Mutex.Lock()
w.watcher.Remove(p)
delete(w.paths, p)
w.Mutex.Unlock()
}
}
for d := range w.dirs {
if _, ok := candidateDirs[d]; !ok {
delete(w.dirs, d)
w.watcher.Remove(d)
}
}
return nil
Expand Down Expand Up @@ -229,6 +238,10 @@ func onWatchChanges(
if !ok {
return
}
if _, ok = watcher.paths[event.Name]; !ok {
// Not a file we are watching.
continue
}
if event.Op&fsnotify.Write == fsnotify.Write {
if !fired {
fmt.Printf("File modified '%s'\n", event.Name)
Expand Down

0 comments on commit b9e9e32

Please sign in to comment.