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 Feb 4, 2018
1 parent 5a9ac70 commit 1810cdc
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
36 changes: 36 additions & 0 deletions core/coreapi/interface/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,38 @@ type BlockStat interface {
Path() Path
}

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
}

// CoreAPI defines an unified interface to IPFS for Go programs.
type CoreAPI interface {
// Unixfs returns an implementation of Unixfs API.
Expand Down Expand Up @@ -313,6 +345,10 @@ type ObjectAPI interface {

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

// Diff returns a set of changes needed to transform the first object into the
// second.
Diff(context.Context, Path, Path) ([]ObjectChange, error)
}

// ObjectStat provides information about dag nodes
Expand Down
29 changes: 29 additions & 0 deletions core/coreapi/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,35 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R
return api.ParseCid(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: api.ParseCid(change.Before),
After: api.ParseCid(change.After),
}
}

return out, nil
}

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

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

func TestNew(t *testing.T) {
Expand Down Expand Up @@ -383,3 +385,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 1810cdc

Please sign in to comment.