Merge lp:~chipaca/ubuntu-push/persistence into lp:ubuntu-push

Proposed by John Lenton
Status: Merged
Approved by: John Lenton
Approved revision: 67
Merged at revision: 79
Proposed branch: lp:~chipaca/ubuntu-push/persistence
Merge into: lp:ubuntu-push
Prerequisite: lp:~chipaca/ubuntu-push/sqlevelmap-in-session
Diff against target: 484 lines (+91/-51)
2 files modified
client/client.go (+28/-17)
client/client_test.go (+63/-34)
To merge this branch: bzr merge lp:~chipaca/ubuntu-push/persistence
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Review via email: mp+205484@code.launchpad.net

Commit message

and this gives the client the ability to persist its session's levelmap

Description of the change

With this, NewPushClient takes a second argument that is the path to
the sqlite db in which to persist its level map. If the path is "",
use the good ol' mapLevelMap instead.

To post a comment you must log in.
Revision history for this message
Samuele Pedroni (pedronis) wrote :

good time to do: pushClient => PushClient ?

c.Check(fmt.Sprintf("%T", ln), Equals, "*levelmap.sqliteLevelMap")

maybe giving LevelMap again a String() ?

review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (4.5 KiB)

The attempt to merge lp:~chipaca/ubuntu-push/persistence into lp:ubuntu-push failed. Below is the output from the failed tests.

