resolve.go 4.55 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"
Steven Allen's avatar
Steven Allen committed
17
	path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"
Jan Winkelmann's avatar
Jan Winkelmann committed
18

19
	"gx/ipfs/QmPTfgFTo9PFr1PvPKyKoeMgBvYPh6cX3aDP7DHKVbnCbi/go-ipfs-cmds"
20
	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
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) {
Łukasz Magiera's avatar
Łukasz Magiera committed
72 73 74 75 76 77
		api, err := cmdenv.GetApi(env)
		if err != nil {
			res.SetError(err, cmdkit.ErrNormal)
			return
		}

78
		n, err := cmdenv.GetNode(env)
79
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
80
			res.SetError(err, cmdkit.ErrNormal)
81
			return
82 83
		}

Łukasz Magiera's avatar
Łukasz Magiera committed
84 85 86 87 88 89 90 91
		if !n.OnlineMode() {
			err := n.SetupOfflineRouting()
			if err != nil {
				res.SetError(err, cmdkit.ErrNormal)
				return
			}
		}

92 93
		name := req.Arguments[0]
		recursive, _ := req.Options["recursive"].(bool)
94 95 96

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

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

128
		// else, ipfs path or ipns with recursive flag
Łukasz Magiera's avatar
Łukasz Magiera committed
129
		p, err := coreiface.ParsePath(name)
130
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
131
			res.SetError(err, cmdkit.ErrNormal)
132
			return
133
		}
134

Łukasz Magiera's avatar
Łukasz Magiera committed
135
		rp, err := api.ResolvePath(req.Context, p)
136
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
137
			res.SetError(err, cmdkit.ErrNormal)
138 139 140
			return
		}

Łukasz Magiera's avatar
Łukasz Magiera committed
141
		c := rp.Cid()
142

143
		cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.FromCid(c)})
144
	},
145 146
	Encoders: cmds.EncoderMap{
		cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
147
			output, ok := v.(*ncmd.ResolvedPath)
148
			if !ok {
149
				return e.TypeErr(output, v)
150
			}
151 152 153 154

			fmt.Fprintln(w, output.Path.String())
			return nil
		}),
155
	},
156
	Type: ncmd.ResolvedPath{},
157
}