add.go 2.97 KB
Newer Older
1 2 3
package commands

import (
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
4
	"errors"
5
	"fmt"
6
	"io"
7 8 9 10 11 12 13 14 15 16 17 18 19
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/jbenet/go-ipfs/core"
	"github.com/jbenet/go-ipfs/importer"
	dag "github.com/jbenet/go-ipfs/merkledag"
	u "github.com/jbenet/go-ipfs/util"
)

// Error indicating the max depth has been exceded.
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")

20
// Add is a command that imports files and directories -- given as arguments -- into ipfs.
21 22
func Add(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
	depth := 1
23 24

	// if recursive, set depth to reflect so
25 26 27
	if r, ok := opts["r"].(bool); r && ok {
		depth = -1
	}
28 29

	// add every path in args
30
	for _, path := range args {
31 32 33 34 35 36 37 38

		// get absolute path, as incoming arg may be relative
		path, err := filepath.Abs(path)
		if err != nil {
			return fmt.Errorf("addFile error: %v", err)
		}

		// Add the file
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
39
		_, err = AddPath(n, path, depth)
40
		if err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
41
			if err == ErrDepthLimitExceeded && depth == 1 {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
42
				err = errors.New("use -r to recursively add directories")
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
43
			}
44 45 46
			return fmt.Errorf("addFile error: %v", err)
		}

47
		// get the key to print it
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
48 49 50 51 52 53 54
		// k, err := nd.Key()
		// if err != nil {
		// 	return fmt.Errorf("addFile error: %v", err)
		// }
		//
		// Commenting out of here, because it's already in addNode below.
		// fmt.Fprintf(out, "added %s %s\n", k.Pretty(), path)
55 56 57 58
	}
	return nil
}

59
// AddPath adds a particular path to ipfs.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
func AddPath(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
	if depth == 0 {
		return nil, ErrDepthLimitExceeded
	}

	fi, err := os.Stat(fpath)
	if err != nil {
		return nil, err
	}

	if fi.IsDir() {
		return addDir(n, fpath, depth)
	}

	return addFile(n, fpath, depth)
}

func addDir(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
	tree := &dag.Node{Data: dag.FolderPBData()}

	files, err := ioutil.ReadDir(fpath)
	if err != nil {
		return nil, err
	}

	// construct nodes for containing files.
	for _, f := range files {
		fp := filepath.Join(fpath, f.Name())
		nd, err := AddPath(n, fp, depth-1)
		if err != nil {
			return nil, err
		}

		if err = tree.AddNodeLink(f.Name(), nd); err != nil {
			return nil, err
		}
	}

	return tree, addNode(n, tree, fpath)
}

func addFile(n *core.IpfsNode, fpath string, depth int) (*dag.Node, error) {
	root, err := importer.NewDagFromFile(fpath)
	if err != nil {
		return nil, err
	}

Jeromy's avatar
Jeromy committed
107 108 109 110 111 112 113 114 115 116
	k, err := root.Key()
	if err != nil {
		return nil, err
	}

	log.Info("Adding file: %s = %s\n", fpath, k.Pretty())
	for _, l := range root.Links {
		log.Info("SubBlock: %s\n", l.Hash.B58String())
	}

117 118 119 120 121 122 123 124 125 126 127
	return root, addNode(n, root, fpath)
}

// addNode adds the node to the graph + local storage
func addNode(n *core.IpfsNode, nd *dag.Node, fpath string) error {
	// add the file to the graph + local storage
	err := n.DAG.AddRecursive(nd)
	if err != nil {
		return err
	}

128 129 130 131 132 133
	k, err := nd.Key()
	if err != nil {
		return err
	}

	u.POut("added %s %s\n", k.Pretty(), fpath)
134 135

	// ensure we keep it. atm no-op
136
	return n.PinDagNodeRecursively(nd, -1)
137
}