-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsubscribe.go
81 lines (68 loc) · 2.08 KB
/
subscribe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package watchman
import (
"github.com/yookoala/realpath"
)
// Subscribe is the return object of the Subscribe call
type Subscribe struct {
Clock string `bser:"clock"`
Subscribe string `bser:"subscribe"`
}
// SubscribeEvent is the unilateral message that indicates an
// fs event occurred for the specified subscription
type SubscribeEvent struct {
Clock string `bser:"clock"`
Files []SubscribeFile `bser:"files"`
IsFreshInstance bool `bser:"is_fresh_instance"`
Root string `bser:"root"`
Since string `bser:"since"`
Subscription string `bser:"subscription"`
}
// SubscribeFile is a representation of the file that was somehow changed
type SubscribeFile struct {
Mode int `bser:"mode"`
New bool `bser:"new"`
Size int `bser:"size"`
Exists bool `bser:"exists"`
Name string `bser:"name"`
}
// Subscribe subscribes to changes against a specified root and requests that they be sent to the client via its connection. The updates will continue to be sent while the connection is open. If the connection is closed, the subscription is implicitly removed
// https://facebook.github.io/watchman/docs/cmd/subscribe.html
// todo(isao) - add expression type?
func (c *Client) Subscribe(path, name string, expr map[string]interface{}, ch chan<- *SubscribeEvent) (*Subscribe, func(), error) {
path, err := realpath.Realpath(path)
if err != nil {
return nil, nil, err
}
var data struct {
Subscribe
base
}
all := make(chan interface{})
stop, err := c.Receive(all)
if err != nil {
return nil, nil, err
}
if err := c.Send(&data, "subscribe", path, name, expr); err != nil {
stop()
return nil, nil, err
}
go func() {
// all will get closed when stop is called
// so we close ch when the func returns
defer func() {
close(ch)
}()
for m := range all {
sub, _ := m.(*SubscribeEvent)
if sub == nil || sub.Subscription != name {
continue
}
ch <- sub
}
}()
if data.Error != "" {
stop()
return nil, nil, data.Error
}
return &data.Subscribe, stop, nil
}