coreapi: implement Object.Diff
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Feb 2, 2018 at 21:50 UTC
432ab62127c9d5773027e3e8cc4e4aa0170df511
3 files changed
+106
core/coreapi/interface/object.go
+37
@@ -31,6 +31,39 @@ type ObjectStat struct {
31
CumulativeSize int
32
}
33
34
+
35
+const (
36
+ // DiffAdd is a Type of ObjectChange where a link was added to the graph
37
+ DiffAdd = iota
38
+
39
+ // DiffRemove is a Type of ObjectChange where a link was removed from the graph
40
+ DiffRemove
41
+
42
+ // DiffMod is a Type of ObjectChange where a link was changed in the graph
43
+ DiffMod
44
+)
45
+
46
+// ObjectChange represents a change ia a graph
47
+// TODO: do we want this to be an interface?
48
+type ObjectChange struct {
49
+ // Type of the change, either:
50
+ // * DiffAdd - Added a link
51
+ // * DiffRemove - Removed a link
52
+ // * DiffMod - Modified a link
53
+ Type int
54
+
55
+ // Path to the changed link
56
+ Path string
57
+
58
+ // Before holds the link path before the change. Note that when a link is
59
+ // added, this will be nil.
60
+ Before Path
61
+
62
+ // After holds the link path after the change. Note that when a link is
63
+ // removed, this will be nil.
64
+ After Path
65
+}
66
+
67
// ObjectAPI specifies the interface to MerkleDAG and contains useful utilities
68
// for manipulating MerkleDAG data structures.
69
type ObjectAPI interface {
@@ -65,4 +98,8 @@ type ObjectAPI interface {
98
99
// SetData sets the data contained in the node
100
SetData(context.Context, Path, io.Reader) (ResolvedPath, error)
101
+
102
+ // Diff returns a set of changes needed to transform the first object into the
103
+ // second.
104
+ Diff(context.Context, Path, Path) ([]ObjectChange, error)
105
}
core/coreapi/object.go
+29
@@ -297,6 +297,35 @@ func (api *ObjectAPI) patchData(ctx context.Context, path coreiface.Path, r io.R
297
return coreiface.IpfsPath(pbnd.Cid()), nil
298
}
299
300
+func (api *ObjectAPI) Diff(ctx context.Context, before coreiface.Path, after coreiface.Path) ([]coreiface.ObjectChange, error) {
301
+ beforeNd, err := api.core().ResolveNode(ctx, before)
302
+ if err != nil {
303
+ return nil, err
304
+ }
305
+
306
+ afterNd, err := api.core().ResolveNode(ctx, after)
307
+ if err != nil {
308
+ return nil, err
309
+ }
310
+
311
+ changes, err := dagutils.Diff(ctx, api.node.DAG, beforeNd, afterNd)
312
+ if err != nil {
313
+ return nil, err
314
+ }
315
+
316
+ out := make([]coreiface.ObjectChange, len(changes))
317
+ for i, change := range changes {
318
+ out[i] = coreiface.ObjectChange{
319
+ Type: change.Type,
320
+ Path: change.Path,
321
+ Before: coreiface.IpfsPath(change.Before),
322
+ After: coreiface.IpfsPath(change.After),
323
+ }
324
+ }
325
+
326
+ return out, nil
327
+}
328
+
329
func (api *ObjectAPI) core() coreiface.CoreAPI {
330
return (*CoreAPI)(api)
331
}
core/coreapi/object_test.go
+40
@@ -8,6 +8,7 @@ import (
8
"strings"
9
"testing"
10
11
+ "github.com/ipfs/go-ipfs/core/coreapi/interface"
12
opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
13
)
14
@@ -385,3 +386,42 @@ func TestObjectSetData(t *testing.T) {
386
t.Error("unexpected data")
387
}
388
}
389
+
390
+func TestDiffTest(t *testing.T) {
391
+ ctx := context.Background()
392
+ _, api, err := makeAPI(ctx)
393
+ if err != nil {
394
+ t.Fatal(err)
395
+ }
396
+
397
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
398
+ if err != nil {
399
+ t.Fatal(err)
400
+ }
401
+
402
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bar"}`))
403
+ if err != nil {
404
+ t.Fatal(err)
405
+ }
406
+
407
+ changes, err := api.Object().Diff(ctx, p1, p2)
408
+ if err != nil {
409
+ t.Fatal(err)
410
+ }
411
+
412
+ if len(changes) != 1 {
413
+ t.Fatal("unexpected changes len")
414
+ }
415
+
416
+ if changes[0].Type != iface.DiffMod {
417
+ t.Fatal("unexpected change type")
418
+ }
419
+
420
+ if changes[0].Before.String() != p1.String() {
421
+ t.Fatal("unexpected before path")
422
+ }
423
+
424
+ if changes[0].After.String() != p2.String() {
425
+ t.Fatal("unexpected before path")
426
+ }
427
+}