master
go 131 lines 3.5 KB
Raw
1 package objectcmd
2
3 import (
4 "fmt"
5 "io"
6
7 "github.com/ipfs/boxo/ipld/merkledag/dagutils"
8 "github.com/ipfs/boxo/path"
9 cmds "github.com/ipfs/go-ipfs-cmds"
10
11 cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
12 "github.com/ipfs/kubo/core/commands/cmdutils"
13 )
14
15 const (
16 verboseOptionName = "verbose"
17 )
18
19 type Changes struct {
20 Changes []*dagutils.Change
21 }
22
23 var ObjectDiffCmd = &cmds.Command{
24 Status: cmds.Deprecated, // https://github.com/ipfs/kubo/issues/7936
25 Helptext: cmds.HelpText{
26 Tagline: "Display the diff between two IPFS objects.",
27 ShortDescription: `
28 'ipfs object diff' is a command used to show the differences between
29 two IPFS objects.`,
30 LongDescription: `
31 'ipfs object diff' is a command used to show the differences between
32 two IPFS objects.
33
34 Example:
35
36 > ls foo
37 bar baz/ giraffe
38 > ipfs add -r foo
39 ...
40 Added QmegHcnrPgMwC7tBiMxChD54fgQMBUecNw9nE9UUU4x1bz foo
41 > OBJ_A=QmegHcnrPgMwC7tBiMxChD54fgQMBUecNw9nE9UUU4x1bz
42 > echo "different content" > foo/bar
43 > ipfs add -r foo
44 ...
45 Added QmcmRptkSPWhptCttgHg27QNDmnV33wAJyUkCnAvqD3eCD foo
46 > OBJ_B=QmcmRptkSPWhptCttgHg27QNDmnV33wAJyUkCnAvqD3eCD
47 > ipfs object diff -v $OBJ_A $OBJ_B
48 Changed "bar" from QmNgd5cz2jNftnAHBhcRUGdtiaMzb5Rhjqd4etondHHST8 to QmRfFVsjSXkhFxrfWnLpMae2M4GBVsry6VAuYYcji5MiZb.
49 `,
50 },
51 Arguments: []cmds.Argument{
52 cmds.StringArg("obj_a", true, false, "Object to diff against."),
53 cmds.StringArg("obj_b", true, false, "Object to diff."),
54 },
55 Options: []cmds.Option{
56 cmds.BoolOption(verboseOptionName, "v", "Print extra information."),
57 },
58 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
59 api, err := cmdenv.GetApi(env, req)
60 if err != nil {
61 return err
62 }
63
64 pa, err := cmdutils.PathOrCidPath(req.Arguments[0])
65 if err != nil {
66 return err
67 }
68
69 pb, err := cmdutils.PathOrCidPath(req.Arguments[1])
70 if err != nil {
71 return err
72 }
73
74 changes, err := api.Object().Diff(req.Context, pa, pb)
75 if err != nil {
76 return err
77 }
78
79 out := make([]*dagutils.Change, len(changes))
80 for i, change := range changes {
81 out[i] = &dagutils.Change{
82 Type: dagutils.ChangeType(change.Type),
83 Path: change.Path,
84 }
85
86 if (change.Before != path.ImmutablePath{}) {
87 out[i].Before = change.Before.RootCid()
88 }
89
90 if (change.After != path.ImmutablePath{}) {
91 out[i].After = change.After.RootCid()
92 }
93 }
94
95 return cmds.EmitOnce(res, &Changes{out})
96 },
97 Type: Changes{},
98 Encoders: cmds.EncoderMap{
99 cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Changes) error {
100 enc, err := cmdenv.GetCidEncoder(req)
101 if err != nil {
102 return err
103 }
104 verbose, _ := req.Options[verboseOptionName].(bool)
105
106 for _, change := range out.Changes {
107 if verbose {
108 switch change.Type {
109 case dagutils.Add:
110 fmt.Fprintf(w, "Added new link %q pointing to %s.\n", change.Path, enc.Encode(change.After))
111 case dagutils.Mod:
112 fmt.Fprintf(w, "Changed %q from %s to %s.\n", change.Path, enc.Encode(change.Before), enc.Encode(change.After))
113 case dagutils.Remove:
114 fmt.Fprintf(w, "Removed link %q (was %s).\n", change.Path, enc.Encode(change.Before))
115 }
116 } else {
117 switch change.Type {
118 case dagutils.Add:
119 fmt.Fprintf(w, "+ %s %q\n", enc.Encode(change.After), change.Path)
120 case dagutils.Mod:
121 fmt.Fprintf(w, "~ %s %s %q\n", enc.Encode(change.Before), enc.Encode(change.After), change.Path)
122 case dagutils.Remove:
123 fmt.Fprintf(w, "- %s %q\n", enc.Encode(change.Before), change.Path)
124 }
125 }
126 }
127
128 return nil
129 }),
130 },
131 }