fix: use error instead of strings as error in blockstoreutil/remove
Jorropo committed
Apr 1, 2022 at 01:18 UTC
f72110c2d8676ec770722aad44547d6169216eec
3 files changed
+46
-22
blocks/blockstoreutil/remove.go
+14
-13
@@ -3,6 +3,7 @@ package blockstoreutil
3
4
import (
5
"context"
6
+ "errors"
7
"fmt"
8
"io"
9
@@ -13,14 +14,14 @@ import (
14
)
15
16
// RemovedBlock is used to represent the result of removing a block.
16
-// If a block was removed successfully, then the Error string will be
17
-// empty. If a block could not be removed, then Error will contain the
17
+// If a block was removed successfully, then the Error will be empty.
18
+// If a block could not be removed, then Error will contain the
19
// reason the block could not be removed. If the removal was aborted
20
// due to a fatal error, Hash will be empty, Error will contain the
21
// reason, and no more results will be sent.
22
type RemovedBlock struct {
22
- Hash string `json:",omitempty"`
23
- Error string `json:",omitempty"`
23
+ Hash string
24
+ Error error
25
}
26
27
// RmBlocksOpts is used to wrap options for RmBlocks().
@@ -51,17 +52,17 @@ func RmBlocks(ctx context.Context, blocks bs.GCBlockstore, pins pin.Pinner, cids
52
// remove this sometime in the future.
53
has, err := blocks.Has(ctx, c)
54
if err != nil {
54
- out <- &RemovedBlock{Hash: c.String(), Error: err.Error()}
55
+ out <- &RemovedBlock{Hash: c.String(), Error: err}
56
continue
57
}
58
if !has && !opts.Force {
58
- out <- &RemovedBlock{Hash: c.String(), Error: format.ErrNotFound{Cid: c}.Error()}
59
+ out <- &RemovedBlock{Hash: c.String(), Error: format.ErrNotFound{Cid: c}}
60
continue
61
}
62
63
err = blocks.DeleteBlock(ctx, c)
64
if err != nil {
64
- out <- &RemovedBlock{Hash: c.String(), Error: err.Error()}
65
+ out <- &RemovedBlock{Hash: c.String(), Error: err}
66
} else if !opts.Quiet {
67
out <- &RemovedBlock{Hash: c.String()}
68
}
@@ -79,7 +80,7 @@ func FilterPinned(ctx context.Context, pins pin.Pinner, out chan<- interface{},
80
stillOkay := make([]cid.Cid, 0, len(cids))
81
res, err := pins.CheckIfPinned(ctx, cids...)
82
if err != nil {
82
- out <- &RemovedBlock{Error: fmt.Sprintf("pin check failed: %s", err)}
83
+ out <- &RemovedBlock{Error: fmt.Errorf("pin check failed: %w", err)}
84
return nil
85
}
86
for _, r := range res {
@@ -88,7 +89,7 @@ func FilterPinned(ctx context.Context, pins pin.Pinner, out chan<- interface{},
89
} else {
90
out <- &RemovedBlock{
91
Hash: r.Key.String(),
91
- Error: r.String(),
92
+ Error: errors.New(r.String()),
93
}
94
}
95
}
@@ -107,11 +108,11 @@ func ProcRmOutput(next func() (interface{}, error), sout io.Writer, serr io.Writ
108
return err
109
}
110
r := res.(*RemovedBlock)
110
- if r.Hash == "" && r.Error != "" {
111
- return fmt.Errorf("aborted: %s", r.Error)
112
- } else if r.Error != "" {
111
+ if r.Hash == "" && r.Error != nil {
112
+ return fmt.Errorf("aborted: %w", r.Error)
113
+ } else if r.Error != nil {
114
someFailed = true
114
- fmt.Fprintf(serr, "cannot remove %s: %s\n", r.Hash, r.Error)
115
+ fmt.Fprintf(serr, "cannot remove %s: %v\n", r.Hash, r.Error)
116
} else {
117
fmt.Fprintf(sout, "removed %s\n", r.Hash)
118
}
core/commands/block.go
+30
-5
@@ -8,7 +8,6 @@ import (
8
9
files "github.com/ipfs/go-ipfs-files"
10
11
- util "github.com/ipfs/go-ipfs/blocks/blockstoreutil"
11
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
12
"github.com/ipfs/go-ipfs/core/commands/cmdutils"
13
@@ -213,6 +212,11 @@ const (
212
blockQuietOptionName = "quiet"
213
)
214
215
+type removedBlock struct {
216
+ Hash string `json:",omitempty"`
217
+ Error string `json:",omitempty"`
218
+}
219
+
220
var blockRmCmd = &cmds.Command{
221
Helptext: cmds.HelpText{
222
Tagline: "Remove IPFS block(s).",
@@ -246,7 +250,7 @@ It takes a list of base58 encoded multihashes to remove.
250
251
err = api.Block().Rm(req.Context, rp, options.Block.Force(force))
252
if err != nil {
249
- if err := res.Emit(&util.RemovedBlock{
253
+ if err := res.Emit(&removedBlock{
254
Hash: rp.Cid().String(),
255
Error: err.Error(),
256
}); err != nil {
@@ -256,7 +260,7 @@ It takes a list of base58 encoded multihashes to remove.
260
}
261
262
if !quiet {
259
- err := res.Emit(&util.RemovedBlock{
263
+ err := res.Emit(&removedBlock{
264
Hash: rp.Cid().String(),
265
})
266
if err != nil {
@@ -269,8 +273,29 @@ It takes a list of base58 encoded multihashes to remove.
273
},
274
PostRun: cmds.PostRunMap{
275
cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {
272
- return util.ProcRmOutput(res.Next, os.Stdout, os.Stderr)
276
+ someFailed := false
277
+ for {
278
+ res, err := res.Next()
279
+ if err == io.EOF {
280
+ break
281
+ } else if err != nil {
282
+ return err
283
+ }
284
+ r := res.(*removedBlock)
285
+ if r.Hash == "" && r.Error != "" {
286
+ return fmt.Errorf("aborted: %s", r.Error)
287
+ } else if r.Error != "" {
288
+ someFailed = true
289
+ fmt.Fprintf(os.Stderr, "cannot remove %s: %s\n", r.Hash, r.Error)
290
+ } else {
291
+ fmt.Fprintf(os.Stdout, "removed %s\n", r.Hash)
292
+ }
293
+ }
294
+ if someFailed {
295
+ return fmt.Errorf("some blocks not removed")
296
+ }
297
+ return nil
298
},
299
},
275
- Type: util.RemovedBlock{},
300
+ Type: removedBlock{},
301
}
core/coreapi/block.go
+2
-4
@@ -107,10 +107,8 @@ func (api *BlockAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.BlockRm
107
return errors.New("got unexpected output from util.RmBlocks")
108
}
109
110
- // Because errors come as strings we lose information about
111
- // the error type.
112
- if remBlock.Error != "" {
113
- return errors.New(remBlock.Error)
110
+ if remBlock.Error != nil {
111
+ return remBlock.Error
112
}
113
return nil
114
case <-ctx.Done():