package reprovide import ( "context" pin "github.com/ipfs/go-ipfs/pin" cid "github.com/ipfs/go-cid" cidutil "github.com/ipfs/go-cidutil" blocks "github.com/ipfs/go-ipfs-blockstore" ipld "github.com/ipfs/go-ipld-format" merkledag "github.com/ipfs/go-merkledag" ) // NewBlockstoreProvider returns key provider using bstore.AllKeysChan func NewBlockstoreProvider(bstore blocks.Blockstore) KeyChanFunc { return func(ctx context.Context) (<-chan cid.Cid, error) { return bstore.AllKeysChan(ctx) } } // NewPinnedProvider returns provider supplying pinned keys func NewPinnedProvider(pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) KeyChanFunc { return func(ctx context.Context) (<-chan cid.Cid, error) { set, err := pinSet(ctx, pinning, dag, onlyRoots) if err != nil { return nil, err } outCh := make(chan cid.Cid) go func() { defer close(outCh) for c := range set.New { select { case <-ctx.Done(): return case outCh <- c: } } }() return outCh, nil } } func pinSet(ctx context.Context, pinning pin.Pinner, dag ipld.DAGService, onlyRoots bool) (*cidutil.StreamingSet, error) { set := cidutil.NewStreamingSet() go func() { ctx, cancel := context.WithCancel(ctx) defer cancel() defer close(set.New) for _, key := range pinning.DirectKeys() { set.Visitor(ctx)(key) } for _, key := range pinning.RecursiveKeys() { set.Visitor(ctx)(key) if !onlyRoots { err := merkledag.EnumerateChildren(ctx, merkledag.GetLinksWithDAG(dag), key, set.Visitor(ctx)) if err != nil { log.Errorf("reprovide indirect pins: %s", err) return } } } }() return set, nil }