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

import (
4 5
	"io"
	"strings"
6
	"time"
7

8
	cmds "github.com/ipfs/go-ipfs/commands"
9
	"github.com/ipfs/go-ipfs/core"
Jan Winkelmann's avatar
Jan Winkelmann committed
10
	e "github.com/ipfs/go-ipfs/core/commands/e"
11
	ns "github.com/ipfs/go-ipfs/namesys"
12
	path "github.com/ipfs/go-ipfs/path"
Jan Winkelmann's avatar
Jan Winkelmann committed
13

14
	"gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
15 16
)

17 18
type ResolvedPath struct {
	Path path.Path
19 20
}

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

36
EXAMPLES
37 38 39

Resolve the value of your identity:

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

Resolve the value of another name:

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

48
Resolve the value of another name recursively:
49

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

53 54
Resolve the value of an IPFS DAG path:

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

58
`,
59
	},
60

Jan Winkelmann's avatar
Jan Winkelmann committed
61 62
	Arguments: []cmdkit.Argument{
		cmdkit.StringArg("name", true, false, "The name to resolve.").EnableStdin(),
63
	},
Jan Winkelmann's avatar
Jan Winkelmann committed
64
	Options: []cmdkit.Option{
65
		cmdkit.BoolOption("recursive", "r", "Resolve until the result is an IPFS name."),
66 67
		cmdkit.UintOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."),
		cmdkit.UintOption("dht-timeout", "dhtt", "Timeout in seconds for DHT resolution. Pass 0 for no timeout."),
68
	},
69
	Run: func(req cmds.Request, res cmds.Response) {
70

Jeromy's avatar
Jeromy committed
71
		n, err := req.InvocContext().GetNode()
72
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
73
			res.SetError(err, cmdkit.ErrNormal)
74
			return
75 76
		}

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

85
		name := req.Arguments()[0]
86
		recursive, _, _ := req.Option("recursive").Bool()
87 88 89

		// the case when ipns is resolved step by step
		if strings.HasPrefix(name, "/ipns/") && !recursive {
90 91 92 93 94 95 96 97 98 99 100
			rc, rcok, _ := req.Option("dht-record-count").Int()
			dhtt, dhttok, _ := req.Option("dht-timeout").Int()
			opts := ns.DefaultResolveOpts()
			opts.Depth = 1
			if rcok {
				opts.DhtRecordCount = uint(rc)
			}
			if dhttok {
				opts.DhtTimeout = time.Duration(dhtt) * time.Second
			}
			p, err := n.Namesys.Resolve(req.Context(), name, opts)
101 102
			// ErrResolveRecursion is fine
			if err != nil && err != ns.ErrResolveRecursion {
Jan Winkelmann's avatar
Jan Winkelmann committed
103
				res.SetError(err, cmdkit.ErrNormal)
104 105 106 107
				return
			}
			res.SetOutput(&ResolvedPath{p})
			return
108 109
		}

110 111 112
		// else, ipfs path or ipns with recursive flag
		p, err := path.ParsePath(name)
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
113
			res.SetError(err, cmdkit.ErrNormal)
114
			return
115
		}
116

117
		node, err := core.Resolve(req.Context(), n.Namesys, n.Resolver, p)
118
		if err != nil {
Jan Winkelmann's avatar
Jan Winkelmann committed
119
			res.SetError(err, cmdkit.ErrNormal)
120 121 122
			return
		}

Jeromy's avatar
Jeromy committed
123
		c := node.Cid()
124

Jeromy's avatar
Jeromy committed
125
		res.SetOutput(&ResolvedPath{path.FromCid(c)})
126
	},
127
	Marshalers: cmds.MarshalerMap{
128
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
Jan Winkelmann's avatar
Jan Winkelmann committed
129 130 131 132 133 134
			v, err := unwrapOutput(res.Output())
			if err != nil {
				return nil, err
			}

			output, ok := v.(*ResolvedPath)
135
			if !ok {
Jan Winkelmann's avatar
Jan Winkelmann committed
136
				return nil, e.TypeErr(output, v)
137
			}
138
			return strings.NewReader(output.Path.String() + "\n"), nil
139
		},
140
	},
141
	Type: ResolvedPath{},
142
}