mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-24 14:08:13 +08:00
block cmd: use coreapi
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
This commit is contained in:

committed by
Steven Allen

parent
66b54d9ac2
commit
daae93ad89
@ -1,23 +1,19 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
util "github.com/ipfs/go-ipfs/blocks/blockstoreutil"
|
||||
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
|
||||
e "github.com/ipfs/go-ipfs/core/commands/e"
|
||||
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
|
||||
"github.com/ipfs/go-ipfs/core/coreapi/interface/options"
|
||||
|
||||
"gx/ipfs/QmPTfgFTo9PFr1PvPKyKoeMgBvYPh6cX3aDP7DHKVbnCbi/go-ipfs-cmds"
|
||||
mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash"
|
||||
"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
|
||||
blocks "gx/ipfs/QmWAzSEoqZ6xU6pu8yL8e5WaMb7wtbfbhhN4p1DknUPtr3/go-block-format"
|
||||
cid "gx/ipfs/QmZFbDTY9jfSBms2MchvYM9oYRbAF19K7Pby47yDBfpPrb/go-cid"
|
||||
)
|
||||
|
||||
type BlockStat struct {
|
||||
@ -64,15 +60,27 @@ on raw IPFS blocks. It outputs the following to stdout:
|
||||
cmdkit.StringArg("key", true, false, "The base58 multihash of an existing block to stat.").EnableStdin(),
|
||||
},
|
||||
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
|
||||
b, err := getBlockForKey(req.Context, env, req.Arguments[0])
|
||||
api, err := cmdenv.GetApi(env)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := coreiface.ParsePath(req.Arguments[0])
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := api.Block().Stat(req.Context, p)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = cmds.EmitOnce(res, &BlockStat{
|
||||
Key: b.Cid().String(),
|
||||
Size: len(b.RawData()),
|
||||
Key: b.Path().Cid().String(),
|
||||
Size: b.Size(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
@ -104,13 +112,25 @@ It outputs to stdout, and <key> is a base58 encoded multihash.
|
||||
cmdkit.StringArg("key", true, false, "The base58 multihash of an existing block to get.").EnableStdin(),
|
||||
},
|
||||
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
|
||||
b, err := getBlockForKey(req.Context, env, req.Arguments[0])
|
||||
api, err := cmdenv.GetApi(env)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = res.Emit(bytes.NewReader(b.RawData()))
|
||||
p, err := coreiface.ParsePath(req.Arguments[0])
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
r, err := api.Block().Get(req.Context, p)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = res.Emit(r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
@ -138,7 +158,7 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
|
||||
cmdkit.IntOption("mhlen", "multihash hash length").WithDefault(-1),
|
||||
},
|
||||
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
|
||||
n, err := cmdenv.GetNode(env)
|
||||
api, err := cmdenv.GetApi(env)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
@ -150,18 +170,6 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
mhtype, _ := req.Options["mhtype"].(string)
|
||||
mhtval, ok := mh.Names[mhtype]
|
||||
if !ok {
|
||||
@ -170,8 +178,11 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
|
||||
return
|
||||
}
|
||||
|
||||
var pref cid.Prefix
|
||||
pref.Version = 1
|
||||
mhlen, ok := req.Options["mhlen"].(int)
|
||||
if !ok {
|
||||
res.SetError("missing option \"mhlen\"", cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
format, formatSet := req.Options["format"].(string)
|
||||
if !formatSet {
|
||||
@ -182,50 +193,15 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
|
||||
}
|
||||
}
|
||||
|
||||
if format == "v0" {
|
||||
pref.Version = 0
|
||||
}
|
||||
formatval, ok := cid.Codecs[format]
|
||||
if !ok {
|
||||
res.SetError(fmt.Errorf("unrecognized format: '%s'", format), cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
if mhtval != mh.SHA2_256 && pref.Version == 0 {
|
||||
res.SetError(errors.New("cannot generate CIDv0 with non-sha256 hash function"), cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
pref.Codec = formatval
|
||||
pref.MhType = mhtval
|
||||
|
||||
mhlen, ok := req.Options["mhlen"].(int)
|
||||
if !ok {
|
||||
res.SetError("missing option \"mhlen\"", cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
pref.MhLength = mhlen
|
||||
|
||||
bcid, err := pref.Sum(data)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := blocks.NewBlockWithCid(data, bcid)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = n.Blocks.AddBlock(b)
|
||||
p, err := api.Block().Put(req.Context, file, options.Block.Hash(mhtval, mhlen), options.Block.Format(format))
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
err = cmds.EmitOnce(res, &BlockStat{
|
||||
Key: b.Cid().String(),
|
||||
Size: len(data),
|
||||
Key: p.Path().Cid().String(),
|
||||
Size: p.Size(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
@ -244,29 +220,6 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1.
|
||||
Type: BlockStat{},
|
||||
}
|
||||
|
||||
func getBlockForKey(ctx context.Context, env cmds.Environment, skey string) (blocks.Block, error) {
|
||||
if len(skey) == 0 {
|
||||
return nil, fmt.Errorf("zero length cid invalid")
|
||||
}
|
||||
|
||||
n, err := cmdenv.GetNode(env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := cid.Decode(skey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := n.Blocks.GetBlock(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
var blockRmCmd = &cmds.Command{
|
||||
Helptext: cmdkit.HelpText{
|
||||
Tagline: "Remove IPFS block(s).",
|
||||
@ -283,38 +236,40 @@ It takes a list of base58 encoded multihashes to remove.
|
||||
cmdkit.BoolOption("quiet", "q", "Write minimal output."),
|
||||
},
|
||||
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
|
||||
n, err := cmdenv.GetNode(env)
|
||||
api, err := cmdenv.GetApi(env)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
hashes := req.Arguments
|
||||
|
||||
force, _ := req.Options["force"].(bool)
|
||||
quiet, _ := req.Options["quiet"].(bool)
|
||||
cids := make([]*cid.Cid, 0, len(hashes))
|
||||
for _, hash := range hashes {
|
||||
c, err := cid.Decode(hash)
|
||||
|
||||
// TODO: use batching coreapi when done
|
||||
for _, b := range req.Arguments {
|
||||
p, err := coreiface.ParsePath(b)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid content id: %s (%s)", hash, err)
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
cids = append(cids, c)
|
||||
}
|
||||
ch, err := util.RmBlocks(n.Blockstore, n.Pinning, cids, util.RmBlocksOpts{
|
||||
Quiet: quiet,
|
||||
Force: force,
|
||||
})
|
||||
rp, err := api.ResolvePath(req.Context, p)
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
res.SetError(err, cmdkit.ErrNormal)
|
||||
return
|
||||
}
|
||||
err = api.Block().Rm(req.Context, rp, options.Block.Force(force))
|
||||
if err != nil && !quiet {
|
||||
res.Emit(&util.RemovedBlock{
|
||||
Hash: rp.Cid().String(),
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err = res.Emit(ch)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
res.Emit(&util.RemovedBlock{
|
||||
Hash: rp.Cid().String(),
|
||||
})
|
||||
}
|
||||
},
|
||||
PostRun: cmds.PostRunMap{
|
||||
|
@ -24,7 +24,7 @@ type BlockStat struct {
|
||||
size int
|
||||
}
|
||||
|
||||
func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.ResolvedPath, error) {
|
||||
func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.BlockStat, error) {
|
||||
settings, err := caopts.BlockPutOptions(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -65,7 +65,7 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return coreiface.IpldPath(b.Cid()), nil
|
||||
return &BlockStat{path: coreiface.IpldPath(b.Cid()), size: len(data)}, nil
|
||||
}
|
||||
|
||||
func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) {
|
||||
|
@ -23,8 +23,8 @@ func TestBlockPut(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if res.Cid().String() != "QmPyo15ynbVrSTVdJL9th7JysHaAbXt9dM9tXk1bMHbRtk" {
|
||||
t.Errorf("got wrong cid: %s", res.Cid().String())
|
||||
if res.Path().Cid().String() != "QmPyo15ynbVrSTVdJL9th7JysHaAbXt9dM9tXk1bMHbRtk" {
|
||||
t.Errorf("got wrong cid: %s", res.Path().Cid().String())
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,8 +40,8 @@ func TestBlockPutFormat(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if res.Cid().String() != "zdpuAn4amuLWo8Widi5v6VQpuo2dnpnwbVE3oB6qqs7mDSeoa" {
|
||||
t.Errorf("got wrong cid: %s", res.Cid().String())
|
||||
if res.Path().Cid().String() != "zdpuAn4amuLWo8Widi5v6VQpuo2dnpnwbVE3oB6qqs7mDSeoa" {
|
||||
t.Errorf("got wrong cid: %s", res.Path().Cid().String())
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +57,8 @@ func TestBlockPutHash(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if res.Cid().String() != "zBurKB9YZkcDf6xa53WBE8CFX4ydVqAyf9KPXBFZt5stJzEstaS8Hukkhu4gwpMtc1xHNDbzP7sPtQKyWsP3C8fbhkmrZ" {
|
||||
t.Errorf("got wrong cid: %s", res.Cid().String())
|
||||
if res.Path().Cid().String() != "zBurKB9YZkcDf6xa53WBE8CFX4ydVqAyf9KPXBFZt5stJzEstaS8Hukkhu4gwpMtc1xHNDbzP7sPtQKyWsP3C8fbhkmrZ" {
|
||||
t.Errorf("got wrong cid: %s", res.Path().Cid().String())
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ func TestBlockGet(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
r, err := api.Block().Get(ctx, res)
|
||||
r, err := api.Block().Get(ctx, res.Path())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -101,7 +101,7 @@ func TestBlockRm(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
r, err := api.Block().Get(ctx, res)
|
||||
r, err := api.Block().Get(ctx, res.Path())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -115,12 +115,12 @@ func TestBlockRm(t *testing.T) {
|
||||
t.Error("didn't get correct data back")
|
||||
}
|
||||
|
||||
err = api.Block().Rm(ctx, res)
|
||||
err = api.Block().Rm(ctx, res.Path())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = api.Block().Get(ctx, res)
|
||||
_, err = api.Block().Get(ctx, res.Path())
|
||||
if err == nil {
|
||||
t.Error("expected err to exist")
|
||||
}
|
||||
@ -128,7 +128,7 @@ func TestBlockRm(t *testing.T) {
|
||||
t.Errorf("unexpected error; %s", err.Error())
|
||||
}
|
||||
|
||||
err = api.Block().Rm(ctx, res)
|
||||
err = api.Block().Rm(ctx, res.Path())
|
||||
if err == nil {
|
||||
t.Error("expected err to exist")
|
||||
}
|
||||
@ -136,7 +136,7 @@ func TestBlockRm(t *testing.T) {
|
||||
t.Errorf("unexpected error; %s", err.Error())
|
||||
}
|
||||
|
||||
err = api.Block().Rm(ctx, res, opt.Block.Force(true))
|
||||
err = api.Block().Rm(ctx, res.Path(), opt.Block.Force(true))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -154,12 +154,12 @@ func TestBlockStat(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
stat, err := api.Block().Stat(ctx, res)
|
||||
stat, err := api.Block().Stat(ctx, res.Path())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if stat.Path().String() != res.String() {
|
||||
if stat.Path().String() != res.Path().String() {
|
||||
t.Error("paths don't match")
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ type BlockStat interface {
|
||||
// BlockAPI specifies the interface to the block layer
|
||||
type BlockAPI interface {
|
||||
// Put imports raw block data, hashing it using specified settings.
|
||||
Put(context.Context, io.Reader, ...options.BlockPutOption) (ResolvedPath, error)
|
||||
Put(context.Context, io.Reader, ...options.BlockPutOption) (BlockStat, error)
|
||||
|
||||
// Get attempts to resolve the path and return a reader for data in the block
|
||||
Get(context.Context, Path) (io.Reader, error)
|
||||
|
@ -31,7 +31,7 @@ func TestMutablePath(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if blk.Mutable() {
|
||||
if blk.Path().Mutable() {
|
||||
t.Error("expected /ipld path to be immutable")
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,7 @@ func TestPathRoot(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Cid().String()+`"}}`))
|
||||
obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Path().Cid().String()+`"}}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -148,7 +148,7 @@ func TestPathRoot(t *testing.T) {
|
||||
t.Error("unexpected path root")
|
||||
}
|
||||
|
||||
if rp.Cid().String() != blk.Cid().String() {
|
||||
if rp.Cid().String() != blk.Path().Cid().String() {
|
||||
t.Error("unexpected path cid")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user