From f4a74abf25f27ea6ffa0c14d10a2ba6bbc8da31f Mon Sep 17 00:00:00 2001 From: Jeromy Date: Sat, 2 May 2015 12:54:11 -0700 Subject: [PATCH] initial implementation of save --- core/commands/root.go | 1 + core/commands/save.go | 116 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 core/commands/save.go diff --git a/core/commands/root.go b/core/commands/root.go index 5b1ef364d48..59ef85359ef 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -95,6 +95,7 @@ var rootSubcommands = map[string]*cmds.Command{ "ping": PingCmd, "refs": RefsCmd, "repo": RepoCmd, + "save": SaveCmd, "stats": StatsCmd, "swarm": SwarmCmd, "update": UpdateCmd, diff --git a/core/commands/save.go b/core/commands/save.go new file mode 100644 index 00000000000..2c9e00d2cca --- /dev/null +++ b/core/commands/save.go @@ -0,0 +1,116 @@ +package commands + +import ( + "bytes" + "errors" + "fmt" + "io" + "strings" + + cmds "github.com/ipfs/go-ipfs/commands" + core "github.com/ipfs/go-ipfs/core" + nsfs "github.com/ipfs/go-ipfs/ipnsfs" + dag "github.com/ipfs/go-ipfs/merkledag" + path "github.com/ipfs/go-ipfs/path" +) + +var SaveCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Save a hash to a location within your ipns keyspace", + ShortDescription: ``, + }, + Arguments: []cmds.Argument{ + cmds.StringArg("object", true, false, "The object to save"), + cmds.StringArg("path", true, false, "The path within ipns/local to save the object"), + }, + Run: func(req cmds.Request, res cmds.Response) { + nd, err := req.Context().GetNode() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + p, err := path.ParsePath(req.Arguments()[0]) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + obj, err := core.Resolve(nd, p) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + err = saveNodeTo(nd, obj, req.Arguments()[1]) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + k, err := obj.Key() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(&SavedEntry{ + Entry: k.Pretty(), + Path: req.Arguments()[1], + }) + }, + Type: SavedEntry{}, + Marshalers: cmds.MarshalerMap{ + cmds.Text: func(res cmds.Response) (io.Reader, error) { + se, ok := res.Output().(*SavedEntry) + if !ok { + return nil, cmds.ErrIncorrectType + } + + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "save %s to %s\n", se.Entry, se.Path) + return buf, nil + }, + }, +} + +type SavedEntry struct { + Entry string + Path string +} + +func saveNodeTo(nd *core.IpfsNode, obj *dag.Node, target string) error { + root, err := nd.IpnsFs.GetRoot(nd.Identity.Pretty()) + if err != nil { + return err + } + + rdir, ok := root.GetValue().(*nsfs.Directory) + if !ok { + return errors.New("your ipns entry doesnt point to a directory") + } + + parts := strings.Split(target, "/") + + cur := rdir + for i := 0; i < len(parts)-1; i++ { + child, err := cur.Child(parts[i]) + if err != nil { + return err + } + + switch child := child.(type) { + case *nsfs.Directory: + cur = child + case *nsfs.File: + return fmt.Errorf("%s is a file", strings.Join(parts[:i+1], "/")) + } + } + + err = cur.AddChild(parts[len(parts)-1], obj) + if err != nil { + return err + } + + return nil +}