github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/core/coreunix/add.go (about)

     1  package coreunix
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"os"
     7  	gopath "path"
     8  
     9  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    10  
    11  	"github.com/ipfs/go-ipfs/commands/files"
    12  	core "github.com/ipfs/go-ipfs/core"
    13  	importer "github.com/ipfs/go-ipfs/importer"
    14  	chunk "github.com/ipfs/go-ipfs/importer/chunk"
    15  	merkledag "github.com/ipfs/go-ipfs/merkledag"
    16  	"github.com/ipfs/go-ipfs/pin"
    17  	"github.com/ipfs/go-ipfs/thirdparty/eventlog"
    18  	unixfs "github.com/ipfs/go-ipfs/unixfs"
    19  )
    20  
    21  var log = eventlog.Logger("coreunix")
    22  
    23  // Add builds a merkledag from the a reader, pinning all objects to the local
    24  // datastore. Returns a key representing the root node.
    25  func Add(n *core.IpfsNode, r io.Reader) (string, error) {
    26  	// TODO more attractive function signature importer.BuildDagFromReader
    27  
    28  	dagNode, err := importer.BuildDagFromReader(
    29  		n.DAG,
    30  		chunk.NewSizeSplitter(r, chunk.DefaultBlockSize),
    31  		importer.BasicPinnerCB(n.Pinning.GetManual()),
    32  	)
    33  	if err != nil {
    34  		return "", err
    35  	}
    36  	k, err := dagNode.Key()
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  
    41  	return k.String(), nil
    42  }
    43  
    44  // AddR recursively adds files in |path|.
    45  func AddR(n *core.IpfsNode, root string) (key string, err error) {
    46  	stat, err := os.Lstat(root)
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  
    51  	f, err := files.NewSerialFile(root, root, stat)
    52  	if err != nil {
    53  		return "", err
    54  	}
    55  	defer f.Close()
    56  
    57  	dagnode, err := addFile(n, f)
    58  	if err != nil {
    59  		return "", err
    60  	}
    61  
    62  	k, err := dagnode.Key()
    63  	if err != nil {
    64  		return "", err
    65  	}
    66  
    67  	n.Pinning.GetManual().RemovePinWithMode(k, pin.Indirect)
    68  	if err := n.Pinning.Flush(); err != nil {
    69  		return "", err
    70  	}
    71  
    72  	return k.String(), nil
    73  }
    74  
    75  // AddWrapped adds data from a reader, and wraps it with a directory object
    76  // to preserve the filename.
    77  // Returns the path of the added file ("<dir hash>/filename"), the DAG node of
    78  // the directory, and and error if any.
    79  func AddWrapped(n *core.IpfsNode, r io.Reader, filename string) (string, *merkledag.Node, error) {
    80  	file := files.NewReaderFile(filename, filename, ioutil.NopCloser(r), nil)
    81  	dir := files.NewSliceFile("", "", []files.File{file})
    82  	dagnode, err := addDir(n, dir)
    83  	if err != nil {
    84  		return "", nil, err
    85  	}
    86  	k, err := dagnode.Key()
    87  	if err != nil {
    88  		return "", nil, err
    89  	}
    90  	return gopath.Join(k.String(), filename), dagnode, nil
    91  }
    92  
    93  func add(n *core.IpfsNode, reader io.Reader) (*merkledag.Node, error) {
    94  	mp := n.Pinning.GetManual()
    95  
    96  	return importer.BuildDagFromReader(
    97  		n.DAG,
    98  		chunk.DefaultSplitter(reader),
    99  		importer.PinIndirectCB(mp),
   100  	)
   101  }
   102  
   103  func addNode(n *core.IpfsNode, node *merkledag.Node) error {
   104  	if err := n.DAG.AddRecursive(node); err != nil { // add the file to the graph + local storage
   105  		return err
   106  	}
   107  	ctx, cancel := context.WithCancel(n.Context())
   108  	defer cancel()
   109  	err := n.Pinning.Pin(ctx, node, true) // ensure we keep it
   110  	return err
   111  }
   112  
   113  func addFile(n *core.IpfsNode, file files.File) (*merkledag.Node, error) {
   114  	if file.IsDirectory() {
   115  		return addDir(n, file)
   116  	}
   117  	return add(n, file)
   118  }
   119  
   120  func addDir(n *core.IpfsNode, dir files.File) (*merkledag.Node, error) {
   121  
   122  	tree := &merkledag.Node{Data: unixfs.FolderPBData()}
   123  
   124  Loop:
   125  	for {
   126  		file, err := dir.NextFile()
   127  		switch {
   128  		case err != nil && err != io.EOF:
   129  			return nil, err
   130  		case err == io.EOF:
   131  			break Loop
   132  		}
   133  
   134  		node, err := addFile(n, file)
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  
   139  		_, name := gopath.Split(file.FileName())
   140  
   141  		if err := tree.AddNodeLink(name, node); err != nil {
   142  			return nil, err
   143  		}
   144  	}
   145  
   146  	if err := addNode(n, tree); err != nil {
   147  		return nil, err
   148  	}
   149  	return tree, nil
   150  }