mkdir -p /mnt/tarmac/cache/ubuntu-push/go-ws/bin
mkdir -p /mnt/tarmac/cache/ubuntu-push/go-ws/pkg
go get -u launchpad.net/godeps
go get -d -u launchpad.net/gocheck launchpad.net/go-dbus/v1 code.google.com/p/gosqlite/sqlite3
/mnt/tarmac/cache/ubuntu-push/go-ws/bin/godeps -u dependencies.tsv
"/mnt/tarmac/cache/ubuntu-push/go-ws/src/launchpad.net/gocheck" now at <email address hidden>
go install launchpad.net/gocheck launchpad.net/go-dbus/v1 code.google.com/p/gosqlite/sqlite3
go test launchpad.net/ubuntu-push/...
ok launchpad.net/ubuntu-push/bus 0.009s
ok launchpad.net/ubuntu-push/bus/connectivity 0.148s
ok launchpad.net/ubuntu-push/bus/networkmanager 0.027s
ok launchpad.net/ubuntu-push/bus/notifications 0.017s
ok launchpad.net/ubuntu-push/bus/testing 0.025s
ok launchpad.net/ubuntu-push/bus/urldispatcher 0.005s
ok launchpad.net/ubuntu-push/client 0.098s
ok launchpad.net/ubuntu-push/client/session 0.086s
ok launchpad.net/ubuntu-push/client/session/levelmap 0.068s
ok launchpad.net/ubuntu-push/config 0.015s
ok launchpad.net/ubuntu-push/logger 0.006s
ok launchpad.net/ubuntu-push/protocol 0.010s
ok launchpad.net/ubuntu-push/server 0.027s
ok launchpad.net/ubuntu-push/server/acceptance 0.015s
? launchpad.net/ubuntu-push/server/acceptance/cmd [no test files]
? launchpad.net/ubuntu-push/server/acceptance/suites [no test files]
ok launchpad.net/ubuntu-push/server/api 0.017s
ok launchpad.net/ubuntu-push/server/broker 0.010s
ok launchpad.net/ubuntu-push/server/broker/simple 0.007s
? launchpad.net/ubuntu-push/server/broker/testing [no test files]
? launchpad.net/ubuntu-push/server/broker/testsuite [no test files]
? launchpad.net/ubuntu-push/server/dev [no test files]
ok launchpad.net/ubuntu-push/server/listener 0.384s
ok launchpad.net/ubuntu-push/server/session 0.162s
ok launchpad.net/ubuntu-push/server/store 0.210s
? launchpad.net/ubuntu-push/testing [no test files]
ok launchpad.net/ubuntu-push/testing/condition 0.004s
ok launchpad.net/ubuntu-push/util 0.006s
? launchpad.net/ubuntu-push/whoopsie [no test files]
ok launchpad.net/ubuntu-push/whoopsie/identifier 0.007s
ok launchpad.net/ubuntu-push/whoopsie/identifier/testing 0.011s
go test -race launchpad.net/ubuntu-push/...
ok launchpad.net/ubuntu-push/bus 1.018s
ok launchpad.net/ubuntu-push/bus/connectivity 1.190s
ok launchpad.net/ubuntu-push/bus/networkmanager 1.038s
ok launchpad.net/ubuntu-push/bus/notifications 1.026s
ok launchpad.net/ubuntu-push/bus/testing 1.035s
ok launchpad.net/ubuntu-push/bus/urldispatcher 1.015s
ok launchpad.net/ubuntu-push/client 1.270s
ok launchpad.net/ubuntu-push/client/session 1.462s
ok launchpad.net/ubuntu-push/client/session/levelmap 1.041s
ok launchpad.net/ubuntu-push/config 1.033s
ok launchpad.net/ubuntu-push/logger 1.049s
ok launchpad.net/ubuntu-push/protocol 1.051s
ok launchpad.net/ubuntu-push/server 1.119s
ok launchpad.net/ubuntu-push/server/acceptance 1.042s
? launchpad.net/ubuntu-push/server/acceptance/cmd [no tes...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/client.go'
2--- client/client.go 2014-02-21 16:17:28 +0000
3+++ client/client.go 2014-03-12 11:09:23 +0000
4@@ -50,8 +50,9 @@
5 LogLevel string `json:"log_level"`
6 }
7
8-// pushClient is the Ubuntu Push Notifications client-side daemon.
9-type pushClient struct {
10+// PushClient is the Ubuntu Push Notifications client-side daemon.
11+type PushClient struct {
12+ leveldbPath string
13 configPath string
14 config ClientConfig
15 log logger.Logger
16@@ -70,15 +71,16 @@
17
18 // Creates a new Ubuntu Push Notifications client-side daemon that will use
19 // the given configuration file.
20-func NewPushClient(configPath string) *pushClient {
21- client := new(pushClient)
22+func NewPushClient(configPath string, leveldbPath string) *PushClient {
23+ client := new(PushClient)
24 client.configPath = configPath
25+ client.leveldbPath = leveldbPath
26
27 return client
28 }
29
30 // configure loads its configuration, and sets it up.
31-func (client *pushClient) configure() error {
32+func (client *PushClient) configure() error {
33 f, err := os.Open(client.configPath)
34 if err != nil {
35 return fmt.Errorf("opening config: %v", err)
36@@ -115,7 +117,7 @@
37 }
38
39 // getDeviceId gets the whoopsie identifier for the device
40-func (client *pushClient) getDeviceId() error {
41+func (client *PushClient) getDeviceId() error {
42 err := client.idder.Generate()
43 if err != nil {
44 return err
45@@ -125,7 +127,7 @@
46 }
47
48 // takeTheBus starts the connection(s) to D-Bus and sets up associated event channels
49-func (client *pushClient) takeTheBus() error {
50+func (client *PushClient) takeTheBus() error {
51 go connectivity.ConnectedState(client.connectivityEndp,
52 client.config.ConnectivityConfig, client.log, client.connCh)
53 iniCh := make(chan uint32)
54@@ -140,10 +142,10 @@
55 }
56
57 // initSession creates the session object
58-func (client *pushClient) initSession() error {
59+func (client *PushClient) initSession() error {
60 sess, err := session.NewSession(string(client.config.Addr), client.pem,
61 client.config.ExchangeTimeout.Duration, client.deviceId,
62- levelmap.NewLevelMap, client.log)
63+ client.levelMapFactory, client.log)
64 if err != nil {
65 return err
66 }
67@@ -151,8 +153,17 @@
68 return nil
69 }
70
71+// levelmapFactory returns a levelMap for the session
72+func (client *PushClient) levelMapFactory() (levelmap.LevelMap, error) {
73+ if client.leveldbPath == "" {
74+ return levelmap.NewLevelMap()
75+ } else {
76+ return levelmap.NewSqliteLevelMap(client.leveldbPath)
77+ }
78+}
79+
80 // handleConnState deals with connectivity events
81-func (client *pushClient) handleConnState(hasConnectivity bool) {
82+func (client *PushClient) handleConnState(hasConnectivity bool) {
83 if client.hasConnectivity == hasConnectivity {
84 // nothing to do!
85 return
86@@ -166,7 +177,7 @@
87 }
88
89 // handleErr deals with the session erroring out of its loop
90-func (client *pushClient) handleErr(err error) {
91+func (client *PushClient) handleErr(err error) {
92 // if we're not connected, we don't really care
93 client.log.Errorf("session exited: %s", err)
94 if client.hasConnectivity {
95@@ -175,7 +186,7 @@
96 }
97
98 // handleNotification deals with receiving a notification
99-func (client *pushClient) handleNotification() error {
100+func (client *PushClient) handleNotification() error {
101 action_id := "dummy_id"
102 a := []string{action_id, "Go get it!"} // action value not visible on the phone
103 h := map[string]*dbus.Variant{"x-canonical-switch-to-application": &dbus.Variant{true}}
104@@ -199,14 +210,14 @@
105 }
106
107 // handleClick deals with the user clicking a notification
108-func (client *pushClient) handleClick() error {
109+func (client *PushClient) handleClick() error {
110 // it doesn't get much simpler...
111 urld := urldispatcher.New(client.urlDispatcherEndp, client.log)
112 return urld.DispatchURL("settings:///system/system-update")
113 }
114
115 // doLoop connects events with their handlers
116-func (client *pushClient) doLoop(connhandler func(bool), clickhandler, notifhandler func() error, errhandler func(error)) {
117+func (client *PushClient) doLoop(connhandler func(bool), clickhandler, notifhandler func() error, errhandler func(error)) {
118 for {
119 select {
120 case state := <-client.connCh:
121@@ -225,7 +236,7 @@
122
123 // doStart calls each of its arguments in order, returning the first non-nil
124 // error (or nil at the end)
125-func (client *pushClient) doStart(fs ...func() error) error {
126+func (client *PushClient) doStart(fs ...func() error) error {
127 for _, f := range fs {
128 if err := f(); err != nil {
129 return err
130@@ -235,13 +246,13 @@
131 }
132
133 // Loop calls doLoop with the "real" handlers
134-func (client *pushClient) Loop() {
135+func (client *PushClient) Loop() {
136 client.doLoop(client.handleConnState, client.handleClick,
137 client.handleNotification, client.handleErr)
138 }
139
140 // Start calls doStart with the "real" starters
141-func (client *pushClient) Start() error {
142+func (client *PushClient) Start() error {
143 return client.doStart(
144 client.configure,
145 client.getDeviceId,
146
147=== modified file 'client/client_test.go'
148--- client/client_test.go 2014-02-08 18:26:49 +0000
149+++ client/client_test.go 2014-03-12 11:09:23 +0000
150@@ -52,9 +52,10 @@
151 }
152
153 type clientSuite struct {
154- timeouts []time.Duration
155- configPath string
156- log *helpers.TestLogger
157+ timeouts []time.Duration
158+ configPath string
159+ leveldbPath string
160+ log *helpers.TestLogger
161 }
162
163 var _ = Suite(&clientSuite{})
164@@ -74,6 +75,7 @@
165
166 func (cs *clientSuite) SetUpSuite(c *C) {
167 cs.timeouts = util.SwapTimeouts([]time.Duration{0})
168+ cs.leveldbPath = ""
169 }
170
171 func (cs *clientSuite) TearDownSuite(c *C) {
172@@ -99,12 +101,21 @@
173 ioutil.WriteFile(cs.configPath, []byte(cfg), 0600)
174 }
175
176+type sqlientSuite struct{ clientSuite }
177+
178+func (s *sqlientSuite) SetUpSuite(c *C) {
179+ s.clientSuite.SetUpSuite(c)
180+ s.leveldbPath = ":memory:"
181+}
182+
183+var _ = Suite(&sqlientSuite{})
184+
185 /*****************************************************************
186 configure tests
187 ******************************************************************/
188
189 func (cs *clientSuite) TestConfigureWorks(c *C) {
190- cli := NewPushClient(cs.configPath)
191+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
192 err := cli.configure()
193 c.Assert(err, IsNil)
194 c.Assert(cli.config, NotNil)
195@@ -112,7 +123,7 @@
196 }
197
198 func (cs *clientSuite) TestConfigureSetsUpLog(c *C) {
199- cli := NewPushClient(cs.configPath)
200+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
201 c.Check(cli.log, IsNil)
202 err := cli.configure()
203 c.Assert(err, IsNil)
204@@ -120,7 +131,7 @@
205 }
206
207 func (cs *clientSuite) TestConfigureSetsUpPEM(c *C) {
208- cli := NewPushClient(cs.configPath)
209+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
210 c.Check(cli.pem, IsNil)
211 err := cli.configure()
212 c.Assert(err, IsNil)
213@@ -128,7 +139,7 @@
214 }
215
216 func (cs *clientSuite) TestConfigureSetsUpIdder(c *C) {
217- cli := NewPushClient(cs.configPath)
218+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
219 c.Check(cli.idder, IsNil)
220 err := cli.configure()
221 c.Assert(err, IsNil)
222@@ -136,7 +147,7 @@
223 }
224
225 func (cs *clientSuite) TestConfigureSetsUpEndpoints(c *C) {
226- cli := NewPushClient(cs.configPath)
227+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
228 c.Check(cli.notificationsEndp, IsNil)
229 c.Check(cli.urlDispatcherEndp, IsNil)
230 c.Check(cli.connectivityEndp, IsNil)
231@@ -148,7 +159,7 @@
232 }
233
234 func (cs *clientSuite) TestConfigureSetsUpConnCh(c *C) {
235- cli := NewPushClient(cs.configPath)
236+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
237 c.Check(cli.connCh, IsNil)
238 err := cli.configure()
239 c.Assert(err, IsNil)
240@@ -156,13 +167,13 @@
241 }
242
243 func (cs *clientSuite) TestConfigureBailsOnBadFilename(c *C) {
244- cli := NewPushClient("/does/not/exist")
245+ cli := NewPushClient("/does/not/exist", cs.leveldbPath)
246 err := cli.configure()
247 c.Assert(err, NotNil)
248 }
249
250 func (cs *clientSuite) TestConfigureBailsOnBadConfig(c *C) {
251- cli := NewPushClient("/etc/passwd")
252+ cli := NewPushClient("/etc/passwd", cs.leveldbPath)
253 err := cli.configure()
254 c.Assert(err, NotNil)
255 }
256@@ -180,7 +191,7 @@
257 "recheck_timeout": "3h"
258 }`), 0600)
259
260- cli := NewPushClient(cs.configPath)
261+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
262 err := cli.configure()
263 c.Assert(err, ErrorMatches, "reading PEM file: .*")
264 }
265@@ -198,7 +209,7 @@
266 "recheck_timeout": "3h"
267 }`), 0600)
268
269- cli := NewPushClient(cs.configPath)
270+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
271 err := cli.configure()
272 c.Assert(err, ErrorMatches, "no PEM found.*")
273 }
274@@ -208,7 +219,7 @@
275 ******************************************************************/
276
277 func (cs *clientSuite) TestGetDeviceIdWorks(c *C) {
278- cli := NewPushClient(cs.configPath)
279+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
280 cli.log = cs.log
281 cli.idder = identifier.New()
282 c.Check(cli.deviceId, Equals, "")
283@@ -217,7 +228,7 @@
284 }
285
286 func (cs *clientSuite) TestGetDeviceIdCanFail(c *C) {
287- cli := NewPushClient(cs.configPath)
288+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
289 cli.log = cs.log
290 cli.idder = idtesting.Failing()
291 c.Check(cli.deviceId, Equals, "")
292@@ -245,7 +256,7 @@
293 )
294 testibus.SetWatchTicker(cEndp, make(chan bool))
295 // ok, create the thing
296- cli := NewPushClient(cs.configPath)
297+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
298 cli.log = cs.log
299 err := cli.configure()
300 c.Assert(err, IsNil)
301@@ -273,7 +284,7 @@
302
303 // takeTheBus can, in fact, fail
304 func (cs *clientSuite) TestTakeTheBusCanFail(c *C) {
305- cli := NewPushClient(cs.configPath)
306+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
307 err := cli.configure()
308 cli.log = cs.log
309 c.Assert(err, IsNil)
310@@ -294,7 +305,7 @@
311 ******************************************************************/
312
313 func (cs *clientSuite) TestHandleErr(c *C) {
314- cli := NewPushClient(cs.configPath)
315+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
316 cli.log = cs.log
317 c.Assert(cli.initSession(), IsNil)
318 cli.hasConnectivity = true
319@@ -303,11 +314,29 @@
320 }
321
322 /*****************************************************************
323+ levelmapFactory tests
324+******************************************************************/
325+
326+func (cs *clientSuite) TestLevelMapFactoryNoDbPath(c *C) {
327+ cli := NewPushClient(cs.configPath, "")
328+ ln, err := cli.levelMapFactory()
329+ c.Assert(err, IsNil)
330+ c.Check(fmt.Sprintf("%T", ln), Equals, "*levelmap.mapLevelMap")
331+}
332+
333+func (cs *clientSuite) TestLevelMapFactoryWithDbPath(c *C) {
334+ cli := NewPushClient(cs.configPath, ":memory:")
335+ ln, err := cli.levelMapFactory()
336+ c.Assert(err, IsNil)
337+ c.Check(fmt.Sprintf("%T", ln), Equals, "*levelmap.sqliteLevelMap")
338+}
339+
340+/*****************************************************************
341 handleConnState tests
342 ******************************************************************/
343
344 func (cs *clientSuite) TestHandleConnStateD2C(c *C) {
345- cli := NewPushClient(cs.configPath)
346+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
347 cli.log = cs.log
348 c.Assert(cli.initSession(), IsNil)
349
350@@ -318,7 +347,7 @@
351 }
352
353 func (cs *clientSuite) TestHandleConnStateSame(c *C) {
354- cli := NewPushClient(cs.configPath)
355+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
356 cli.log = cs.log
357 // here we want to check that we don't do anything
358 c.Assert(cli.session, IsNil)
359@@ -332,7 +361,7 @@
360 }
361
362 func (cs *clientSuite) TestHandleConnStateC2D(c *C) {
363- cli := NewPushClient(cs.configPath)
364+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
365 cli.log = cs.log
366 cli.session, _ = session.NewSession(string(cli.config.Addr), cli.pem, cli.config.ExchangeTimeout.Duration, cli.deviceId, levelmap.NewLevelMap, cs.log)
367 cli.session.Dial()
368@@ -345,7 +374,7 @@
369 }
370
371 func (cs *clientSuite) TestHandleConnStateC2DPending(c *C) {
372- cli := NewPushClient(cs.configPath)
373+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
374 cli.log = cs.log
375 cli.session, _ = session.NewSession(string(cli.config.Addr), cli.pem, cli.config.ExchangeTimeout.Duration, cli.deviceId, levelmap.NewLevelMap, cs.log)
376 cli.hasConnectivity = true
377@@ -359,7 +388,7 @@
378 ******************************************************************/
379
380 func (cs *clientSuite) TestHandleNotification(c *C) {
381- cli := NewPushClient(cs.configPath)
382+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
383 endp := testibus.NewTestingEndpoint(nil, condition.Work(true), uint32(1))
384 cli.notificationsEndp = endp
385 cli.log = cs.log
386@@ -372,7 +401,7 @@
387 }
388
389 func (cs *clientSuite) TestHandleNotificationFail(c *C) {
390- cli := NewPushClient(cs.configPath)
391+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
392 cli.log = cs.log
393 endp := testibus.NewTestingEndpoint(nil, condition.Work(false))
394 cli.notificationsEndp = endp
395@@ -384,7 +413,7 @@
396 ******************************************************************/
397
398 func (cs *clientSuite) TestHandleClick(c *C) {
399- cli := NewPushClient(cs.configPath)
400+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
401 cli.log = cs.log
402 endp := testibus.NewTestingEndpoint(nil, condition.Work(true), nil)
403 cli.urlDispatcherEndp = endp
404@@ -401,7 +430,7 @@
405 ******************************************************************/
406
407 func (cs *clientSuite) TestDoLoopConn(c *C) {
408- cli := NewPushClient(cs.configPath)
409+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
410 cli.log = cs.log
411 cli.connCh = make(chan bool, 1)
412 cli.connCh <- true
413@@ -413,7 +442,7 @@
414 }
415
416 func (cs *clientSuite) TestDoLoopClick(c *C) {
417- cli := NewPushClient(cs.configPath)
418+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
419 cli.log = cs.log
420 c.Assert(cli.initSession(), IsNil)
421 aCh := make(chan notifications.RawActionReply, 1)
422@@ -426,7 +455,7 @@
423 }
424
425 func (cs *clientSuite) TestDoLoopNotif(c *C) {
426- cli := NewPushClient(cs.configPath)
427+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
428 cli.log = cs.log
429 c.Assert(cli.initSession(), IsNil)
430 cli.session.MsgCh = make(chan *session.Notification, 1)
431@@ -438,7 +467,7 @@
432 }
433
434 func (cs *clientSuite) TestDoLoopErr(c *C) {
435- cli := NewPushClient(cs.configPath)
436+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
437 cli.log = cs.log
438 c.Assert(cli.initSession(), IsNil)
439 cli.session.ErrCh = make(chan error, 1)
440@@ -454,7 +483,7 @@
441 ******************************************************************/
442
443 func (cs *clientSuite) TestDoStartWorks(c *C) {
444- cli := NewPushClient(cs.configPath)
445+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
446 one_called := false
447 two_called := false
448 one := func() error { one_called = true; return nil }
449@@ -465,7 +494,7 @@
450 }
451
452 func (cs *clientSuite) TestDoStartFailsAsExpected(c *C) {
453- cli := NewPushClient(cs.configPath)
454+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
455 one_called := false
456 two_called := false
457 failure := errors.New("Failure")
458@@ -481,7 +510,7 @@
459 ******************************************************************/
460
461 func (cs *clientSuite) TestLoop(c *C) {
462- cli := NewPushClient(cs.configPath)
463+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
464 cli.connCh = make(chan bool)
465 cli.sessionConnectedCh = make(chan uint32)
466 aCh := make(chan notifications.RawActionReply, 1)
467@@ -559,7 +588,7 @@
468 c.Skip("no dbus")
469 }
470
471- cli := NewPushClient(cs.configPath)
472+ cli := NewPushClient(cs.configPath, cs.leveldbPath)
473 // before start, everything sucks:
474 // no config,
475 c.Check(string(cli.config.Addr), Equals, "")
476@@ -588,7 +617,7 @@
477 }
478
479 func (cs *clientSuite) TestStartCanFail(c *C) {
480- cli := NewPushClient("/does/not/exist")
481+ cli := NewPushClient("/does/not/exist", cs.leveldbPath)
482 // easiest way for it to fail is to feed it a bad config
483 err := cli.Start()
484 // and it works. Err. Doesn't.

Subscribers

People subscribed via source and target branches