resolve.go 4.42 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 14
	coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
	"github.com/ipfs/go-ipfs/core/coreapi/interface/options"
15
	ns "github.com/ipfs/go-ipfs/namesys"
Steven Allen's avatar
Steven Allen committed
16
	path "gx/ipfs/QmX7uSbkNz76yNwBhuwYwRbhihLnJqM73VTCjS3UMJud9A/go-path"
Jan Winkelmann's avatar
Jan Winkelmann committed
17

18
	"gx/ipfs/QmPTfgFTo9PFr1PvPKyKoeMgBvYPh6cX3aDP7DHKVbnCbi/go-ipfs-cmds"
19
	"gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit"
20 21
)

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

37
EXAMPLES
38 39 40

Resolve the value of your identity:

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

Resolve the value of another name:

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

49
Resolve the value of another name recursively:
50

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

54 55
Resolve the value of an IPFS DAG path:

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

59
`,
60
	},
61

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

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

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

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

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

100
			if rcok {
Łukasz Magiera's avatar
Łukasz Magiera committed
101
				ropts = append(ropts, options.Name.DhtRecordCount(rc))
102 103
			}
			if dhttok {
104 105 106 107 108 109 110 111 112
				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
				}
Łukasz Magiera's avatar
Łukasz Magiera committed
113
				ropts = append(ropts, options.Name.DhtTimeout(d))
114
			}
Łukasz Magiera's avatar
Łukasz Magiera committed
115
			p, err := api.Name().Resolve(req.Context, name, ropts...)
116 117
			// ErrResolveRecursion is fine
			if err != nil && err != ns.ErrResolveRecursion {
Jan Winkelmann's avatar
Jan Winkelmann committed
118
				res.SetError(err, cmdkit.ErrNormal)
119 120
				return
			}
Łukasz Magiera's avatar
Łukasz Magiera committed
121
			cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: path.Path(p.String())})
122
			return
123 124
		}

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

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

Łukasz Magiera's avatar
Łukasz Magiera committed
138
		c := rp.Cid()
139

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

			fmt.Fprintln(w, output.Path.String())
			return nil
		}),
152
	},
153
	Type: ncmd.ResolvedPath{},
154
}