github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/core/commands/add.go (about)

     1  package commands
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/jbenet/go-ipfs/core"
    12  	"github.com/jbenet/go-ipfs/importer"
    13  	dag "github.com/jbenet/go-ipfs/merkledag"
    14  	"github.com/jbenet/go-ipfs/pin"
    15  	ft "github.com/jbenet/go-ipfs/unixfs"
    16  )
    17  
    18  // Error indicating the max depth has been exceded.
    19  var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
    20  
    21  // Add is a command that imports files and directories -- given as arguments -- into ipfs.
    22  func Add(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
    23  	depth := 1
    24  
    25  	// if recursive, set depth to reflect so
    26  	if r, ok := opts["r"].(bool); r && ok {
    27  		depth = -1
    28  	}
    29  
    30  	// add every path in args
    31  	for _, path := range args {
    32  
    33  		// Add the file
    34  		_, err := AddPath(n, path, depth, out)
    35  		if err != nil {
    36  			if err == ErrDepthLimitExceeded && depth == 1 {
    37  				err = errors.New("use -r to recursively add directories")
    38  			}
    39  			return fmt.Errorf("addFile error: %v", err)
    40  		}
    41  
    42  	}
    43  	return nil
    44  }
    45  
    46  // AddPath adds a particular path to ipfs.
    47  func AddPath(n *core.IpfsNode, fpath string, depth int, out io.Writer) (*dag.Node, error) {
    48  	if depth == 0 {
    49  		return nil, ErrDepthLimitExceeded
    50  	}
    51  
    52  	fi, err := os.Stat(fpath)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	if fi.IsDir() {
    58  		return addDir(n, fpath, depth, out)
    59  	}
    60  
    61  	return addFile(n, fpath, depth, out)
    62  }
    63  
    64  func addDir(n *core.IpfsNode, fpath string, depth int, out io.Writer) (*dag.Node, error) {
    65  	tree := &dag.Node{Data: ft.FolderPBData()}
    66  
    67  	files, err := ioutil.ReadDir(fpath)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	// construct nodes for containing files.
    73  	for _, f := range files {
    74  		fp := filepath.Join(fpath, f.Name())
    75  		nd, err := AddPath(n, fp, depth-1, out)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  
    80  		if err = tree.AddNodeLink(f.Name(), nd); err != nil {
    81  			return nil, err
    82  		}
    83  	}
    84  
    85  	log.Infof("adding dir: %s", fpath)
    86  
    87  	return tree, addNode(n, tree, fpath, out)
    88  }
    89  
    90  func addFile(n *core.IpfsNode, fpath string, depth int, out io.Writer) (*dag.Node, error) {
    91  	mp, ok := n.Pinning.(pin.ManualPinner)
    92  	if !ok {
    93  		return nil, errors.New("invalid pinner type! expected manual pinner")
    94  	}
    95  
    96  	root, err := importer.BuildDagFromFile(fpath, n.DAG, mp)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  
   101  	log.Infof("adding file: %s", fpath)
   102  
   103  	for _, l := range root.Links {
   104  		log.Infof("adding subblock: '%s' %s", l.Name, l.Hash.B58String())
   105  	}
   106  
   107  	k, err := root.Key()
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	// output that we've added this node
   113  	fmt.Fprintf(out, "added %s %s\n", k, fpath)
   114  
   115  	return root, nil
   116  }
   117  
   118  // addNode adds the node to the graph + local storage
   119  func addNode(n *core.IpfsNode, nd *dag.Node, fpath string, out io.Writer) error {
   120  	// add the file to the graph + local storage
   121  	err := n.DAG.AddRecursive(nd)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	k, err := nd.Key()
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	// output that we've added this node
   132  	fmt.Fprintf(out, "added %s %s\n", k, fpath)
   133  
   134  	// ensure we keep it
   135  	return n.Pinning.Pin(nd, true)
   136  }