func (p *postManager) processPostEvent(ev *fsnotify.FileEvent) { ext := strings.ToLower(filepath.Ext(ev.Name)) switch ext { case p.brog.Config.PostFileExt: case ".md": case ".markdown": case ".mkd": default: p.brog.Debug("Posts ignore files in '%s': %s", ext, ev.Name) return } if ev.IsCreate() { p.processPostCreate(ev) return } if ev.IsModify() { p.processPostModify(ev) return } if ev.IsRename() { p.processPostRename(ev) return } if ev.IsDelete() { p.processPostDelete(ev) return } p.brog.Err("FileEvent '%s' is not recognized", ev.String()) }
func (this *Watcher) handlecb(v *triggered, ev *fsnotify.FileEvent) { if !v.canrun() { return } defer v.setLastUpdate() // in windows some events are sent 3 times c := time.Tick(g_cooldown) <-c var t EvType // execute if ev.IsModify() { t = C_Modify } else if ev.IsCreate() { t = C_Create } else if ev.IsDelete() { t = C_Delete } else if ev.IsRename() { t = C_Rename } else if ev.IsAttrib() { t = C_Attrib } else { fmt.Fprintln(os.Stderr, "unknown event") return } this.cb(&WatchEvent{ Type: t, Fpath: ev.Name, }) }
// Listen for FS events and signal work when something changes. // Will send errors over e. func (w *Watcher) Handle(work chan bool, e chan error) { var ( evt *fsnotify.FileEvent err error ) for { select { case evt = <-w.watcher.Event: w.gw.log.Printf("Filesystem changed: %v\n", evt.String()) isNewDir := evt.IsCreate() && w.gw.isDir(evt.Name) if isNewDir || evt.IsDelete() || evt.IsRename() { err = w.WatchDirs() if err != nil { e <- err return } } select { case work <- true: // gw.log.Printf("Work queued\n") // Queued work. default: // gw.log.Printf("Work queue full\n") // Work queue full, no worries. } case err = <-w.watcher.Error: e <- err return } } }
func handleChange(channel *amqp.Channel, ev *fsnotify.FileEvent) error { // check to see if the file is locked. If it is then break path, _ := filepath.Rel(rootDir, ev.Name) if FileIsLocked(path) { return nil } log.Printf("PUBLISHER: publishing %dB path (%q)", len(path), path) var change = &Change{ IsCreate: ev.IsCreate(), IsDelete: ev.IsDelete(), IsMod: ev.IsModify(), IsMove: ev.IsRename(), ModDate: time.Now().UTC(), Path: path, Source: hostname, Checksum: Checksum(ev.Name), } msg, err := json.Marshal(change) if err != nil { log.Fatalf("ERROR marshaling msg %s", change) } if err := channel.Publish( "changes", // publish to an exchange "", // routing to 0 or more queues false, // mandatory false, // immediate amqp.Publishing{ Headers: amqp.Table{}, ContentType: "application/json", ContentEncoding: "", Body: msg, DeliveryMode: amqp.Transient, // 1=non-persistent, 2=persistent Priority: 0, // 0-9 // a bunch of application/implementation-specific fields /* ContentType string // MIME content type ContentEncoding string // MIME content encoding DeliveryMode uint8 // Transient (0 or 1) or Persistent (2) Priority uint8 // 0 to 9 CorrelationId string // correlation identifier ReplyTo string // address to to reply to (ex: RPC) Expiration string // message expiration spec MessageId string // message identifier Timestamp time.Time // message timestamp Type string // message type name UserId string // creating user id - ex: "guest" AppId string // creating application id */ }, ); err != nil { log.Fatalf("Exchange Publish: %s", err) panic(err) } return nil }
func (fw *InotifyFileWatcher) ChangeEvents(t tomb.Tomb, fi os.FileInfo) chan bool { w, err := fsnotify.NewWatcher() if err != nil { panic(err) } err = w.Watch(fw.Filename) if err != nil { panic(err) } ch := make(chan bool) fw.Size = fi.Size() go func() { defer w.Close() defer w.RemoveWatch(fw.Filename) defer close(ch) for { prevSize := fw.Size var evt *fsnotify.FileEvent select { case evt = <-w.Event: case <-t.Dying(): return } switch { case evt.IsDelete(): fallthrough case evt.IsRename(): return case evt.IsModify(): fi, err := os.Stat(fw.Filename) if err != nil { // XXX: no panic here panic(err) } fw.Size = fi.Size() if prevSize > 0 && prevSize > fw.Size { return } // send only if channel is empty. select { case ch <- true: default: } } } }() return ch }
func (t *templateManager) processTemplateEvent(ev *fsnotify.FileEvent) { ext := strings.ToLower(filepath.Ext(ev.Name)) switch ext { case ".gohtml": case ".tmpl": default: t.brog.Debug("Templates ignore files in '%s': %s", ext, ev.Name) return } if ev.IsCreate() { // Nothing to do, all usefull templates files MUST exist at this // time or brog would not have started. return } if ev.IsModify() { t.processTemplateModify(ev) return } if ev.IsRename() || ev.IsDelete() { t.processTemplateDelete(ev) return } t.brog.Err("FileEvent '%s' is not recognized", ev.String()) }
func (fw *InotifyFileWatcher) ChangeEvents(t tomb.Tomb, fi os.FileInfo) *FileChanges { changes := NewFileChanges() w, err := fsnotify.NewWatcher() if err != nil { panic(err) } err = w.Watch(fw.Filename) if err != nil { panic(err) } fw.Size = fi.Size() go func() { defer w.Close() defer w.RemoveWatch(fw.Filename) defer changes.Close() for { prevSize := fw.Size var evt *fsnotify.FileEvent select { case evt = <-w.Event: case <-t.Dying(): return } switch { case evt.IsDelete(): fallthrough case evt.IsRename(): changes.NotifyDeleted() return case evt.IsModify(): fi, err := os.Stat(fw.Filename) if err != nil { // XXX: no panic here panic(err) } fw.Size = fi.Size() if prevSize > 0 && prevSize > fw.Size { changes.NotifyTruncated() } else { changes.NotifyModified() } prevSize = fw.Size } } }() return changes }
func eventDesc(ev *fsnotify.FileEvent) string { switch { case ev.IsCreate(): return "created" case ev.IsDelete(): return "removed" case ev.IsModify(): return "modified" case ev.IsRename(): return "renamed" default: return "" } }
func watchChange(ev *fsnotify.FileEvent) { if strings.HasPrefix(ev.Name, Config.GetAbsPath(Config.StaticDir)) { fmt.Println("Static file changed, syncing\n") utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) } else { if !ev.IsRename() { // Rename is always accompanied by a create or modify // Ignoring temp files created by editors (vim) if !strings.HasSuffix(ev.Name, "~") && !strings.HasSuffix(ev.Name, ".swp") { fmt.Println("Change detected, rebuilding site\n") utils.StopOnErr(buildSite(true)) } } } }
func watch() { var event *fsnotify.FileEvent var open bool for { if event, open = <-watcher.Event; open == false { break } else if event.IsModify() { go fileModified(event) } else if event.IsDelete() { out("DELETED", event.Name) } else if event.IsCreate() { go fileCreated(event) } else if event.IsRename() { } } }
func PreprocessEvent(event *fsnotify.FileEvent) { path := event.Name //ignore 5 root dir for _, p := range dir_list { if p == path { return } } if event.IsDelete() { ProcessDeleteEvent(event) } else { if isDir, err := pathutil.IsDir(path); isDir && err == nil { if event.IsCreate() { ProcessCreateEvent(event) } else if event.IsModify() { ProcessModifyEvent(event) } else if event.IsRename() { ProcessRenameEvent(event) } } } }
func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, fi os.FileInfo) *FileChanges { changes := NewFileChanges() w, err := inotifyTracker.NewWatcher() if err != nil { util.Fatal("Error creating fsnotify watcher: %v", err) } err = w.Watch(fw.Filename) if err != nil { util.Fatal("Error watching %v: %v", fw.Filename, err) } fw.Size = fi.Size() go func() { defer inotifyTracker.CloseWatcher(w) for { prevSize := fw.Size var evt *fsnotify.FileEvent var ok bool select { case evt, ok = <-w.Event: if !ok { return } case <-t.Dying(): return } switch { case evt.IsDelete(): fallthrough case evt.IsRename(): changes.NotifyDeleted() return case evt.IsModify(): fi, err := os.Stat(fw.Filename) if err != nil { if os.IsNotExist(err) { changes.NotifyDeleted() return } // XXX: report this error back to the user util.Fatal("Failed to stat file %v: %v", fw.Filename, err) } fw.Size = fi.Size() if prevSize > 0 && prevSize > fw.Size { changes.NotifyTruncated() } else { changes.NotifyModified() } prevSize = fw.Size } } }() return changes }
func (self *Launcher) itemChangedHandler(ev *fsnotify.FileEvent, name string, info map[string]ItemChangedStatus) { if _, ok := info[name]; !ok { info[name] = ItemChangedStatus{ make(chan bool), make(chan bool), make(chan bool), make(chan bool), 0, } } if ev.IsRename() { logger.Info("renamed") select { case <-info[name].renamed: default: } go func() { select { case <-info[name].notRenamed: return case <-time.After(time.Second): <-info[name].renamed if true { self.emitItemChanged(name, SoftwareStatusDeleted, info) } } }() info[name].renamed <- true } else if ev.IsCreate() { self.emitItemChanged(name, SoftwareStatusCreated, info) go func() { select { case <-info[name].renamed: // logger.Info("not renamed") info[name].notRenamed <- true info[name].renamed <- true default: // logger.Info("default") } select { case <-info[name].notCreated: return case <-time.After(time.Second): <-info[name].created } }() info[name].created <- true } else if ev.IsModify() && !ev.IsAttrib() { go func() { select { case <-info[name].created: info[name].notCreated <- true } select { case <-info[name].renamed: self.emitItemChanged(name, SoftwareStatusModified, info) default: } }() } else if ev.IsAttrib() { go func() { select { case <-info[name].renamed: <-info[name].created info[name].notCreated <- true default: } }() } else if ev.IsDelete() { if true { self.emitItemChanged(name, SoftwareStatusDeleted, info) } } }
func goFileTouched(event *fsnotify.FileEvent) bool { return (event.IsModify() || event.IsRename()) && strings.HasSuffix(event.Name, ".go") }