diff --git a/core/commands/object/diff.go b/core/commands/object/diff.go index dd2a6e3ffe9d..a77b9c90400c 100644 --- a/core/commands/object/diff.go +++ b/core/commands/object/diff.go @@ -6,11 +6,17 @@ import ( "io" cmds "github.com/ipfs/go-ipfs/commands" - e "github.com/ipfs/go-ipfs/core/commands/e" + "github.com/ipfs/go-ipfs/core/commands/e" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/dagutils" - cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" +) + +const ( + objA = "obj_a" + objB = "obj_b" + verbose = "verbose" ) type Changes struct { @@ -45,11 +51,11 @@ Example: `, }, Arguments: []cmdkit.Argument{ - cmdkit.StringArg("obj_a", true, false, "Object to diff against."), - cmdkit.StringArg("obj_b", true, false, "Object to diff."), + cmdkit.StringArg(objA, true, false, "Object to diff against."), + cmdkit.StringArg(objB, true, false, "Object to diff."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption(verbose, "v", "Print extra information."), }, Run: func(req cmds.Request, res cmds.Response) { api, err := req.InvocContext().GetApi() diff --git a/dagutils/diff.go b/dagutils/diff.go index 9034db35c60d..b1c468154899 100644 --- a/dagutils/diff.go +++ b/dagutils/diff.go @@ -94,7 +94,11 @@ func ApplyChange(ctx context.Context, ds ipld.DAGService, nd *dag.ProtoNode, cs return e.Finalize(ctx, ds) } -// Diff returns a set of changes that transform node 'a' into node 'b' +// Diff returns a set of changes that transform node 'a' into node 'b'. +// It supports two nodes forms: ProtoNode and RawNode. Because we treats +// the nodes as IPLD nodes as long as possible and only convert them +// to ProtoNode when necessary: when we need to remove links, and at that point +// (if they have links to remove) we know they are not raw nodes. func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, error) { // Base case where both nodes are leaves, just compare // their CIDs. @@ -103,7 +107,7 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e return []*Change{}, nil } return []*Change{ - &Change{ + { Type: Mod, Before: a.Cid(), After: b.Cid(), diff --git a/test/sharness/t0052-object-diff.sh b/test/sharness/t0052-object-diff.sh index 949088c27f0b..eb6b0bf45254 100755 --- a/test/sharness/t0052-object-diff.sh +++ b/test/sharness/t0052-object-diff.sh @@ -15,82 +15,112 @@ test_expect_success "create some objects for testing diffs" ' echo "stuff" > foo/bar && mkdir foo/baz && A=$(ipfs add -r -q foo | tail -n1) && + AR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "more things" > foo/cat && B=$(ipfs add -r -q foo | tail -n1) && + BR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "nested" > foo/baz/dog && C=$(ipfs add -r -q foo | tail -n1) + CR=$(ipfs add --raw-leaves -r -q foo | tail -n1) echo "changed" > foo/bar && D=$(ipfs add -r -q foo | tail -n1) && + DR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "" > single_file && SINGLE_FILE=$(ipfs add -r -q single_file | tail -n1) && + SINGLE_FILE_RAW=$(ipfs add --raw-leaves -r -q single_file | tail -n1) && mkdir empty_dir EMPTY_DIR=$(ipfs add -r -q empty_dir | tail -n1) + EMPTY_DIR_RAW=$(ipfs add --raw-leaves -r -q empty_dir | tail -n1) ' test_expect_success "diff against self is empty" ' - ipfs object diff $A $A > diff_out + ipfs object diff $A $A > diff_out && + ipfs object diff $AR $AR > diff_raw_out ' test_expect_success "identity diff output looks good" ' printf "" > diff_exp && + printf "" > diff_raw_exp && test_cmp diff_exp diff_out + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff against self (single file) is empty" ' - ipfs object diff $SINGLE_FILE $SINGLE_FILE > diff_out + ipfs object diff $SINGLE_FILE $SINGLE_FILE > diff_out && + ipfs object diff $SINGLE_FILE_RAW $SINGLE_FILE_RAW > diff_raw_out printf "" > diff_exp && - test_cmp diff_exp diff_out + printf "" > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff against self (empty dir) is empty" ' ipfs object diff $EMPTY_DIR $EMPTY_DIR > diff_out + ipfs object diff $EMPTY_DIR_RAW $EMPTY_DIR_RAW > diff_raw_out printf "" > diff_exp && - test_cmp diff_exp diff_out + printf "" > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff added link works" ' ipfs object diff $A $B > diff_out + ipfs object diff $AR $BR > diff_raw_out ' test_expect_success "diff added link looks right" ' echo + QmUSvcqzhdfYM1KLDbM76eLPdS9ANFtkJvFuPYeZt73d7A \"cat\" > diff_exp && - test_cmp diff_exp diff_out + echo + zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4 \"cat\" > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "verbose diff added link works" ' ipfs object diff -v $A $B > diff_out + ipfs object diff -v $AR $BR > diff_raw_out ' test_expect_success "verbose diff added link looks right" ' echo Added new link \"cat\" pointing to QmUSvcqzhdfYM1KLDbM76eLPdS9ANFtkJvFuPYeZt73d7A. > diff_exp && - test_cmp diff_exp diff_out + echo Added new link \"cat\" pointing to zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4. > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff removed link works" ' - ipfs object diff -v $B $A > diff_out + ipfs object diff -v $B $A > diff_out && + ipfs object diff -v $BR $AR > diff_raw_out ' test_expect_success "diff removed link looks right" ' echo Removed link \"cat\" \(was QmUSvcqzhdfYM1KLDbM76eLPdS9ANFtkJvFuPYeZt73d7A\). > diff_exp && - test_cmp diff_exp diff_out + echo Removed link \"cat\" \(was zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4\). > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff nested add works" ' - ipfs object diff -v $B $C > diff_out + ipfs object diff -v $B $C > diff_out && + ipfs object diff -v $BR $CR > diff_raw_out ' test_expect_success "diff looks right" ' echo Added new link \"baz/dog\" pointing to QmdNJQUTZuDpsUcec7YDuCfRfvw1w4J13DCm7YcU4VMZdS. > diff_exp && - test_cmp diff_exp diff_out + echo Added new link \"baz/dog\" pointing to zb2rhaM8wjDfi8A22dEqk89raWtViq8pjxvKQu2eaKtWhYKgE. > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_expect_success "diff changed link works" ' - ipfs object diff -v $C $D > diff_out + ipfs object diff -v $C $D > diff_out && + ipfs object diff -v $CR $DR > diff_raw_out ' test_expect_success "diff looks right" ' echo Changed \"bar\" from QmNgd5cz2jNftnAHBhcRUGdtiaMzb5Rhjqd4etondHHST8 to QmRfFVsjSXkhFxrfWnLpMae2M4GBVsry6VAuYYcji5MiZb. > diff_exp && - test_cmp diff_exp diff_out + echo Changed \"bar\" from zb2rhdUECGnPgMJNgmghaMKdqqGdpTe9GmEJiPna488ThfLBz to zb2rhfEA1M13SPoeayrsPcKhCezgMQPjguGFLH56G8qQ2qpDn. > diff_raw_exp && + test_cmp diff_exp diff_out && + test_cmp diff_raw_exp diff_raw_out ' test_done