retrieval: Support DM-paths in ls
This commit is contained in:
parent
dd78e75dd6
commit
2c583b03ff
@ -5,11 +5,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/lotus/markets/utils"
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
|
||||||
"github.com/ipld/go-ipld-prime/traversal"
|
|
||||||
selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse"
|
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -24,6 +21,14 @@ import (
|
|||||||
"github.com/ipfs/go-merkledag"
|
"github.com/ipfs/go-merkledag"
|
||||||
carv2 "github.com/ipld/go-car/v2"
|
carv2 "github.com/ipld/go-car/v2"
|
||||||
"github.com/ipld/go-car/v2/blockstore"
|
"github.com/ipld/go-car/v2/blockstore"
|
||||||
|
"github.com/ipld/go-ipld-prime"
|
||||||
|
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||||
|
basicnode "github.com/ipld/go-ipld-prime/node/basic"
|
||||||
|
"github.com/ipld/go-ipld-prime/traversal"
|
||||||
|
"github.com/ipld/go-ipld-prime/traversal/selector"
|
||||||
|
"github.com/ipld/go-ipld-prime/traversal/selector/builder"
|
||||||
|
selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse"
|
||||||
|
textselector "github.com/ipld/go-ipld-selector-text-lite"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
manet "github.com/multiformats/go-multiaddr/net"
|
manet "github.com/multiformats/go-multiaddr/net"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@ -35,6 +40,7 @@ import (
|
|||||||
|
|
||||||
lapi "github.com/filecoin-project/lotus/api"
|
lapi "github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/markets/utils"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -322,8 +328,13 @@ func ClientExportStream(apiAddr string, apiAuth http.Header, eref lapi.ExportRef
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
em, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("reading error body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
resp.Body.Close() // nolint
|
resp.Body.Close() // nolint
|
||||||
return nil, xerrors.Errorf("getting root car: http %d", resp.StatusCode)
|
return nil, xerrors.Errorf("getting root car: http %d: %s", resp.StatusCode, string(em))
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.Body, nil
|
return resp.Body, nil
|
||||||
@ -373,6 +384,20 @@ var clientRetrieveCatCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pathToSel(psel string, sub builder.SelectorSpec) (lapi.Selector, error) {
|
||||||
|
rs, err := textselector.SelectorSpecFromPath(textselector.Expression(psel), sub)
|
||||||
|
if err != nil {
|
||||||
|
return "", xerrors.Errorf("failed to parse path-selector '%s': %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := dagjson.Encode(rs.Node(), &b); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return lapi.Selector(b.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
var clientRetrieveLsCmd = &cli.Command{
|
var clientRetrieveLsCmd = &cli.Command{
|
||||||
Name: "ls",
|
Name: "ls",
|
||||||
Usage: "Show object links",
|
Usage: "Show object links",
|
||||||
@ -388,7 +413,7 @@ var clientRetrieveLsCmd = &cli.Command{
|
|||||||
Value: 1,
|
Value: 1,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "path-selector",
|
Name: "datamodel-path",
|
||||||
Usage: "a rudimentary (DM-level-only) text-path selector",
|
Usage: "a rudimentary (DM-level-only) text-path selector",
|
||||||
},
|
},
|
||||||
}, retrFlagsCommon...),
|
}, retrFlagsCommon...),
|
||||||
@ -411,13 +436,30 @@ var clientRetrieveLsCmd = &cli.Command{
|
|||||||
afmt := NewAppFmt(cctx.App)
|
afmt := NewAppFmt(cctx.App)
|
||||||
|
|
||||||
rootSelector := lapi.Selector(`{".": {}}`)
|
rootSelector := lapi.Selector(`{".": {}}`)
|
||||||
dataSelector := lapi.Selector(fmt.Sprintf(`{"a":{">":{"R":{"l":{"depth":%d},":>":{"a":{">":{"|": [{"@":{}}, {".": {}}]}}}}}}}`, cctx.Int("depth")))
|
dataSelector := lapi.Selector(fmt.Sprintf(`{"a":{">":{"R":{"l":{"depth":%d},":>":{"a":{">":{"|":[{"@":{}},{".":{}}]}}}}}}}`, cctx.Int("depth")))
|
||||||
|
|
||||||
|
if cctx.IsSet("datamodel-path") {
|
||||||
|
rootSelector, err = pathToSel(cctx.String("datamodel-path"), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Any)
|
||||||
|
dataSelector, err = pathToSel(cctx.String("datamodel-path"), ssb.ExploreAll(
|
||||||
|
ssb.ExploreRecursive(selector.RecursionLimitDepth(int64(cctx.Int("depth"))), ssb.ExploreAll(ssb.ExploreUnion(ssb.Matcher(), ssb.ExploreRecursiveEdge()))),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eref, err := retrieve(ctx, cctx, fapi, &dataSelector, afmt.Printf)
|
eref, err := retrieve(ctx, cctx, fapi, &dataSelector, afmt.Printf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println() // separate retrieval events from results
|
||||||
|
|
||||||
eref.DAGs = append(eref.DAGs, lapi.DagSpec{
|
eref.DAGs = append(eref.DAGs, lapi.DagSpec{
|
||||||
RootSelector: &rootSelector,
|
RootSelector: &rootSelector,
|
||||||
DataSelector: &dataSelector,
|
DataSelector: &dataSelector,
|
||||||
@ -453,7 +495,6 @@ var clientRetrieveLsCmd = &cli.Command{
|
|||||||
dserv := merkledag.NewDAGService(blockservice.New(cbs, offline.Exchange(cbs)))
|
dserv := merkledag.NewDAGService(blockservice.New(cbs, offline.Exchange(cbs)))
|
||||||
|
|
||||||
if !cctx.Bool("ipld") {
|
if !cctx.Bool("ipld") {
|
||||||
|
|
||||||
links, err := dserv.GetLinks(ctx, roots[0])
|
links, err := dserv.GetLinks(ctx, roots[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("getting links: %w", err)
|
return xerrors.Errorf("getting links: %w", err)
|
||||||
@ -463,7 +504,16 @@ var clientRetrieveLsCmd = &cli.Command{
|
|||||||
fmt.Printf("%s %s\t%d\n", link.Cid, link.Name, link.Size)
|
fmt.Printf("%s %s\t%d\n", link.Cid, link.Name, link.Size)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sel, _ := selectorparse.ParseJSONSelector(fmt.Sprintf(`{"R":{"l":{"depth":%d},":>":{"a":{">":{"|":[{"@":{}},{".":{}}]}}}}}`, cctx.Int("depth")))
|
jsel := lapi.Selector(fmt.Sprintf(`{"R":{"l":{"depth":%d},":>":{"a":{">":{"|":[{"@":{}},{".":{}}]}}}}}`, cctx.Int("depth")))
|
||||||
|
|
||||||
|
if cctx.IsSet("datamodel-path") {
|
||||||
|
ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Any)
|
||||||
|
jsel, err = pathToSel(cctx.String("datamodel-path"),
|
||||||
|
ssb.ExploreRecursive(selector.RecursionLimitDepth(int64(cctx.Int("depth"))), ssb.ExploreAll(ssb.ExploreUnion(ssb.Matcher(), ssb.ExploreRecursiveEdge()))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sel, _ := selectorparse.ParseJSONSelector(string(jsel))
|
||||||
|
|
||||||
if err := utils.TraverseDag(
|
if err := utils.TraverseDag(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -1052,10 +1052,6 @@ func parseDagSpec(ctx context.Context, root cid.Cid, dsp []api.DagSpec, ds forma
|
|||||||
func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error {
|
func(p traversal.Progress, n ipld.Node, r traversal.VisitReason) error {
|
||||||
if r == traversal.VisitReason_SelectionMatch {
|
if r == traversal.VisitReason_SelectionMatch {
|
||||||
|
|
||||||
if p.LastBlock.Path.String() != p.Path.String() {
|
|
||||||
return xerrors.Errorf("unsupported selection path '%s' does not correspond to a block boundary (a.k.a. CID link)", p.Path.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.LastBlock.Link == nil {
|
if p.LastBlock.Link == nil {
|
||||||
// this is likely the root node that we've matched here
|
// this is likely the root node that we've matched here
|
||||||
// todo: is this a correct assumption
|
// todo: is this a correct assumption
|
||||||
|
Loading…
Reference in New Issue
Block a user