diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index d5d7479f2685..b584ad8cf595 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -41,6 +41,7 @@ the existing 'ipfs object' command moving forward. "import": DagImportCmd, "export": DagExportCmd, "stat": DagStatCmd, + "diff": DagDiffCmd, }, } @@ -322,3 +323,37 @@ Note: This command skips duplicate blocks in reporting both size and the number }), }, } + +type DagDiff struct { + s string +} + +// DagDiffCmd is a command for comparing DAG nodes. +// FIXME: Right now only supports DAG-PB encoding (for the roadmap of this +// command see https://github.com/ipfs/go-ipfs/issues/4801). +var DagDiffCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Diffs two DAG nodes.", + ShortDescription: ` +'ipfs dag diff' fetches two DAG nodes and returns their differences. +`, + }, + Arguments: []cmds.Argument{ + cmds.StringArg("node_before", true, false, "First node, \"before\", in the diff."), + cmds.StringArg("node_after", true, false, "First node, \"after\", in the diff."), + }, + Options: []cmds.Option{ // FIXME: Remove if unused. + }, + Run: dagDiff, + Type: DagDiff{}, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, d *DagDiff) error { + _, err := fmt.Fprintf( + w, + "%s\n", + d.s, + ) + return err + }), + }, +} diff --git a/core/commands/dag/diff.go b/core/commands/dag/diff.go new file mode 100644 index 000000000000..bf6ff6c455f7 --- /dev/null +++ b/core/commands/dag/diff.go @@ -0,0 +1,56 @@ +package dagcmd + +import ( + "encoding/json" + cmds "github.com/ipfs/go-ipfs-cmds" + "github.com/ipfs/go-ipfs/core/commands/cmdenv" + "io/ioutil" + + "github.com/wI2L/jsondiff" +) + +func dagDiff(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env, req) + if err != nil { + return err + } + + getArgNodeAsJson := func(argNumber int) ([]byte, error) { + r, err := getNodeWithCodec(req.Context, req.Arguments[argNumber], "dag-json", api) + if err != nil { + return nil, err + } + + jsonOutput, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + + return jsonOutput, nil + } + + nodeBefore, err := getArgNodeAsJson(0) + if err != nil { + return err + } + nodeAfter, err := getArgNodeAsJson(1) + if err != nil { + return err + } + + patch, err := jsondiff.CompareJSONOpts(nodeBefore, nodeAfter, jsondiff.Invertible()) + if err != nil { + return err + } + + indented, err := json.MarshalIndent(patch, "", " ") + if err != nil { + return err + } + + if err := res.Emit(DagDiff{string(indented)}); err != nil { + return err + } + + return nil +}