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, }) }
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 (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 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 (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 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 (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 handleEvent(ev *fsnotify.FileEvent) { if len(ev.Name) > 0 { switch { case ev.IsCreate(): handleCreate(ev.Name) case ev.IsDelete(): handleDelete(ev.Name) case ev.IsModify(): handleModify(ev.Name) } } }
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 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 (r Rule) MatchedCommand(ev *fsnotify.FileEvent) (string, bool) { if r.eventName == "MODIFY" && !ev.IsModify() { return "", false } if r.eventName == "CREATE" && !ev.IsCreate() { return "", false } if r.eventName == "DELETE" && !ev.IsDelete() { return "", false } match := r.match.FindStringSubmatch(ev.Name) if match == nil { return "", false } if len(match) == 1 { return r.cmd, true } return r.match.ReplaceAllString(ev.Name, r.cmd), true }
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") }