core/commands2: Added 'refs' command
Matt Bell committed
Nov 9, 2014 at 19:22 UTC
3406ee0ef4ee8549621a658c4a08392519380ee0
2 files changed
+133
core/commands2/refs.go
new
+132
@@ -0,0 +1,132 @@
1
+package commands
2
+
3
+import (
4
+ "fmt"
5
+
6
+ mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
7
+ cmds "github.com/jbenet/go-ipfs/commands"
8
+ "github.com/jbenet/go-ipfs/core"
9
+ "github.com/jbenet/go-ipfs/core/commands2/internal"
10
+ dag "github.com/jbenet/go-ipfs/merkledag"
11
+ u "github.com/jbenet/go-ipfs/util"
12
+)
13
+
14
+type RefsOutput struct {
15
+ Refs []string
16
+}
17
+
18
+var refsCmd = &cmds.Command{
19
+ Description: "Lists link hashes from an object",
20
+ Help: `Retrieves the object named by <ipfs-path> and displays the link
21
+ hashes it contains, with the following format:
22
+
23
+ <link base58 hash>`,
24
+
25
+ Arguments: []cmds.Argument{
26
+ cmds.Argument{"ipfs-path", cmds.ArgString, true, true,
27
+ "Path to the object(s) to list refs from"},
28
+ },
29
+ Options: []cmds.Option{
30
+ cmds.Option{[]string{"unique", "u"}, cmds.Bool,
31
+ "Omit duplicate refs from output"},
32
+ cmds.Option{[]string{"recursive", "r"}, cmds.Bool,
33
+ "Recursively list links of child nodes"},
34
+ },
35
+ Run: func(res cmds.Response, req cmds.Request) {
36
+ n := req.Context().Node
37
+
38
+ opt, found := req.Option("unique")
39
+ unique, ok := opt.(bool)
40
+ if !ok && found {
41
+ unique = false
42
+ }
43
+
44
+ opt, found = req.Option("recursive")
45
+ recursive, ok := opt.(bool)
46
+ if !ok && found {
47
+ recursive = false
48
+ }
49
+
50
+ paths, err := internal.CastToStrings(req.Arguments())
51
+ if err != nil {
52
+ res.SetError(err, cmds.ErrNormal)
53
+ return
54
+ }
55
+
56
+ output, err := getRefs(n, paths, unique, recursive)
57
+ if err != nil {
58
+ res.SetError(err, cmds.ErrNormal)
59
+ return
60
+ }
61
+
62
+ res.SetOutput(output)
63
+ },
64
+ Type: &RefsOutput{},
65
+ Marshallers: map[cmds.EncodingType]cmds.Marshaller{
66
+ cmds.Text: func(res cmds.Response) ([]byte, error) {
67
+ output := res.Output().(*RefsOutput)
68
+ s := ""
69
+ for _, ref := range output.Refs {
70
+ s += fmt.Sprintln(ref)
71
+ }
72
+ return []byte(s), nil
73
+ },
74
+ },
75
+}
76
+
77
+func getRefs(n *core.IpfsNode, paths []string, unique, recursive bool) (*RefsOutput, error) {
78
+ var refsSeen map[u.Key]bool
79
+ if unique {
80
+ refsSeen = make(map[u.Key]bool)
81
+ }
82
+
83
+ refs := make([]string, 0)
84
+
85
+ for _, path := range paths {
86
+ object, err := n.Resolver.ResolvePath(path)
87
+ if err != nil {
88
+ return nil, err
89
+ }
90
+
91
+ refs, err = addRefs(n, object, refs, refsSeen, recursive)
92
+ if err != nil {
93
+ return nil, err
94
+ }
95
+ }
96
+
97
+ return &RefsOutput{refs}, nil
98
+}
99
+
100
+func addRefs(n *core.IpfsNode, object *dag.Node, refs []string, refsSeen map[u.Key]bool, recursive bool) ([]string, error) {
101
+ for _, link := range object.Links {
102
+ var found bool
103
+ found, refs = addRef(link.Hash, refs, refsSeen)
104
+
105
+ if recursive && !found {
106
+ child, err := n.DAG.Get(u.Key(link.Hash))
107
+ if err != nil {
108
+ return nil, fmt.Errorf("cannot retrieve %s (%s)", link.Hash.B58String(), err)
109
+ }
110
+
111
+ refs, err = addRefs(n, child, refs, refsSeen, recursive)
112
+ if err != nil {
113
+ return nil, err
114
+ }
115
+ }
116
+ }
117
+
118
+ return refs, nil
119
+}
120
+
121
+func addRef(h mh.Multihash, refs []string, refsSeen map[u.Key]bool) (bool, []string) {
122
+ if refsSeen != nil {
123
+ _, found := refsSeen[u.Key(h)]
124
+ if found {
125
+ return true, refs
126
+ }
127
+ refsSeen[u.Key(h)] = true
128
+ }
129
+
130
+ refs = append(refs, h.B58String())
131
+ return false, refs
132
+}
core/commands2/root.go
+1
@@ -71,6 +71,7 @@ var rootSubcommands = map[string]*cmds.Command{
71
"block": blockCmd,
72
"update": updateCmd,
73
"object": objectCmd,
74
+ "refs": refsCmd,
75
}
76
77
func init() {