// recursive watches the given dir and recurses into all subdirectories as well func recursive(watcher *fsnotify.Watcher, dir string) error { info, err := os.Stat(dir) if err == nil && !info.Mode().IsDir() { err = errors.New("Watching a file is not supported. Expected a directory") } // Watch the specified dir if err == nil { err = watcher.Watch(dir) } var list []os.FileInfo // Grab list of subdirs if err == nil { list, err = ioutil.ReadDir(dir) } // Call recursive for each dir in list if err == nil { for _, file := range list { recursive(watcher, filepath.Join(dir, file.Name())) } } return err }
// Walk a path and watch non-hidden or build directories func walkAndWatch(path string, w *fsnotify.Watcher) (watched uint) { f := func(path string, fi os.FileInfo, err error) error { if fi.IsDir() { // Skip hidden directories if fi.Name()[0] == '.' { return filepath.SkipDir } // Skip *build* directories if strings.Contains(fi.Name(), "build") { return filepath.SkipDir } // Skip *static* directories if strings.Contains(fi.Name(), "static") { return filepath.SkipDir } // Watch this path err = w.Watch(path) watched++ if err != nil { log.Fatalf("Error trying to watch %s:\n%v\n%d paths watched", path, err, watched) } } return nil } err := filepath.Walk(path, f) if err != nil && err != filepath.SkipDir { log.Fatal("Error walking tree: %v\n", err) } return }
func processSubdir(watcher *fsnotify.Watcher, ev *fsnotify.FileEvent) { if ev.IsModify() { return } if ev.IsDelete() { log.Println("remove watch", ev.Name) // FIXME: what to do with err? watcher.RemoveWatch(ev.Name) return } // FIXME: Lstat or Stat? // TODO: what to do with err? can we safely ignore? mode, err := os.Lstat(ev.Name) if err != nil { log.Println("error processing subdir:", err.Error()) return } if !mode.IsDir() { return } // FIXME: handle renames if ev.IsCreate() { log.Println("add watch", ev.Name) // FIXME: what to do with err? watcher.Watch(ev.Name) } }
func watchDir(w *fsnotify.Watcher, dir string, reload func()) error { if err := w.Watch(dir); err != nil { return err } // And also watch subdirectories if d, err := os.Open(dir); err != nil { return err } else { defer d.Close() if subDirs, err := d.Readdir(-1); err != nil { return err } else { for _, f := range subDirs { if !f.IsDir() { continue } if err := watchDir(w, path.Join(dir, f.Name()), reload); err != nil { return err } } } } return nil }
func refreshIndex(dir string, watcher *fsnotify.Watcher, sync chan *SyncEvent) { entries, err := ioutil.ReadDir(dir) if err != nil { log.Println(err) return } _, inIndex := index[dir] if !inIndex { watcher.Watch(dir) } index[dir] = true for _, e := range entries { name := e.Name() if e.IsDir() && !strings.HasPrefix(name, ".") { refreshIndex(filepath.Join(dir, name), watcher, sync) // Schedule the file for syncing if the directory was not found // within the index } else if !inIndex { sync <- &SyncEvent{Name: filepath.Join(dir, name), Type: SYNC_PUT} } } }
func MonitorFile(filename string, out chan []string, watcher *fsnotify.Watcher) { size := GetFileSize(filename) go func() { for { select { case ev := <-watcher.Event: if ev.IsModify() { NewSize := GetFileSize(ev.Name) if NewSize <= size { MonitorFile(ev.Name, out, watcher) return } content := ReadNBytes(ev.Name, size, NewSize-1) size = NewSize out <- ByteArrayToMultiLines(content) } case err := <-watcher.Error: log.Println("error:", err) } } }() err := watcher.Watch(filename) if err != nil { log.Fatal(err) } }
// WatchDeep watches a directory and all // of its subdirectories. If the path is not // a directory then watchDeep is a no-op. func watchDeep(w *fsnotify.Watcher, path string) { info, err := os.Stat(path) if os.IsNotExist(err) { // This file disapeared on us, fine. return } if err != nil { die(err) } if !info.IsDir() { return } if err := w.Watch(path); err != nil { die(err) } f, err := os.Open(path) if err != nil { die(err) } ents, err := f.Readdirnames(-1) if err != nil { die(err) } f.Close() for _, e := range ents { watchDeep(w, filepath.Join(path, e)) } }
func _watch(watcher *fsnotify.Watcher, sig chan<- *fsnotify.FileEvent, match func(*fsnotify.FileEvent) bool) { for cont := true; cont; { select { case ev := <-watcher.Event: Debug(2, "event:", ev) if ev.IsCreate() { info, err := os.Stat(ev.Name) if err != nil { Debug(2, "stat error: ", err) continue } if info.IsDir() { Debug(1, "watching: ", ev.Name) err := watcher.Watch(ev.Name) if err != nil { Error("watch error: ", err) } } } if match(ev) { sig <- ev } case err := <-watcher.Error: Print("watcher error:", err) } } close(sig) }
func watch(root string, watcher *fsnotify.Watcher, names chan<- string, done chan<- error) { if err := filepath.Walk(root, walker(watcher)); err != nil { // TODO: handle this somehow? infoPrintf(-1, "Error while walking path %s: %s\n", root, err) } for { select { case e := <-watcher.Event: path := strings.TrimPrefix(e.Name, "./") names <- path if e.IsCreate() { if err := filepath.Walk(path, walker(watcher)); err != nil { // TODO: handle this somehow? infoPrintf(-1, "Error while walking path %s: %s\n", path, err) } } if e.IsDelete() { watcher.RemoveWatch(path) } case err := <-watcher.Error: done <- err return } } }
func rerun(buildpath string, args []string) (err error) { log.Printf("setting up %s %v", buildpath, args) pkg, err := build.Import(buildpath, "", 0) if err != nil { return } if pkg.Name != "main" { err = errors.New(fmt.Sprintf("expected package %q, got %q", "main", pkg.Name)) return } _, binName := path.Split(buildpath) binPath := filepath.Join(pkg.BinDir, binName) runch := run(binName, binPath, args) var errorOutput string _, errorOutput, ierr := install(buildpath, errorOutput) if ierr == nil { runch <- true } var watcher *fsnotify.Watcher watcher, err = getWatcher(buildpath) if err != nil { return } for { we, _ := <-watcher.Event var installed bool installed, errorOutput, _ = install(buildpath, errorOutput) if installed { log.Print(we.Name) runch <- true watcher.Close() /* empty the buffer */ go func(events chan *fsnotify.FileEvent) { for _ = range events { } }(watcher.Event) go func(errors chan error) { for _ = range errors { } }(watcher.Error) /* rescan */ log.Println("rescanning") watcher, err = getWatcher(buildpath) if err != nil { return } } } return }
func (t *InotifyTracker) CloseWatcher(w *fsnotify.Watcher) (err error) { t.mux.Lock() defer t.mux.Unlock() if _, ok := t.watchers[w]; ok { err = w.Close() delete(t.watchers, w) } return }
// watchAllDirs will watch a directory and then walk through all subdirs // of that directory and watch them too func watchAllDirs(watcher *fsnotify.Watcher, root string) (err error) { walkFn := func(path string, info os.FileInfo, err error) error { if info.IsDir() { watcher.Watch(path) } return nil } return filepath.Walk(root, walkFn) }
func watchAll(watcher *fsnotify.Watcher) filepath.WalkFunc { return func(fn string, fi os.FileInfo, err error) error { if err != nil { return nil } watcher.Watch(fn) return nil } }
func monitorConf(file string, wa *fsnotify.Watcher) { for { err := wa.Watch(file) if err != nil { time.Sleep(2 * time.Second) continue } log.Error("Set Watch [%s] ok!", file) break } }
func main() { var ( err error watcher *fsnotify.Watcher done chan bool includePattern string include *regexp.Regexp watchedFile string ) flag.StringVar(&watchedFile, "watch", "none", `Directory to watch for modification events`) flag.StringVar(&includePattern, "include", "", `Filename pattern to include (regex)`) flag.Parse() include = nil if includePattern != "" { include = regexp.MustCompile(includePattern) } watcher, err = fsnotify.NewWatcher() if err != nil { log.Fatal(err) } done = make(chan bool) go func(include *regexp.Regexp, hdlr modifyHandler) { for { select { case ev := <-watcher.Event: // log.Println("event:", ev) if include == nil || include.MatchString(ev.Name) { if ev.IsModify() || ev.IsCreate() { log.Printf("Calling handler\n") hdlr(ev.Name, "make") } } case err := <-watcher.Error: log.Println("error:", err) } } }(include, triggerCmd) err = watcher.Watch(watchedFile) if err != nil { fmt.Printf("%s: %v\n", watchedFile, err) os.Exit(1) } <-done watcher.Close() }
func walker(watcher *fsnotify.Watcher) filepath.WalkFunc { return func(path string, f os.FileInfo, err error) error { if err != nil || !f.IsDir() { // TODO: Is there some other thing we should be doing to handle errors? When watching large // directories that have lots of programs modifying them (esp. if they're making tempfiles along the // way), we often get errors. return nil } if err := watcher.Watch(path); err != nil { // TODO: handle this somehow? infoPrintf(-1, "Error while watching new path %s: %s\n", path, err) } return nil } }
func (db *DB) watchEvents(watcher *fsnotify.Watcher) { for { select { case ev := <-watcher.Event: if ev.Name == db.file && (ev.IsCreate() || ev.IsModify()) { db.openFile() } case <-watcher.Error: case <-db.notifyQuit: watcher.Close() return } time.Sleep(time.Second) // Suppress high-rate events. } }
func addToWatcher(watcher *fsnotify.Watcher, importpath string, watching map[string]bool) { pkg, err := build.Import(importpath, "", 0) if err != nil { return } if pkg.Goroot { return } watcher.Watch(pkg.Dir) watching[importpath] = true for _, imp := range pkg.Imports { if !watching[imp] { addToWatcher(watcher, imp, watching) } } }
func watchRecursive(dir string, watcher *fsnotify.Watcher) error { err := watcher.Watch(dir) if err != nil { return err } dirFiles, err := ioutil.ReadDir(dir) for _, file := range dirFiles { if file.IsDir() { err = watchRecursive(path.Join(dir, file.Name()), watcher) if err != nil { return err } } } return nil }
// adds a watcher.Watch to every directory func walkHandler(watcher *fsnotify.Watcher) filepath.WalkFunc { return func(path string, info os.FileInfo, err error) error { if err != nil { return err } // add a watch if path is a directory if info.IsDir() { errAddWatch := watcher.Watch(path) if errAddWatch != nil { // handle return errAddWatch } log.Println("Watching dir:", path) } return nil } }
func add2Watcher(ws *fsnotify.Watcher, pkgpath string, assets map[string]bool) { pkg, err := build.Import(pkgpath, "", 0) if err != nil { log.Printf("Import path watch error %s", err.Error()) return } if pkg.Goroot { return } ws.Watch(pkg.Dir) assets[pkgpath] = true for _, imp := range pkg.Imports { if !assets[imp] { add2Watcher(ws, imp, assets) } } }
func watchDir(ws *fsnotify.Watcher, dir string, assets map[string]bool, skip []string) { mo, err := os.Stat(dir) if err != nil { return } if !mo.IsDir() { return } filepath.Walk(filepath.ToSlash(dir), func(path string, info os.FileInfo, err error) error { if strings.Contains(path, ".git") { return nil } if info == nil { return nil } if hasIn(skip, path) { return nil } // log.Printf("adding: %s", path) // if !info.IsDir() { // return nil // } if assets[path] { return nil } ws.Watch(path) assets[path] = true return nil }) }
// Adds all sub directories of the given directory to the watcher // and returns the number of watched directories. func watchRecursive(dir string, watcher *fsnotify.Watcher) int { var watched int entries, err := ioutil.ReadDir(dir) if err != nil { log.Println(err) return 0 } watcher.Watch(dir) watched++ for _, e := range entries { name := e.Name() if e.IsDir() && !strings.HasPrefix(name, ".") { watched += watchRecursive(filepath.Join(dir, name), watcher) } } return watched }
func recursiveAddPath(watcher *fsnotify.Watcher, path string) error { // recursivly find all dirs wf := func(path string, info os.FileInfo, err error) (err2 error) { // fmt.Printf("walk path:%v info:%v er:%v\n", path, info) if err2 != nil { return err2 } if isDir(path) { fmt.Printf("add to watcher: path:%v info:%v er:%v\n", path, info) err3 := watcher.Watch(path) if err3 != nil { panic(err3) } } return nil } filepath.Walk(path, wf) return nil }
func watch(watcher *fsnotify.Watcher, dir string, handler func(name string)) { defer watcher.Close() err := recursive(watcher, dir) if err != nil { return } for { select { case ev := <-watcher.Event: if ev.IsCreate() { recursive(watcher, ev.Name) } handler(ev.Name) case <-watcher.Error: // nothing to do for now } } }
func (self *Launcher) eventHandler(watcher *fsnotify.Watcher) { var info = map[string]ItemChangedStatus{} for { select { case ev := <-watcher.Event: name := path.Clean(ev.Name) basename := path.Base(name) if basename == "kde4" { if ev.IsCreate() { watcher.Watch(name) } else if ev.IsDelete() { watcher.RemoveWatch(name) } } matched, _ := path.Match(`[^#.]*.desktop`, basename) if matched { go self.itemChangedHandler(ev, name, info) } case <-watcher.Error: } } }
func (n *Notifier) Watch(o Observer) { var err error var abspath string for _, basePath := range o.Path() { abspath, err = filepath.Abs(basePath) if err != nil { ERROR.Println("create watcher error:", err) continue } if n.contain(abspath) { continue } var watcher *fsnotify.Watcher watcher, err = fsnotify.NewWatcher() //collect 100 events watcher.Event = make(chan *fsnotify.FileEvent, 200) //collect 10 error watcher.Error = make(chan error, 20) obsWatcher := &observerWatcher{o, watcher, abspath} n.watchers = append(n.watchers, obsWatcher) var ignoreObserver IgnoreObserver = nil var isIgnoreObserver bool ignoreObserver, isIgnoreObserver = o.(IgnoreObserver) watcher.Watch(abspath) err = filepath.Walk(abspath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { return nil } if isIgnoreObserver { if info.IsDir() && ignoreObserver.IgnoreDir(info) { return filepath.SkipDir } } watcher.Watch(path) return nil }) if err != nil { ERROR.Println("watch error:", err) } } }
// initWatchers initializes the watcher flags for all the monitored directories func initWatchers(watcher *fsnotify.Watcher, ctx Context) (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("initWatchers() -> %v", e) } ctx.Channels.Log <- mig.Log{Desc: "leaving initWatchers()"}.Debug() }() err = watcher.WatchFlags(ctx.Directories.Action.New, fsnotify.FSN_CREATE) if err != nil { e := fmt.Errorf("%v '%s'", err, ctx.Directories.Action.New) panic(e) } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("watcher.Watch(): %s", ctx.Directories.Action.New)}.Debug() err = watcher.WatchFlags(ctx.Directories.Command.InFlight, fsnotify.FSN_CREATE) if err != nil { e := fmt.Errorf("%v '%s'", err, ctx.Directories.Command.InFlight) panic(e) } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("watcher.Watch(): %s", ctx.Directories.Command.InFlight)}.Debug() err = watcher.WatchFlags(ctx.Directories.Command.Returned, fsnotify.FSN_CREATE) if err != nil { e := fmt.Errorf("%v '%s'", err, ctx.Directories.Command.Returned) panic(e) } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("watcher.Watch(): %s", ctx.Directories.Command.Returned)}.Debug() err = watcher.WatchFlags(ctx.Directories.Action.Done, fsnotify.FSN_CREATE) if err != nil { e := fmt.Errorf("%v '%s'", err, ctx.Directories.Action.Done) panic(e) } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("watcher.Watch(): %s", ctx.Directories.Action.Done)}.Debug() return }
func rerun(buildpath string, args []string) (err error) { log.Printf("setting up %s %v", buildpath, args) pkg, err := build.Import(buildpath, "", 0) if err != nil { return } if pkg.Name != "main" { err = errors.New(fmt.Sprintf("expected package %q, got %q", "main", pkg.Name)) return } _, binName := path.Split(buildpath) var binPath string if *outfile != "" { if *outfile == "getwd" { p, err := os.Getwd() if err == nil { binPath = filepath.Join(p, binName) } else { panic("Can't usw getwd: " + err.Error()) } } else { p, err := filepath.Abs(*outfile) if err == nil { binPath = filepath.Join(p, binName) } else { panic("Can't usw abs: " + err.Error()) } } } else { if gobin := os.Getenv("GOBIN"); gobin != "" { binPath = filepath.Join(gobin, binName) } else { binPath = filepath.Join(pkg.BinDir, binName) } } var runch chan bool if !(*never_run) { runch = run(binName, binPath, args) } no_run := false if *do_tests { passed, _ := test(buildpath) if !passed { no_run = true } } if *do_build && !no_run { gobuild(buildpath) } var errorOutput string _, errorOutput, ierr := install(buildpath, errorOutput) if !no_run && !(*never_run) && ierr == nil { runch <- true } var watcher *fsnotify.Watcher watcher, err = getWatcher(buildpath) if err != nil { return } for { // read event from the watcher we, _ := <-watcher.Event // other files in the directory don't count - we watch the whole thing in case new .go files appear. if filepath.Ext(we.Name) != ".go" { continue } log.Print(we.Name) // close the watcher watcher.Close() // to clean things up: read events from the watcher until events chan is closed. go func(events chan *fsnotify.FileEvent) { for _ = range events { } }(watcher.Event) // create a new watcher log.Println("rescanning") watcher, err = getWatcher(buildpath) if err != nil { return } // we don't need the errors from the new watcher. // we continiously discard them from the channel to avoid a deadlock. go func(errors chan error) { for _ = range errors { } }(watcher.Error) var installed bool // rebuild installed, errorOutput, _ = install(buildpath, errorOutput) if !installed { continue } if *do_tests { passed, _ := test(buildpath) if !passed { continue } } if *do_build { gobuild(buildpath) } // rerun. if we're only testing, sending if !(*never_run) { runch <- true } } return }
func (s segments) Watch(watcher *fsnotify.Watcher) error { return watcher.Watch(string(s)) }