Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve: use unixfs ResolveOnce #5484

Merged
merged 4 commits into from
Sep 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions core/commands/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@ package commands

import (
"errors"
"fmt"
"io"
"strings"
"time"

cmds "github.com/ipfs/go-ipfs/commands"
"github.com/ipfs/go-ipfs/core"
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
e "github.com/ipfs/go-ipfs/core/commands/e"
ncmd "github.com/ipfs/go-ipfs/core/commands/name"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
ns "github.com/ipfs/go-ipfs/namesys"
nsopts "github.com/ipfs/go-ipfs/namesys/opts"
path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"

"gx/ipfs/QmPTfgFTo9PFr1PvPKyKoeMgBvYPh6cX3aDP7DHKVbnCbi/go-ipfs-cmds"
"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
)

Expand Down Expand Up @@ -62,12 +65,17 @@ Resolve the value of an IPFS DAG path:
},
Options: []cmdkit.Option{
cmdkit.BoolOption("recursive", "r", "Resolve until the result is an IPFS name."),
cmdkit.UintOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."),
cmdkit.IntOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."),
cmdkit.StringOption("dht-timeout", "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
},
Run: func(req cmds.Request, res cmds.Response) {
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
api, err := cmdenv.GetApi(env)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

n, err := req.InvocContext().GetNode()
n, err := cmdenv.GetNode(env)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
Expand All @@ -81,16 +89,19 @@ Resolve the value of an IPFS DAG path:
}
}

name := req.Arguments()[0]
recursive, _, _ := req.Option("recursive").Bool()
name := req.Arguments[0]
recursive, _ := req.Options["recursive"].(bool)

// the case when ipns is resolved step by step
if strings.HasPrefix(name, "/ipns/") && !recursive {
rc, rcok, _ := req.Option("dht-record-count").Int()
dhtt, dhttok, _ := req.Option("dht-timeout").String()
ropts := []nsopts.ResolveOpt{nsopts.Depth(1)}
rc, rcok := req.Options["dht-record-count"].(uint)
dhtt, dhttok := req.Options["dht-timeout"].(string)
ropts := []options.NameResolveOption{
options.Name.ResolveOption(nsopts.Depth(1)),
}

if rcok {
ropts = append(ropts, nsopts.DhtRecordCount(uint(rc)))
ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtRecordCount(rc)))
}
if dhttok {
d, err := time.ParseDuration(dhtt)
Expand All @@ -102,48 +113,45 @@ Resolve the value of an IPFS DAG path:
res.SetError(errors.New("DHT timeout value must be >= 0"), cmdkit.ErrNormal)
return
}
ropts = append(ropts, nsopts.DhtTimeout(d))
ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtTimeout(d)))
}
p, err := n.Namesys.Resolve(req.Context(), name, ropts...)
p, err := api.Name().Resolve(req.Context, name, ropts...)
// ErrResolveRecursion is fine
if err != nil && err != ns.ErrResolveRecursion {
res.SetError(err, cmdkit.ErrNormal)
return
}
res.SetOutput(&ncmd.ResolvedPath{Path: p})
cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.Path(p.String())})
return
}

// else, ipfs path or ipns with recursive flag
p, err := path.ParsePath(name)
p, err := coreiface.ParsePath(name)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

node, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, p)
rp, err := api.ResolvePath(req.Context, p)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

c := node.Cid()
c := rp.Cid()

res.SetOutput(&ncmd.ResolvedPath{Path: path.FromCid(c)})
cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.FromCid(c)})
},
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
v, err := unwrapOutput(res.Output())
if err != nil {
return nil, err
}

Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
output, ok := v.(*ncmd.ResolvedPath)
if !ok {
return nil, e.TypeErr(output, v)
return e.TypeErr(output, v)
}
return strings.NewReader(output.Path.String() + "\n"), nil
},

