mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-25 23:21:54 +08:00
coreapi: implement Object.Diff
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
This commit is contained in:
@ -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 {
|
||||
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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"
|
||||
)
|
||||
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user