Example #1
1
// 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
}
Example #2
0
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
}
Example #3
0
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)
	}
}
Example #4
0
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)
}
Example #5
0
// 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
}
Example #7
0
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)
	}
}
Example #8
0
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}
		}
	}
}
Example #9
0
// 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)
}
Example #10
0
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
	}
}
Example #11
0
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()
}
Example #12
0
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
	}
}
Example #13
0
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
	}
}
Example #14
0
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
}
Example #15
0
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)
		}
	}
}
Example #16
0
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)
		}
	}
}
Example #17
0
// 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
	}
}
Example #18
0
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)
		}
	}
}
Example #19
0
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
	})
}
Example #20
0
// 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
}
Example #21
0
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:
		}
	}
}
Example #22
0
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
}
Example #23
0
func (s segments) Watch(watcher *fsnotify.Watcher) error {
	return watcher.Watch(string(s))
}
Example #24
0
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
}