Skip to content

Commit

Permalink
coreapi: implement Object.Diff
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
  • Loading branch information
magik6k committed Jul 30, 2018
1 parent a59e957 commit 9315e67
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
37 changes: 37 additions & 0 deletions core/coreapi/interface/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,39 @@ type ObjectStat struct {
CumulativeSize int
}


const (
// DiffAdd is a Type of ObjectChange where a link was added to the graph
DiffAdd = iota

// DiffRemove is a Type of ObjectChange where a link was removed from the graph
DiffRemove

// DiffMod is a Type of ObjectChange where a link was changed in the graph
DiffMod
)

// ObjectChange represents a change ia a graph
// TODO: do we want this to be an interface?
type ObjectChange struct {
// Type of the change, either:
// * DiffAdd - Added a link
// * DiffRemove - Removed a link
// * DiffMod - Modified a link
Type int

// Path to the changed link
Path string

// Before holds the link path before the change. Note that when a link is
// added, this will be nil.
Before Path

// After holds the link path after the change. Note that when a link is
// removed, this will be nil.
After Path
}

// ObjectAPI specifies the interface to MerkleDAG and contains useful utilities
// for manipulating MerkleDAG data structures.
type ObjectAPI interface {
Expand Down Expand Up @@ -65,4 +98,8 @@ type ObjectAPI interface {

// SetData sets the data contained in the node
SetData(context.Context, Path, io.Reader) (ResolvedPath, error)

// Diff returns a set of changes needed to transform the first object into the
// second.
Diff(context.Context, Path, Path) ([]ObjectChange, error)
}
29 changes: 29 additions & 0 deletions core/coreapi/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,35 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R
return coreiface.IpfsPath(pbnd.Cid()), nil
}

func (api *ObjectAPI) Diff(ctx context.Context, before coreiface.Path, after coreiface.Path) ([]coreiface.ObjectChange, error) {
beforeNd, err := api.core().ResolveNode(ctx, before)
if err != nil {
return nil, err
}

afterNd, err := api.core().ResolveNode(ctx, after)
if err != nil {
return nil, err
}

changes, err := dagutils.Diff(ctx, api.node.DAG, beforeNd, afterNd)
if err != nil {
return nil, err
}

out := make([]coreiface.ObjectChange, len(changes))
for i, change := range changes {
out[i] = coreiface.ObjectChange{
Type: change.Type,
Path: change.Path,
Before: coreiface.IpfsPath(change.Before),
After: coreiface.IpfsPath(change.After),
}
}

return out, nil
}

func (api *ObjectAPI) core() coreiface.CoreAPI {
return (*CoreAPI)(api)
}
Expand Down
40 changes: 40 additions & 0 deletions core/coreapi/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"testing"

"github.com/ipfs/go-ipfs/core/coreapi/interface"
opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
)

Expand Down Expand Up @@ -385,3 +386,42 @@ func TestObjectSetData(t *testing.T) {
t.Error("unexpected data")
}
}

func TestDiffTest(t *testing.T) {
ctx := context.Background()
_, api, err := makeAPI(ctx)
if err != nil {
t.Fatal(err)
}

p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
if err != nil {
t.Fatal(err)
}

p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bar"}`))
if err != nil {
t.Fatal(err)
}

changes, err := api.Object().Diff(ctx, p1, p2)
if err != nil {
t.Fatal(err)
}

if len(changes) != 1 {
t.Fatal("unexpected changes len")
}

if changes[0].Type != iface.DiffMod {
t.Fatal("unexpected change type")
}

if changes[0].Before.String() != p1.String() {
t.Fatal("unexpected before path")
}

if changes[0].After.String() != p2.String() {
t.Fatal("unexpected before path")
}
}

0 comments on commit 9315e67

Please sign in to comment.