block cmd: use coreapi
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Aug 2, 2018 at 09:48 UTC
daae93ad89ce4a6de85169f3d8888ee3ae004a9c
5 files changed
+81
-126
core/commands/block.go
+61
-106
@@ -1,23 +1,19 @@
1
package commands
2
3
import (
4
- "bytes"
5
- "context"
6
- "errors"
4
"fmt"
5
"io"
9
- "io/ioutil"
6
"os"
7
8
util "github.com/ipfs/go-ipfs/blocks/blockstoreutil"
9
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
10
e "github.com/ipfs/go-ipfs/core/commands/e"
11
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
12
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
13
14
"gx/ipfs/QmPTfgFTo9PFr1PvPKyKoeMgBvYPh6cX3aDP7DHKVbnCbi/go-ipfs-cmds"
15
mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash"
16
"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
19
- blocks "gx/ipfs/QmWAzSEoqZ6xU6pu8yL8e5WaMb7wtbfbhhN4p1DknUPtr3/go-block-format"
20
- cid "gx/ipfs/QmZFbDTY9jfSBms2MchvYM9oYRbAF19K7Pby47yDBfpPrb/go-cid"
17
)
18
19
type BlockStat struct {
@@ -64,15 +60,27 @@ on raw IPFS blocks. It outputs the following to stdout:
60
cmdkit.StringArg("key", true, false, "The base58 multihash of an existing block to stat.").EnableStdin(),
61
},
62
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
67
- b, err := getBlockForKey(req.Context, env, req.Arguments[0])
63
+ api, err := cmdenv.GetApi(env)
64
+ if err != nil {
65
+ res.SetError(err, cmdkit.ErrNormal)
66
+ return
67
+ }
68
+
69
+ p, err := coreiface.ParsePath(req.Arguments[0])
70
+ if err != nil {
71
+ res.SetError(err, cmdkit.ErrNormal)
72
+ return
73
+ }
74
+
75
+ b, err := api.Block().Stat(req.Context, p)
76
if err != nil {
77
res.SetError(err, cmdkit.ErrNormal)
78
return
79
}
80
81
err = cmds.EmitOnce(res, &BlockStat{
74
- Key: b.Cid().String(),
75
- Size: len(b.RawData()),
82
+ Key: b.Path().Cid().String(),
83
+ Size: b.Size(),
84
})
85
if err != nil {
86
log.Error(err)
@@ -104,13 +112,25 @@ It outputs to stdout, and <key> is a base58 encoded multihash.
112
cmdkit.StringArg("key", true, false, "The base58 multihash of an existing block to get.").EnableStdin(),
113
},
114
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
107
- b, err := getBlockForKey(req.Context, env, req.Arguments[0])
115
+ api, err := cmdenv.GetApi(env)
116
+ if err != nil {
117
+ res.SetError(err, cmdkit.ErrNormal)
118
+ return
119
+ }
120
+
121
+ p, err := coreiface.ParsePath(req.Arguments[0])
122
+ if err != nil {
123
+ res.SetError(err, cmdkit.ErrNormal)
124
+ return
125
+ }
126
+
127
+ r, err := api.Block().Get(req.Context, p)
128
if err != nil {
129
res.SetError(err, cmdkit.ErrNormal)
130
return
131
}
132
113
- err = res.Emit(bytes.NewReader(b.RawData()))
133
+ err = res.Emit(r)
134
if err != nil {
135
log.Error(err)
136
}
@@ -138,7 +158,7 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
158
cmdkit.IntOption("mhlen", "multihash hash length").WithDefault(-1),
159
},
160
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
141
- n, err := cmdenv.GetNode(env)
161
+ api, err := cmdenv.GetApi(env)
162
if err != nil {
163
res.SetError(err, cmdkit.ErrNormal)
164
return
@@ -150,18 +170,6 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
170
return
171
}
172
153
- data, err := ioutil.ReadAll(file)
154
- if err != nil {
155
- res.SetError(err, cmdkit.ErrNormal)
156
- return
157
- }
158
-
159
- err = file.Close()
160
- if err != nil {
161
- res.SetError(err, cmdkit.ErrNormal)
162
- return
163
- }
164
-
173
mhtype, _ := req.Options["mhtype"].(string)
174
mhtval, ok := mh.Names[mhtype]
175
if !ok {
@@ -170,8 +178,11 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
178
return
179
}
180
173
- var pref cid.Prefix
174
- pref.Version = 1
181
+ mhlen, ok := req.Options["mhlen"].(int)
182
+ if !ok {
183
+ res.SetError("missing option \"mhlen\"", cmdkit.ErrNormal)
184
+ return
185
+ }
186
187
format, formatSet := req.Options["format"].(string)
188
if !formatSet {
@@ -182,50 +193,15 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
193
}
194
}
195
185
- if format == "v0" {
186
- pref.Version = 0
187
- }
188
- formatval, ok := cid.Codecs[format]
189
- if !ok {
190
- res.SetError(fmt.Errorf("unrecognized format: '%s'", format), cmdkit.ErrNormal)
191
- return
192
- }
193
- if mhtval != mh.SHA2_256 && pref.Version == 0 {
194
- res.SetError(errors.New("cannot generate CIDv0 with non-sha256 hash function"), cmdkit.ErrNormal)
195
- return
196
- }
197
-
198
- pref.Codec = formatval
199
- pref.MhType = mhtval
200
-
201
- mhlen, ok := req.Options["mhlen"].(int)
202
- if !ok {
203
- res.SetError("missing option \"mhlen\"", cmdkit.ErrNormal)
204
- return
205
- }
206
- pref.MhLength = mhlen
207
-
208
- bcid, err := pref.Sum(data)
209
- if err != nil {
210
- res.SetError(err, cmdkit.ErrNormal)
211
- return
212
- }
213
-
214
- b, err := blocks.NewBlockWithCid(data, bcid)
215
- if err != nil {
216
- res.SetError(err, cmdkit.ErrNormal)
217
- return
218
- }
219
-
220
- err = n.Blocks.AddBlock(b)
196
+ p, err := api.Block().Put(req.Context, file, options.Block.Hash(mhtval, mhlen), options.Block.Format(format))
197
if err != nil {
198
res.SetError(err, cmdkit.ErrNormal)
199
return
200
}
201
202
err = cmds.EmitOnce(res, &BlockStat{
227
- Key: b.Cid().String(),
228
- Size: len(data),
203
+ Key: p.Path().Cid().String(),
204
+ Size: p.Size(),
205
})
206
if err != nil {
207
log.Error(err)
@@ -244,29 +220,6 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
220
Type: BlockStat{},
221
}
222
247
-func getBlockForKey(ctx context.Context, env cmds.Environment, skey string) (blocks.Block, error) {
248
- if len(skey) == 0 {
249
- return nil, fmt.Errorf("zero length cid invalid")
250
- }
251
-
252
- n, err := cmdenv.GetNode(env)
253
- if err != nil {
254
- return nil, err
255
- }
256
-
257
- c, err := cid.Decode(skey)
258
- if err != nil {
259
- return nil, err
260
- }
261
-
262
- b, err := n.Blocks.GetBlock(ctx, c)
263
- if err != nil {
264
- return nil, err
265
- }
266
-
267
- return b, nil
268
-}
269
-
223
var blockRmCmd = &cmds.Command{
224
Helptext: cmdkit.HelpText{
225
Tagline: "Remove IPFS block(s).",
@@ -283,38 +236,40 @@ It takes a list of base58 encoded multihashes to remove.
236
cmdkit.BoolOption("quiet", "q", "Write minimal output."),
237
},
238
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
286
- n, err := cmdenv.GetNode(env)
239
+ api, err := cmdenv.GetApi(env)
240
if err != nil {
241
res.SetError(err, cmdkit.ErrNormal)
242
return
243
}
291
- hashes := req.Arguments
244
+
245
force, _ := req.Options["force"].(bool)
246
quiet, _ := req.Options["quiet"].(bool)
294
- cids := make([]*cid.Cid, 0, len(hashes))
295
- for _, hash := range hashes {
296
- c, err := cid.Decode(hash)
247
+
248
+ // TODO: use batching coreapi when done
249
+ for _, b := range req.Arguments {
250
+ p, err := coreiface.ParsePath(b)
251
if err != nil {
298
- err = fmt.Errorf("invalid content id: %s (%s)", hash, err)
252
res.SetError(err, cmdkit.ErrNormal)
253
return
254
}
255
303
- cids = append(cids, c)
304
- }
305
- ch, err := util.RmBlocks(n.Blockstore, n.Pinning, cids, util.RmBlocksOpts{
306
- Quiet: quiet,
307
- Force: force,
308
- })
256
+ rp, err := api.ResolvePath(req.Context, p)
257
+ if err != nil {
258
+ res.SetError(err, cmdkit.ErrNormal)
259
+ return
260
+ }
261
310
- if err != nil {
311
- res.SetError(err, cmdkit.ErrNormal)
312
- return
313
- }
262
+ err = api.Block().Rm(req.Context, rp, options.Block.Force(force))
263
+ if err != nil && !quiet {
264
+ res.Emit(&util.RemovedBlock{
265
+ Hash: rp.Cid().String(),
266
+ Error: err.Error(),
267
+ })
268
+ }
269
315
- err = res.Emit(ch)
316
- if err != nil {
317
- log.Error(err)
270
+ res.Emit(&util.RemovedBlock{
271
+ Hash: rp.Cid().String(),
272
+ })
273
}
274
},
275
PostRun: cmds.PostRunMap{
core/coreapi/block.go
+2
-2
@@ -24,7 +24,7 @@ type BlockStat struct {
24
size int
25
}
26
27
-func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.ResolvedPath, error) {
27
+func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.BlockStat, error) {
28
settings, err := caopts.BlockPutOptions(opts...)
29
if err != nil {
30
return nil, err
@@ -65,7 +65,7 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc
65
return nil, err
66
}
67
68
- return coreiface.IpldPath(b.Cid()), nil
68
+ return &BlockStat{path: coreiface.IpldPath(b.Cid()), size: len(data)}, nil
69
}
70
71
func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) {
core/coreapi/block_test.go
+14
-14
@@ -23,8 +23,8 @@ func TestBlockPut(t *testing.T) {
23
t.Error(err)
24
}
25
26
- if res.Cid().String() != "QmPyo15ynbVrSTVdJL9th7JysHaAbXt9dM9tXk1bMHbRtk" {
27
- t.Errorf("got wrong cid: %s", res.Cid().String())
26
+ if res.Path().Cid().String() != "QmPyo15ynbVrSTVdJL9th7JysHaAbXt9dM9tXk1bMHbRtk" {
27
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
28
}
29
}
30
@@ -40,8 +40,8 @@ func TestBlockPutFormat(t *testing.T) {
40
t.Error(err)
41
}
42
43
- if res.Cid().String() != "zdpuAn4amuLWo8Widi5v6VQpuo2dnpnwbVE3oB6qqs7mDSeoa" {
44
- t.Errorf("got wrong cid: %s", res.Cid().String())
43
+ if res.Path().Cid().String() != "zdpuAn4amuLWo8Widi5v6VQpuo2dnpnwbVE3oB6qqs7mDSeoa" {
44
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
45
}
46
}
47
@@ -57,8 +57,8 @@ func TestBlockPutHash(t *testing.T) {
57
t.Error(err)
58
}
59
60
- if res.Cid().String() != "zBurKB9YZkcDf6xa53WBE8CFX4ydVqAyf9KPXBFZt5stJzEstaS8Hukkhu4gwpMtc1xHNDbzP7sPtQKyWsP3C8fbhkmrZ" {
61
- t.Errorf("got wrong cid: %s", res.Cid().String())
60
+ if res.Path().Cid().String() != "zBurKB9YZkcDf6xa53WBE8CFX4ydVqAyf9KPXBFZt5stJzEstaS8Hukkhu4gwpMtc1xHNDbzP7sPtQKyWsP3C8fbhkmrZ" {
61
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
62
}
63
}
64
@@ -74,7 +74,7 @@ func TestBlockGet(t *testing.T) {
74
t.Error(err)
75
}
76
77
- r, err := api.Block().Get(ctx, res)
77
+ r, err := api.Block().Get(ctx, res.Path())
78
if err != nil {
79
t.Error(err)
80
}
@@ -101,7 +101,7 @@ func TestBlockRm(t *testing.T) {
101
t.Error(err)
102
}
103
104
- r, err := api.Block().Get(ctx, res)
104
+ r, err := api.Block().Get(ctx, res.Path())
105
if err != nil {
106
t.Error(err)
107
}
@@ -115,12 +115,12 @@ func TestBlockRm(t *testing.T) {
115
t.Error("didn't get correct data back")
116
}
117
118
- err = api.Block().Rm(ctx, res)
118
+ err = api.Block().Rm(ctx, res.Path())
119
if err != nil {
120
t.Error(err)
121
}
122
123
- _, err = api.Block().Get(ctx, res)
123
+ _, err = api.Block().Get(ctx, res.Path())
124
if err == nil {
125
t.Error("expected err to exist")
126
}
@@ -128,7 +128,7 @@ func TestBlockRm(t *testing.T) {
128
t.Errorf("unexpected error; %s", err.Error())
129
}
130
131
- err = api.Block().Rm(ctx, res)
131
+ err = api.Block().Rm(ctx, res.Path())
132
if err == nil {
133
t.Error("expected err to exist")
134
}
@@ -136,7 +136,7 @@ func TestBlockRm(t *testing.T) {
136
t.Errorf("unexpected error; %s", err.Error())
137
}
138
139
- err = api.Block().Rm(ctx, res, opt.Block.Force(true))
139
+ err = api.Block().Rm(ctx, res.Path(), opt.Block.Force(true))
140
if err != nil {
141
t.Error(err)
142
}
@@ -154,12 +154,12 @@ func TestBlockStat(t *testing.T) {
154
t.Error(err)
155
}
156
157
- stat, err := api.Block().Stat(ctx, res)
157
+ stat, err := api.Block().Stat(ctx, res.Path())
158
if err != nil {
159
t.Error(err)
160
}
161
162
- if stat.Path().String() != res.String() {
162
+ if stat.Path().String() != res.Path().String() {
163
t.Error("paths don't match")
164
}
165
core/coreapi/interface/block.go
+1
-1
@@ -19,7 +19,7 @@ type BlockStat interface {
19
// BlockAPI specifies the interface to the block layer
20
type BlockAPI interface {
21
// Put imports raw block data, hashing it using specified settings.
22
- Put(context.Context, io.Reader, ...options.BlockPutOption) (ResolvedPath, error)
22
+ Put(context.Context, io.Reader, ...options.BlockPutOption) (BlockStat, error)
23
24
// Get attempts to resolve the path and return a reader for data in the block
25
Get(context.Context, Path) (io.Reader, error)
core/coreapi/path_test.go
+3
-3
@@ -31,7 +31,7 @@ func TestMutablePath(t *testing.T) {
31
t.Error(err)
32
}
33
34
- if blk.Mutable() {
34
+ if blk.Path().Mutable() {
35
t.Error("expected /ipld path to be immutable")
36
}
37
}
@@ -129,7 +129,7 @@ func TestPathRoot(t *testing.T) {
129
t.Error(err)
130
}
131
132
- obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Cid().String()+`"}}`))
132
+ obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Path().Cid().String()+`"}}`))
133
if err != nil {
134
t.Fatal(err)
135
}
@@ -148,7 +148,7 @@ func TestPathRoot(t *testing.T) {
148
t.Error("unexpected path root")
149
}
150
151
- if rp.Cid().String() != blk.Cid().String() {
151
+ if rp.Cid().String() != blk.Path().Cid().String() {
152
t.Error("unexpected path cid")
153
}
154
}