@cryptotaxi247 / kubo / commits / ace0b0b98

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=