From bf7da8522cf05df21c77a6b3d2c5e0c5ad560069 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Thu, 14 Apr 2016 13:06:51 -0700 Subject: [PATCH 1/4] basic implementation of object diff License: MIT Signed-off-by: Jeromy --- core/commands/object/diff.go | 85 ++++++++++++++++++++++++++++++ core/commands/object/object.go | 16 +++--- merkledag/utils/diff.go | 35 +++++++++--- test/sharness/t0052-object-diff.sh | 71 +++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 15 deletions(-) create mode 100644 core/commands/object/diff.go create mode 100755 test/sharness/t0052-object-diff.sh diff --git a/core/commands/object/diff.go b/core/commands/object/diff.go new file mode 100644 index 000000000..72626ad8d --- /dev/null +++ b/core/commands/object/diff.go @@ -0,0 +1,85 @@ +package objectcmd + +import ( + "bytes" + "fmt" + "io" + + cmds "github.com/ipfs/go-ipfs/commands" + dagutils "github.com/ipfs/go-ipfs/merkledag/utils" + path "github.com/ipfs/go-ipfs/path" +) + +var ObjectDiffCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "takes a diff of the two given objects", + ShortDescription: ` +`, + }, + Arguments: []cmds.Argument{ + cmds.StringArg("obj_a", true, false, "object to diff against"), + cmds.StringArg("obj_b", true, false, "object to diff"), + }, + Run: func(req cmds.Request, res cmds.Response) { + node, err := req.InvocContext().GetNode() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + a := req.Arguments()[0] + b := req.Arguments()[1] + + pa, err := path.ParsePath(a) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + pb, err := path.ParsePath(b) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + ctx := req.Context() + + obj_a, err := node.Resolver.ResolvePath(ctx, pa) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + obj_b, err := node.Resolver.ResolvePath(ctx, pb) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + changes, err := dagutils.Diff(ctx, node.DAG, obj_a, obj_b) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(changes) + }, + Type: []*dagutils.Change{}, + Marshalers: cmds.MarshalerMap{ + cmds.Text: func(res cmds.Response) (io.Reader, error) { + changes := res.Output().([]*dagutils.Change) + buf := new(bytes.Buffer) + for _, change := range changes { + switch change.Type { + case dagutils.Add: + fmt.Fprintf(buf, "added new link %q pointing to %s\n", change.Path, change.After) + case dagutils.Mod: + fmt.Fprintf(buf, "changed %q from %s to %s\n", change.Path, change.Before, change.After) + case dagutils.Remove: + fmt.Fprintf(buf, "removed link %q (was %s)\n", change.Path, change.Before) + } + } + return buf, nil + }, + }, +} diff --git a/core/commands/object/object.go b/core/commands/object/object.go index 68869119d..f39b35d09 100644 --- a/core/commands/object/object.go +++ b/core/commands/object/object.go @@ -48,13 +48,14 @@ var ObjectCmd = &cmds.Command{ 'ipfs object' is a plumbing command used to manipulate DAG objects directly.`, Synopsis: ` -ipfs object data - Outputs raw bytes in an object -ipfs object get - Get the DAG node named by -ipfs object links - Outputs links pointed to by object -ipfs object new