// 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 }
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 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 _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) }
// 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)) } }
// 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 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) } }
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} } } }
// 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 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 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 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 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 }
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 (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) } } }
// 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 (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 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 (s segments) Watch(watcher *fsnotify.Watcher) error { return watcher.Watch(string(s)) }
func WatchRecursively(watcher *fsnotify.Watcher, root string, monitored string) error { if ignore(root, monitored) { fmt.Println("Ignored: ", root) return nil } safeRoot := PathSafe(root) mapFiles := make(map[string]IndexedFile) func() { db, _ := sql.Open("sqlite3", SlashSuffix(monitored)+".sync/index.db") defer db.Close() psSelectFilesLike, _ := db.Prepare("SELECT * FROM FILES WHERE FILE_PATH LIKE ?") defer psSelectFilesLike.Close() rows, _ := psSelectFilesLike.Query(SlashSuffix(LikeSafe(safeRoot)[len(monitored):]) + "%") defer rows.Close() for rows.Next() { file := new(IndexedFile) rows.Scan(&file.FilePath, &file.LastModified, &file.FileSize, &file.FileMode, &file.Status, &file.LastIndexed) mapFiles[file.FilePath] = *file } }() filepath.Walk(safeRoot, (filepath.WalkFunc)(func(path string, info os.FileInfo, err error) error { db, _ := sql.Open("sqlite3", SlashSuffix(monitored)+".sync/index.db") defer db.Close() //fmt.Println(path) if ignore(path, monitored) { fmt.Println("Ignored: ", path) return nil } var thePath string if info.IsDir() { thePath = SlashSuffix(PathSafe(path)) if strings.HasPrefix(thePath, SlashSuffix(safeRoot)+".sync/") { return nil } watcher.Watch(thePath[0 : len(thePath)-1]) // update index func() { if v, ok := mapFiles[thePath[len(monitored):]]; !ok { psInsertFiles, _ := db.Prepare(`INSERT INTO FILES (FILE_PATH,LAST_MODIFIED,FILE_SIZE,FILE_MODE,STATUS,LAST_INDEXED) VALUES(?,?,?,?,?,?)`) defer psInsertFiles.Close() psInsertFiles.Exec(thePath[len(monitored):], info.ModTime().Unix(), -1, uint32(info.Mode().Perm()), "ready", time.Now().Unix()) } else { if v.Status != "ready" { psUpdateFiles, _ := db.Prepare(`UPDATE FILES SET FILE_MODE=?,STATUS='ready',LAST_MODIFIED=?,LAST_INDEXED=? WHERE FILE_PATH=?`) defer psUpdateFiles.Close() psUpdateFiles.Exec(info.Mode().Perm(), info.ModTime().Unix(), time.Now().Unix(), v.FilePath) } } }() } else { thePath = PathSafe(path) if strings.HasPrefix(PathSafe(filepath.Dir(thePath)), SlashSuffix(safeRoot)+".sync") { return nil } ProcessFileChange(thePath, info, monitored) } delete(mapFiles, thePath[len(monitored):]) return nil })) // remove zombies for k, v := range mapFiles { if k != "/" && v.Status == "ready" { fmt.Println("Zombie removed: ", v.FilePath) ProcessFileDelete(monitored+k, monitored) } } return nil }