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 }