mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-01 22:37:51 +08:00
feat(coreunix): AddR for recursive Adds
This commit is contained in:
parent
faded10870
commit
7f6bd2807d
@ -1,11 +1,18 @@
|
||||
package coreunix
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/jbenet/go-ipfs/commands/files"
|
||||
core "github.com/jbenet/go-ipfs/core"
|
||||
importer "github.com/jbenet/go-ipfs/importer"
|
||||
chunk "github.com/jbenet/go-ipfs/importer/chunk"
|
||||
merkledag "github.com/jbenet/go-ipfs/merkledag"
|
||||
"github.com/jbenet/go-ipfs/pin"
|
||||
unixfs "github.com/jbenet/go-ipfs/unixfs"
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
|
||||
@ -22,5 +29,107 @@ func Add(n *core.IpfsNode, r io.Reader) (u.Key, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// TODO(btc): is it necessary to flush the pinner?
|
||||
return dagNode.Key()
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
_, name := path.Split(file.FileName())
|
||||
|
||||
err = tree.AddNodeLink(name, node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err := addNode(n, tree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
37
core/coreunix/add_test.go
Normal file
37
core/coreunix/add_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
package coreunix
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||
"github.com/jbenet/go-ipfs/core"
|
||||
"github.com/jbenet/go-ipfs/repo"
|
||||
"github.com/jbenet/go-ipfs/repo/config"
|
||||
"github.com/jbenet/go-ipfs/util/testutil"
|
||||
)
|
||||
|
||||
func TestAddRecursive(t *testing.T) {
|
||||
here, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := &repo.Mock{
|
||||
C: config.Config{
|
||||
Identity: config.Identity{
|
||||
PeerID: "Qmfoo", // required by offline node
|
||||
},
|
||||
},
|
||||
D: testutil.ThreadSafeCloserMapDatastore(),
|
||||
}
|
||||
node, err := core.NewIPFSNode(context.Background(), core.Offline(r))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if k, err := AddR(node, path.Join(here, "test_data")); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if k != "QmWCCga8AbTyfAQ7pTnGT6JgmRMAB3Qp8ZmTEFi5q5o8jC" {
|
||||
t.Fatal("keys do not match")
|
||||
}
|
||||
}
|
||||
BIN
core/coreunix/test_data/colors/orange
Normal file
BIN
core/coreunix/test_data/colors/orange
Normal file
Binary file not shown.
BIN
core/coreunix/test_data/corps/apple
Normal file
BIN
core/coreunix/test_data/corps/apple
Normal file
Binary file not shown.
BIN
core/coreunix/test_data/fruits/apple
Normal file
BIN
core/coreunix/test_data/fruits/apple
Normal file
Binary file not shown.
BIN
core/coreunix/test_data/fruits/orange
Normal file
BIN
core/coreunix/test_data/fruits/orange
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user