Skip to content

Commit

Permalink
feat(only-watch-suffixes): adds flags to support only specified suffixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nxtcoder17 committed Dec 9, 2024
1 parent ebff05b commit d1e77e4
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 28 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## fwatcher

fwatcher is a simple golang CLI tool to monitor file changes and run some commands on those events.
fwatcher is a simple utility to monitor file changes and run some commands on those events.

### Installation

Expand Down Expand Up @@ -32,20 +32,24 @@ NAME:
USAGE:
fwatcher [global options] command [command options] [arguments...]

VERSION:
dev

COMMANDS:
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--debug toggles showing debug logs (default: false)
--command value, -c value specifies command to execute on file change
--dir value, -d value directory to watch on (default: ".")
--dir value, -d value directory to watch on (default: "/var/home/nxtcoder17/workspace/nxtcoder17/fwatcher")
--ignore-suffixes value, -i value [ --ignore-suffixes value, -i value ] files suffixes to ignore
--only-watch-suffixes value, -w value [ --only-watch-suffixes value, -w value ] files suffixes to watch
--exclude-dir value, -x value, -e value [ --exclude-dir value, -x value, -e value ] directory to exclude from watching
--no-default-ignore, -I disables ignoring from default ignore list (default: false)
--help, -h show help
--version, -v print the version
```

[See fwatcher in action](https://github.com/nxtcoder17/fwatcher/assets/22402557/ce1b1908-cb9f-438f-85c1-3a8858265c40)
[See fwatcher in action](fwatcher_recording)

![fwatcher recording](https://github.com/nxtcoder17/fwatcher/assets/22402557/ce1b1908-cb9f-438f-85c1-3a8858265c40)
70 changes: 45 additions & 25 deletions pkg/watcher/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,54 @@ var (
Chmod = fsnotify.Chmod
)

func (f fsnWatcher) ignoreEvent(event fsnotify.Event) bool {
func (f fsnWatcher) ignoreEvent(event fsnotify.Event) (ignore bool, reason string) {
if event.Op == fsnotify.Chmod {
return true, "event is of type CHMOD"
}

// Vim/Neovim creates this temporary file to see whether it can write
// into a target directory. It screws up our watching algorithm,
// so ignore it.
// [source](https://brandur.org/live-reload)
if filepath.Base(event.Name) == "4913" {
return true
return true, "event is from a temporary file created by vim/neovim"
}

// Special case for Vim:
// vim creates files with ~ suffixes, which we don't want to watch.
if strings.HasSuffix(event.Name, "~") {
return true
return true, "event is from a special file from vim/neovim which ends in ~"
}

for _, suffix := range f.IgnoreSuffixes {
if strings.HasSuffix(event.Name, suffix) {
f.Logger.Debug("file is ignored", "file", event.Name)
return true
return true, fmt.Sprintf("because, file has suffix (%s), which is in ignore suffixes array(%+v)", suffix, f.IgnoreSuffixes)
}
}

if len(f.OnlyWatchSuffixes) == 0 {
return false
return false, "event not in ignore list, and only-watch list is also empty"
}

matched := false
for _, suffix := range f.OnlyWatchSuffixes {
f.Logger.Debug("[only-watch-suffix] suffix: (%s), event.name: %s", suffix, event.Name)
if strings.HasSuffix(event.Name, suffix) {
return false
matched = true
break
}
}
if matched {
return false, "event suffix is present in only-watch-suffixes"
}

return true
return true, "event ignored as suffix is not present in only-watch-suffixes"
}

func (f *fsnWatcher) WatchEvents(watcherFunc func(event Event, fp string) error) {
f.eventMap = map[string]eventInfo{}
// f.eventMap = map[string]eventInfo{}
lastProcessingTime := time.Now()
for {
select {
case event, ok := <-f.watcher.Events:
Expand All @@ -93,34 +104,37 @@ func (f *fsnWatcher) WatchEvents(watcherFunc func(event Event, fp string) error)
t := time.Now()
f.Logger.Debug(fmt.Sprintf("event %+v received", event))

if f.ignoreEvent(event) {
if ignore, reason := f.ignoreEvent(event); ignore {
f.Logger.Debug("IGNORING", "event.name", event.Name, "reason", reason)
continue
}

fi, err := os.Stat(event.Name)
if err != nil {
return
}
f.Logger.Debug("PROCESSING", "event.name", event.Name, "event.op", event.Op.String())

eInfo, ok := f.eventMap[event.Name]
if !ok {
eInfo = eventInfo{Time: time.Now(), FileInfo: nil, Counter: 0}
}
eInfo.Counter += 1
f.eventMap[event.Name] = eInfo
// _, err := os.Stat(event.Name)
// if err != nil {
// return
// }

// eInfo, ok := f.eventMap[event.Name]
// if !ok {
// eInfo = eventInfo{Time: time.Now(), FileInfo: nil, Counter: 0}
// }
// eInfo.Counter += 1
// f.eventMap[event.Name] = eInfo

if time.Since(eInfo.Time) < 100*time.Millisecond {
f.Logger.Debug("too many events under 1s, ignoring...", "counter", eInfo.Counter)
if time.Since(lastProcessingTime) < 100*time.Millisecond {
// f.Logger.Debug("too many events under 100ms, ignoring...", "counter", eInfo.Counter)
continue
}

if err := watcherFunc(Event(event), event.Name); err != nil {
f.Logger.Error("while processing event, got", "err", err)
return
}
eInfo.Time = time.Now()
eInfo.Counter = 0
f.eventMap[event.Name] = eInfo
// eInfo.Time = time.Now()
// eInfo.Counter = 0
// f.eventMap[event.Name] = eInfo

f.Logger.Debug("watch loop completed", "took", fmt.Sprintf("%dms", time.Since(t).Milliseconds()))
}
Expand Down Expand Up @@ -211,5 +225,11 @@ func NewWatcher(args WatcherArgs) (Watcher, error) {
args.Logger.Error("failed to create watcher, got", "err", err)
return nil, err
}
return &fsnWatcher{watcher: watcher, Logger: args.Logger, ExcludeDirs: excludeDirs, IgnoreSuffixes: args.IgnoreSuffixes, OnlyWatchSuffixes: args.OnlyWatchSuffixes}, nil
return &fsnWatcher{
watcher: watcher,
Logger: args.Logger,
ExcludeDirs: excludeDirs,
IgnoreSuffixes: args.IgnoreSuffixes,
OnlyWatchSuffixes: args.OnlyWatchSuffixes,
}, nil
}

0 comments on commit d1e77e4

Please sign in to comment.