add.go 3.04 KB
Newer Older
Brian Tiger Chow's avatar
Brian Tiger Chow committed
1
package coreunix
2 3

import (
4
	"errors"
5
	"io"
6
	"os"
7
	gopath "path"
8

9
	"github.com/jbenet/go-ipfs/commands/files"
10 11 12
	core "github.com/jbenet/go-ipfs/core"
	importer "github.com/jbenet/go-ipfs/importer"
	chunk "github.com/jbenet/go-ipfs/importer/chunk"
13 14
	merkledag "github.com/jbenet/go-ipfs/merkledag"
	"github.com/jbenet/go-ipfs/pin"
15
	"github.com/jbenet/go-ipfs/thirdparty/eventlog"
16
	unixfs "github.com/jbenet/go-ipfs/unixfs"
17 18
)

19 20
var log = eventlog.Logger("coreunix")

Brian Tiger Chow's avatar
Brian Tiger Chow committed
21 22
// Add builds a merkledag from the a reader, pinning all objects to the local
// datastore. Returns a key representing the root node.
23
func Add(n *core.IpfsNode, r io.Reader) (string, error) {
24 25 26 27
	// TODO more attractive function signature importer.BuildDagFromReader
	dagNode, err := importer.BuildDagFromReader(
		r,
		n.DAG,
28
		n.Pinning.GetManual(), // Fix this interface
29 30 31 32 33
		chunk.DefaultSplitter,
	)
	if err != nil {
		return "", err
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
34 35 36
	if err := n.Pinning.Flush(); err != nil {
		return "", err
	}
37 38 39 40 41 42
	k, err := dagNode.Key()
	if err != nil {
		return "", err
	}

	return k.String(), nil
43
}
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

// AddR recursively adds files in |path|.
func AddR(n *core.IpfsNode, root string) (key string, err error) {
	f, err := os.Open(root)
	if err != nil {
		return "", err
	}
	defer f.Close()
	ff, err := files.NewSerialFile(root, f)
	if err != nil {
		return "", err
	}
	dagnode, err := addFile(n, ff)
	if err != nil {
		return "", err
	}
	k, err := dagnode.Key()
	if err != nil {
		return "", err
	}
	return k.String(), nil
}

func add(n *core.IpfsNode, readers []io.Reader) ([]*merkledag.Node, error) {
	mp, ok := n.Pinning.(pin.ManualPinner)
	if !ok {
		return nil, errors.New("invalid pinner type! expected manual pinner")
	}
	dagnodes := make([]*merkledag.Node, 0)
	for _, reader := range readers {
		node, err := importer.BuildDagFromReader(reader, n.DAG, mp, chunk.DefaultSplitter)
		if err != nil {
			return nil, err
		}
		dagnodes = append(dagnodes, node)
	}
	err := n.Pinning.Flush()
	if err != nil {
		return nil, err
	}
	return dagnodes, nil
}

func addNode(n *core.IpfsNode, node *merkledag.Node) error {
	err := n.DAG.AddRecursive(node) // add the file to the graph + local storage
	if err != nil {
		return err
	}
	err = n.Pinning.Pin(node, true) // ensure we keep it
	if err != nil {
		return err
	}
	return nil
}

func addFile(n *core.IpfsNode, file files.File) (*merkledag.Node, error) {
	if file.IsDirectory() {
		return addDir(n, file)
	}

	dns, err := add(n, []io.Reader{file})
	if err != nil {
		return nil, err
	}

	return dns[len(dns)-1], nil // last dag node is the file.
}

func addDir(n *core.IpfsNode, dir files.File) (*merkledag.Node, error) {

	tree := &merkledag.Node{Data: unixfs.FolderPBData()}

Loop:
	for {
		file, err := dir.NextFile()
		switch {
		case err != nil && err != io.EOF:
			return nil, err
		case err == io.EOF:
			break Loop
		}

		node, err := addFile(n, file)
		if err != nil {
			return nil, err
		}

131
		_, name := gopath.Split(file.FileName())
132 133 134 135 136 137 138 139 140 141 142 143 144

		err = tree.AddNodeLink(name, node)
		if err != nil {
			return nil, err
		}
	}

	err := addNode(n, tree)
	if err != nil {
		return nil, err
	}
	return tree, nil
}