@cryptotaxi247 / kubo / commits / 5abf3c2ae

added ls + recusrive directory adding

Juan Batiz-Benet committed Jul 5, 2014 at 18:19 UTC 5abf3c2ae9f0818ca74fd9a352a05dc903d419b1
5 files changed +115 -21
cli/add.go
+43 -20
@@ -6,11 +6,16 @@ import (
6 "github.com/jbenet/commander"
7 core "github.com/jbenet/go-ipfs/core"
8 importer "github.com/jbenet/go-ipfs/importer"
9 + dag "github.com/jbenet/go-ipfs/merkledag"
10 u "github.com/jbenet/go-ipfs/util"
11 mh "github.com/jbenet/go-multihash"
12 + "io/ioutil"
13 "os"
14 + "path/filepath"
15 )
16
17 +var DepthLimitExceeded = fmt.Errorf("depth limit exceeded")
18 +
19 var cmdIpfsAdd = &commander.Command{
20 UsageLine: "add",
21 Short: "Add an object to ipfs.",
@@ -49,18 +54,26 @@ func addCmd(c *commander.Command, inp []string) error {
54 }
55
56 for _, fpath := range inp {
52 - err = addPath(n, fpath, depth)
57 + _, err := addPath(n, fpath, depth)
58 if err != nil {
54 - u.PErr("error adding %s: %v\n", fpath, err)
59 + if !recursive {
60 + return fmt.Errorf("%s is a directory. Use -r to add recursively.", fpath)
61 + } else {
62 + u.PErr("error adding %s: %v\n", fpath, err)
63 + }
64 }
65 }
66 return err
67 }
68
60 -func addPath(n *core.IpfsNode, fpath string, depth int) error {
69 +func addPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
70 + if depth == 0 {
71 + return nil, DepthLimitExceeded
72 + }
73 +
74 fi, err := os.Stat(fpath)
75 if err != nil {
63 - return err
76 + return nil, err
77 }
78
79 if fi.IsDir() {
@@ -70,33 +83,43 @@ func addPath(n *core.IpfsNode, fpath string, depth int) error {
83 }
84 }
85
73 -func addDir(n *core.IpfsNode, fpath string, depth int) error {
74 - return u.NotImplementedError
75 -}
86 +func addDir(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
87 + tree := &dag.Node{}
88
77 -func addFile(n *core.IpfsNode, fpath string, depth int) error {
78 - stat, err := os.Stat(fpath)
89 + files, err := ioutil.ReadDir(fpath)
90 if err != nil {
80 - return err
91 + return nil, err
92 }
93
83 - if stat.IsDir() {
84 - return fmt.Errorf("addFile: `fpath` is a directory")
85 - }
94 + // construct nodes for containing files.
95 + for _, f := range files {
96 + fp := filepath.Join(fpath, f.Name())
97 + nd, err := addPath(n, fp, depth-1)
98 + if err != nil {
99 + return nil, err
100 + }
101
87 - f, err := os.Open(fpath)
88 - if err != nil {
89 - return err
102 + if err = tree.AddNodeLink(f.Name(), nd); err != nil {
103 + return nil, err
104 + }
105 }
91 - defer f.Close()
106
93 - root, err := importer.NewDagFromReader(f, stat.Size())
107 + return tree, addNode(n, tree, fpath)
108 +}
109 +
110 +func addFile(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
111 + root, err := importer.NewDagFromFile(fpath)
112 if err != nil {
95 - return err
113 + return nil, err
114 }
115
116 + return root, addNode(n, root, fpath)
117 +}
118 +
119 +// addNode adds the node to the graph + local storage
120 +func addNode(n *core.IpfsNode, nd *dag.Node, fpath string) error {
121 // add the file to the graph + local storage
99 - k, err := n.AddDagNode(root)
122 + k, err := n.AddDagNode(nd)
123 if err != nil {
124 return err
125 }
cli/ipfs.go
+1
@@ -38,6 +38,7 @@ Use "ipfs help <command>" for more information about a command.
38 Subcommands: []*commander.Command{
39 cmdIpfsAdd,
40 cmdIpfsCat,
41 + cmdIpfsLs,
42 cmdIpfsVersion,
43 cmdIpfsCommands,
44 },
cli/ls.go new
+51
@@ -0,0 +1,51 @@
1 +package main
2 +
3 +import (
4 + "github.com/gonuts/flag"
5 + "github.com/jbenet/commander"
6 + u "github.com/jbenet/go-ipfs/util"
7 + mh "github.com/jbenet/go-multihash"
8 +)
9 +
10 +var cmdIpfsLs = &commander.Command{
11 + UsageLine: "ls",
12 + Short: "List links from an object.",
13 + Long: `ipfs ls <ipfs-path> - List links from an object.
14 +
15 + Retrieves the object named by <ipfs-path> and displays the links
16 + it contains, with the following format:
17 +
18 + <link base58 hash> <link size in bytes> <link name>
19 +
20 +`,
21 + Run: lsCmd,
22 + Flag: *flag.NewFlagSet("ipfs-ls", flag.ExitOnError),
23 +}
24 +
25 +func lsCmd(c *commander.Command, inp []string) error {
26 + if len(inp) < 1 {
27 + u.POut(c.Long)
28 + return nil
29 + }
30 +
31 + // for now only hashes, no path resolution
32 + h, err := mh.FromB58String(inp[0])
33 + if err != nil {
34 + return err
35 + }
36 +
37 + n, err := localNode()
38 + if err != nil {
39 + return err
40 + }
41 +
42 + nd, err := n.GetDagNode(u.Key(h))
43 + if err != nil {
44 + return err
45 + }
46 +
47 + for _, link := range nd.Links {
48 + u.POut("%s %d %s\n", link.Hash.B58String(), link.Size, link.Name)
49 + }
50 + return nil
51 +}
core/core.go
-1
@@ -11,7 +11,6 @@ import (
11 )
12
13 // IPFS Core module. It represents an IPFS instance.
14 -
14 type IpfsNode struct {
15
16 // the node's configuration
importer/importer.go
+20
@@ -5,6 +5,7 @@ import (
5 dag "github.com/jbenet/go-ipfs/merkledag"
6 "io"
7 "io/ioutil"
8 + "os"
9 )
10
11 var BlockSizeLimit = int64(1048576) // 1 MB
@@ -38,3 +39,22 @@ func NewDagFromReader(r io.Reader, size int64) (*dag.Node, error) {
39 // no children for now because not block splitting yet
40 return root, nil
41 }
42 +
43 +func NewDagFromFile(fpath string) (*dag.Node, error) {
44 + stat, err := os.Stat(fpath)
45 + if err != nil {
46 + return nil, err
47 + }
48 +
49 + if stat.IsDir() {
50 + return nil, fmt.Errorf("`fpath` is a directory")
51 + }
52 +
53 + f, err := os.Open(fpath)
54 + if err != nil {
55 + return nil, err
56 + }
57 + defer f.Close()
58 +
59 + return NewDagFromReader(f, stat.Size())
60 +}