add.go 3.02 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
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/jbenet/go-ipfs/core"
	"github.com/jbenet/go-ipfs/importer"
13
	ft "github.com/jbenet/go-ipfs/importer/format"
14 15 16 17 18 19 20
	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")

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

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

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

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

48
		// get the key to print it
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
49 50 51 52 53 54 55
		// 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)
56 57 58 59
	}
	return nil
}

60
// AddPath adds a particular path to ipfs.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
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) {
79
	tree := &dag.Node{Data: ft.FolderPBData()}
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 107

	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
108 109 110 111 112 113 114 115 116 117
	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())
	}

118 119 120 121 122 123 124 125 126 127 128
	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
	}

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

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

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