@cryptotaxi247 / kubo / commits / daae93ad8

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 }