mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-28 17:03:58 +08:00
Merge pull request #4665 from ipfs/doc/golint-merkledag
Golint: fix golint warnings in merkledag submodule
This commit is contained in:
@ -102,7 +102,7 @@ func (n *ProtoNode) EncodeProtobuf(force bool) ([]byte, error) {
|
|||||||
return n.encoded, nil
|
return n.encoded, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decoded decodes raw data and returns a new Node instance.
|
// DecodeProtobuf decodes raw data and returns a new Node instance.
|
||||||
func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
|
func DecodeProtobuf(encoded []byte) (*ProtoNode, error) {
|
||||||
n := new(ProtoNode)
|
n := new(ProtoNode)
|
||||||
err := n.unmarshal(encoded)
|
err := n.unmarshal(encoded)
|
||||||
|
@ -14,28 +14,34 @@ type ErrorService struct {
|
|||||||
|
|
||||||
var _ ipld.DAGService = (*ErrorService)(nil)
|
var _ ipld.DAGService = (*ErrorService)(nil)
|
||||||
|
|
||||||
|
// Add returns the cs.Err.
|
||||||
func (cs *ErrorService) Add(ctx context.Context, nd ipld.Node) error {
|
func (cs *ErrorService) Add(ctx context.Context, nd ipld.Node) error {
|
||||||
return cs.Err
|
return cs.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMany returns the cs.Err.
|
||||||
func (cs *ErrorService) AddMany(ctx context.Context, nds []ipld.Node) error {
|
func (cs *ErrorService) AddMany(ctx context.Context, nds []ipld.Node) error {
|
||||||
return cs.Err
|
return cs.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns the cs.Err.
|
||||||
func (cs *ErrorService) Get(ctx context.Context, c *cid.Cid) (ipld.Node, error) {
|
func (cs *ErrorService) Get(ctx context.Context, c *cid.Cid) (ipld.Node, error) {
|
||||||
return nil, cs.Err
|
return nil, cs.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMany many returns the cs.Err.
|
||||||
func (cs *ErrorService) GetMany(ctx context.Context, cids []*cid.Cid) <-chan *ipld.NodeOption {
|
func (cs *ErrorService) GetMany(ctx context.Context, cids []*cid.Cid) <-chan *ipld.NodeOption {
|
||||||
ch := make(chan *ipld.NodeOption)
|
ch := make(chan *ipld.NodeOption)
|
||||||
close(ch)
|
close(ch)
|
||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove returns the cs.Err.
|
||||||
func (cs *ErrorService) Remove(ctx context.Context, c *cid.Cid) error {
|
func (cs *ErrorService) Remove(ctx context.Context, c *cid.Cid) error {
|
||||||
return cs.Err
|
return cs.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveMany returns the cs.Err.
|
||||||
func (cs *ErrorService) RemoveMany(ctx context.Context, cids []*cid.Cid) error {
|
func (cs *ErrorService) RemoveMany(ctx context.Context, cids []*cid.Cid) error {
|
||||||
return cs.Err
|
return cs.Err
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// package merkledag implements the IPFS Merkle DAG datastructures.
|
// Package merkledag implements the IPFS Merkle DAG data structures.
|
||||||
package merkledag
|
package merkledag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -23,7 +23,13 @@ func init() {
|
|||||||
ipld.Register(cid.DagCBOR, ipldcbor.DecodeBlock)
|
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).
|
// NewDAGService constructs a new DAGService (using the default implementation).
|
||||||
|
// Note that the default implementation is also an ipld.LinkGetter.
|
||||||
func NewDAGService(bs bserv.BlockService) *dagService {
|
func NewDAGService(bs bserv.BlockService) *dagService {
|
||||||
return &dagService{Blocks: bs}
|
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.
|
// Session returns a NodeGetter using a new session for block fetches.
|
||||||
func (ds *dagService) Session(ctx context.Context) ipld.NodeGetter {
|
func (n *dagService) Session(ctx context.Context) ipld.NodeGetter {
|
||||||
return &sesGetter{bserv.NewSession(ctx, ds.Blocks)}
|
return &sesGetter{bserv.NewSession(ctx, n.Blocks)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchGraph fetches all nodes that are children of the given node
|
// 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)}
|
ng = &sesGetter{bserv.NewSession(ctx, ds.Blocks)}
|
||||||
}
|
}
|
||||||
|
|
||||||
v, _ := ctx.Value("progress").(*ProgressTracker)
|
v, _ := ctx.Value(progressContextKey).(*ProgressTracker)
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return EnumerateChildrenAsync(ctx, GetLinksDirect(ng), root, cid.NewSet().Visit)
|
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) {
|
if set.Visit(c) {
|
||||||
v.Increment()
|
v.Increment()
|
||||||
return true
|
return true
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return EnumerateChildrenAsync(ctx, GetLinksDirect(ng), root, visit)
|
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
|
// returns the indexes of any links pointing to it
|
||||||
func FindLinks(links []*cid.Cid, c *cid.Cid, start int) []int {
|
func FindLinks(links []*cid.Cid, c *cid.Cid, start int) []int {
|
||||||
var out []int
|
var out []int
|
||||||
for i, lnk_c := range links[start:] {
|
for i, lnkC := range links[start:] {
|
||||||
if c.Equals(lnk_c) {
|
if c.Equals(lnkC) {
|
||||||
out = append(out, i+start)
|
out = append(out, i+start)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,21 +270,26 @@ func EnumerateChildren(ctx context.Context, getLinks GetLinks, root *cid.Cid, vi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProgressTracker is used to show progress when fetching nodes.
|
||||||
type ProgressTracker struct {
|
type ProgressTracker struct {
|
||||||
Total int
|
Total int
|
||||||
lk sync.Mutex
|
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 {
|
func (p *ProgressTracker) DeriveContext(ctx context.Context) context.Context {
|
||||||
return context.WithValue(ctx, "progress", p)
|
return context.WithValue(ctx, progressContextKey, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment adds one to the total progress.
|
||||||
func (p *ProgressTracker) Increment() {
|
func (p *ProgressTracker) Increment() {
|
||||||
p.lk.Lock()
|
p.lk.Lock()
|
||||||
defer p.lk.Unlock()
|
defer p.lk.Unlock()
|
||||||
p.Total++
|
p.Total++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value returns the current progress.
|
||||||
func (p *ProgressTracker) Value() int {
|
func (p *ProgressTracker) Value() int {
|
||||||
p.lk.Lock()
|
p.lk.Lock()
|
||||||
defer p.lk.Unlock()
|
defer p.lk.Unlock()
|
||||||
|
@ -22,11 +22,11 @@ import (
|
|||||||
mdpb "github.com/ipfs/go-ipfs/merkledag/pb"
|
mdpb "github.com/ipfs/go-ipfs/merkledag/pb"
|
||||||
dstest "github.com/ipfs/go-ipfs/merkledag/test"
|
dstest "github.com/ipfs/go-ipfs/merkledag/test"
|
||||||
uio "github.com/ipfs/go-ipfs/unixfs/io"
|
uio "github.com/ipfs/go-ipfs/unixfs/io"
|
||||||
blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
|
|
||||||
|
|
||||||
u "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
|
u "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
|
||||||
cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
|
cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
|
||||||
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
||||||
|
blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNode(t *testing.T) {
|
func TestNode(t *testing.T) {
|
||||||
@ -241,9 +241,9 @@ func TestFetchGraph(t *testing.T) {
|
|||||||
// create an offline dagstore and ensure all blocks were fetched
|
// create an offline dagstore and ensure all blocks were fetched
|
||||||
bs := bserv.New(bsis[1].Blockstore(), offline.Exchange(bsis[1].Blockstore()))
|
bs := bserv.New(bsis[1].Blockstore(), offline.Exchange(bsis[1].Blockstore()))
|
||||||
|
|
||||||
offline_ds := NewDAGService(bs)
|
offlineDS := NewDAGService(bs)
|
||||||
|
|
||||||
err = EnumerateChildren(context.Background(), offline_ds.GetLinks, root.Cid(), func(_ *cid.Cid) bool { return true })
|
err = EnumerateChildren(context.Background(), offlineDS.GetLinks, root.Cid(), func(_ *cid.Cid) bool { return true })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -260,6 +260,7 @@ func TestEnumerateChildren(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set := cid.NewSet()
|
set := cid.NewSet()
|
||||||
|
|
||||||
err = EnumerateChildren(context.Background(), ds.GetLinks, root.Cid(), set.Visit)
|
err = EnumerateChildren(context.Background(), ds.GetLinks, root.Cid(), set.Visit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -10,10 +10,13 @@ import (
|
|||||||
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotProtobuf = fmt.Errorf("expected protobuf dag node")
|
// Common errors
|
||||||
var ErrLinkNotFound = fmt.Errorf("no link by that name")
|
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.
|
// ProtoNode represents a node in the IPFS Merkle DAG.
|
||||||
// nodes have opaque data and a set of navigable links.
|
// nodes have opaque data and a set of navigable links.
|
||||||
type ProtoNode struct {
|
type ProtoNode struct {
|
||||||
links []*ipld.Link
|
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
|
type LinkSlice []*ipld.Link
|
||||||
|
|
||||||
func (ls LinkSlice) Len() int { return len(ls) }
|
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) 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 }
|
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 {
|
func NodeWithData(d []byte) *ProtoNode {
|
||||||
return &ProtoNode{data: d}
|
return &ProtoNode{data: d}
|
||||||
}
|
}
|
||||||
@ -204,15 +209,18 @@ func (n *ProtoNode) Copy() ipld.Node {
|
|||||||
return nnode
|
return nnode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RawData returns the protobuf-encoded version of the node.
|
||||||
func (n *ProtoNode) RawData() []byte {
|
func (n *ProtoNode) RawData() []byte {
|
||||||
out, _ := n.EncodeProtobuf(false)
|
out, _ := n.EncodeProtobuf(false)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data returns the data stored by this node.
|
||||||
func (n *ProtoNode) Data() []byte {
|
func (n *ProtoNode) Data() []byte {
|
||||||
return n.data
|
return n.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetData stores data in this nodes.
|
||||||
func (n *ProtoNode) SetData(d []byte) {
|
func (n *ProtoNode) SetData(d []byte) {
|
||||||
n.encoded = nil
|
n.encoded = nil
|
||||||
n.cached = nil
|
n.cached = nil
|
||||||
@ -265,12 +273,14 @@ func (n *ProtoNode) Stat() (*ipld.NodeStat, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Loggable implements the ipfs/go-log.Loggable interface.
|
||||||
func (n *ProtoNode) Loggable() map[string]interface{} {
|
func (n *ProtoNode) Loggable() map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"node": n.String(),
|
"node": n.String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON reads the node fields from a JSON-encoded byte slice.
|
||||||
func (n *ProtoNode) UnmarshalJSON(b []byte) error {
|
func (n *ProtoNode) UnmarshalJSON(b []byte) error {
|
||||||
s := struct {
|
s := struct {
|
||||||
Data []byte `json:"data"`
|
Data []byte `json:"data"`
|
||||||
@ -287,6 +297,7 @@ func (n *ProtoNode) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns a JSON representation of the node.
|
||||||
func (n *ProtoNode) MarshalJSON() ([]byte, error) {
|
func (n *ProtoNode) MarshalJSON() ([]byte, error) {
|
||||||
out := map[string]interface{}{
|
out := map[string]interface{}{
|
||||||
"data": n.data,
|
"data": n.data,
|
||||||
@ -296,6 +307,8 @@ func (n *ProtoNode) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(out)
|
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 {
|
func (n *ProtoNode) Cid() *cid.Cid {
|
||||||
if n.encoded != nil && n.cached != nil {
|
if n.encoded != nil && n.cached != nil {
|
||||||
return n.cached
|
return n.cached
|
||||||
@ -316,6 +329,7 @@ func (n *ProtoNode) Cid() *cid.Cid {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String prints the node's Cid.
|
||||||
func (n *ProtoNode) String() string {
|
func (n *ProtoNode) String() string {
|
||||||
return n.Cid().String()
|
return n.Cid().String()
|
||||||
}
|
}
|
||||||
@ -332,18 +346,24 @@ func (n *ProtoNode) Multihash() mh.Multihash {
|
|||||||
return n.cached.Hash()
|
return n.cached.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Links returns the node links.
|
||||||
func (n *ProtoNode) Links() []*ipld.Link {
|
func (n *ProtoNode) Links() []*ipld.Link {
|
||||||
return n.links
|
return n.links
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLinks replaces the node links with the given ones.
|
||||||
func (n *ProtoNode) SetLinks(links []*ipld.Link) {
|
func (n *ProtoNode) SetLinks(links []*ipld.Link) {
|
||||||
n.links = links
|
n.links = links
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve is an alias for ResolveLink.
|
||||||
func (n *ProtoNode) Resolve(path []string) (interface{}, []string, error) {
|
func (n *ProtoNode) Resolve(path []string) (interface{}, []string, error) {
|
||||||
return n.ResolveLink(path)
|
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) {
|
func (n *ProtoNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return nil, nil, fmt.Errorf("end of path, no more links to resolve")
|
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
|
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 {
|
func (n *ProtoNode) Tree(p string, depth int) []string {
|
||||||
// ProtoNodes are only ever one path deep, anything below that results in
|
|
||||||
// nothing
|
|
||||||
if p != "" {
|
if p != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RawNode represents a node which only contains data.
|
||||||
type RawNode struct {
|
type RawNode struct {
|
||||||
blocks.Block
|
blocks.Block
|
||||||
}
|
}
|
||||||
@ -52,22 +53,27 @@ func NewRawNodeWPrefix(data []byte, prefix cid.Prefix) (*RawNode, error) {
|
|||||||
return &RawNode{blk}, nil
|
return &RawNode{blk}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Links returns nil.
|
||||||
func (rn *RawNode) Links() []*ipld.Link {
|
func (rn *RawNode) Links() []*ipld.Link {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveLink returns an error.
|
||||||
func (rn *RawNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
|
func (rn *RawNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
|
||||||
return nil, nil, ErrLinkNotFound
|
return nil, nil, ErrLinkNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve returns an error.
|
||||||
func (rn *RawNode) Resolve(path []string) (interface{}, []string, error) {
|
func (rn *RawNode) Resolve(path []string) (interface{}, []string, error) {
|
||||||
return nil, nil, ErrLinkNotFound
|
return nil, nil, ErrLinkNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tree returns nil.
|
||||||
func (rn *RawNode) Tree(p string, depth int) []string {
|
func (rn *RawNode) Tree(p string, depth int) []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy performs a deep copy of this node and returns it as an ipld.Node
|
||||||
func (rn *RawNode) Copy() ipld.Node {
|
func (rn *RawNode) Copy() ipld.Node {
|
||||||
copybuf := make([]byte, len(rn.RawData()))
|
copybuf := make([]byte, len(rn.RawData()))
|
||||||
copy(copybuf, rn.RawData())
|
copy(copybuf, rn.RawData())
|
||||||
@ -80,10 +86,12 @@ func (rn *RawNode) Copy() ipld.Node {
|
|||||||
return &RawNode{nblk}
|
return &RawNode{nblk}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the size of this node
|
||||||
func (rn *RawNode) Size() (uint64, error) {
|
func (rn *RawNode) Size() (uint64, error) {
|
||||||
return uint64(len(rn.RawData())), nil
|
return uint64(len(rn.RawData())), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stat returns some Stats about this node.
|
||||||
func (rn *RawNode) Stat() (*ipld.NodeStat, error) {
|
func (rn *RawNode) Stat() (*ipld.NodeStat, error) {
|
||||||
return &ipld.NodeStat{
|
return &ipld.NodeStat{
|
||||||
CumulativeSize: len(rn.RawData()),
|
CumulativeSize: len(rn.RawData()),
|
||||||
|
@ -16,26 +16,32 @@ type ComboService struct {
|
|||||||
|
|
||||||
var _ ipld.DAGService = (*ComboService)(nil)
|
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 {
|
func (cs *ComboService) Add(ctx context.Context, nd ipld.Node) error {
|
||||||
return cs.Write.Add(ctx, nd)
|
return cs.Write.Add(ctx, nd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMany adds nodes using the Write DAGService.
|
||||||
func (cs *ComboService) AddMany(ctx context.Context, nds []ipld.Node) error {
|
func (cs *ComboService) AddMany(ctx context.Context, nds []ipld.Node) error {
|
||||||
return cs.Write.AddMany(ctx, nds)
|
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) {
|
func (cs *ComboService) Get(ctx context.Context, c *cid.Cid) (ipld.Node, error) {
|
||||||
return cs.Read.Get(ctx, c)
|
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 {
|
func (cs *ComboService) GetMany(ctx context.Context, cids []*cid.Cid) <-chan *ipld.NodeOption {
|
||||||
return cs.Read.GetMany(ctx, cids)
|
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 {
|
func (cs *ComboService) Remove(ctx context.Context, c *cid.Cid) error {
|
||||||
return cs.Write.Remove(ctx, c)
|
return cs.Write.Remove(ctx, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveMany deletes nodes using the Write DAGService.
|
||||||
func (cs *ComboService) RemoveMany(ctx context.Context, cids []*cid.Cid) error {
|
func (cs *ComboService) RemoveMany(ctx context.Context, cids []*cid.Cid) error {
|
||||||
return cs.Write.RemoveMany(ctx, cids)
|
return cs.Write.RemoveMany(ctx, cids)
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,14 @@ import (
|
|||||||
// Order is an identifier for traversal algorithm orders
|
// Order is an identifier for traversal algorithm orders
|
||||||
type Order int
|
type Order int
|
||||||
|
|
||||||
|
// These constants define different traversing methods
|
||||||
const (
|
const (
|
||||||
DFSPre Order = iota // depth-first pre-order
|
// DFSPre defines depth-first pre-order
|
||||||
DFSPost // depth-first post-order
|
DFSPre Order = iota
|
||||||
BFS // breadth-first
|
// DFSPost defines depth-first post-order
|
||||||
|
DFSPost
|
||||||
|
// BFS defines breadth-first order
|
||||||
|
BFS
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options specifies a series of traversal options
|
// 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.
|
// If an error is returned, processing stops.
|
||||||
type Func func(current State) error
|
type Func func(current State) error
|
||||||
|
|
||||||
// If there is a problem walking to the Node, and ErrFunc is provided, Traverse
|
// ErrFunc is provided to handle problems when walking to the Node. Traverse
|
||||||
// will call ErrFunc with the error encountered. ErrFunc can decide how to handle
|
// will call ErrFunc with the error encountered. ErrFunc can decide how to
|
||||||
// that error, and return an error back to Traversal with how to proceed:
|
// handle that error, and return an error back to Traversal with how to proceed:
|
||||||
// * nil - skip the Node and its children, but continue processing
|
// * nil - skip the Node and its children, but continue processing
|
||||||
// * all other errors halt processing immediately.
|
// * all other errors halt processing immediately.
|
||||||
//
|
//
|
||||||
@ -98,6 +102,8 @@ type Func func(current State) error
|
|||||||
//
|
//
|
||||||
type ErrFunc func(err error) 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 {
|
func Traverse(root ipld.Node, o Options) error {
|
||||||
t := traversal{
|
t := traversal{
|
||||||
opts: o,
|
opts: o,
|
||||||
@ -127,20 +133,14 @@ func dfsPreTraverse(state State, t *traversal) error {
|
|||||||
if err := t.callFunc(state); err != nil {
|
if err := t.callFunc(state); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := dfsDescend(dfsPreTraverse, state, t); err != nil {
|
return dfsDescend(dfsPreTraverse, state, t)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func dfsPostTraverse(state State, t *traversal) error {
|
func dfsPostTraverse(state State, t *traversal) error {
|
||||||
if err := dfsDescend(dfsPostTraverse, state, t); err != nil {
|
if err := dfsDescend(dfsPostTraverse, state, t); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := t.callFunc(state); err != nil {
|
return t.callFunc(state)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func dfsDescend(df dfsFunc, curr State, t *traversal) error {
|
func dfsDescend(df dfsFunc, curr State, t *traversal) error {
|
||||||
|
@ -11,12 +11,15 @@ import (
|
|||||||
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// These constants define the changes that can be applied to a DAG.
|
||||||
const (
|
const (
|
||||||
Add = iota
|
Add = iota
|
||||||
Remove
|
Remove
|
||||||
Mod
|
Mod
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Change represents a change to a DAG and contains a reference to the old and
|
||||||
|
// new CIDs.
|
||||||
type Change struct {
|
type Change struct {
|
||||||
Type int
|
Type int
|
||||||
Path string
|
Path string
|
||||||
@ -24,6 +27,7 @@ type Change struct {
|
|||||||
After *cid.Cid
|
After *cid.Cid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String prints a human-friendly line about a change.
|
||||||
func (c *Change) String() string {
|
func (c *Change) String() string {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case Add:
|
case Add:
|
||||||
@ -102,8 +106,8 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
var out []*Change
|
var out []*Change
|
||||||
clean_a := a.Copy().(*dag.ProtoNode)
|
cleanA := a.Copy().(*dag.ProtoNode)
|
||||||
clean_b := b.Copy().(*dag.ProtoNode)
|
cleanB := b.Copy().(*dag.ProtoNode)
|
||||||
|
|
||||||
// strip out unchanged stuff
|
// strip out unchanged stuff
|
||||||
for _, lnk := range a.Links() {
|
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)
|
out = append(out, subc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean_a.RemoveNodeLink(l.Name)
|
cleanA.RemoveNodeLink(l.Name)
|
||||||
clean_b.RemoveNodeLink(l.Name)
|
cleanB.RemoveNodeLink(l.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, lnk := range clean_a.Links() {
|
for _, lnk := range cleanA.Links() {
|
||||||
out = append(out, &Change{
|
out = append(out, &Change{
|
||||||
Type: Remove,
|
Type: Remove,
|
||||||
Path: lnk.Name,
|
Path: lnk.Name,
|
||||||
Before: lnk.Cid,
|
Before: lnk.Cid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, lnk := range clean_b.Links() {
|
for _, lnk := range cleanB.Links() {
|
||||||
out = append(out, &Change{
|
out = append(out, &Change{
|
||||||
Type: Add,
|
Type: Add,
|
||||||
Path: lnk.Name,
|
Path: lnk.Name,
|
||||||
@ -165,11 +169,17 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conflict represents two incompatible changes and is returned by MergeDiffs().
|
||||||
type Conflict struct {
|
type Conflict struct {
|
||||||
A *Change
|
A *Change
|
||||||
B *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) {
|
func MergeDiffs(a, b []*Change) ([]*Change, []Conflict) {
|
||||||
var out []*Change
|
var out []*Change
|
||||||
var conflicts []Conflict
|
var conflicts []Conflict
|
||||||
|
@ -15,6 +15,8 @@ import (
|
|||||||
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Editor represents a ProtoNode tree editor and provides methods to
|
||||||
|
// modify it.
|
||||||
type Editor struct {
|
type Editor struct {
|
||||||
root *dag.ProtoNode
|
root *dag.ProtoNode
|
||||||
|
|
||||||
@ -83,6 +85,7 @@ func addLink(ctx context.Context, ds ipld.DAGService, root *dag.ProtoNode, child
|
|||||||
return root, nil
|
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 {
|
func (e *Editor) InsertNodeAtPath(ctx context.Context, pth string, toinsert ipld.Node, create func() *dag.ProtoNode) error {
|
||||||
splpath := path.SplitList(pth)
|
splpath := path.SplitList(pth)
|
||||||
nd, err := e.insertNodeAtPath(ctx, e.root, splpath, toinsert, create)
|
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
|
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 {
|
func (e *Editor) RmLink(ctx context.Context, pth string) error {
|
||||||
splpath := path.SplitList(pth)
|
splpath := path.SplitList(pth)
|
||||||
nd, err := e.rmLink(ctx, e.root, splpath)
|
nd, err := e.rmLink(ctx, e.root, splpath)
|
||||||
|
Reference in New Issue
Block a user