mirror of
https://github.com/ipfs/kubo.git
synced 2025-08-06 19:44:01 +08:00
244 lines
5.9 KiB
Go
244 lines
5.9 KiB
Go
package dagcmd
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/ipfs/go-ipfs/core/commands/cmdenv"
|
|
"github.com/ipfs/go-ipfs/core/coredag"
|
|
|
|
cid "github.com/ipfs/go-cid"
|
|
cidenc "github.com/ipfs/go-cidutil/cidenc"
|
|
cmds "github.com/ipfs/go-ipfs-cmds"
|
|
files "github.com/ipfs/go-ipfs-files"
|
|
ipld "github.com/ipfs/go-ipld-format"
|
|
ipfspath "github.com/ipfs/go-path"
|
|
path "github.com/ipfs/interface-go-ipfs-core/path"
|
|
mh "github.com/multiformats/go-multihash"
|
|
)
|
|
|
|
var DagCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Interact with ipld dag objects.",
|
|
ShortDescription: `
|
|
'ipfs dag' is used for creating and manipulating dag objects.
|
|
|
|
This subcommand is currently an experimental feature, but it is intended
|
|
to deprecate and replace the existing 'ipfs object' command moving forward.
|
|
`,
|
|
},
|
|
Subcommands: map[string]*cmds.Command{
|
|
"put": DagPutCmd,
|
|
"get": DagGetCmd,
|
|
"resolve": DagResolveCmd,
|
|
},
|
|
}
|
|
|
|
// OutputObject is the output type of 'dag put' command
|
|
type OutputObject struct {
|
|
Cid cid.Cid
|
|
}
|
|
|
|
// ResolveOutput is the output type of 'dag resolve' command
|
|
type ResolveOutput struct {
|
|
Cid cid.Cid
|
|
RemPath string
|
|
}
|
|
|
|
var DagPutCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Add a dag node to ipfs.",
|
|
ShortDescription: `
|
|
'ipfs dag put' accepts input from a file or stdin and parses it
|
|
into an object of the specified format.
|
|
`,
|
|
},
|
|
Arguments: []cmds.Argument{
|
|
cmds.FileArg("object data", true, true, "The object to put").EnableStdin(),
|
|
},
|
|
Options: []cmds.Option{
|
|
cmds.StringOption("format", "f", "Format that the object will be added as.").WithDefault("cbor"),
|
|
cmds.StringOption("input-enc", "Format that the input object will be.").WithDefault("json"),
|
|
cmds.BoolOption("pin", "Pin this object when adding."),
|
|
cmds.StringOption("hash", "Hash function to use").WithDefault(""),
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
api, err := cmdenv.GetApi(env, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ienc, _ := req.Options["input-enc"].(string)
|
|
format, _ := req.Options["format"].(string)
|
|
hash, _ := req.Options["hash"].(string)
|
|
dopin, _ := req.Options["pin"].(bool)
|
|
|
|
// mhType tells inputParser which hash should be used. MaxUint64 means 'use
|
|
// default hash' (sha256 for cbor, sha1 for git..)
|
|
mhType := uint64(math.MaxUint64)
|
|
|
|
if hash != "" {
|
|
var ok bool
|
|
mhType, ok = mh.Names[hash]
|
|
if !ok {
|
|
return fmt.Errorf("%s in not a valid multihash name", hash)
|
|
}
|
|
}
|
|
|
|
var adder ipld.NodeAdder = api.Dag()
|
|
if dopin {
|
|
adder = api.Dag().Pinning()
|
|
}
|
|
b := ipld.NewBatch(req.Context, adder)
|
|
|
|
it := req.Files.Entries()
|
|
for it.Next() {
|
|
file := files.FileFromEntry(it)
|
|
if file == nil {
|
|
return fmt.Errorf("expected a regular file")
|
|
}
|
|
nds, err := coredag.ParseInputs(ienc, format, file, mhType, -1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(nds) == 0 {
|
|
return fmt.Errorf("no node returned from ParseInputs")
|
|
}
|
|
|
|
for _, nd := range nds {
|
|
err := b.Add(req.Context, nd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
cid := nds[0].Cid()
|
|
if err := res.Emit(&OutputObject{Cid: cid}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if it.Err() != nil {
|
|
return it.Err()
|
|
}
|
|
|
|
if err := b.Commit(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
Type: OutputObject{},
|
|
Encoders: cmds.EncoderMap{
|
|
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *OutputObject) error {
|
|
enc, err := cmdenv.GetLowLevelCidEncoder(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(w, enc.Encode(out.Cid))
|
|
return nil
|
|
}),
|
|
},
|
|
}
|
|
|
|
var DagGetCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Get a dag node from ipfs.",
|
|
ShortDescription: `
|
|
'ipfs dag get' fetches a dag node from ipfs and prints it out in the specified
|
|
format.
|
|
`,
|
|
},
|
|
Arguments: []cmds.Argument{
|
|
cmds.StringArg("ref", true, false, "The object to get").EnableStdin(),
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
api, err := cmdenv.GetApi(env, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rp, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
obj, err := api.Dag().Get(req.Context, rp.Cid())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var out interface{} = obj
|
|
if len(rp.Remainder()) > 0 {
|
|
rem := strings.Split(rp.Remainder(), "/")
|
|
final, _, err := obj.Resolve(rem)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out = final
|
|
}
|
|
return cmds.EmitOnce(res, &out)
|
|
},
|
|
}
|
|
|
|
// DagResolveCmd returns address of highest block within a path and a path remainder
|
|
var DagResolveCmd = &cmds.Command{
|
|
Helptext: cmds.HelpText{
|
|
Tagline: "Resolve ipld block",
|
|
ShortDescription: `
|
|
'ipfs dag resolve' fetches a dag node from ipfs, prints it's address and remaining path.
|
|
`,
|
|
},
|
|
Arguments: []cmds.Argument{
|
|
cmds.StringArg("ref", true, false, "The path to resolve").EnableStdin(),
|
|
},
|
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
|
api, err := cmdenv.GetApi(env, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rp, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return cmds.EmitOnce(res, &ResolveOutput{
|
|
Cid: rp.Cid(),
|
|
RemPath: rp.Remainder(),
|
|
})
|
|
},
|
|
Encoders: cmds.EncoderMap{
|
|
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ResolveOutput) error {
|
|
var (
|
|
enc cidenc.Encoder
|
|
err error
|
|
)
|
|
switch {
|
|
case !cmdenv.CidBaseDefined(req):
|
|
// Not specified, check the path.
|
|
enc, err = cmdenv.CidEncoderFromPath(req.Arguments[0])
|
|
if err == nil {
|
|
break
|
|
}
|
|
// Nope, fallback on the default.
|
|
fallthrough
|
|
default:
|
|
enc, err = cmdenv.GetLowLevelCidEncoder(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
p := enc.Encode(out.Cid)
|
|
if out.RemPath != "" {
|
|
p = ipfspath.Join([]string{p, out.RemPath})
|
|
}
|
|
|
|
fmt.Fprint(w, p)
|
|
return nil
|
|
}),
|
|
},
|
|
Type: ResolveOutput{},
|
|
}
|