Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract an interface for fsnotify #182

Merged
merged 1 commit into from
Dec 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ platforms:
ubuntu1404:
build_targets:
- "..."
test_args:
test_flags:
- "--features=race"
test_targets:
- "..."
ubuntu1604:
build_targets:
- "..."
test_args:
test_flags:
- "--features=race"
test_targets:
- "..."
macos:
build_targets:
- "..."
test_args:
test_flags:
- "--features=race"
test_targets:
- "..."
2 changes: 1 addition & 1 deletion ibazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ go_binary(
# Since we don't have any cgo dependencies, force build to be pure
# golang. This will make multi-os compatability *MUCH* easier.
pure = "on",
race = "on",
visibility = ["//visibility:public"],
x_defs = {
"main.Version": "{STABLE_GIT_VERSION}",
Expand All @@ -31,6 +30,7 @@ go_binary(
go_library(
name = "go_default_library",
srcs = [
"fsnotfy.go",
"ibazel.go",
"lifecycle.go",
"main.go",
Expand Down
31 changes: 31 additions & 0 deletions ibazel/fsnotfy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"github.com/fsnotify/fsnotify"
)

type fSNotifyWatcher interface {
Close() error
Add(name string) error
Remove(name string) error
Events() chan fsnotify.Event
Errors() chan error
Watcher() *fsnotify.Watcher
}

type realFSNotifyWatcher struct {
w *fsnotify.Watcher
}

var _ fSNotifyWatcher = &realFSNotifyWatcher{}

func (w *realFSNotifyWatcher) Close() error { return w.w.Close() }
func (w *realFSNotifyWatcher) Add(name string) error { return w.w.Add(name) }
func (w *realFSNotifyWatcher) Remove(name string) error { return w.w.Remove(name) }
func (w *realFSNotifyWatcher) Events() chan fsnotify.Event { return w.w.Events }
func (w *realFSNotifyWatcher) Errors() chan error { return w.w.Errors }
func (w *realFSNotifyWatcher) Watcher() *fsnotify.Watcher { return w.w }

func wrapWatcher(w *fsnotify.Watcher, err error) (fSNotifyWatcher, error) {
return &realFSNotifyWatcher{w: w}, err
}
20 changes: 10 additions & 10 deletions ibazel/ibazel.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ type IBazel struct {

workspaceFinder workspace_finder.WorkspaceFinder

buildFileWatcher *fsnotify.Watcher
sourceFileWatcher *fsnotify.Watcher
buildFileWatcher fSNotifyWatcher
sourceFileWatcher fSNotifyWatcher

filesWatched map[*fsnotify.Watcher]map[string]struct{} // Inner map is a surrogate for a set
filesWatched map[fSNotifyWatcher]map[string]struct{} // Inner map is a surrogate for a set

sourceEventHandler *SourceEventHandler
lifecycleListeners []Lifecycle
Expand All @@ -87,7 +87,7 @@ func New() (*IBazel, error) {
}

i.debounceDuration = 100 * time.Millisecond
i.filesWatched = map[*fsnotify.Watcher]map[string]struct{}{}
i.filesWatched = map[fSNotifyWatcher]map[string]struct{}{}
i.workspaceFinder = &workspace_finder.MainWorkspaceFinder{}

i.sigs = make(chan os.Signal, 1)
Expand Down Expand Up @@ -220,17 +220,17 @@ func (i *IBazel) setup() error {

// Even though we are going to recreate this when the query happens, create
// the pointer we will use to refer to the watchers right now.
i.buildFileWatcher, err = fsnotify.NewWatcher()
i.buildFileWatcher, err = wrapWatcher(fsnotify.NewWatcher())
if err != nil {
return err
}

i.sourceFileWatcher, err = fsnotify.NewWatcher()
i.sourceFileWatcher, err = wrapWatcher(fsnotify.NewWatcher())
if err != nil {
return err
}

i.sourceEventHandler = NewSourceEventHandler(i.sourceFileWatcher)
i.sourceEventHandler = NewSourceEventHandler(i.sourceFileWatcher.Watcher())

return nil
}
Expand Down Expand Up @@ -276,7 +276,7 @@ func (i *IBazel) iteration(command string, commandToRun runnableCommand, targets
i.changeDetected(targets, "source", e.Name)
i.state = DEBOUNCE_RUN
}
case e := <-i.buildFileWatcher.Events:
case e := <-i.buildFileWatcher.Events():
if _, ok := i.filesWatched[i.buildFileWatcher][e.Name]; ok && e.Op&modifyingEvents != 0 {
fmt.Fprintf(os.Stderr, "\nBuild graph changed: %q. Requerying...\n", e.Name)
i.changeDetected(targets, "graph", e.Name)
Expand All @@ -285,7 +285,7 @@ func (i *IBazel) iteration(command string, commandToRun runnableCommand, targets
}
case DEBOUNCE_QUERY:
select {
case e := <-i.buildFileWatcher.Events:
case e := <-i.buildFileWatcher.Events():
if _, ok := i.filesWatched[i.buildFileWatcher][e.Name]; ok && e.Op&modifyingEvents != 0 {
i.changeDetected(targets, "graph", e.Name)
}
Expand Down Expand Up @@ -466,7 +466,7 @@ func (i *IBazel) queryForSourceFiles(query string) []string {
return toWatch
}

func (i *IBazel) watchFiles(query string, watcher *fsnotify.Watcher) {
func (i *IBazel) watchFiles(query string, watcher fSNotifyWatcher) {
toWatch := i.queryForSourceFiles(query)
filesFound := map[string]struct{}{}
filesWatched := map[string]struct{}{}
Expand Down
24 changes: 20 additions & 4 deletions ibazel/ibazel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ import (
"github.com/golang/protobuf/proto"
)

type fakeFSNotifyWatcher struct {
ErrorChan chan error
EventChan chan fsnotify.Event
}

var _ fSNotifyWatcher = &fakeFSNotifyWatcher{}

func (w *fakeFSNotifyWatcher) Close() error { return nil }
func (w *fakeFSNotifyWatcher) Add(name string) error { return nil }
func (w *fakeFSNotifyWatcher) Remove(name string) error { return nil }
func (w *fakeFSNotifyWatcher) Events() chan fsnotify.Event { return w.EventChan }
func (w *fakeFSNotifyWatcher) Errors() chan error { return w.ErrorChan }
func (w *fakeFSNotifyWatcher) Watcher() *fsnotify.Watcher { return nil }

var oldCommandDefaultCommand = command.DefaultCommand

func assertEqual(t *testing.T, want, got interface{}, msg string) {
Expand Down Expand Up @@ -138,15 +152,17 @@ func TestIBazelLifecycle(t *testing.T) {

// Now inspect private API. If things weren't closed properly this will block
// and the test will timeout.
<-i.sourceFileWatcher.Events
<-i.buildFileWatcher.Events
<-i.sourceFileWatcher.Events()
<-i.buildFileWatcher.Events()
}

func TestIBazelLoop(t *testing.T) {
i := newIBazel(t)

// Replace the file watching channel with one that has a buffer.
i.buildFileWatcher.Events = make(chan fsnotify.Event, 1)
i.buildFileWatcher = &fakeFSNotifyWatcher{
EventChan: make(chan fsnotify.Event, 1),
}
i.sourceEventHandler.SourceFileEvents = make(chan fsnotify.Event, 1)

defer i.Cleanup()
Expand Down Expand Up @@ -202,7 +218,7 @@ func TestIBazelLoop(t *testing.T) {
assertRun()
assertState(WAIT)
// Build file change.
i.buildFileWatcher.Events <- fsnotify.Event{Op: fsnotify.Write, Name: "/path/to/BUILD"}
i.buildFileWatcher.Events() <- fsnotify.Event{Op: fsnotify.Write, Name: "/path/to/BUILD"}
step()
assertState(DEBOUNCE_QUERY)
// Don't send another event in to test the timer
Expand Down