@cryptotaxi247 / kubo / commits / e735addbb

object plumbing commands

Henry committed Oct 18, 2014 at 04:35 UTC e735addbb2721e92831715664f515720203c0866
3 files changed +248
cmd/ipfs/ipfs.go
+5
@@ -37,6 +37,10 @@ Tool commands:
37 version Show ipfs version information.
38 commands List all available commands.
39
40 +Plumbing commands:
41 + block Interact with raw blocks in the datastore
42 + object Interact with raw dag nodes
43 +
44 Advanced Commands:
45
46 mount Mount an ipfs read-only mountpoint.
@@ -63,6 +67,7 @@ Use "ipfs help <command>" for more information about a command.
67 cmdIpfsBootstrap,
68 cmdIpfsDiag,
69 cmdIpfsBlock,
70 + cmdIpfsObject,
71 cmdIpfsLog,
72 },
73 Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
cmd/ipfs/objects.go new
+112
@@ -0,0 +1,112 @@
1 +package main
2 +
3 +import (
4 + flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5 + commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6 + "github.com/jbenet/go-ipfs/core/commands"
7 +)
8 +
9 +var cmdIpfsObject = &commander.Command{
10 + UsageLine: "object",
11 + Short: "interact with ipfs objects",
12 + Long: `ipfs object - interact with ipfs objects
13 +
14 + ipfs object data <key> - return the data for this key as raw bytes
15 + ipfs object links <key> - lists (the keys of ?) the links this key points to
16 + ipfs object get <key> - output dag object to stdout
17 + ipfs object put - add dag object from stdin
18 +
19 +ipfs object is a plumbing command used to manipulate dag objects directly.
20 +- <key> is a base58 encoded multihash.
21 +- It reads from stdin or writes to stdout.
22 +- It accepts multiple encodings: --encoding=[ protobuf, json, ... ]`,
23 + Subcommands: []*commander.Command{
24 + cmdIpfsObjectData,
25 + cmdIpfsObjectLinks,
26 + cmdIpfsObjectGet,
27 + cmdIpfsObjectPut,
28 + },
29 + Flag: *flag.NewFlagSet("ipfs-object", flag.ExitOnError),
30 +}
31 +
32 +var cmdIpfsObjectData = &commander.Command{
33 + UsageLine: "data <key>",
34 + Short: "data outputs the raw bytes named by <key>",
35 + Long: `ipfs data <key> - data outputs the raw bytes named by <key>
36 +
37 +ipfs data is a plumbing command for retreiving the raw bytes stored in a dag node.
38 +It outputs to stdout, and <key> is a base58 encoded multihash.`,
39 + Run: makeCommand(command{
40 + name: "objectData",
41 + args: 1,
42 + flags: nil,
43 + online: true,
44 + cmdFn: commands.ObjectData,
45 + }),
46 +}
47 +
48 +var cmdIpfsObjectLinks = &commander.Command{
49 + UsageLine: "links <key>",
50 + Short: "outputs the links pointed to by <key>",
51 + Long: `ipfs links <key> - outputs the links pointed to by <key>
52 +
53 +ipfs block get is a plumbing command for retreiving raw ipfs blocks.
54 +It outputs to stdout, and <key> is a base58 encoded multihash.`,
55 + Run: makeCommand(command{
56 + name: "objectLinks",
57 + args: 1,
58 + flags: nil,
59 + online: true,
60 + cmdFn: commands.ObjectLinks,
61 + }),
62 +}
63 +
64 +func init() {
65 + cmdIpfsObjectGet.Flag.String("encoding", "json", "the encoding to use..")
66 + cmdIpfsObjectPut.Flag.String("encoding", "json", "the encoding to use..")
67 +}
68 +
69 +var cmdIpfsObjectGet = &commander.Command{
70 + UsageLine: "get <key>",
71 + Short: "get and serialize the dag node named by <key>",
72 + Long: `ipfs get <key> - get and output the dag node named by <key>
73 +
74 +ipfs object get is a plumbing command for retreiving dag nodes.
75 +It serialize the dag node to the format specified by the format flag.
76 +It outputs to stdout, and <key> is a base58 encoded multihash.
77 +
78 +Formats:
79 +
80 +This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
81 +Use the --encoding flag
82 +`,
83 + Run: makeCommand(command{
84 + name: "blockGet",
85 + args: 1,
86 + flags: []string{"encoding"},
87 + online: true,
88 + cmdFn: commands.ObjectGet,
89 + }),
90 +}
91 +
92 +var cmdIpfsObjectPut = &commander.Command{
93 + UsageLine: "put",
94 + Short: "store stdin as a dag object, outputs <key>",
95 + Long: `ipfs put - store stdin as a dag object, outputs <key>
96 +
97 +ipfs object put is a plumbing command for storing dag nodes.
98 +It serialize the dag node to the format specified by the format flag.
99 +It reads from stding, and <key> is a base58 encoded multihash.
100 +
101 +Formats:
102 +
103 +This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
104 +Use the --encoding flag`,
105 + Run: makeCommand(command{
106 + name: "blockPut",
107 + args: 0,
108 + flags: []string{"encoding"},
109 + online: true,
110 + cmdFn: commands.ObjectPut,
111 + }),
112 +}
core/commands/object.go new
+131
@@ -0,0 +1,131 @@
1 +package commands
2 +
3 +import (
4 + "bytes"
5 + "encoding/json"
6 + "errors"
7 + "fmt"
8 + "io"
9 + "io/ioutil"
10 + "os"
11 +
12 + "github.com/jbenet/go-ipfs/core"
13 + dag "github.com/jbenet/go-ipfs/merkledag"
14 +)
15 +
16 +// ObjectData takes a key string from args and writes out the raw bytes of that node (if there is one)
17 +func ObjectData(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
18 + dagnode, err := n.Resolver.ResolvePath(args[0])
19 + if err != nil {
20 + return fmt.Errorf("objectData error: %v", err)
21 + }
22 + log.Debug("objectData: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
23 +
24 + _, err = io.Copy(out, bytes.NewReader(dagnode.Data))
25 + return err
26 +}
27 +
28 +// ObjectLinks takes a key string from args and lists the links it points to
29 +func ObjectLinks(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
30 + dagnode, err := n.Resolver.ResolvePath(args[0])
31 + if err != nil {
32 + return fmt.Errorf("objectLinks error: %v", err)
33 + }
34 + log.Debug("ObjectLinks: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
35 +
36 + if len(dagnode.Links) == 0 {
37 + // TODO(cryptix): named error?
38 + return errors.New("objectLinks: no links in this node")
39 + }
40 +
41 + for _, link := range dagnode.Links {
42 + _, err = fmt.Fprintf(out, "%s %d %q\n", link.Hash.B58String(), link.Size, link.Name)
43 + if err != nil {
44 + break
45 + }
46 + }
47 +
48 + return err
49 +}
50 +
51 +// ErrUnknownObjectEnc is returned if a invalid encoding is supplied
52 +var ErrUnknownObjectEnc = errors.New("unknown object encoding")
53 +
54 +type objectEncoding string
55 +
56 +const (
57 + objectEncodingJSON objectEncoding = "json"
58 + objectEncodingProtobuf = "protobuf"
59 +)
60 +
61 +func getObjectEnc(o interface{}) objectEncoding {
62 + v, ok := o.(string)
63 + if !ok {
64 + // chosen as default because it's human readable
65 + log.Warning("option is not a string - falling back to json")
66 + return objectEncodingJSON
67 + }
68 +
69 + return objectEncoding(v)
70 +}
71 +
72 +// ObjectGet takes a key string from args and a format option and serializes the dagnode to that format
73 +func ObjectGet(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
74 + dagnode, err := n.Resolver.ResolvePath(args[0])
75 + if err != nil {
76 + return fmt.Errorf("ObjectGet error: %v", err)
77 + }
78 + log.Debug("objectGet: found dagnode %q (# of bytes: %d - # links: %d)", args[0], len(dagnode.Data), len(dagnode.Links))
79 +
80 + // sadly all encodings dont implement a common interface
81 + var data []byte
82 + switch getObjectEnc(opts["encoding"]) {
83 + case objectEncodingJSON:
84 + data, err = json.MarshalIndent(dagnode, "", " ")
85 +
86 + case objectEncodingProtobuf:
87 + data, err = dagnode.Marshal()
88 +
89 + default:
90 + return ErrUnknownObjectEnc
91 + }
92 +
93 + if err != nil {
94 + return fmt.Errorf("ObjectGet error: %v", err)
95 + }
96 +
97 + _, err = io.Copy(out, bytes.NewReader(data))
98 + return err
99 +}
100 +
101 +// ObjectPut takes a format option, serilizes bytes from stdin and updates the dag with that data
102 +func ObjectPut(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
103 + var (
104 + dagnode *dag.Node
105 + data []byte
106 + err error
107 + )
108 +
109 + data, err = ioutil.ReadAll(os.Stdin)
110 + if err != nil {
111 + return fmt.Errorf("ObjectPut error: %v", err)
112 + }
113 +
114 + switch getObjectEnc(opts["encoding"]) {
115 + case objectEncodingJSON:
116 + dagnode = new(dag.Node)
117 + err = json.Unmarshal(data, dagnode)
118 +
119 + case objectEncodingProtobuf:
120 + dagnode, err = dag.Decoded(data)
121 +
122 + default:
123 + return ErrUnknownObjectEnc
124 + }
125 +
126 + if err != nil {
127 + return fmt.Errorf("ObjectPut error: %v", err)
128 + }
129 +
130 + return addNode(n, dagnode, "stdin", out)
131 +}