resolve.go 3.92 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"
Dirk McCormick's avatar
Dirk McCormick committed
12
	nsopts "github.com/ipfs/go-ipfs/namesys/opts"
13
	path "github.com/ipfs/go-ipfs/path"
Jan Winkelmann's avatar
Jan Winkelmann committed
14

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

18 19
type ResolvedPath struct {
	Path path.Path
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."),
67 68
		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."),
69
	},
70
	Run: func(req cmds.Request, res cmds.Response) {
71

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

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

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

		// the case when ipns is resolved step by step
		if strings.HasPrefix(name, "/ipns/") && !recursive {
91 92
			rc, rcok, _ := req.Option("dht-record-count").Int()
			dhtt, dhttok, _ := req.Option("dht-timeout").Int()
Dirk McCormick's avatar
Dirk McCormick committed
93
			ropts := []nsopts.ResolveOpt{nsopts.Depth(1)}
94
			if rcok {
Dirk McCormick's avatar
Dirk McCormick committed
95
				ropts = append(ropts, nsopts.DhtRecordCount(uint(rc)))
96 97
			}
			if dhttok {
Dirk McCormick's avatar
Dirk McCormick committed
98
				ropts = append(ropts, nsopts.DhtTimeout(time.Duration(dhtt)*time.Second))
99
			}
Dirk McCormick's avatar
Dirk McCormick committed
100
			p, err := n.Namesys.Resolve(req.Context(), name, ropts...)
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
}