resolve.go 4.61 KB
Newer Older
1 2 3
package commands

import (
4
	"errors"
5
	"fmt"
6 7
	"io"
	"strings"
8
	"time"
9

10
	cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"
11
	ncmd "github.com/ipfs/go-ipfs/core/commands/name"
Łukasz Magiera's avatar
Łukasz Magiera committed
12
	coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
13
	options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
14
	ns "github.com/ipfs/go-ipfs/namesys"
15
	nsopts "github.com/ipfs/go-ipfs/namesys/opts"
Steven Allen's avatar
Steven Allen committed
16
	path "gx/ipfs/QmNYPETsdAu2uQ1k9q9S1jYEGURaLHV6cbYRSVFVRftpF8/go-path"
Jan Winkelmann's avatar
Jan Winkelmann committed
17

Hector Sanjuan's avatar
Hector Sanjuan committed
18
	cmds "gx/ipfs/QmWGm4AbZEbnmdgVTza52MSNpEmBdFVqzmAysRbjrRyGbH/go-ipfs-cmds"
Overbool's avatar
Overbool committed
19
	cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
20 21
)

Kejie Zhang's avatar
Kejie Zhang committed
22 23 24 25 26 27
const (
	resolveRecursiveOptionName      = "recursive"
	resolveDhtRecordCountOptionName = "dht-record-count"
	resolveDhtTimeoutOptionName     = "dht-timeout"
)

28
var ResolveCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
29
	Helptext: cmdkit.HelpText{
rht's avatar
rht committed
30
		Tagline: "Resolve the value of names to IPFS.",
31
		ShortDescription: `
32
There are a number of mutable name protocols that can link among
33
themselves and into IPNS. This command accepts any of these
34
identifiers and resolves them to the referenced item.
35 36
`,
		LongDescription: `
37
There are a number of mutable name protocols that can link among
38 39 40
themselves and into IPNS. For example IPNS references can (currently)
point at an IPFS object, and DNS links can point at other DNS links, IPNS
entries, or IPFS objects. This command accepts any of these
41
identifiers and resolves them to the referenced item.
42

43
EXAMPLES
44 45 46

Resolve the value of your identity:

47
  $ ipfs resolve /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
48 49 50 51
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj

Resolve the value of another name:

52
  $ ipfs resolve /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
53
  /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
54

55
Resolve the value of another name recursively:
56

57
  $ ipfs resolve -r /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
58
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
59

60 61
Resolve the value of an IPFS DAG path:

62
  $ ipfs resolve /ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop
63 64
  /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1

65
`,
66
	},
67

Jan Winkelmann's avatar
Jan Winkelmann committed
68 69
	Arguments: []cmdkit.Argument{
		cmdkit.StringArg("name", true, false, "The name to resolve.").EnableStdin(),
70
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
71
	Options: []cmdkit.Option{
Kejie Zhang's avatar
Kejie Zhang committed
72 73 74
		cmdkit.BoolOption(resolveRecursiveOptionName, "r", "Resolve until the result is an IPFS name."),
		cmdkit.IntOption(resolveDhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."),
		cmdkit.StringOption(resolveDhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
75
	},
76
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
77
		api, err := cmdenv.GetApi(env, req)
Łukasz Magiera's avatar
Łukasz Magiera committed
78
		if err != nil {
79
			return err
Łukasz Magiera's avatar
Łukasz Magiera committed
80 81
		}

82
		name := req.Arguments[0]
Kejie Zhang's avatar
Kejie Zhang committed
83
		recursive, _ := req.Options[resolveRecursiveOptionName].(bool)
84

85 86 87 88 89 90 91 92
		enc, err := cmdenv.GetCidEncoder(req)
		if err != nil {
			return err
		}
		if !cmdenv.CidBaseDefined(req) {
			enc, _ = cmdenv.CidEncoderFromPath(enc, name)
		}

93 94
		// the case when ipns is resolved step by step
		if strings.HasPrefix(name, "/ipns/") && !recursive {
Kejie Zhang's avatar
Kejie Zhang committed
95 96
			rc, rcok := req.Options[resolveDhtRecordCountOptionName].(uint)
			dhtt, dhttok := req.Options[resolveDhtTimeoutOptionName].(string)
97 98 99
			ropts := []options.NameResolveOption{
				options.Name.ResolveOption(nsopts.Depth(1)),
			}
Łukasz Magiera's avatar
Łukasz Magiera committed
100

101
			if rcok {
102
				ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtRecordCount(rc)))
103 104
			}
			if dhttok {
105 106
				d, err := time.ParseDuration(dhtt)
				if err != nil {
107
					return err
108 109
				}
				if d < 0 {
110
					return errors.New("DHT timeout value must be >= 0")
111
				}
112
				ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtTimeout(d)))
113
			}
Łukasz Magiera's avatar
Łukasz Magiera committed
114
			p, err := api.Name().Resolve(req.Context, name, ropts...)
115 116
			// ErrResolveRecursion is fine
			if err != nil && err != ns.ErrResolveRecursion {
117
				return err
118
			}
119
			return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.Path(p.String())})
120 121
		}

122
		// else, ipfs path or ipns with recursive flag
Łukasz Magiera's avatar
Łukasz Magiera committed
123
		p, err := coreiface.ParsePath(name)
124
		if err != nil {
125
			return err
126
		}
127

Łukasz Magiera's avatar
Łukasz Magiera committed
128
		rp, err := api.ResolvePath(req.Context, p)
129
		if err != nil {
130
			return err
131 132
		}

133
		if rp.Remainder() != "" {
Steven Allen's avatar
Steven Allen committed
134 135 136
			// TODO: js expects this error. Instead of fixing this
			// error, we should fix #5703.
			return fmt.Errorf("found non-link at given path")
137
		}
138

139
		return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.Path("/" + rp.Namespace() + "/" + enc.Encode(rp.Cid()))})
140
	},
141
	Encoders: cmds.EncoderMap{
Overbool's avatar
Overbool committed
142 143
		cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, rp *ncmd.ResolvedPath) error {
			fmt.Fprintln(w, rp.Path.String())
144 145
			return nil
		}),
146
	},
147
	Type: ncmd.ResolvedPath{},
148
}