diff --git a/core/commands2/add.go b/core/commands2/add.go index 148bb03c9246942521a1509f7cb1118aab44c9f4..862f3962dc7e21f45d53d18a454affe599818d5f 100644 --- a/core/commands2/add.go +++ b/core/commands2/add.go @@ -4,6 +4,9 @@ import ( "errors" "fmt" "io" + "io/ioutil" + "os" + "path/filepath" cmds "github.com/jbenet/go-ipfs/commands" core "github.com/jbenet/go-ipfs/core" @@ -12,6 +15,7 @@ import ( "github.com/jbenet/go-ipfs/importer/chunk" dag "github.com/jbenet/go-ipfs/merkledag" pinning "github.com/jbenet/go-ipfs/pin" + ft "github.com/jbenet/go-ipfs/unixfs" ) // Error indicating the max depth has been exceded. @@ -26,7 +30,7 @@ var addCmd = &cmds.Command{ cmds.BoolOption("recursive", "r", "Must be specified when adding directories"), }, Arguments: []cmds.Argument{ - cmds.FileArg("file", true, true, "The path to a file to be added to IPFS"), + cmds.StringArg("file", true, true, "The path to a file to be added to IPFS"), }, Description: "Add an object to ipfs.", Help: `Adds contents of <path> to ipfs. Use -r to add directories. @@ -37,27 +41,115 @@ remains to be implemented. Run: func(req cmds.Request) (interface{}, error) { n := req.Context().Node - readers, err := internal.CastToReaders(req.Arguments()) - if err != nil { - return nil, err + // THIS IS A HORRIBLE HACK -- FIXME!!! + // see https://github.com/jbenet/go-ipfs/issues/309 + var added []*Object + + // returns the last one + addDagnodes := func(dns []*dag.Node) error { + for _, dn := range dns { + o, err := getOutput(dn) + if err != nil { + return err + } + + added = append(added, o) + } + return nil } - dagnodes, err := add(n, readers) - if err != nil { - return nil, err + addFile := func(name string) (*dag.Node, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + + dns, err := add(n, []io.Reader{f}) + if err != nil { + return nil, err + } + + if err := addDagnodes(dns); err != nil { + return nil, err + } + return dns[len(dns)-1], nil // last dag node is the file. } - // TODO: include fs paths in output (will need a way to specify paths in underlying filearg system) - added := make([]*Object, 0, len(req.Arguments())) - for _, dagnode := range dagnodes { - object, err := getOutput(dagnode) + var addPath func(name string) (*dag.Node, error) + addDir := func(name string) (*dag.Node, error) { + tree := &dag.Node{Data: ft.FolderPBData()} + + entries, err := ioutil.ReadDir(name) if err != nil { return nil, err } - added = append(added, object) + // construct nodes for containing files. + for _, e := range entries { + fp := filepath.Join(name, e.Name()) + nd, err := addPath(fp) + if err != nil { + return nil, err + } + + if err = tree.AddNodeLink(e.Name(), nd); err != nil { + return nil, err + } + } + + log.Infof("adding dir: %s", name) + + if err := addDagnodes([]*dag.Node{tree}); err != nil { + return nil, err + } + return tree, nil + } + + addPath = func(fpath string) (*dag.Node, error) { + fi, err := os.Stat(fpath) + if err != nil { + return nil, err + } + + if fi.IsDir() { + return addDir(fpath) + } + return addFile(fpath) } + paths, err := internal.CastToStrings(req.Arguments()) + if err != nil { + return nil, err + } + + for _, f := range paths { + if _, err := addPath(f); err != nil { + return nil, err + } + } + + // readers, err := internal.CastToReaders(req.Arguments()) + // if err != nil { + // return nil, err + // } + // + // dagnodes, err := add(n, readers) + // if err != nil { + // return nil, err + // } + // + // // TODO: include fs paths in output (will need a way to specify paths in underlying filearg system) + // added := make([]*Object, 0, len(req.Arguments())) + // for _, dagnode := range dagnodes { + // object, err := getOutput(dagnode) + // if err != nil { + // return nil, err + // } + // + // added = append(added, object) + // } + return &AddOutput{added}, nil }, Marshallers: map[cmds.EncodingType]cmds.Marshaller{