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 }
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 (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 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 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 watch(command, importable, bin, exts string, dobuild, watchbuild, withdir bool, args []string) error { log.Printf("Command: %s %s %s %t", command, importable, bin, dobuild) extcls := multispaces.ReplaceAllString(exts, " ") extens := multispaces.Split(extcls, -1) if len(extens) == 1 && extens[0] == "" { extens = extens[:0] } var buildName string var ubin string var buildHandler = func() error { var pkgs *build.Package var err error pkgs, err = build.Import(importable, "", 0) if err != nil { return err } _, buildName = path.Split(pkgs.ImportPath) // _, buildName := path.Split("./") wd, _ := os.Getwd() if bin != "" { ubin = filepath.ToSlash(filepath.Join(wd, bin)) } else { ubin = pkgs.BinDir } // lets install _, err = goDeps("./") if err != nil { log.Printf("go.install.err: %s", err.Error()) // return err } log.Printf("Building Pkg %s \nBin: %s \nUsing name: %s", pkgs.ImportPath, ubin, buildName) done, err := gobuild(ubin, buildName) if err != nil { return err } _ = done return nil } var buildWatch = func() (*fsnotify.Watcher, error) { var err error var watch *fsnotify.Watcher added := make(map[string]bool) if watchbuild { log.Printf("Watch import Path enabled") watch, err = buildPkgWatcher(importable, added) } else { if !added["./"] { watch, err = buildWatcher("./") } } //lets watch the current directory also if allowed if withdir && err == nil { wod, ex := os.Getwd() if ex == nil && wod != "" { watchDir(watch, wod, added, []string{ubin}) } } return watch, err } var err error var watch *fsnotify.Watcher var binRun bool var binChan chan bool //lets build if we are allowed if dobuild { if err = buildHandler(); err != nil { return err } binChan = runBin(ubin, buildName, args) binRun = true binChan <- true } log.Printf("Building dir watchers.....") watch, err = buildWatch() if err != nil { log.Printf("Unable to build err %s", err.Error()) return err } for { //should we watch we, _ := <-watch.Event exo := filepath.Ext(we.Name) //if its a .git directory skip it if strings.Contains(filepath.ToSlash(we.Name), ".git") { continue } //if its our bin directory skip it if filepath.ToSlash(we.Name) == filepath.ToSlash(ubin) { continue } log.Printf("Watch: %s -> %s with extensions: %s", exo, we.Name, extens) if len(extens) > 0 { var found bool for _, mo := range extens { if exo == mo { found = true break } } if !found { continue } } log.Printf("Watcher notified change: %s", we.Name) watch.Close() go func(evs chan *fsnotify.FileEvent) { for _ = range evs { } }(watch.Event) log.Printf("Re-initiating watch scans .....") if command != "" { log.Printf("Running cmd '%s' with result: '%s'", command, goRun(command)) } if dobuild { if err = buildHandler(); err != nil { return err } if binRun { binChan <- true } } watch, err = buildWatch() if err != nil { return err } go func(errors chan error) { for _ = range errors { } }(watch.Error) } }
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 gobin := os.Getenv("GOBIN"); gobin != "" { binPath = filepath.Join(gobin, binName) } else { 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 { // read event from the watcher we, _ := <-watcher.Event var installed bool installed, errorOutput, _ = install(buildpath, errorOutput) if installed { log.Print(we.Name) // re-build and re-run the application runch <- true // 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. // therfore we continiously discard them from the channel to avoid a deadlock. go func(errors chan error) { for _ = range errors { } }(watcher.Error) } } return }