Replace use of go-car v1 with go-car/v2 (#10845)
* Replace use of go-car v1 with go-car/v2 The `dag export` commend needed to be updated to use go-car/v2. This removes the last dependency on go-car v1.
Andrew Gillis committed
Jun 23, 2025 at 07:18 UTC
ace0b0b987f5abe6a4480d3f9e14f55bb233785e
3 files changed
+72
-60
core/commands/dag/export.go
+72
-24
@@ -9,15 +9,14 @@ import (
9
"time"
10
11
"github.com/cheggaaa/pb"
12
- blocks "github.com/ipfs/go-block-format"
12
cid "github.com/ipfs/go-cid"
13
+ cmds "github.com/ipfs/go-ipfs-cmds"
14
ipld "github.com/ipfs/go-ipld-format"
15
"github.com/ipfs/kubo/core/commands/cmdenv"
16
"github.com/ipfs/kubo/core/commands/cmdutils"
17
iface "github.com/ipfs/kubo/core/coreiface"
18
-
19
- cmds "github.com/ipfs/go-ipfs-cmds"
20
- gocar "github.com/ipld/go-car"
18
+ gocar "github.com/ipld/go-car/v2"
19
+ cidlink "github.com/ipld/go-ipld-prime/linking/cid"
20
selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse"
21
)
22
@@ -51,14 +50,27 @@ func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
50
close(errCh)
51
}()
52
54
- store := dagStore{dag: api.Dag(), ctx: req.Context}
55
- dag := gocar.Dag{Root: c, Selector: selectorparse.CommonSelector_ExploreAllRecursively}
56
- // TraverseLinksOnlyOnce is safe for an exhaustive selector but won't be when we allow
57
- // arbitrary selectors here
58
- car := gocar.NewSelectiveCar(req.Context, store, []gocar.Dag{dag}, gocar.TraverseLinksOnlyOnce())
59
- if err := car.Write(pipeW); err != nil {
53
+ lsys := cidlink.DefaultLinkSystem()
54
+ lsys.SetReadStorage(&dagStore{dag: api.Dag(), ctx: req.Context})
55
+
56
+ // Uncomment the following to support CARv2 output.
57
+ /*
58
+ car, err := gocar.NewSelectiveWriter(req.Context, &lsys, c, selectorparse.CommonSelector_ExploreAllRecursively, gocar.AllowDuplicatePuts(false))
59
+ if err != nil {
60
+ errCh <- err
61
+ return
62
+ }
63
+ if _, err = car.WriteTo(pipeW); err != nil {
64
+ errCh <- err
65
+ return
66
+ }
67
+ */
68
+ _, err := gocar.TraverseV1(req.Context, &lsys, c, selectorparse.CommonSelector_ExploreAllRecursively, pipeW, gocar.AllowDuplicatePuts(false))
69
+ if err != nil {
70
errCh <- err
71
+ return
72
}
73
+
74
}()
75
76
if err := res.Emit(pipeR); err != nil {
@@ -69,7 +81,7 @@ func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
81
err = <-errCh
82
83
// minimal user friendliness
72
- if ipld.IsNotFound(err) {
84
+ if errors.Is(err, ipld.ErrNotFound{}) {
85
explicitOffline, _ := req.Options["offline"].(bool)
86
if explicitOffline {
87
err = fmt.Errorf("%s (currently offline, perhaps retry without the offline flag)", err)
@@ -112,16 +124,17 @@ func finishCLIExport(res cmds.Response, re cmds.ResponseEmitter) error {
124
var processedOneResponse bool
125
for {
126
v, err := res.Next()
115
- if err == io.EOF {
116
-
117
- // We only write the final bar update on success
118
- // On error it looks too weird
119
- bar.Finish()
120
-
121
- return re.Close()
122
- } else if err != nil {
127
+ if err != nil {
128
+ if errors.Is(err, io.EOF) {
129
+ // We only write the final bar update on success
130
+ // On error it looks too weird
131
+ bar.Finish()
132
+ return re.Close()
133
+ }
134
return re.CloseWithError(err)
124
- } else if processedOneResponse {
135
+ }
136
+
137
+ if processedOneResponse {
138
return re.CloseWithError(errors.New("unexpected multipart response during emit, please file a bugreport"))
139
}
140
@@ -133,18 +146,53 @@ func finishCLIExport(res cmds.Response, re cmds.ResponseEmitter) error {
146
147
processedOneResponse = true
148
136
- if err := re.Emit(bar.NewProxyReader(r)); err != nil {
149
+ if err = re.Emit(bar.NewProxyReader(r)); err != nil {
150
return err
151
}
152
}
153
}
154
142
-// FIXME(@Jorropo): https://github.com/ipld/go-car/issues/315
155
type dagStore struct {
156
dag iface.APIDagService
157
ctx context.Context
158
}
159
148
-func (ds dagStore) Get(_ context.Context, c cid.Cid) (blocks.Block, error) {
149
- return ds.dag.Get(ds.ctx, c)
160
+func (ds *dagStore) Get(ctx context.Context, key string) ([]byte, error) {
161
+ if ctx.Err() != nil {
162
+ return nil, ctx.Err()
163
+ }
164
+
165
+ c, err := cidFromBinString(key)
166
+ if err != nil {
167
+ return nil, err
168
+ }
169
+
170
+ block, err := ds.dag.Get(ds.ctx, c)
171
+ if err != nil {
172
+ return nil, err
173
+ }
174
+
175
+ return block.RawData(), nil
176
+}
177
+
178
+func (ds *dagStore) Has(ctx context.Context, key string) (bool, error) {
179
+ _, err := ds.Get(ctx, key)
180
+ if err != nil {
181
+ if errors.Is(err, ipld.ErrNotFound{}) {
182
+ return false, nil
183
+ }
184
+ return false, err
185
+ }
186
+ return true, nil
187
+}
188
+
189
+func cidFromBinString(key string) (cid.Cid, error) {
190
+ l, k, err := cid.CidFromBytes([]byte(key))
191
+ if err != nil {
192
+ return cid.Undef, fmt.Errorf("dagStore: key was not a cid: %w", err)
193
+ }
194
+ if l != len(key) {
195
+ return cid.Undef, fmt.Errorf("dagSore: key was not a cid: had %d bytes leftover", len(key)-l)
196
+ }
197
+ return k, nil
198
}
go.mod
-9
@@ -43,7 +43,6 @@ require (
43
github.com/ipfs/go-metrics-prometheus v0.1.0
44
github.com/ipfs/go-test v0.2.2
45
github.com/ipfs/go-unixfsnode v1.10.1
46
- github.com/ipld/go-car v0.6.2
46
github.com/ipld/go-car/v2 v2.14.3
47
github.com/ipld/go-codec-dagpb v1.7.0
48
github.com/ipld/go-ipld-prime v0.21.0
@@ -148,18 +147,11 @@ require (
147
github.com/huin/goupnp v1.3.0 // indirect
148
github.com/ipfs/bbloom v0.0.4 // indirect
149
github.com/ipfs/go-bitfield v1.1.0 // indirect
151
- github.com/ipfs/go-blockservice v0.5.2 // indirect
152
- github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect
150
github.com/ipfs/go-ipfs-delay v0.0.1 // indirect
151
github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
155
- github.com/ipfs/go-ipfs-exchange-interface v0.2.1 // indirect
152
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
153
github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
158
- github.com/ipfs/go-ipfs-util v0.0.3 // indirect
159
- github.com/ipfs/go-log v1.0.5 // indirect
160
- github.com/ipfs/go-merkledag v0.11.0 // indirect
154
github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
162
- github.com/ipfs/go-verifcid v0.0.3 // indirect
155
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
156
github.com/klauspost/compress v1.18.0 // indirect
157
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
@@ -256,7 +248,6 @@ require (
248
go.opentelemetry.io/otel/exporters/zipkin v1.31.0 // indirect
249
go.opentelemetry.io/otel/metric v1.35.0 // indirect
250
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
259
- go.uber.org/atomic v1.11.0 // indirect
251
go.uber.org/automaxprocs v1.6.0 // indirect
252
go.uber.org/mock v0.5.2 // indirect
253
go.uber.org/zap/exp v0.3.0 // indirect
go.sum
-27
@@ -358,13 +358,9 @@ github.com/ipfs/boxo v0.32.0 h1:rBs3P53Wt9bFW9WJwVdkzLtzYCXAj2bMjM7+1nrazZw=
358
github.com/ipfs/boxo v0.32.0/go.mod h1:VEtO3gOmr+sXGodalaTV9Vvsp3qVYegc4Rcu08Iw+wM=
359
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
360
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
361
-github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
362
-github.com/ipfs/go-bitswap v0.11.0/go.mod h1:05aE8H3XOU+LXpTedeAS0OZpcO1WFsj5niYQH9a1Tmk=
361
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
362
github.com/ipfs/go-block-format v0.2.1 h1:96kW71XGNNa+mZw/MTzJrCpMhBWCrd9kBLoKm9Iip/Q=
363
github.com/ipfs/go-block-format v0.2.1/go.mod h1:frtvXHMQhM6zn7HvEQu+Qz5wSTj+04oEH/I+NjDgEjk=
366
-github.com/ipfs/go-blockservice v0.5.2 h1:in9Bc+QcXwd1apOVM7Un9t8tixPKdaHQFdLSUM1Xgk8=
367
-github.com/ipfs/go-blockservice v0.5.2/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk=
364
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
365
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
366
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
@@ -394,8 +390,6 @@ github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw
390
github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0=
391
github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
392
github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
397
-github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
398
-github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk=
393
github.com/ipfs/go-ipfs-cmds v0.15.0 h1:nQDgKadrzyiFyYoZMARMIoVoSwe3gGTAfGvrWLeAQbQ=
394
github.com/ipfs/go-ipfs-cmds v0.15.0/go.mod h1:VABf/mv/wqvYX6hLG6Z+40eNAEw3FQO0bSm370Or3Wk=
395
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
@@ -403,16 +397,10 @@ github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1I
397
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
398
github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
399
github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
406
-github.com/ipfs/go-ipfs-exchange-interface v0.2.1 h1:jMzo2VhLKSHbVe+mHNzYgs95n0+t0Q69GQ5WhRDZV/s=
407
-github.com/ipfs/go-ipfs-exchange-interface v0.2.1/go.mod h1:MUsYn6rKbG6CTtsDp+lKJPmVt3ZrCViNyH3rfPGsZ2E=
408
-github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA=
409
-github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB02e++Z7521fMxqCNRrz9s=
400
github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
401
github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4=
402
github.com/ipfs/go-ipfs-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68QvB2FTWk08ZQk=
403
github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw=
414
-github.com/ipfs/go-ipfs-routing v0.3.0 h1:9W/W3N+g+y4ZDeffSgqhgo7BsBSJwPMcyssET9OWevc=
415
-github.com/ipfs/go-ipfs-routing v0.3.0/go.mod h1:dKqtTFIql7e1zYsEuWLyuOU+E0WJWW8JjbTPLParDWo=
404
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
405
github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
406
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
@@ -428,11 +416,8 @@ github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCk
416
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
417
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
418
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
431
-github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
419
github.com/ipfs/go-log/v2 v2.6.0 h1:2Nu1KKQQ2ayonKp4MPo6pXCjqw1ULc9iohRqWV5EYqg=
420
github.com/ipfs/go-log/v2 v2.6.0/go.mod h1:p+Efr3qaY5YXpx9TX7MoLCSEZX5boSWj9wh86P5HJa8=
434
-github.com/ipfs/go-merkledag v0.11.0 h1:DgzwK5hprESOzS4O1t/wi6JDpyVQdvm9Bs59N/jqfBY=
435
-github.com/ipfs/go-merkledag v0.11.0/go.mod h1:Q4f/1ezvBiJV0YCIXvt51W/9/kqJGH4I1LsA7+djsM4=
421
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
422
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
423
github.com/ipfs/go-metrics-prometheus v0.1.0 h1:bApWOHkrH3VTBHzTHrZSfq4n4weOZDzZFxUXv+HyKcA=
@@ -443,10 +428,6 @@ github.com/ipfs/go-test v0.2.2 h1:1yjYyfbdt1w93lVzde6JZ2einh3DIV40at4rVoyEcE8=
428
github.com/ipfs/go-test v0.2.2/go.mod h1:cmLisgVwkdRCnKu/CFZOk2DdhOcwghr5GsHeqwexoRA=
429
github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
430
github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
446
-github.com/ipfs/go-verifcid v0.0.3 h1:gmRKccqhWDocCRkC+a59g5QW7uJw5bpX9HWBevXa0zs=
447
-github.com/ipfs/go-verifcid v0.0.3/go.mod h1:gcCtGniVzelKrbk9ooUSX/pM3xlH73fZZJDzQJRvOUw=
448
-github.com/ipld/go-car v0.6.2 h1:Hlnl3Awgnq8icK+ze3iRghk805lu8YNq3wlREDTF2qc=
449
-github.com/ipld/go-car v0.6.2/go.mod h1:oEGXdwp6bmxJCZ+rARSkDliTeYnVzv3++eXajZ+Bmr8=
431
github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
432
github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
433
github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
@@ -986,8 +967,6 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
967
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
968
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
969
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
989
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
990
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
970
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
971
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
972
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
@@ -1000,12 +979,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
979
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
980
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
981
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
1003
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
1004
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
982
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
983
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
1007
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
1008
-go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
984
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
985
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
986
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
@@ -1272,8 +1247,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
1247
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1248
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1249
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1275
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1276
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1250
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1251
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
1252
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=