Commit e91a9c49 authored by Hector Sanjuan's avatar Hector Sanjuan

Golint: fix golint warnings in merkledag submodule

License: MIT
Signed-off-by: default avatarHector Sanjuan <hector@protocol.ai>
parent deacce76
...@@ -102,7 +102,7 @@ func (n *ProtoNode) EncodeProtobuf(force bool) ([]byte, error) { ...@@ -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 { ...@@ -14,28 +14,34 @@ type ErrorService struct {
var _ ipld.DAGService = (*ErrorService)(nil) var _ ipld.DAGService = (*ErrorService)(nil)
// Add returns an error.
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 an error.
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 an error.
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 an error.
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 an error.
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 an error.
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
} }
// package merkledag implements the IPFS Merkle DAG datastructures. // Package merkledag implements the IPFS Merkle DAG data structures.
package merkledag package merkledag
import ( import (
...@@ -23,8 +23,14 @@ func init() { ...@@ -23,8 +23,14 @@ 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).
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} return &dagService{Blocks: bs}
} }
...@@ -147,8 +153,8 @@ func (sg *sesGetter) GetMany(ctx context.Context, keys []*cid.Cid) <-chan *ipld. ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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()
......
...@@ -13,6 +13,8 @@ import ( ...@@ -13,6 +13,8 @@ import (
"testing" "testing"
"time" "time"
blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
bserv "github.com/ipfs/go-ipfs/blockservice" bserv "github.com/ipfs/go-ipfs/blockservice"
bstest "github.com/ipfs/go-ipfs/blockservice/test" bstest "github.com/ipfs/go-ipfs/blockservice/test"
offline "github.com/ipfs/go-ipfs/exchange/offline" offline "github.com/ipfs/go-ipfs/exchange/offline"
...@@ -22,7 +24,6 @@ import ( ...@@ -22,7 +24,6 @@ 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"
...@@ -241,9 +242,10 @@ func TestFetchGraph(t *testing.T) { ...@@ -241,9 +242,10 @@ 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) // 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(), offlineDS.GetLinks, root.Cid(), func(_ *cid.Cid) bool { return true })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -260,7 +262,9 @@ func TestEnumerateChildren(t *testing.T) { ...@@ -260,7 +262,9 @@ func TestEnumerateChildren(t *testing.T) {
} }
set := cid.NewSet() 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -491,7 +495,7 @@ func TestCidRetention(t *testing.T) { ...@@ -491,7 +495,7 @@ func TestCidRetention(t *testing.T) {
} }
func TestCidRawDoesnNeedData(t *testing.T) { func TestCidRawDoesnNeedData(t *testing.T) {
srv := NewDAGService(dstest.Bserv()) srv := NewDAGService(dstest.Bserv()).(ipld.LinkGetter)
nd := NewRawNode([]byte("somedata")) nd := NewRawNode([]byte("somedata"))
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
......
...@@ -10,10 +10,13 @@ import ( ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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 ( ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 ( ...@@ -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) { ...@@ -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 ...@@ -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 { ...@@ -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 ( ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ( ...@@ -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 ...@@ -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 ...@@ -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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment