/* DESCRIPTION watcher.go provides a tool for watching a file for modifications and performing an action when the file is modified. AUTHORS Saxon A. Nelson-Milton LICENSE Copyright (C) 2022 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see http://www.gnu.org/licenses. */ package main import ( "fmt" "path" "bitbucket.org/ausocean/utils/logging" "github.com/fsnotify/fsnotify" ) // watchFile watches a file for modifications and calls onWrite when the file // is modified. Technically, the directory is watched instead of the file. // This is because watching the file itself will cause problems if changes // are done atomically. // See fsnotify documentation: // https://godocs.io/github.com/fsnotify/fsnotify#hdr-Watching_files func watchFile(file string, onWrite func(), l logging.Logger) error { watcher, err := fsnotify.NewWatcher() if err != nil { return fmt.Errorf("could not create watcher: %w", err) } go func() { for { select { case event, ok := <-watcher.Events: if !ok { l.Warning("watcher events chan closed, terminating") return } if event.Op&fsnotify.Write == fsnotify.Write && event.Name == file { l.Info("file modification event", "file", file) onWrite() } case err, ok := <-watcher.Errors: if !ok { l.Warning("watcher error chan closed, terminating") return } l.Error("file watcher error", "error", err) } } }() // Watch the directory over the file. err = watcher.Add(path.Dir(file)) if err != nil { return fmt.Errorf("could not add file %s to watcher: %w", file, err) } return nil }