Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-merkledag
Commits
e91a9c49
Commit
e91a9c49
authored
Feb 06, 2018
by
Hector Sanjuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Golint: fix golint warnings in merkledag submodule
License: MIT Signed-off-by:
Hector Sanjuan
<
hector@protocol.ai
>
parent
deacce76
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
111 additions
and
41 deletions
+111
-41
coding.go
coding.go
+1
-1
errservice.go
errservice.go
+6
-0
merkledag.go
merkledag.go
+20
-10
merkledag_test.go
merkledag_test.go
+9
-5
node.go
node.go
+26
-5
raw.go
raw.go
+8
-0
rwservice.go
rwservice.go
+6
-0
traverse/traverse.go
traverse/traverse.go
+14
-14
utils/diff.go
utils/diff.go
+16
-6
utils/utils.go
utils/utils.go
+5
-0
No files found.
coding.go
View file @
e91a9c49
...
...
@@ -102,7 +102,7 @@ func (n *ProtoNode) EncodeProtobuf(force bool) ([]byte, error) {
return
n
.
encoded
,
nil
}
// Decode
d
decodes raw data and returns a new Node instance.
// Decode
Protobuf
decodes raw data and returns a new Node instance.
func
DecodeProtobuf
(
encoded
[]
byte
)
(
*
ProtoNode
,
error
)
{
n
:=
new
(
ProtoNode
)
err
:=
n
.
unmarshal
(
encoded
)
...
...
errservice.go
View file @
e91a9c49
...
...
@@ -14,28 +14,34 @@ type ErrorService struct {
var
_
ipld
.
DAGService
=
(
*
ErrorService
)(
nil
)
// Add returns an error.
func
(
cs
*
ErrorService
)
Add
(
ctx
context
.
Context
,
nd
ipld
.
Node
)
error
{
return
cs
.
Err
}
// AddMany returns an error.
func
(
cs
*
ErrorService
)
AddMany
(
ctx
context
.
Context
,
nds
[]
ipld
.
Node
)
error
{
return
cs
.
Err
}
// Get returns an error.
func
(
cs
*
ErrorService
)
Get
(
ctx
context
.
Context
,
c
*
cid
.
Cid
)
(
ipld
.
Node
,
error
)
{
return
nil
,
cs
.
Err
}
// GetMany many returns an error.
func
(
cs
*
ErrorService
)
GetMany
(
ctx
context
.
Context
,
cids
[]
*
cid
.
Cid
)
<-
chan
*
ipld
.
NodeOption
{
ch
:=
make
(
chan
*
ipld
.
NodeOption
)
close
(
ch
)
return
ch
}
// Remove returns an error.
func
(
cs
*
ErrorService
)
Remove
(
ctx
context
.
Context
,
c
*
cid
.
Cid
)
error
{
return
cs
.
Err
}
// RemoveMany returns an error.
func
(
cs
*
ErrorService
)
RemoveMany
(
ctx
context
.
Context
,
cids
[]
*
cid
.
Cid
)
error
{
return
cs
.
Err
}
merkledag.go
View file @
e91a9c49
//
p
ackage merkledag implements the IPFS Merkle DAG datastructures.
//
P
ackage merkledag implements the IPFS Merkle DAG data
structures.
package
merkledag
import
(
...
...
@@ -23,8 +23,14 @@ func init() {
ipld
.
Register
(
cid
.
DagCBOR
,
ipldcbor
.
DecodeBlock
)
}
// contextKey is a type to use as value for the ProgressTracker contexts.
type
contextKey
string
const
progressContextKey
contextKey
=
"progress"
// NewDAGService constructs a new DAGService (using the default implementation).
func
NewDAGService
(
bs
bserv
.
BlockService
)
*
dagService
{
// Note that the default implementation is also an ipld.LinkGetter.
func
NewDAGService
(
bs
bserv
.
BlockService
)
ipld
.
DAGService
{
return
&
dagService
{
Blocks
:
bs
}
}
...
...
@@ -147,8 +153,8 @@ func (sg *sesGetter) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *ipld.
}
// Session returns a NodeGetter using a new session for block fetches.
func
(
ds
*
dagService
)
Session
(
ctx
context
.
Context
)
ipld
.
NodeGetter
{
return
&
sesGetter
{
bserv
.
NewSession
(
ctx
,
ds
.
Blocks
)}
func
(
n
*
dagService
)
Session
(
ctx
context
.
Context
)
ipld
.
NodeGetter
{
return
&
sesGetter
{
bserv
.
NewSession
(
ctx
,
n
.
Blocks
)}
}
// FetchGraph fetches all nodes that are children of the given node
...
...
@@ -159,7 +165,7 @@ func FetchGraph(ctx context.Context, root *cid.Cid, serv ipld.DAGService) error
ng
=
&
sesGetter
{
bserv
.
NewSession
(
ctx
,
ds
.
Blocks
)}
}
v
,
_
:=
ctx
.
Value
(
"
progress
"
)
.
(
*
ProgressTracker
)
v
,
_
:=
ctx
.
Value
(
progress
ContextKey
)
.
(
*
ProgressTracker
)
if
v
==
nil
{
return
EnumerateChildrenAsync
(
ctx
,
GetLinksDirect
(
ng
),
root
,
cid
.
NewSet
()
.
Visit
)
}
...
...
@@ -168,9 +174,8 @@ func FetchGraph(ctx context.Context, root *cid.Cid, serv ipld.DAGService) error
if
set
.
Visit
(
c
)
{
v
.
Increment
()
return
true
}
else
{
return
false
}
return
false
}
return
EnumerateChildrenAsync
(
ctx
,
GetLinksDirect
(
ng
),
root
,
visit
)
}
...
...
@@ -179,8 +184,8 @@ func FetchGraph(ctx context.Context, root *cid.Cid, serv ipld.DAGService) error
// returns the indexes of any links pointing to it
func
FindLinks
(
links
[]
*
cid
.
Cid
,
c
*
cid
.
Cid
,
start
int
)
[]
int
{
var
out
[]
int
for
i
,
lnk
_c
:=
range
links
[
start
:
]
{
if
c
.
Equals
(
lnk
_c
)
{
for
i
,
lnk
C
:=
range
links
[
start
:
]
{
if
c
.
Equals
(
lnk
C
)
{
out
=
append
(
out
,
i
+
start
)
}
}
...
...
@@ -265,21 +270,26 @@ func EnumerateChildren(ctx context.Context, getLinks GetLinks, root *cid.Cid, vi
return
nil
}
// ProgressTracker is used to show progress when fetching nodes.
type
ProgressTracker
struct
{
Total
int
lk
sync
.
Mutex
}
// DeriveContext returns a new context with value "progress" derived from
// the given one.
func
(
p
*
ProgressTracker
)
DeriveContext
(
ctx
context
.
Context
)
context
.
Context
{
return
context
.
WithValue
(
ctx
,
"
progress
"
,
p
)
return
context
.
WithValue
(
ctx
,
progress
ContextKey
,
p
)
}
// Increment adds one to the total progress.
func
(
p
*
ProgressTracker
)
Increment
()
{
p
.
lk
.
Lock
()
defer
p
.
lk
.
Unlock
()
p
.
Total
++
}
// Value returns the current progress.
func
(
p
*
ProgressTracker
)
Value
()
int
{
p
.
lk
.
Lock
()
defer
p
.
lk
.
Unlock
()
...
...
merkledag_test.go
View file @
e91a9c49
...
...
@@ -13,6 +13,8 @@ import (
"testing"
"time"
blocks
"gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
bserv
"github.com/ipfs/go-ipfs/blockservice"
bstest
"github.com/ipfs/go-ipfs/blockservice/test"
offline
"github.com/ipfs/go-ipfs/exchange/offline"
...
...
@@ -22,7 +24,6 @@ import (
mdpb
"github.com/ipfs/go-ipfs/merkledag/pb"
dstest
"github.com/ipfs/go-ipfs/merkledag/test"
uio
"github.com/ipfs/go-ipfs/unixfs/io"
blocks
"gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
u
"gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
cid
"gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
...
...
@@ -241,9 +242,10 @@ func TestFetchGraph(t *testing.T) {
// create an offline dagstore and ensure all blocks were fetched
bs
:=
bserv
.
New
(
bsis
[
1
]
.
Blockstore
(),
offline
.
Exchange
(
bsis
[
1
]
.
Blockstore
()))
offline_ds
:=
NewDAGService
(
bs
)
// we know the default dagService implements LinkGetter
offlineDS
:=
NewDAGService
(
bs
)
.
(
ipld
.
LinkGetter
)
err
=
EnumerateChildren
(
context
.
Background
(),
offline
_ds
.
GetLinks
,
root
.
Cid
(),
func
(
_
*
cid
.
Cid
)
bool
{
return
true
})
err
=
EnumerateChildren
(
context
.
Background
(),
offline
DS
.
GetLinks
,
root
.
Cid
(),
func
(
_
*
cid
.
Cid
)
bool
{
return
true
})
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -260,7 +262,9 @@ func TestEnumerateChildren(t *testing.T) {
}
set
:=
cid
.
NewSet
()
err
=
EnumerateChildren
(
context
.
Background
(),
ds
.
GetLinks
,
root
.
Cid
(),
set
.
Visit
)
lg
:=
ds
.
(
ipld
.
LinkGetter
)
err
=
EnumerateChildren
(
context
.
Background
(),
lg
.
GetLinks
,
root
.
Cid
(),
set
.
Visit
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -491,7 +495,7 @@ func TestCidRetention(t *testing.T) {
}
func
TestCidRawDoesnNeedData
(
t
*
testing
.
T
)
{
srv
:=
NewDAGService
(
dstest
.
Bserv
())
srv
:=
NewDAGService
(
dstest
.
Bserv
())
.
(
ipld
.
LinkGetter
)
nd
:=
NewRawNode
([]
byte
(
"somedata"
))
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Second
)
...
...
node.go
View file @
e91a9c49
...
...
@@ -10,10 +10,13 @@ import (
ipld
"gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
)
var
ErrNotProtobuf
=
fmt
.
Errorf
(
"expected protobuf dag node"
)
var
ErrLinkNotFound
=
fmt
.
Errorf
(
"no link by that name"
)
// Common errors
var
(
ErrNotProtobuf
=
fmt
.
Errorf
(
"expected protobuf dag node"
)
ErrLinkNotFound
=
fmt
.
Errorf
(
"no link by that name"
)
)
// Node represents a node in the IPFS Merkle DAG.
//
Proto
Node represents a node in the IPFS Merkle DAG.
// nodes have opaque data and a set of navigable links.
type
ProtoNode
struct
{
links
[]
*
ipld
.
Link
...
...
@@ -73,12 +76,14 @@ func (n *ProtoNode) SetPrefix(prefix *cid.Prefix) {
}
}
// LinkSlice is a slice of ipld.Links
type
LinkSlice
[]
*
ipld
.
Link
func
(
ls
LinkSlice
)
Len
()
int
{
return
len
(
ls
)
}
func
(
ls
LinkSlice
)
Swap
(
a
,
b
int
)
{
ls
[
a
],
ls
[
b
]
=
ls
[
b
],
ls
[
a
]
}
func
(
ls
LinkSlice
)
Less
(
a
,
b
int
)
bool
{
return
ls
[
a
]
.
Name
<
ls
[
b
]
.
Name
}
// NodeWithData builds a new Protonode with the given data.
func
NodeWithData
(
d
[]
byte
)
*
ProtoNode
{
return
&
ProtoNode
{
data
:
d
}
}
...
...
@@ -204,15 +209,18 @@ func (n *ProtoNode) Copy() ipld.Node {
return
nnode
}
// RawData returns the protobuf-encoded version of the node.
func
(
n
*
ProtoNode
)
RawData
()
[]
byte
{
out
,
_
:=
n
.
EncodeProtobuf
(
false
)
return
out
}
// Data returns the data stored by this node.
func
(
n
*
ProtoNode
)
Data
()
[]
byte
{
return
n
.
data
}
// SetData stores data in this nodes.
func
(
n
*
ProtoNode
)
SetData
(
d
[]
byte
)
{
n
.
encoded
=
nil
n
.
cached
=
nil
...
...
@@ -265,12 +273,14 @@ func (n *ProtoNode) Stat() (*ipld.NodeStat, error) {
},
nil
}
// Loggable implements the ipfs/go-log.Loggable interface.
func
(
n
*
ProtoNode
)
Loggable
()
map
[
string
]
interface
{}
{
return
map
[
string
]
interface
{}{
"node"
:
n
.
String
(),
}
}
// UnmarshalJSON reads the node fields from a JSON-encoded byte slice.
func
(
n
*
ProtoNode
)
UnmarshalJSON
(
b
[]
byte
)
error
{
s
:=
struct
{
Data
[]
byte
`json:"data"`
...
...
@@ -287,6 +297,7 @@ func (n *ProtoNode) UnmarshalJSON(b []byte) error {
return
nil
}
// MarshalJSON returns a JSON representation of the node.
func
(
n
*
ProtoNode
)
MarshalJSON
()
([]
byte
,
error
)
{
out
:=
map
[
string
]
interface
{}{
"data"
:
n
.
data
,
...
...
@@ -296,6 +307,8 @@ func (n *ProtoNode) MarshalJSON() ([]byte, error) {
return
json
.
Marshal
(
out
)
}
// Cid returns the node's Cid, calculated according to its prefix
// and raw data contents.
func
(
n
*
ProtoNode
)
Cid
()
*
cid
.
Cid
{
if
n
.
encoded
!=
nil
&&
n
.
cached
!=
nil
{
return
n
.
cached
...
...
@@ -316,6 +329,7 @@ func (n *ProtoNode) Cid() *cid.Cid {
return
c
}
// String prints the node's Cid.
func
(
n
*
ProtoNode
)
String
()
string
{
return
n
.
Cid
()
.
String
()
}
...
...
@@ -332,18 +346,24 @@ func (n *ProtoNode) Multihash() mh.Multihash {
return
n
.
cached
.
Hash
()
}
// Links returns the node links.
func
(
n
*
ProtoNode
)
Links
()
[]
*
ipld
.
Link
{
return
n
.
links
}
// SetLinks replaces the node links with the given ones.
func
(
n
*
ProtoNode
)
SetLinks
(
links
[]
*
ipld
.
Link
)
{
n
.
links
=
links
}
// Resolve is an alias for ResolveLink.
func
(
n
*
ProtoNode
)
Resolve
(
path
[]
string
)
(
interface
{},
[]
string
,
error
)
{
return
n
.
ResolveLink
(
path
)
}
// ResolveLink consumes the first element of the path and obtains the link
// corresponding to it from the node. It returns the link
// and the path without the consumed element.
func
(
n
*
ProtoNode
)
ResolveLink
(
path
[]
string
)
(
*
ipld
.
Link
,
[]
string
,
error
)
{
if
len
(
path
)
==
0
{
return
nil
,
nil
,
fmt
.
Errorf
(
"end of path, no more links to resolve"
)
...
...
@@ -357,9 +377,10 @@ func (n *ProtoNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
return
lnk
,
path
[
1
:
],
nil
}
// Tree returns the link names of the ProtoNode.
// ProtoNodes are only ever one path deep, so anything different than an empty
// string for p results in nothing. The depth parameter is ignored.
func
(
n
*
ProtoNode
)
Tree
(
p
string
,
depth
int
)
[]
string
{
// ProtoNodes are only ever one path deep, anything below that results in
// nothing
if
p
!=
""
{
return
nil
}
...
...
raw.go
View file @
e91a9c49
...
...
@@ -9,6 +9,7 @@ import (
ipld
"gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
)
// RawNode represents a node which only contains data.
type
RawNode
struct
{
blocks
.
Block
}
...
...
@@ -52,22 +53,27 @@ func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) {
return
&
RawNode
{
blk
},
nil
}
// Links returns nil.
func
(
rn
*
RawNode
)
Links
()
[]
*
ipld
.
Link
{
return
nil
}
// ResolveLink returns an error.
func
(
rn
*
RawNode
)
ResolveLink
(
path
[]
string
)
(
*
ipld
.
Link
,
[]
string
,
error
)
{
return
nil
,
nil
,
ErrLinkNotFound
}
// Resolve returns an error.
func
(
rn
*
RawNode
)
Resolve
(
path
[]
string
)
(
interface
{},
[]
string
,
error
)
{
return
nil
,
nil
,
ErrLinkNotFound
}
// Tree returns nil.
func
(
rn
*
RawNode
)
Tree
(
p
string
,
depth
int
)
[]
string
{
return
nil
}
// Copy performs a deep copy of this node and returns it as an ipld.Node
func
(
rn
*
RawNode
)
Copy
()
ipld
.
Node
{
copybuf
:=
make
([]
byte
,
len
(
rn
.
RawData
()))
copy
(
copybuf
,
rn
.
RawData
())
...
...
@@ -80,10 +86,12 @@ func (rn *RawNode) Copy() ipld.Node {
return
&
RawNode
{
nblk
}
}
// Size returns the size of this node
func
(
rn
*
RawNode
)
Size
()
(
uint64
,
error
)
{
return
uint64
(
len
(
rn
.
RawData
())),
nil
}
// Stat returns some Stats about this node.
func
(
rn
*
RawNode
)
Stat
()
(
*
ipld
.
NodeStat
,
error
)
{
return
&
ipld
.
NodeStat
{
CumulativeSize
:
len
(
rn
.
RawData
()),
...
...
rwservice.go
View file @
e91a9c49
...
...
@@ -16,26 +16,32 @@ type ComboService struct {
var
_
ipld
.
DAGService
=
(
*
ComboService
)(
nil
)
// Add writes a new node using the Write DAGService.
func
(
cs
*
ComboService
)
Add
(
ctx
context
.
Context
,
nd
ipld
.
Node
)
error
{
return
cs
.
Write
.
Add
(
ctx
,
nd
)
}
// AddMany adds nodes using the Write DAGService.
func
(
cs
*
ComboService
)
AddMany
(
ctx
context
.
Context
,
nds
[]
ipld
.
Node
)
error
{
return
cs
.
Write
.
AddMany
(
ctx
,
nds
)
}
// Get fetches a node using the Read DAGService.
func
(
cs
*
ComboService
)
Get
(
ctx
context
.
Context
,
c
*
cid
.
Cid
)
(
ipld
.
Node
,
error
)
{
return
cs
.
Read
.
Get
(
ctx
,
c
)
}
// GetMany fetches nodes using the Read DAGService.
func
(
cs
*
ComboService
)
GetMany
(
ctx
context
.
Context
,
cids
[]
*
cid
.
Cid
)
<-
chan
*
ipld
.
NodeOption
{
return
cs
.
Read
.
GetMany
(
ctx
,
cids
)
}
// Remove deletes a node using the Write DAGService.
func
(
cs
*
ComboService
)
Remove
(
ctx
context
.
Context
,
c
*
cid
.
Cid
)
error
{
return
cs
.
Write
.
Remove
(
ctx
,
c
)
}
// RemoveMany deletes nodes using the Write DAGService.
func
(
cs
*
ComboService
)
RemoveMany
(
ctx
context
.
Context
,
cids
[]
*
cid
.
Cid
)
error
{
return
cs
.
Write
.
RemoveMany
(
ctx
,
cids
)
}
traverse/traverse.go
View file @
e91a9c49
...
...
@@ -11,10 +11,14 @@ import (
// Order is an identifier for traversal algorithm orders
type
Order
int
// These constants define different traversing methods
const
(
DFSPre
Order
=
iota
// depth-first pre-order
DFSPost
// depth-first post-order
BFS
// breadth-first
// DFSPre defines depth-first pre-order
DFSPre
Order
=
iota
// DFSPost defines depth-first post-order
DFSPost
// BFS defines breadth-first order
BFS
)
// Options specifies a series of traversal options
...
...
@@ -86,9 +90,9 @@ func (t *traversal) getNode(link *ipld.Link) (ipld.Node, error) {
// If an error is returned, processing stops.
type
Func
func
(
current
State
)
error
//
If there is a
problem walking to the Node
, and ErrFunc is provided,
Traverse
// will call ErrFunc with the error encountered. ErrFunc can decide how to
handle
// that error, and return an error back to Traversal with how to proceed:
//
ErrFunc is provided to handle
problem
s when
walking to the Node
.
Traverse
// will call ErrFunc with the error encountered. ErrFunc can decide how to
//
handle
that error, and return an error back to Traversal with how to proceed:
// * nil - skip the Node and its children, but continue processing
// * all other errors halt processing immediately.
//
...
...
@@ -98,6 +102,8 @@ type Func func(current State) error
//
type
ErrFunc
func
(
err
error
)
error
// Traverse initiates a DAG traversal with the given options starting at
// the given root.
func
Traverse
(
root
ipld
.
Node
,
o
Options
)
error
{
t
:=
traversal
{
opts
:
o
,
...
...
@@ -127,20 +133,14 @@ func dfsPreTraverse(state State, t *traversal) error {
if
err
:=
t
.
callFunc
(
state
);
err
!=
nil
{
return
err
}
if
err
:=
dfsDescend
(
dfsPreTraverse
,
state
,
t
);
err
!=
nil
{
return
err
}
return
nil
return
dfsDescend
(
dfsPreTraverse
,
state
,
t
)
}
func
dfsPostTraverse
(
state
State
,
t
*
traversal
)
error
{
if
err
:=
dfsDescend
(
dfsPostTraverse
,
state
,
t
);
err
!=
nil
{
return
err
}
if
err
:=
t
.
callFunc
(
state
);
err
!=
nil
{
return
err
}
return
nil
return
t
.
callFunc
(
state
)
}
func
dfsDescend
(
df
dfsFunc
,
curr
State
,
t
*
traversal
)
error
{
...
...
utils/diff.go
View file @
e91a9c49
...
...
@@ -11,12 +11,15 @@ import (
ipld
"gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
)
// These constants define the changes that can be applied to a DAG.
const
(
Add
=
iota
Remove
Mod
)
// Change represents a change to a DAG and contains a reference to the old and
// new CIDs.
type
Change
struct
{
Type
int
Path
string
...
...
@@ -24,6 +27,7 @@ type Change struct {
After
*
cid
.
Cid
}
// String prints a human-friendly line about a change.
func
(
c
*
Change
)
String
()
string
{
switch
c
.
Type
{
case
Add
:
...
...
@@ -102,8 +106,8 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e
}
var
out
[]
*
Change
clean
_a
:=
a
.
Copy
()
.
(
*
dag
.
ProtoNode
)
clean
_b
:=
b
.
Copy
()
.
(
*
dag
.
ProtoNode
)
clean
A
:=
a
.
Copy
()
.
(
*
dag
.
ProtoNode
)
clean
B
:=
b
.
Copy
()
.
(
*
dag
.
ProtoNode
)
// strip out unchanged stuff
for
_
,
lnk
:=
range
a
.
Links
()
{
...
...
@@ -142,19 +146,19 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e
out
=
append
(
out
,
subc
)
}
}
clean
_a
.
RemoveNodeLink
(
l
.
Name
)
clean
_b
.
RemoveNodeLink
(
l
.
Name
)
clean
A
.
RemoveNodeLink
(
l
.
Name
)
clean
B
.
RemoveNodeLink
(
l
.
Name
)
}
}
for
_
,
lnk
:=
range
clean
_a
.
Links
()
{
for
_
,
lnk
:=
range
clean
A
.
Links
()
{
out
=
append
(
out
,
&
Change
{
Type
:
Remove
,
Path
:
lnk
.
Name
,
Before
:
lnk
.
Cid
,
})
}
for
_
,
lnk
:=
range
clean
_b
.
Links
()
{
for
_
,
lnk
:=
range
clean
B
.
Links
()
{
out
=
append
(
out
,
&
Change
{
Type
:
Add
,
Path
:
lnk
.
Name
,
...
...
@@ -165,11 +169,17 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e
return
out
,
nil
}
// Conflict represents two incompatible changes and is returned by MergeDiffs().
type
Conflict
struct
{
A
*
Change
B
*
Change
}
// MergeDiffs takes two slice of changes and adds them to a single slice.
// When a Change from b happens to the same path of an existing change in a,
// a conflict is created and b is not added to the merged slice.
// A slice of Conflicts is returned and contains pointers to the
// Changes involved (which share the same path).
func
MergeDiffs
(
a
,
b
[]
*
Change
)
([]
*
Change
,
[]
Conflict
)
{
var
out
[]
*
Change
var
conflicts
[]
Conflict
...
...
utils/utils.go
View file @
e91a9c49
...
...
@@ -15,6 +15,8 @@ import (
ipld
"gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
)
// Editor represents a ProtoNode tree editor and provides methods to
// modify it.
type
Editor
struct
{
root
*
dag
.
ProtoNode
...
...
@@ -83,6 +85,7 @@ func addLink(ctx context.Context, ds ipld.DAGService, root *dag.ProtoNode, child
return
root
,
nil
}
// InsertNodeAtPath inserts a new node in the tree and replaces the current root with the new one.
func
(
e
*
Editor
)
InsertNodeAtPath
(
ctx
context
.
Context
,
pth
string
,
toinsert
ipld
.
Node
,
create
func
()
*
dag
.
ProtoNode
)
error
{
splpath
:=
path
.
SplitList
(
pth
)
nd
,
err
:=
e
.
insertNodeAtPath
(
ctx
,
e
.
root
,
splpath
,
toinsert
,
create
)
...
...
@@ -137,6 +140,8 @@ func (e *Editor) insertNodeAtPath(ctx context.Context, root *dag.ProtoNode, path
return
root
,
nil
}
// RmLink removes the link with the given name and updates the root node of
// the editor.
func
(
e
*
Editor
)
RmLink
(
ctx
context
.
Context
,
pth
string
)
error
{
splpath
:=
path
.
SplitList
(
pth
)
nd
,
err
:=
e
.
rmLink
(
ctx
,
e
.
root
,
splpath
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment