resolve.go 4.28 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"
Jan Winkelmann's avatar
Jan Winkelmann committed
11
	e "github.com/ipfs/go-ipfs/core/commands/e"
12
	ncmd "github.com/ipfs/go-ipfs/core/commands/name"
Łukasz Magiera's avatar
Łukasz Magiera committed
13
	coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
14
	options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
15
	ns "github.com/ipfs/go-ipfs/namesys"
16
	nsopts "github.com/ipfs/go-ipfs/namesys/opts"
17
	path "gx/ipfs/QmV4QxScV9Y7LbaWhHazFfRd8uyeUd4pAH8a7fFFbi5odJ/go-path"
Jan Winkelmann's avatar
Jan Winkelmann committed
18

19
	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
Steven Allen's avatar
Steven Allen committed
20
	"gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds"
21 22
)

23
var ResolveCmd = &cmds.Command{
Jan Winkelmann's avatar
Jan Winkelmann committed
24
	Helptext: cmdkit.HelpText{
rht's avatar
rht committed
25
		Tagline: "Resolve the value of names to IPFS.",
26
		ShortDescription: `
27
There are a number of mutable name protocols that can link among
28
themselves and into IPNS. This command accepts any of these
29
identifiers and resolves them to the referenced item.
30 31
`,
		LongDescription: `
32
There are a number of mutable name protocols that can link among
33 34 35
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
36
identifiers and resolves them to the referenced item.
37

38
EXAMPLES
39 40 41

Resolve the value of your identity:

42
  $ ipfs resolve /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
43 44 45 46
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj

Resolve the value of another name:

47
  $ ipfs resolve /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
48
  /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
49

50
Resolve the value of another name recursively:
51

52
  $ ipfs resolve -r /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
53
  /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
54

55 56
Resolve the value of an IPFS DAG path:

57
  $ ipfs resolve /ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop
58 59
  /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1

60
`,
61
	},
62

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

77
		n, err := cmdenv.GetNode(env)
78
		if err != nil {
79
			return err
80 81
		}

Łukasz Magiera's avatar
Łukasz Magiera committed
82 83 84
		if !n.OnlineMode() {
			err := n.SetupOfflineRouting()
			if err != nil {
85
				return err
Łukasz Magiera's avatar
Łukasz Magiera committed
86 87 88
			}
		}

89 90
		name := req.Arguments[0]
		recursive, _ := req.Options["recursive"].(bool)
91 92 93

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

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

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

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

Łukasz Magiera's avatar
Łukasz Magiera committed
132
		c := rp.Cid()
133

134
		return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.FromCid(c)})
135
	},
136 137
	Encoders: cmds.EncoderMap{
		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
138
			output, ok := v.(*ncmd.ResolvedPath)
139
			if !ok {
140
				return e.TypeErr(output, v)
141
			}
142 143 144 145

			fmt.Fprintln(w, output.Path.String())
			return nil
		}),
146
	},
147
	Type: ncmd.ResolvedPath{},
148
}