halimath / globwatch

Recursive glob watches of filesystems for go(lang)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

globwatch

A file system glob watcher for golang.

CI Status Go Report Card Package Doc Releases

globwatch provides a file system watcher that detects changes recursively for files that match a glob pattern.

Installation

globwatch is provided as a go module and requires go >= 1.18.

go get github.com/halimath/globwatch@main

Usage

Creating a Watcher

globwatch provides a Watcher that can be created using the New function. The function receives a fs.FS handle to watch, a pattern (see below) and a check interval.

Once a Watcher has been created, you can start the watch routine by invoking Start or StartContext. The second function expects a context.Context that - when done - causes the watcher to terminate. Otherwise you can invoke Close to finish watching. Once finished a Watcher cannot be restarted.

watcher, err := globwatch.New(fsys, "**/*_test.go", time.Millisecond)
if err != nil {
    // ...
}

if err := watcher.Start(); err != nil {
    // ...
}

// ..

watcher.Close()

Receiving changes

A Watcher communicates changes via a channel. The channel is available via the C method.

for e := range watcher.C() {
    fmt.Printf("%8s %s\n", e.Type, e.Path)
}

In addition you can subscribe for errors by reading from an errors channel available via the ErrorsChan method.

Pattern format

The pattern format used by globwatch works similar to the pattern format of .gitignore. It is completely compatible with the pattern format used by os.Glob or fs.Glob and extends it.

The format is specified as the following EBNF:

pattern = term, { '/', term };

term        = '**' | name;
name        = { charSpecial | group | escapedChar | '*' | '?' };
charSpecial = (* any unicode rune except '/', '*', '?', '[' and '\' *);
char        = (* any unicode rune *);
escapedChar = '\\', char;
group       = '[', [ '^' ] { escapedChar | groupChar | range } ']';
groupChar   = (* any unicode rune except '-' and ']' *);
range       = ( groupChar | escapedChar ), '-', (groupChar | escapedChar);

The format operators have the following meaning:

  • any character (rune) matches the exactly this rune - with the following exceptions
  • / works as a directory separator. It matches directory boundarys of the underlying system independently of the separator char used by the OS.
  • ? matches exactly one non-separator char
  • * matches any number of non-separator chars - including zero
  • \ escapes a character's special meaning allowing * and ? to be used as regular characters.
  • ** matches any number of nested directories. If anything is matched it always extends until a separator or the end of the name.
  • Groups can be defined using the [ and ] characters. Inside a group the special meaning of the characters mentioned before is disabled but the following rules apply
    • any character used as part of the group acts as a choice to pick from
    • if the group's first character is a ^ the whole group is negated
    • a range can be defined using - matching any rune between low and high inclusive
    • Multiple ranges can be given. Ranges can be combined with choices.
    • The meaning of - and ] can be escacped using \

Performance

globwatch separates pattern parsing and matching. This can create a performance benefit when applied repeatedly. When reusing a precompiled pattern to match filenames globwatch outperforms filepath.Match with both simple and complex patterns. When not reusing the parsed pattern, filepath works much faster (but lacks the additional features).

Test Execution time [ns/op] Memory usage [B/op] Allocations per op
filepath simple pattern 15.5 0 0
globwatch simple pattern (reuse) 3.9 0 0
globwatch simple pattern (noreuse) 495.0 1112 5
filepath complex pattern 226.2 0 0
globwatch complex pattern (reuse) 108.1 0 0
globwatch complex pattern (noreuse) 1103.0 2280 8
globwatch directory wildcard pattern (reuse) 111.7 0 0
globwatch directory wildcard pattern (noreuse) 1229.0 2280 8

License

Copyright 2022 Alexander Metzner.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

Recursive glob watches of filesystems for go(lang)

License:Apache License 2.0


Languages

Language:Go 100.0%