From 3a0773c28d3d242849b6f97f4e5397051da841f4 Mon Sep 17 00:00:00 2001 From: Rafal Jeczalik Date: Sat, 31 Jan 2015 13:50:12 +0100 Subject: [PATCH] (wip) --- bigtree.go | 1 - node.go | 16 ++++++++++--- recursivetree.go | 53 +++++++++++++++++++++++++++++++++++++++++-- recursivetree_test.go | 32 ++++++++++++++++++++++---- testing_test.go | 18 ++++++++++----- 5 files changed, 103 insertions(+), 17 deletions(-) diff --git a/bigtree.go b/bigtree.go index 7099119..83f7de9 100644 --- a/bigtree.go +++ b/bigtree.go @@ -618,7 +618,6 @@ func (t *bigTree) Stop(c chan<- EventInfo) { } delete(t.cnd, c) } - } // Close TODO diff --git a/node.go b/node.go index 991c799..2fbfa36 100644 --- a/node.go +++ b/node.go @@ -2,6 +2,7 @@ package notify import ( "errors" + "fmt" "os" "path/filepath" "sort" @@ -146,7 +147,7 @@ func (nd node) Get(name string) (node, error) { return nd, nil } -// Del TODO +// Del TODO: rework func (nd node) Del(name string) error { i := indexbase(nd.Name, name) if i == -1 { @@ -290,6 +291,7 @@ func (r root) Get(name string) (node, error) { if err != nil { return node{}, err } + // BUG(rjeczalik): if name == "/" || name == "" we should return nd return nd.Get(name) } @@ -297,10 +299,16 @@ func (r root) Get(name string) (node, error) { func (r root) Walk(name string, fn walkFunc) error { nd, err := r.root(name) if err != nil { + fmt.Println("(root).Walk 1") return err } - if nd, err = nd.Get(name); err != nil { - return err + // BUG(rjeczalik): if name == "/" || name == "" we should start walking + // here + if nd.Name != name { + if nd, err = nd.Get(name); err != nil { + fmt.Println("(root).Walk 2") + return err + } } return nd.Walk(fn) } @@ -311,6 +319,8 @@ func (r root) WalkPath(name string, fn walkPathFunc) error { if err != nil { return err } + // BUG(rjeczalik): if name == "/" || name == "" we should start walking + // here return nd.WalkPath(name, fn) } diff --git a/recursivetree.go b/recursivetree.go index 4ffc35b..1b5ad15 100644 --- a/recursivetree.go +++ b/recursivetree.go @@ -1,6 +1,7 @@ package notify import ( + "fmt" "path/filepath" "strings" ) @@ -219,10 +220,58 @@ func (t *recursiveTree) Watch(path string, c chan<- EventInfo, events ...Event) return nil } +const all = ^Event(0) + +func (t *recursiveTree) unwatch(c chan<- EventInfo) func(node) error { + return func(nd node) error { + // NOTE(rjeczalik): ignoring diff, no watchpoint here + nd.Watch.Del(c, all) + return nil + } +} + // Stop TODO(rjeczalik) func (t *recursiveTree) Stop(c chan<- EventInfo) { - // TODO - + var err error + fn := func(nd node) error { + if e, ok := nd.Watch[c]; ok { + diff := nd.Watch.Del(c, e) + fmt.Printf("found c in %q: %v (diff=%v -> %v)\n", nd.Name, e, diff[0], diff[1]) + for c, e := range nd.Watch { + fmt.Printf("Watch[%p] = %v\n", c, e) + } + switch { + case diff == none: + return nil + case diff[1] == 0: + if nd.Watch.IsRecursive() { + err = t.w.RecursiveUnwatch(nd.Name) + } else { + err = t.w.Unwatch(nd.Name) + } + default: + if nd.Watch.IsRecursive() { + err = t.w.RecursiveRewatch(nd.Name, nd.Name, diff[0], diff[1]) + } else { + err = t.w.Rewatch(nd.Name, diff[0], diff[1]) + } + } + fn := func(nd node) error { + nd.Watch.Del(c, all) + return nil + } + err = nonil(err, nd.Walk(fn)) + return skip + } + return nil + } + // TODO(rjeczalik): use max root per c + if e := t.root.Walk("", fn); e != nil { + err = nonil(err, e) + } + if err != nil { + fmt.Printf("Stop(%p) walk error: %v\n", c, err) + } } // Close TODO(rjeczalik) diff --git a/recursivetree_test.go b/recursivetree_test.go index 985db3f..23fbfbd 100644 --- a/recursivetree_test.go +++ b/recursivetree_test.go @@ -6,9 +6,9 @@ func TestRecursiveTreeWatch(t *testing.T) { n := NewRecursiveTreeTest(t, "testdata/vfs.txt") defer n.Close() - ch := NewChans(3) + ch := NewChans(10) - calls := [...]RCase{ + watches := [...]RCase{ // i=0 { Call: Call{ @@ -86,7 +86,7 @@ func TestRecursiveTreeWatch(t *testing.T) { Call: Call{ F: FuncWatch, P: "src/github.com/ppknap/link/include/...", - C: ch[0], + C: ch[4], E: Delete, }, Record: []Call{ @@ -191,7 +191,7 @@ func TestRecursiveTreeWatch(t *testing.T) { Call: Call{ F: FuncWatch, P: "src/github.com/rjeczalik/fs/cmd/gotree", - C: ch[0], + C: ch[1], E: Create | Delete, }, Record: nil, @@ -277,7 +277,7 @@ func TestRecursiveTreeWatch(t *testing.T) { }, } - n.ExpectRecordedCalls(calls[:]) + n.ExpectRecordedCalls(watches[:]) events := [...]TCase{ // i=0 @@ -353,4 +353,26 @@ func TestRecursiveTreeWatch(t *testing.T) { } n.ExpectTreeEvents(events[:], ch) + + stops := [...]RCase{ + { + Call: Call{ + F: FuncStop, + C: ch[1], + }, + Record: []Call{ + { + F: FuncRecursiveRewatch, + P: "src/github.com/rjeczalik/fs", + NP: "src/github.com/rjeczalik/fs", + E: Create | Delete | Move, + NE: Create | Move, + }, + }, + }, + } + + ch.Debug() + + n.ExpectRecordedCalls(stops[:]) } diff --git a/testing_test.go b/testing_test.go index 0fc963f..8aa99b7 100644 --- a/testing_test.go +++ b/testing_test.go @@ -273,6 +273,9 @@ func EqualEventInfo(want, got EventInfo) error { // EqualCall TODO(rjeczalik) func EqualCall(want, got Call) error { + if want.F != got.F { + return fmt.Errorf("want F=%v; got %v (P=%q)", want.F, got.F, want.P) + } if got.E != want.E { return fmt.Errorf("want E=%v; got %v (P=%q)", want.E, got.E, want.P) } @@ -288,9 +291,6 @@ func EqualCall(want, got Call) error { if want := filepath.FromSlash(want.NP); !strings.HasSuffix(got.NP, want) { return fmt.Errorf("want NP=%s; got %s", want, got.NP) } - if want.F != got.F { - return fmt.Errorf("want F=%v; got %v (P=%q)", want.F, got.F, want.P) - } return nil } @@ -454,6 +454,12 @@ func (c Chans) Drain() (ei []EventInfo) { return } +func (c Chans) Debug() { + for i, c := range c { + fmt.Printf("ch[%d] = %p\n", i, c) + } +} + // NewChans TODO func NewChans(n int) Chans { ch := make([]chan EventInfo, n) @@ -554,6 +560,7 @@ type N struct { w *W spy *Spy c chan<- EventInfo + j int // spy offset } func newN(t *testing.T, tree string) *N { @@ -662,15 +669,14 @@ func (n *N) ExpectDry(ch Chans) { // ExpectRecordedCalls TODO(rjeczalik) func (n *N) ExpectRecordedCalls(cases []RCase) { - j := 0 for i, cas := range cases { dbg.Printf("ExpectRecordedCalls: i=%d\n", i) n.Call(cas.Call) - record := (*n.spy)[j:] + record := (*n.spy)[n.j:] if len(cas.Record) == 0 && len(record) == 0 { continue } - j = len(*n.spy) + n.j = len(*n.spy) if len(record) != len(cas.Record) { n.t.Fatalf("%s: want len(record)=%d; got %d [%+v] (i=%d)", caller(), len(cas.Record), len(record), record, i)