From 6b797f10a41002d7b9dfcba473e187b31e6ea0a1 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Mon, 24 Oct 2016 12:00:29 -0700 Subject: [PATCH 1/4] Implement cbor ipld nodes and a first pass at the 'dag' command License: MIT Signed-off-by: Jeromy --- core/commands/block.go | 5 - core/commands/dag/dag.go | 216 +++++++++++++++++++++++++++++++++++++++ core/commands/root.go | 2 + merkledag/merkledag.go | 7 ++ package.json | 7 +- 5 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 core/commands/dag/dag.go diff --git a/core/commands/block.go b/core/commands/block.go index e8e7890f1de..c907a8593d3 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -2,7 +2,6 @@ package commands import ( "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -168,10 +167,6 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) { return nil, err } - if !u.IsValidHash(skey) { - return nil, errors.New("Not a valid hash") - } - c, err := cid.Decode(skey) if err != nil { return nil, err diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go new file mode 100644 index 00000000000..34b1f1bb1c7 --- /dev/null +++ b/core/commands/dag/dag.go @@ -0,0 +1,216 @@ +package dagcmd + +import ( + "encoding/json" + "fmt" + "io" + "strings" + + cmds "github.com/ipfs/go-ipfs/commands" + + node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" + cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" + ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor" +) + +var DagCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Interact with ipld dag objects.", + ShortDescription: ``, + }, + + 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.", + }, + Arguments: []cmds.Argument{ + cmds.FileArg("object data", true, false, "The object to put").EnableStdin(), + }, + Options: []cmds.Option{ + cmds.StringOption("format", "f", "Format that the object will be.").Default("cbor"), + cmds.StringOption("input-enc", "Format that the object will be.").Default("json"), + }, + 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() + _ = format + switch ienc { + case "json": + var obj map[string]interface{} + err := json.NewDecoder(fi).Decode(&obj) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + nd, err := convertJsonToType(obj, 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 + } + + res.SetOutput(&OutputObject{Cid: c}) + return + /* + case "btc": + data, err := ioutil.ReadAll(fi) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + blk, err := ipldbtc.DecodeBlock(data) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + c, err := n.DAG.Add(blk) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(&OutputObject{Cid: c}) + return + */ + } + }, + 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.", + }, + Arguments: []cmds.Argument{ + cmds.StringArg("cid", true, false, "The cid of the object to get").EnableStdin(), + }, + Run: func(req cmds.Request, res cmds.Response) { + n, err := req.InvocContext().GetNode() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + c, err := cid.Decode(req.Arguments()[0]) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + obj, err := n.DAG.Get(req.Context(), c) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(obj) + }, +} + +func convertJsonToType(obj map[string]interface{}, format string) (node.Node, error) { + switch format { + case "cbor", "dag-cbor": + return convertJsonToCbor(obj) + 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) + } +} + +func convertJsonToCbor(from map[string]interface{}) (*ipldcbor.Node, error) { + out, err := convertMapSIToCbor(from) + if err != nil { + return nil, err + } + + return ipldcbor.WrapMap(out) +} +func convertMapSIToCbor(from map[string]interface{}) (map[interface{}]interface{}, error) { + to := make(map[interface{}]interface{}) + for k, v := range from { + out, err := convertToCborIshObj(v) + if err != nil { + return nil, err + } + to[k] = out + } + + return to, nil +} + +func convertToCborIshObj(i interface{}) (interface{}, error) { + switch v := i.(type) { + case map[string]interface{}: + if lnk, ok := v["/"]; ok && len(v) == 1 { + // special case for links + vstr, ok := lnk.(string) + if !ok { + return nil, fmt.Errorf("link should have been a string") + } + + c, err := cid.Decode(vstr) + if err != nil { + return nil, err + } + + return &ipldcbor.Link{Target: c}, nil + } + + return convertMapSIToCbor(v) + case []interface{}: + var out []interface{} + for _, o := range v { + obj, err := convertToCborIshObj(o) + if err != nil { + return nil, err + } + + out = append(out, obj) + } + + return out, nil + default: + return v, nil + } +} diff --git a/core/commands/root.go b/core/commands/root.go index 288090275d1..a034bd8b37f 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -5,6 +5,7 @@ import ( "strings" cmds "github.com/ipfs/go-ipfs/commands" + dag "github.com/ipfs/go-ipfs/core/commands/dag" files "github.com/ipfs/go-ipfs/core/commands/files" ocmd "github.com/ipfs/go-ipfs/core/commands/object" unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs" @@ -86,6 +87,7 @@ var rootSubcommands = map[string]*cmds.Command{ "cat": CatCmd, "commands": CommandsDaemonCmd, "config": ConfigCmd, + "dag": dag.DagCmd, "dht": DhtCmd, "diag": DiagCmd, "dns": DNSCmd, diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 4867e583f3d..7b15fa4d5b5 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -14,6 +14,7 @@ import ( logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" + ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor" ) var log = logging.Logger("merkledag") @@ -105,6 +106,12 @@ func decodeBlock(b blocks.Block) (node.Node, error) { return decnd, nil case cid.Raw: return NewRawNode(b.RawData()), nil + case cid.CBOR: + return ipldcbor.Decode(b.RawData()) + /* + case cid.Bitcoin: + return ipldbtc.DecodeBlock(b.RawData()) + */ default: return nil, fmt.Errorf("unrecognized object type: %s", c.Type()) } diff --git a/package.json b/package.json index 829fb15277f..21e9ec4a96c 100644 --- a/package.json +++ b/package.json @@ -277,9 +277,10 @@ "version": "0.3.2" }, { - "hash": "QmQKEgGgYCDyk8VNY6A65FpuE4YwbspvjXHco1rdb75PVc", - "name": "go-libp2p-routing", - "version": "2.2.2" + "author": "whyrusleeping", + "hash": "QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4", + "name": "go-ipld-cbor", + "version": "0.2.1" } ], "gxVersion": "0.4.0", From f7d3f61673e0ac183649b0a0aca8477fb8506f32 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Thu, 27 Oct 2016 15:49:41 -0700 Subject: [PATCH 2/4] clean up some code, update cbor package, and add tests License: MIT Signed-off-by: Jeromy --- core/commands/dag/dag.go | 52 +++++++++++---------------------- merkledag/merkledag.go | 6 +--- package.json | 4 +-- test/sharness/t0053-dag.sh | 59 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 43 deletions(-) create mode 100755 test/sharness/t0053-dag.sh diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 34b1f1bb1c7..dc09a408456 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -10,7 +10,7 @@ import ( node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" - ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor" + ipldcbor "gx/ipfs/QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr/go-ipld-cbor" ) var DagCmd = &cmds.Command{ @@ -37,8 +37,8 @@ var DagPutCmd = &cmds.Command{ cmds.FileArg("object data", true, false, "The object to put").EnableStdin(), }, Options: []cmds.Option{ - cmds.StringOption("format", "f", "Format that the object will be.").Default("cbor"), - cmds.StringOption("input-enc", "Format that the object will be.").Default("json"), + 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"), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -55,17 +55,10 @@ var DagPutCmd = &cmds.Command{ ienc, _, _ := req.Option("input-enc").String() format, _, _ := req.Option("format").String() - _ = format + switch ienc { case "json": - var obj map[string]interface{} - err := json.NewDecoder(fi).Decode(&obj) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - nd, err := convertJsonToType(obj, format) + nd, err := convertJsonToType(fi, format) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -79,29 +72,9 @@ var DagPutCmd = &cmds.Command{ res.SetOutput(&OutputObject{Cid: c}) return - /* - case "btc": - data, err := ioutil.ReadAll(fi) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - blk, err := ipldbtc.DecodeBlock(data) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - c, err := n.DAG.Add(blk) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - - res.SetOutput(&OutputObject{Cid: c}) - return - */ + default: + res.SetError(fmt.Errorf("unrecognized input encoding: %s", ienc), cmds.ErrNormal) + return } }, Type: OutputObject{}, @@ -147,7 +120,13 @@ var DagGetCmd = &cmds.Command{ }, } -func convertJsonToType(obj map[string]interface{}, format string) (node.Node, error) { +func convertJsonToType(r io.Reader, format string) (node.Node, error) { + var obj map[string]interface{} + err := json.NewDecoder(r).Decode(&obj) + if err != nil { + return nil, err + } + switch format { case "cbor", "dag-cbor": return convertJsonToCbor(obj) @@ -166,6 +145,7 @@ func convertJsonToCbor(from map[string]interface{}) (*ipldcbor.Node, error) { return ipldcbor.WrapMap(out) } + func convertMapSIToCbor(from map[string]interface{}) (map[interface{}]interface{}, error) { to := make(map[interface{}]interface{}) for k, v := range from { diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 7b15fa4d5b5..5d3c3aebd8a 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -14,7 +14,7 @@ import ( logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" - ipldcbor "gx/ipfs/QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4/go-ipld-cbor" + ipldcbor "gx/ipfs/QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr/go-ipld-cbor" ) var log = logging.Logger("merkledag") @@ -108,10 +108,6 @@ func decodeBlock(b blocks.Block) (node.Node, error) { return NewRawNode(b.RawData()), nil case cid.CBOR: return ipldcbor.Decode(b.RawData()) - /* - case cid.Bitcoin: - return ipldbtc.DecodeBlock(b.RawData()) - */ default: return nil, fmt.Errorf("unrecognized object type: %s", c.Type()) } diff --git a/package.json b/package.json index 21e9ec4a96c..a99ddb2a39d 100644 --- a/package.json +++ b/package.json @@ -278,9 +278,9 @@ }, { "author": "whyrusleeping", - "hash": "QmYRzW9YDHVNCDbfFzbS7TEXAG1swE1yjq1basZ5WnJYH4", + "hash": "QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr", "name": "go-ipld-cbor", - "version": "0.2.1" + "version": "0.2.2" } ], "gxVersion": "0.4.0", diff --git a/test/sharness/t0053-dag.sh b/test/sharness/t0053-dag.sh new file mode 100755 index 00000000000..bce877893ad --- /dev/null +++ b/test/sharness/t0053-dag.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Copyright (c) 2016 Jeromy Johnson +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test dag command" + +. lib/test-lib.sh + +test_init_ipfs + +test_expect_success "make a few test files" ' + echo "foo" > file1 && + echo "bar" > file2 && + echo "baz" > file3 && + echo "qux" > file4 && + HASH1=$(ipfs add -q file1) && + HASH2=$(ipfs add -q file2) && + HASH3=$(ipfs add -q file3) && + HASH4=$(ipfs add -q file4) +' + +test_expect_success "make an ipld object in json" ' + printf "{\"hello\":\"world\",\"cats\":[{\"/\":\"%s\"},{\"water\":{\"/\":\"%s\"}}],\"magic\":{\"/\":\"%s\"}}" $HASH1 $HASH2 $HASH3 > ipld_object +' + +test_dag_cmd() { + test_expect_success "can add an ipld object" ' + IPLDHASH=$(cat ipld_object | ipfs dag put) + ' + + test_expect_success "output looks correct" ' + EXPHASH="zdpuApvChR5xM7ttbQmpmtna7wcShHi4gPyxUcWbB7nh8K7cN" + test $EXPHASH = $IPLDHASH + ' + + test_expect_success "various path traversals work" ' + ipfs cat $IPLDHASH/cats/0 > out1 && + ipfs cat $IPLDHASH/cats/1/water > out2 && + ipfs cat $IPLDHASH/magic > out3 + ' + + test_expect_success "outputs look correct" ' + test_cmp file1 out1 && + test_cmp file2 out2 && + test_cmp file3 out3 + ' +} + +# should work offline +test_dag_cmd + +# should work online +test_launch_ipfs_daemon +test_dag_cmd +test_kill_ipfs_daemon + +test_done From 4c5a5c8a8f8bec697467b94d04401068eee8faee Mon Sep 17 00:00:00 2001 From: Jeromy Date: Fri, 28 Oct 2016 12:56:47 -0700 Subject: [PATCH 3/4] more cleanup, update cboripld package License: MIT Signed-off-by: Jeromy --- core/commands/dag/dag.go | 70 ++-------------------------------------- merkledag/merkledag.go | 2 +- package.json | 4 +-- 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index dc09a408456..a7159d41993 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -1,16 +1,15 @@ package dagcmd import ( - "encoding/json" "fmt" "io" "strings" cmds "github.com/ipfs/go-ipfs/commands" + ipldcbor "gx/ipfs/QmRcAVqrbY5wryx7hfNLtiUZbCcstzaJL7YJFBboitcqWF/go-ipld-cbor" node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" - ipldcbor "gx/ipfs/QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr/go-ipld-cbor" ) var DagCmd = &cmds.Command{ @@ -18,7 +17,6 @@ var DagCmd = &cmds.Command{ Tagline: "Interact with ipld dag objects.", ShortDescription: ``, }, - Subcommands: map[string]*cmds.Command{ "put": DagPutCmd, "get": DagGetCmd, @@ -121,76 +119,12 @@ var DagGetCmd = &cmds.Command{ } func convertJsonToType(r io.Reader, format string) (node.Node, error) { - var obj map[string]interface{} - err := json.NewDecoder(r).Decode(&obj) - if err != nil { - return nil, err - } - switch format { case "cbor", "dag-cbor": - return convertJsonToCbor(obj) + return ipldcbor.FromJson(r) 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) } } - -func convertJsonToCbor(from map[string]interface{}) (*ipldcbor.Node, error) { - out, err := convertMapSIToCbor(from) - if err != nil { - return nil, err - } - - return ipldcbor.WrapMap(out) -} - -func convertMapSIToCbor(from map[string]interface{}) (map[interface{}]interface{}, error) { - to := make(map[interface{}]interface{}) - for k, v := range from { - out, err := convertToCborIshObj(v) - if err != nil { - return nil, err - } - to[k] = out - } - - return to, nil -} - -func convertToCborIshObj(i interface{}) (interface{}, error) { - switch v := i.(type) { - case map[string]interface{}: - if lnk, ok := v["/"]; ok && len(v) == 1 { - // special case for links - vstr, ok := lnk.(string) - if !ok { - return nil, fmt.Errorf("link should have been a string") - } - - c, err := cid.Decode(vstr) - if err != nil { - return nil, err - } - - return &ipldcbor.Link{Target: c}, nil - } - - return convertMapSIToCbor(v) - case []interface{}: - var out []interface{} - for _, o := range v { - obj, err := convertToCborIshObj(o) - if err != nil { - return nil, err - } - - out = append(out, obj) - } - - return out, nil - default: - return v, nil - } -} diff --git a/merkledag/merkledag.go b/merkledag/merkledag.go index 5d3c3aebd8a..bb115aae10d 100644 --- a/merkledag/merkledag.go +++ b/merkledag/merkledag.go @@ -11,10 +11,10 @@ import ( bserv "github.com/ipfs/go-ipfs/blockservice" offline "github.com/ipfs/go-ipfs/exchange/offline" + ipldcbor "gx/ipfs/QmRcAVqrbY5wryx7hfNLtiUZbCcstzaJL7YJFBboitcqWF/go-ipld-cbor" logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" node "gx/ipfs/QmU7bFWQ793qmvNy7outdCaMfSDNk8uqhx4VNrxYj5fj5g/go-ipld-node" cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid" - ipldcbor "gx/ipfs/QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr/go-ipld-cbor" ) var log = logging.Logger("merkledag") diff --git a/package.json b/package.json index a99ddb2a39d..988da8d8d65 100644 --- a/package.json +++ b/package.json @@ -278,9 +278,9 @@ }, { "author": "whyrusleeping", - "hash": "QmY7L2aEa1rHjkSSbXJB8oC7825JTpUUvDygmM2JPQeqhr", + "hash": "QmRcAVqrbY5wryx7hfNLtiUZbCcstzaJL7YJFBboitcqWF", "name": "go-ipld-cbor", - "version": "0.2.2" + "version": "0.3.0" } ], "gxVersion": "0.4.0", From c6a273fd05175dadd43d0fb40f00fed6de0c8112 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Sat, 29 Oct 2016 18:03:25 -0700 Subject: [PATCH 4/4] add more helptext to dag commands License: MIT Signed-off-by: Jeromy --- core/commands/dag/dag.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index a7159d41993..3adf0f97c22 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -14,8 +14,13 @@ import ( var DagCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Interact with ipld dag objects.", - ShortDescription: ``, + 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, @@ -30,6 +35,10 @@ type OutputObject struct { 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, false, "The object to put").EnableStdin(), @@ -91,6 +100,9 @@ var DagPutCmd = &cmds.Command{ 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 specifed format. +`, }, Arguments: []cmds.Argument{ cmds.StringArg("cid", true, false, "The cid of the object to get").EnableStdin(),