Skip to content

Commit

Permalink
feat(cmds): add dag diff
Browse files Browse the repository at this point in the history
  • Loading branch information
schomatis committed Apr 28, 2022
1 parent 4f7d4bc commit cdefb64
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 10 deletions.
35 changes: 35 additions & 0 deletions core/commands/dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ the existing 'ipfs object' command moving forward.
"import": DagImportCmd,
"export": DagExportCmd,
"stat": DagStatCmd,
"diff": DagDiffCmd,
},
}

Expand Down Expand Up @@ -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
}),
},
}
56 changes: 56 additions & 0 deletions core/commands/dag/diff.go
Original file line number Diff line number Diff line change
@@ -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
}
32 changes: 22 additions & 10 deletions core/commands/dag/get.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dagcmd

import (
"context"
"fmt"
coreiface "github.com/ipfs/interface-go-ipfs-core"
"io"

"github.com/ipfs/go-ipfs/core/commands/cmdenv"
Expand All @@ -23,24 +25,34 @@ func dagGet(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e
}

codecStr, _ := req.Options["output-codec"].(string)
var codec mc.Code
if err := codec.Set(codecStr); err != nil {

r, err := getNodeWithCodec(req.Context, codecStr, req.Arguments[0], api)
if err != nil {
return err
}

rp, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
return res.Emit(r)
}

func getNodeWithCodec(ctx context.Context, nodePath string, codecName string, api coreiface.CoreAPI) (io.Reader, error) {
var codec mc.Code
if err := codec.Set(codecName); err != nil {
return nil, err
}

rp, err := api.ResolvePath(ctx, path.New(nodePath))
if err != nil {
return err
return nil, err
}

obj, err := api.Dag().Get(req.Context, rp.Cid())
obj, err := api.Dag().Get(ctx, rp.Cid())
if err != nil {
return err
return nil, err
}

universal, ok := obj.(ipldlegacy.UniversalNode)
if !ok {
return fmt.Errorf("%T is not a valid IPLD node", obj)
return nil, fmt.Errorf("%T is not a valid IPLD node", obj)
}

finalNode := universal.(ipld.Node)
Expand All @@ -50,13 +62,13 @@ func dagGet(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e

finalNode, err = traversal.Get(finalNode, remainderPath)
if err != nil {
return err
return nil, err
}
}

encoder, err := multicodec.LookupEncoder(uint64(codec))
if err != nil {
return fmt.Errorf("invalid encoding: %s - %s", codec, err)
return nil, fmt.Errorf("invalid encoding: %s - %s", codec, err)
}

r, w := io.Pipe()
Expand All @@ -67,5 +79,5 @@ func dagGet(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e
}
}()

return res.Emit(r)
return r, nil
}

0 comments on commit cdefb64

Please sign in to comment.