dag.go 4.07 KB
Newer Older
1 2 3 4 5
package dagcmd

import (
	"fmt"
	"io"
Jeromy's avatar
Jeromy committed
6
	"io/ioutil"
7 8 9
	"strings"

	cmds "github.com/ipfs/go-ipfs/commands"
10
	path "github.com/ipfs/go-ipfs/path"
11

Jeromy's avatar
Jeromy committed
12
	node "gx/ipfs/QmRSU5EqqWVZSNdbU51yXmVoF1uNw3JgTNB6RaiL7DZM16/go-ipld-node"
Jeromy's avatar
Jeromy committed
13
	ipldcbor "gx/ipfs/QmT1B6cKXnMMki8nbuhrnLuiU32HLvwi6xe99bJ79482UK/go-ipld-cbor"
Jeromy's avatar
Jeromy committed
14
	cid "gx/ipfs/QmcTcsTvfaeEBRFo1TkFgT8sRmgi1n1LTZpecfVP8fzpGD/go-cid"
15 16 17 18
)

var DagCmd = &cmds.Command{
	Helptext: cmds.HelpText{
Jeromy's avatar
Jeromy committed
19 20 21 22 23 24 25
		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.
		`,
26 27 28 29 30 31 32 33 34 35 36 37 38 39
	},
	Subcommands: map[string]*cmds.Command{
		"put": DagPutCmd,
		"get": DagGetCmd,
	},
}

type OutputObject struct {
	Cid *cid.Cid
}

var DagPutCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Add a dag node to ipfs.",
Jeromy's avatar
Jeromy committed
40 41 42 43
		ShortDescription: `
'ipfs dag put' accepts input from a file or stdin and parses it
into an object of the specified format.
`,
44 45 46 47 48
	},
	Arguments: []cmds.Argument{
		cmds.FileArg("object data", true, false, "The object to put").EnableStdin(),
	},
	Options: []cmds.Option{
49 50
		cmds.StringOption("format", "f", "Format that the object will be added as.").Default("cbor"),
		cmds.StringOption("input-enc", "Format that the input object will be.").Default("json"),
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
	},
	Run: func(req cmds.Request, res cmds.Response) {
		n, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		fi, err := req.Files().NextFile()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		ienc, _, _ := req.Option("input-enc").String()
		format, _, _ := req.Option("format").String()
67

68 69
		switch ienc {
		case "json":
70
			nd, err := convertJsonToType(fi, format)
71 72 73 74 75 76 77 78 79 80 81
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			c, err := n.DAG.Add(nd)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

Jeromy's avatar
Jeromy committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
			res.SetOutput(&OutputObject{Cid: c})
			return
		case "raw":
			nd, err := convertRawToType(fi, format)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			c, err := n.DAG.Add(nd)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

97 98
			res.SetOutput(&OutputObject{Cid: c})
			return
99 100 101
		default:
			res.SetError(fmt.Errorf("unrecognized input encoding: %s", ienc), cmds.ErrNormal)
			return
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
		}
	},
	Type: OutputObject{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			oobj, ok := res.Output().(*OutputObject)
			if !ok {
				return nil, fmt.Errorf("expected a different object in marshaler")
			}

			return strings.NewReader(oobj.Cid.String()), nil
		},
	},
}

var DagGetCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Get a dag node from ipfs.",
Jeromy's avatar
Jeromy committed
120 121 122
		ShortDescription: `
'ipfs dag get' fetches a dag node from ipfs and prints it out in the specifed format.
`,
123 124
	},
	Arguments: []cmds.Argument{
125
		cmds.StringArg("ref", true, false, "The object to get").EnableStdin(),
126 127 128 129 130 131 132 133
	},
	Run: func(req cmds.Request, res cmds.Response) {
		n, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

134
		p, err := path.ParsePath(req.Arguments()[0])
135 136 137 138 139
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

140
		obj, err := n.Resolver.ResolvePath(req.Context(), p)
141 142 143 144 145 146 147 148 149
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(obj)
	},
}

150
func convertJsonToType(r io.Reader, format string) (node.Node, error) {
151 152
	switch format {
	case "cbor", "dag-cbor":
Jeromy's avatar
Jeromy committed
153
		return ipldcbor.FromJson(r)
154 155 156 157 158 159
	case "dag-pb", "protobuf":
		return nil, fmt.Errorf("protobuf handling in 'dag' command not yet implemented")
	default:
		return nil, fmt.Errorf("unknown target format: %s", format)
	}
}
Jeromy's avatar
Jeromy committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173

func convertRawToType(r io.Reader, format string) (node.Node, error) {
	switch format {
	case "cbor", "dag-cbor":
		data, err := ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}

		return ipldcbor.Decode(data)
	default:
		return nil, fmt.Errorf("unsupported target format for raw input: %s", format)
	}
}