fmt.Fprintln(w, output.Path.String())
return nil
}),
},
Type: ncmd.ResolvedPath{},
}
4 changes: 2 additions & 2 deletions core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ var rootSubcommands = map[string]*cmds.Command{
"ping": lgc.NewCommand(PingCmd),
"p2p": lgc.NewCommand(P2PCmd),
"refs": lgc.NewCommand(RefsCmd),
"resolve": lgc.NewCommand(ResolveCmd),
"resolve": ResolveCmd,
"swarm": lgc.NewCommand(SwarmCmd),
"tar": lgc.NewCommand(TarCmd),
"file": lgc.NewCommand(unixfs.UnixFSCmd),
Expand Down Expand Up @@ -183,7 +183,7 @@ var rootROSubcommands = map[string]*cmds.Command{
"resolve": dag.DagResolveCmd,
},
}),
"resolve": lgc.NewCommand(ResolveCmd),
"resolve": ResolveCmd,
"version": lgc.NewCommand(VersionCmd),
}

Expand Down
31 changes: 16 additions & 15 deletions core/coreapi/interface/options/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package options

import (
"time"

ropts "github.com/ipfs/go-ipfs/namesys/opts"
)

const (
Expand All @@ -14,9 +16,10 @@ type NamePublishSettings struct {
}

type NameResolveSettings struct {
Recursive bool
Local bool
Cache bool
Local bool
Cache bool

ResolveOpts []ropts.ResolveOpt
}

type NamePublishOption func(*NamePublishSettings) error
Expand All @@ -40,9 +43,8 @@ func NamePublishOptions(opts ...NamePublishOption) (*NamePublishSettings, error)

func NameResolveOptions(opts ...NameResolveOption) (*NameResolveSettings, error) {
options := &NameResolveSettings{
Recursive: false,
Local: false,
Cache: true,
Local: false,
Cache: true,
}

for _, opt := range opts {
Expand Down Expand Up @@ -80,15 +82,6 @@ func (nameOpts) Key(key string) NamePublishOption {
}
}

// Recursive is an option for Name.Resolve which specifies whether to perform a
// recursive lookup. Default value is false
func (nameOpts) Recursive(recursive bool) NameResolveOption {
return func(settings *NameResolveSettings) error {
settings.Recursive = recursive
return nil
}
}

// Local is an option for Name.Resolve which specifies if the lookup should be
// offline. Default value is false
func (nameOpts) Local(local bool) NameResolveOption {
Expand All @@ -106,3 +99,11 @@ func (nameOpts) Cache(cache bool) NameResolveOption {
return nil
}
}

//
func (nameOpts) ResolveOption(opt ropts.ResolveOpt) NameResolveOption {
return func(settings *NameResolveSettings) error {
settings.ResolveOpts = append(settings.ResolveOpts, opt)
return nil
}
}
20 changes: 7 additions & 13 deletions core/coreapi/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import (
"strings"
"time"

core "github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/core"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
keystore "github.com/ipfs/go-ipfs/keystore"
namesys "github.com/ipfs/go-ipfs/namesys"
nsopts "github.com/ipfs/go-ipfs/namesys/opts"
"github.com/ipfs/go-ipfs/keystore"
"github.com/ipfs/go-ipfs/namesys"
ipath "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"

crypto "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto"
peer "gx/ipfs/QmQsErDt8Qgw1XrsXf2BpEzDgGWtB1YLsTAARBup5b6B9W/go-libp2p-peer"
offline "gx/ipfs/QmSNe4MWVxZWk6UxxW2z2EKofFo4GdFzud1vfn1iVby3mj/go-ipfs-routing/offline"
"gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto"
"gx/ipfs/QmQsErDt8Qgw1XrsXf2BpEzDgGWtB1YLsTAARBup5b6B9W/go-libp2p-peer"
"gx/ipfs/QmSNe4MWVxZWk6UxxW2z2EKofFo4GdFzud1vfn1iVby3mj/go-ipfs-routing/offline"
)

type NameAPI CoreAPI
Expand Down Expand Up @@ -119,12 +118,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam
name = "/ipns/" + name
}

var ropts []nsopts.ResolveOpt
if !options.Recursive {
ropts = append(ropts, nsopts.Depth(1))
}

output, err := resolver.Resolve(ctx, name, ropts...)
output, err := resolver.Resolve(ctx, name, options.ResolveOpts...)
if err != nil {
return nil, err
}
Expand Down
33 changes: 12 additions & 21 deletions core/coreapi/path.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
package coreapi

import (
context "context"
fmt "fmt"
"context"
"fmt"
gopath "path"

core "github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/core"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
namesys "github.com/ipfs/go-ipfs/namesys"
uio "gx/ipfs/QmPL8bYtbACcSFFiSr4s2du7Na382NxRADR8hC7D9FkEA2/go-unixfs/io"
ipfspath "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"
resolver "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path/resolver"
"gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path/resolver"

cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
"gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format"
)

// ResolveNode resolves the path `p` using Unixfs resolver, gets and returns the
// resolved Node.
func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (ipld.Node, error) {
return resolveNode(ctx, api.node.DAG, api.node.Namesys, p)
}

// ResolvePath resolves the path `p` using Unixfs resolver, returns the
// resolved path.
func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.ResolvedPath, error) {
return resolvePath(ctx, api.node.DAG, api.node.Namesys, p)
}

func resolveNode(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (ipld.Node, error) {
rp, err := resolvePath(ctx, ng, nsys, p)
rp, err := api.ResolvePath(ctx, p)
if err != nil {
return nil, err
}

node, err := ng.Get(ctx, rp.Cid())
node, err := api.node.DAG.Get(ctx, rp.Cid())
if err != nil {
return nil, err
}
return node, nil
}

func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSystem, p coreiface.Path) (coreiface.ResolvedPath, error) {
// ResolvePath resolves the path `p` using Unixfs resolver, returns the
// resolved path.
func (api *CoreAPI) ResolvePath(ctx context.Context, p coreiface.Path) (coreiface.ResolvedPath, error) {
if _, ok := p.(coreiface.ResolvedPath); ok {
return p.(coreiface.ResolvedPath), nil
}

ipath := ipfspath.Path(p.String())
ipath, err := core.ResolveIPNS(ctx, nsys, ipath)
ipath, err := core.ResolveIPNS(ctx, api.node.Namesys, ipath)
if err == core.ErrNoNamesys {
return nil, coreiface.ErrOffline
} else if err != nil {
Expand All @@ -66,7 +57,7 @@ func resolvePath(ctx context.Context, ng ipld.NodeGetter, nsys namesys.NameSyste
}

r := &resolver.Resolver{
DAG: ng,
DAG: api.node.DAG,
ResolveOnce: resolveOnce,
}

Expand Down
2 changes: 1 addition & 1 deletion core/coreapi/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedP
func (api *UnixfsAPI) Cat(ctx context.Context, p coreiface.Path) (coreiface.Reader, error) {
dget := api.node.DAG // TODO: use a session here once routing perf issues are resolved

dagnode, err := resolveNode(ctx, dget, api.node.Namesys, p)
dagnode, err := api.core().ResolveNode(ctx, p)
if err != nil {
return nil, err
}
Expand Down
6 changes: 6 additions & 0 deletions test/sharness/t0260-sharding.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ test_expect_success "gateway can resolve sharded dirs" '
test_cmp expected actual
'

test_expect_success "'ipfs resolve' can resolve sharded dirs" '
echo /ipfs/QmZ3RfWk1u5LEGYLHA633B5TNJy3Du27K6Fny9wcxpowGS > expected &&
ipfs resolve "/ipfs/$SHARDED/file100" > actual &&
test_cmp expected actual
'

test_kill_ipfs_daemon

test_add_large_dir_v1() {
Expand Down